From b4d88c1e7a352ba41e7062a679b740053ef3aff9 Mon Sep 17 00:00:00 2001 From: zhanghaijun <1055190269@qq.com> Date: Thu, 19 Jun 2025 17:29:12 +0800 Subject: [PATCH] init --- .gitignore | 65 ++ pom.xml | 308 +++++ readme.txt | 1 + .../java/com/gci/boot/GciApplication.java | 33 + .../gci/boot/annotation/Query/OrderQuery.java | 27 + .../boot/annotation/Query/SelectQuery.java | 81 ++ .../Query/handle/QueryGenerator.java | 186 +++ .../gci/boot/annotation/fileUrl/FileUrl.java | 23 + .../fileUrl/handle/FileUrlHandle.java | 57 + .../importHandler/ExcelTypeHandler.java | 95 ++ .../importHandler/MyExcelVerifyHandler.java | 179 +++ .../annotation/permission/DataPermission.java | 36 + .../boot/annotation/repeat/FieldRepeat.java | 25 + .../boot/annotation/repeat/TableRepeat.java | 23 + .../repeat/handle/TableRepeatHandle.java | 27 + .../repeat/handle/TableRepeatUtils.java | 84 ++ .../gci/boot/aspect/DataPermissionAspect.java | 164 +++ .../boot/common/config/CancelConverter.java | 56 + .../gci/boot/common/config/DictConfig.java | 14 + .../com/gci/boot/common/config/LogConfig.java | 16 + .../common/config/UtilsInitializeConfig.java | 35 + .../gci/boot/common/dict/annotation/Dict.java | 25 + .../common/dict/annotation/ExcelEnum.java | 12 + .../boot/common/dict/aspect/DictAspect.java | 251 ++++ .../boot/common/dict/excel/DictConverter.java | 147 +++ .../boot/common/dict/excel/DictParser.java | 11 + .../boot/common/dict/excel/EnumConverter.java | 85 ++ .../dict/excel/MyExcelDictHandleImpl.java | 114 ++ .../boot/common/log/annotation/AddSysLog.java | 40 + .../boot/common/log/aspect/SysLogAspect.java | 212 ++++ .../common/query/SuperQueryGenerator.java | 4 + .../boot/common/string/StringValidAspect.java | 170 +++ .../gci/boot/common/util/BeanUtilsCopy.java | 181 +++ .../com/gci/boot/common/util/CacheUtil.java | 43 + .../com/gci/boot/common/util/CalcTool.java | 18 + .../boot/common/util/ClassReflectionUtil.java | 27 + .../common/util/CoordinateConverterUtil.java | 139 +++ .../com/gci/boot/common/util/DateUtils.java | 956 +++++++++++++++ .../com/gci/boot/common/util/FormatUtil.java | 92 ++ .../com/gci/boot/common/util/JsonUtil.java | 233 ++++ .../boot/common/util/LambdaFunctionUtil.java | 41 + .../com/gci/boot/common/util/LatLonPoint.java | 39 + .../gci/boot/common/util/LimitCheckUtil.java | 68 ++ .../java/com/gci/boot/common/util/Lock.java | 40 + .../com/gci/boot/common/util/MD5Util.java | 43 + .../com/gci/boot/common/util/MinioUtils.java | 748 ++++++++++++ .../gci/boot/common/util/ParamsCheckUtil.java | 282 +++++ .../boot/common/util/QueryWrapperUtil.java | 566 +++++++++ .../com/gci/boot/common/util/RedisKey.java | 22 + .../com/gci/boot/common/util/RedisUtil.java | 640 +++++++++++ .../boot/common/util/SpringContextUtil.java | 94 ++ .../common/util/SpringEnvironmentUtil.java | 37 + .../common/util/SqlInjectionCheckUtil.java | 32 + .../com/gci/boot/common/util/StringUtil.java | 74 ++ .../gci/boot/common/util/ValidateUtil.java | 22 + .../gci/boot/common/util/ValidatorUtil.java | 420 +++++++ .../com/gci/boot/common/util/ZipUtil.java | 50 + .../common/validated/ImportValidated.java | 7 + .../boot/common/validated/SaveValidated.java | 8 + .../common/validated/UpdateValidated.java | 7 + .../java/com/gci/boot/common/vo/Result.java | 120 ++ .../java/com/gci/boot/config/MinioConfig.java | 25 + .../gci/boot/config/MyBatisPlusConfig.java | 32 + .../java/com/gci/boot/config/RedisConfig.java | 105 ++ .../java/com/gci/boot/config/ShiroConfig.java | 142 +++ .../com/gci/boot/config/TomcatConfig.java | 25 + .../gci/boot/config/WebMvcConfiguration.java | 19 + .../com/gci/boot/constant/CacheConstant.java | 98 ++ .../com/gci/boot/constant/CommonConstant.java | 419 +++++++ .../gci/boot/constant/DataBaseConstant.java | 113 ++ .../boot/constant/DataPermissionConstant.java | 9 + .../com/gci/boot/constant/FileConstant.java | 84 ++ .../com/gci/boot/enums/AlarmCountType.java | 38 + .../java/com/gci/boot/enums/AlarmType.java | 58 + .../boot/enums/EventCharacteristicsType.java | 64 ++ .../java/com/gci/boot/enums/EventType.java | 55 + .../com/gci/boot/enums/FileExtension.java | 71 ++ .../com/gci/boot/enums/VehicleGpsType.java | 42 + .../gci/boot/exception/GciBootException.java | 19 + .../interceptor/GciBootExceptionHandler.java | 155 +++ .../MybatisDataPermissionInterceptor.java | 141 +++ .../boot/interceptor/MybatisInterceptor.java | 175 +++ .../basedata/controller/ExportController.java | 47 + .../TbCustomerArchivesController.java | 297 +++++ .../TbCustomerFollowTemplateController.java | 132 +++ .../TbExternalAddressBookController.java | 200 ++++ .../TbInspectionTemplateController.java | 131 +++ .../TbInsuranceCompanyArchivesController.java | 187 +++ .../TbRepairShopArchivesController.java | 159 +++ .../TbVehicleCheckTemplateController.java | 217 ++++ ...VehicleCheckTemplateProjectController.java | 114 ++ .../controller/TbVehicleController.java | 345 ++++++ .../TbVehicleSupplierArchivesController.java | 266 +++++ .../basedata/entity/TbCustomerArchives.java | 123 ++ .../entity/TbCustomerFollowTemplate.java | 102 ++ .../entity/TbCustomerFollowTemplatePart.java | 81 ++ .../entity/TbExternalAddressBook.java | 106 ++ .../basedata/entity/TbInspectionTemplate.java | 104 ++ .../entity/TbInspectionTemplateProject.java | 84 ++ .../entity/TbInsuranceCompanyArchives.java | 116 ++ .../basedata/entity/TbRepairShopArchives.java | 138 +++ .../modules/basedata/entity/TbVehicle.java | 334 ++++++ .../entity/TbVehicleCheckTemplate.java | 119 ++ .../entity/TbVehicleCheckTemplateProject.java | 87 ++ .../entity/TbVehicleSupplierArchives.java | 111 ++ .../mapper/TbCustomerArchivesMapper.java | 12 + .../TbCustomerFollowTemplateMapper.java | 16 + .../TbCustomerFollowTemplatePartMapper.java | 16 + .../mapper/TbExternalAddressBookMapper.java | 16 + .../mapper/TbInspectionTemplateMapper.java | 16 + .../TbInspectionTemplateProjectMapper.java | 16 + .../TbInsuranceCompanyArchivesMapper.java | 7 + .../mapper/TbRepairShopArchivesMapper.java | 14 + .../mapper/TbVehicleCheckTemplateMapper.java | 16 + .../TbVehicleCheckTemplateProjectMapper.java | 16 + .../basedata/mapper/TbVehicleMapper.java | 34 + .../TbVehicleSupplierArchivesMapper.java | 15 + .../mapper/xml/TbCustomerArchivesMapper.xml | 5 + .../xml/TbCustomerFollowTemplateMapper.xml | 5 + .../TbCustomerFollowTemplatePartMapper.xml | 5 + .../xml/TbExternalAddressBookMapper.xml | 5 + .../mapper/xml/TbInspectionTemplateMapper.xml | 5 + .../xml/TbInspectionTemplateProjectMapper.xml | 5 + .../xml/TbInsuranceCompanyArchivesMapper.xml | 5 + .../mapper/xml/TbRepairShopArchivesMapper.xml | 14 + .../xml/TbVehicleCheckTemplateMapper.xml | 5 + .../TbVehicleCheckTemplateProjectMapper.xml | 5 + .../basedata/mapper/xml/TbVehicleMapper.xml | 29 + .../xml/TbVehicleSupplierArchivesMapper.xml | 38 + .../query/ProjectVehicleListQuery.java | 48 + .../service/ITbCustomerArchivesService.java | 32 + .../ITbCustomerFollowTemplatePartService.java | 21 + .../ITbCustomerFollowTemplateService.java | 25 + .../ITbExternalAddressBookService.java | 16 + .../ITbInspectionTemplateProjectService.java | 16 + .../service/ITbInspectionTemplateService.java | 35 + .../ITbInsuranceCompanyArchivesService.java | 14 + .../service/ITbRepairShopArchivesService.java | 23 + ...ITbVehicleCheckTemplateProjectService.java | 29 + .../ITbVehicleCheckTemplateService.java | 18 + .../basedata/service/ITbVehicleService.java | 34 + .../ITbVehicleSupplierArchivesService.java | 19 + .../impl/TbCustomerArchivesServiceImpl.java | 102 ++ ...CustomerFollowTemplatePartServiceImpl.java | 39 + .../TbCustomerFollowTemplateServiceImpl.java | 117 ++ .../TbExternalAddressBookServiceImpl.java | 20 + ...bInspectionTemplateProjectServiceImpl.java | 20 + .../impl/TbInspectionTemplateServiceImpl.java | 115 ++ ...TbInsuranceCompanyArchivesServiceImpl.java | 26 + .../impl/TbRepairShopArchivesServiceImpl.java | 35 + ...ehicleCheckTemplateProjectServiceImpl.java | 138 +++ .../TbVehicleCheckTemplateServiceImpl.java | 34 + .../service/impl/TbVehicleServiceImpl.java | 67 ++ .../TbVehicleSupplierArchivesServiceImpl.java | 43 + .../modules/basedata/vo/SupplierPageVO.java | 106 ++ .../TbCustomerFollowController.java | 204 ++++ .../TbCustomerFollowPartController.java | 162 +++ .../TbCustomerOpinionController.java | 194 ++++ .../TbCustomerOpinionHandleController.java | 166 +++ .../TbCustomerTrainingController.java | 153 +++ .../TbInspectionTaskController.java | 160 +++ .../controller/TbScheduledPlanController.java | 107 ++ .../boot/modules/customer/dto/VehicleDto.java | 50 + .../customer/entity/TbCustomerFollow.java | 175 +++ .../customer/entity/TbCustomerFollowPart.java | 76 ++ .../customer/entity/TbCustomerOpinion.java | 160 +++ .../entity/TbCustomerOpinionHandle.java | 75 ++ .../customer/entity/TbCustomerTraining.java | 132 +++ .../customer/entity/TbInspectionTask.java | 170 +++ .../customer/entity/TbInspectionTaskPart.java | 85 ++ .../entity/TbInspectionTaskProject.java | 39 + .../entity/TbInspectionTaskVehicle.java | 47 + .../customer/entity/TbScheduledPlan.java | 80 ++ .../mapper/TbCustomerFollowMapper.java | 23 + .../mapper/TbCustomerFollowPartMapper.java | 16 + .../mapper/TbCustomerOpinionHandleMapper.java | 16 + .../mapper/TbCustomerOpinionMapper.java | 16 + .../mapper/TbCustomerTrainingMapper.java | 16 + .../mapper/TbInspectionTaskMapper.java | 33 + .../mapper/TbInspectionTaskPartMapper.java | 16 + .../mapper/TbInspectionTaskProjectMapper.java | 16 + .../mapper/TbInspectionTaskVehicleMapper.java | 16 + .../mapper/TbScheduledPlanMapper.java | 16 + .../mapper/xml/TbCustomerFollowMapper.xml | 22 + .../mapper/xml/TbCustomerFollowPartMapper.xml | 5 + .../xml/TbCustomerOpinionHandleMapper.xml | 5 + .../mapper/xml/TbCustomerOpinionMapper.xml | 5 + .../mapper/xml/TbCustomerTrainingMapper.xml | 5 + .../mapper/xml/TbInspectionTaskMapper.xml | 111 ++ .../mapper/xml/TbInspectionTaskPartMapper.xml | 5 + .../xml/TbInspectionTaskProjectMapper.xml | 5 + .../xml/TbInspectionTaskVehicleMapper.xml | 5 + .../mapper/xml/TbScheduledPlanMapper.xml | 5 + .../customer/query/CustomerTrainingQuery.java | 43 + .../service/ITbCustomerFollowPartService.java | 21 + .../service/ITbCustomerFollowService.java | 25 + .../ITbCustomerOpinionHandleService.java | 21 + .../service/ITbCustomerOpinionService.java | 29 + .../service/ITbCustomerTrainingService.java | 26 + .../service/ITbInspectionTaskPartService.java | 16 + .../ITbInspectionTaskProjectService.java | 16 + .../service/ITbInspectionTaskService.java | 29 + .../ITbInspectionTaskVehicleService.java | 18 + .../service/ITbScheduledPlanService.java | 25 + .../impl/TbCustomerFollowPartServiceImpl.java | 68 ++ .../impl/TbCustomerFollowServiceImpl.java | 109 ++ .../TbCustomerOpinionHandleServiceImpl.java | 35 + .../impl/TbCustomerOpinionServiceImpl.java | 95 ++ .../impl/TbCustomerTrainingServiceImpl.java | 78 ++ .../impl/TbInspectionTaskPartServiceImpl.java | 20 + .../TbInspectionTaskProjectServiceImpl.java | 20 + .../impl/TbInspectionTaskServiceImpl.java | 389 +++++++ .../TbInspectionTaskVehicleServiceImpl.java | 39 + .../impl/TbScheduledPlanServiceImpl.java | 398 +++++++ .../modules/customer/vo/CustomerFollowVo.java | 47 + .../modules/customer/vo/InspectionTaskVo.java | 47 + .../SafetyDataCenterController.java | 88 ++ .../controller/TbAssetCenterController.java | 131 +++ .../TbBusinessCenterController.java | 123 ++ .../controller/VehiclesCenterController.java | 163 +++ .../dataview/mapper/VehiclesCenterMapper.java | 179 +++ .../mapper/xml/VehiclesCenterMapper.xml | 261 +++++ .../service/ITbAssetCenterService.java | 33 + .../service/ITbBusinessCenterService.java | 37 + .../service/SafetyDataStatisticsService.java | 33 + .../service/VehiclesCenterService.java | 78 ++ .../impl/SafetyDataStatisticsServiceImpl.java | 249 ++++ .../service/impl/TbAssetCenterImpl.java | 140 +++ .../impl/TbBusinessCenterServiceImpl.java | 432 +++++++ .../impl/VehiclesCenterServiceImpl.java | 193 ++++ .../modules/dataview/vo/GisRoadMileVo.java | 27 + .../dataview/vo/ProjectContractVo.java | 40 + .../modules/dataview/vo/ProjectSignInVo.java | 32 + .../modules/dataview/vo/RepairPayMonthVo.java | 33 + .../modules/dataview/vo/VehicleCenterVo.java | 22 + .../dataview/vo/VehicleFaultAlarmVo.java | 21 + .../modules/dataview/vo/VehicleTotalVo.java | 20 + .../modules/dataview/vo/VehicleTypeVo.java | 30 + .../demo/controller/CRUDDemoController.java | 88 ++ .../demo/controller/ExcelDemoController.java | 298 +++++ .../demo/controller/RedisDemoController.java | 118 ++ .../gci/boot/modules/demo/entity/entity.java | 39 + .../GciMybatisPlusCodeGenerator.java | 64 ++ .../modules/demo/utildemo/JsonUtilDemo.java | 69 ++ .../driver/controller/TbDriverController.java | 359 ++++++ .../controller/TbDriverSignInController.java | 220 ++++ .../boot/modules/driver/entity/TbDriver.java | 195 ++++ .../modules/driver/entity/TbDriverSignIn.java | 160 +++ .../modules/driver/mapper/TbDriverMapper.java | 21 + .../driver/mapper/TbDriverSignInMapper.java | 30 + .../driver/mapper/xml/TbDriverMapper.xml | 17 + .../mapper/xml/TbDriverSignInMapper.xml | 64 ++ .../driver/service/ITbDriverService.java | 36 + .../service/ITbDriverSignInService.java | 26 + .../service/impl/TbDriverServiceImpl.java | 238 ++++ .../impl/TbDriverSignInServiceImpl.java | 203 ++++ .../modules/driver/vo/DriverImportVO.java | 123 ++ .../boot/modules/driver/vo/DriverUserVo.java | 41 + .../boot/modules/driver/vo/DriverWorkVO.java | 33 + .../FinanceCalculateController.java | 440 +++++++ .../controller/VehicleCostController.java | 141 +++ .../modules/finance/entity/BaseFinance.java | 82 ++ .../finance/entity/FinanceVehicleCost.java | 106 ++ .../modules/finance/entity/MeasureResult.java | 95 ++ .../modules/finance/entity/VehicleCost.java | 193 ++++ .../finance/mapper/BaseFinanceMapper.java | 19 + .../mapper/FinanceVehicleCostMapper.java | 8 + .../finance/mapper/MeasureResultMapper.java | 8 + .../finance/mapper/VehicleCostMapper.java | 8 + .../finance/mapper/xml/BaseFinanceMapper.xml | 22 + .../mapper/xml/FinanceVehicleCostMapper.xml | 5 + .../mapper/xml/MeasureResultMapper.xml | 5 + .../finance/mapper/xml/VehicleCostMapper.xml | 5 + .../finance/service/IBaseFinanceService.java | 81 ++ .../service/IFinanceVehicleCostService.java | 8 + .../service/IMeasureResultService.java | 8 + .../finance/service/IVehicleCostService.java | 9 + .../service/impl/BaseFinanceServiceImpl.java | 876 ++++++++++++++ .../impl/FinanceVehicleCostServiceImpl.java | 12 + .../impl/MeasureResultServiceImpl.java | 12 + .../service/impl/VehicleCostServiceImpl.java | 12 + .../modules/finance/vo/CalculateListVO.java | 55 + .../modules/finance/vo/CalculateParamVO.java | 13 + .../finance/vo/CalculateResultObjectVO.java | 19 + .../modules/finance/vo/CalculateResultVO.java | 26 + .../modules/finance/vo/DetailObjectVO.java | 43 + .../modules/finance/vo/FinanceItemVO.java | 49 + .../controller/GisGpsAnalysisController.java | 417 +++++++ .../gis/controller/RefuelAlarmController.java | 103 ++ .../TbGisActiveSafetyAlarmController.java | 124 ++ .../controller/TbGisChargeLogController.java | 124 ++ .../controller/TbGisFenceAlarmController.java | 126 ++ .../controller/TbGisFenceInfoController.java | 85 ++ .../controller/TbGisFencePlanController.java | 177 +++ .../TbGisFenceVehicleController.java | 84 ++ .../gis/controller/TbGisGpsController.java | 95 ++ .../TbGisGpsStatisticsController.java | 137 +++ .../controller/TbGisRunningbusController.java | 84 ++ .../TbGisSpeedingAlarmController.java | 126 ++ .../TbGisSpeedingThresholdController.java | 132 +++ .../TbGisStoppingAlarmController.java | 90 ++ .../TbGisVehicleFaultAlarmController.java | 145 +++ .../modules/gis/dto/EverydayMileCountDto.java | 22 + .../boot/modules/gis/dto/VehicleFaultDto.java | 11 + .../gci/boot/modules/gis/entity/GisAlarm.java | 18 + .../modules/gis/entity/GisGpsAnalysis.java | 112 ++ .../modules/gis/entity/GisRoadMileLog.java | 84 ++ .../boot/modules/gis/entity/RefuelAlarm.java | 69 ++ .../gis/entity/TbGisActiveSafetyAlarm.java | 189 +++ .../modules/gis/entity/TbGisChargeLog.java | 145 +++ .../modules/gis/entity/TbGisFenceAlarm.java | 142 +++ .../modules/gis/entity/TbGisFenceInfo.java | 52 + .../modules/gis/entity/TbGisFencePlan.java | 126 ++ .../modules/gis/entity/TbGisFenceVehicle.java | 42 + .../gci/boot/modules/gis/entity/TbGisGps.java | 128 +++ .../gis/entity/TbGisGpsStatistics.java | 132 +++ .../modules/gis/entity/TbGisRunningbus.java | 156 +++ .../gis/entity/TbGisSpeedingAlarm.java | 147 +++ .../gis/entity/TbGisSpeedingThreshold.java | 102 ++ .../gis/entity/TbGisStoppingAlarm.java | 127 ++ .../gis/entity/TbGisVehicleFaultAlarm.java | 147 +++ .../gis/mapper/GisGpsAnalysisMapper.java | 28 + .../gis/mapper/GisRoadMileLogMapper.java | 23 + .../modules/gis/mapper/RefuelAlarmMapper.java | 7 + .../mapper/TbGisActiveSafetyAlarmMapper.java | 27 + .../gis/mapper/TbGisChargeLogMapper.java | 20 + .../gis/mapper/TbGisFenceAlarmMapper.java | 20 + .../gis/mapper/TbGisFenceInfoMapper.java | 16 + .../gis/mapper/TbGisFencePlanMapper.java | 25 + .../gis/mapper/TbGisFenceVehicleMapper.java | 16 + .../modules/gis/mapper/TbGisGpsMapper.java | 16 + .../gis/mapper/TbGisGpsStatisticsMapper.java | 23 + .../gis/mapper/TbGisRunningbusMapper.java | 43 + .../gis/mapper/TbGisSpeedingAlarmMapper.java | 25 + .../mapper/TbGisSpeedingThresholdMapper.java | 16 + .../gis/mapper/TbGisStoppingAlarmMapper.java | 23 + .../mapper/TbGisVehicleFaultAlarmMapper.java | 35 + .../gis/mapper/xml/GisGpsAnalysisMapper.xml | 34 + .../gis/mapper/xml/GisRoadMileLogMapper.xml | 32 + .../gis/mapper/xml/RefuelAlarmMapper.xml | 5 + .../xml/TbGisActiveSafetyAlarmMapper.xml | 33 + .../gis/mapper/xml/TbGisChargeLogMapper.xml | 18 + .../gis/mapper/xml/TbGisFenceAlarmMapper.xml | 18 + .../gis/mapper/xml/TbGisFenceInfoMapper.xml | 5 + .../gis/mapper/xml/TbGisFencePlanMapper.xml | 34 + .../mapper/xml/TbGisFenceVehicleMapper.xml | 5 + .../modules/gis/mapper/xml/TbGisGpsMapper.xml | 5 + .../mapper/xml/TbGisGpsStatisticsMapper.xml | 45 + .../gis/mapper/xml/TbGisRunningbusMapper.xml | 122 ++ .../mapper/xml/TbGisSpeedingAlarmMapper.xml | 34 + .../xml/TbGisSpeedingThresholdMapper.xml | 5 + .../mapper/xml/TbGisStoppingAlarmMapper.xml | 20 + .../xml/TbGisVehicleFaultAlarmMapper.xml | 73 ++ .../modules/gis/query/EverydayInfoQuery.java | 28 + .../boot/modules/gis/query/EverydayQuery.java | 50 + .../gis/query/GisActiveSafetyQuery.java | 59 + .../modules/gis/query/GisChargeLogQuery.java | 49 + .../modules/gis/query/GisFenceAlarmQuery.java | 48 + .../modules/gis/query/GisSpeedingQuery.java | 49 + .../modules/gis/query/GisStoppingQuery.java | 51 + .../gis/query/GisVehicleFaultQuery.java | 56 + .../modules/gis/query/GpsHistoryQuery.java | 36 + .../gis/service/GisRoadMileLogService.java | 39 + .../gis/service/GpsConsumerService.java | 89 ++ .../gis/service/IGisGpsAnalysisService.java | 65 ++ .../gis/service/IRefuelAlarmService.java | 11 + .../ITbGisActiveSafetyAlarmService.java | 36 + .../gis/service/ITbGisChargeLogService.java | 23 + .../gis/service/ITbGisFenceAlarmService.java | 20 + .../gis/service/ITbGisFenceInfoService.java | 16 + .../gis/service/ITbGisFencePlanService.java | 81 ++ .../service/ITbGisFenceVehicleService.java | 16 + .../modules/gis/service/ITbGisGpsService.java | 31 + .../service/ITbGisGpsStatisticsService.java | 27 + .../gis/service/ITbGisRunningbusService.java | 16 + .../service/ITbGisSpeedingAlarmService.java | 34 + .../ITbGisSpeedingThresholdService.java | 42 + .../service/ITbGisStoppingAlarmService.java | 15 + .../ITbGisVehicleFaultAlarmService.java | 44 + .../impl/GisGpsAnalysisServiceImpl.java | 853 ++++++++++++++ .../impl/GisRoadMileLogServiceImpl.java | 255 ++++ .../service/impl/RefuelAlarmServiceImpl.java | 133 +++ .../TbGisActiveSafetyAlarmServiceImpl.java | 105 ++ .../impl/TbGisChargeLogServiceImpl.java | 41 + .../impl/TbGisFenceAlarmServiceImpl.java | 40 + .../impl/TbGisFenceInfoServiceImpl.java | 20 + .../impl/TbGisFencePlanServiceImpl.java | 361 ++++++ .../impl/TbGisFenceVehicleServiceImpl.java | 20 + .../gis/service/impl/TbGisGpsServiceImpl.java | 1021 +++++++++++++++++ .../impl/TbGisGpsStatisticsServiceImpl.java | 194 ++++ .../impl/TbGisRunningbusServiceImpl.java | 20 + .../impl/TbGisSpeedingAlarmServiceImpl.java | 59 + .../TbGisSpeedingThresholdServiceImpl.java | 194 ++++ .../impl/TbGisStoppingAlarmServiceImpl.java | 38 + .../TbGisVehicleFaultAlarmServiceImpl.java | 157 +++ .../boot/modules/gis/vo/EverydayGisVo.java | 140 +++ .../modules/gis/vo/EverydayMileCountVo.java | 23 + .../boot/modules/gis/vo/FenceSpeedBeanVO.java | 29 + .../gci/boot/modules/gis/vo/GisHistoryVo.java | 27 + .../boot/modules/gis/vo/GisProjectTreeVo.java | 29 + .../modules/gis/vo/GisRedisVehicleVo.java | 89 ++ .../gci/boot/modules/gis/vo/GisVehicleVo.java | 20 + .../gci/boot/modules/gis/vo/PointListDTO.java | 55 + .../gci/boot/modules/gis/vo/StatisGisVo.java | 144 +++ .../gci/boot/modules/gis/vo/TimeSlotDTO.java | 100 ++ .../boot/modules/gis/vo/VehicleFaultVo.java | 9 + .../boot/modules/gis/vo/VehicleWorkVO.java | 22 + .../gci/boot/modules/gis/vo/WorkLineVo.java | 10 + .../monitor/controller/MonitorController.java | 118 ++ .../modules/monitor/enums/DirectionEnum.java | 52 + .../monitor/enums/VehicleStatusEnum.java | 68 ++ .../monitor/service/IMonitorService.java | 63 + .../service/impl/MonitorServiceImpl.java | 202 ++++ .../boot/modules/monitor/vo/AlarmCountVO.java | 19 + .../modules/monitor/vo/OverallMonitorVO.java | 97 ++ .../boot/modules/monitor/vo/RunningbusVO.java | 157 +++ .../modules/monitor/vo/VehicleTreeVO.java | 15 + .../modules/msg/enums/RepairSenderEnum.java | 64 ++ .../modules/msg/enums/SenderTypeEnum.java | 35 + .../msg/enums/UpkeepBillSenderEnum.java | 59 + .../boot/modules/msg/enums/WorkOrderType.java | 44 + .../modules/msg/service/MsgPushService.java | 11 + .../msg/service/impl/MsgPushServiceImpl.java | 30 + .../gci/boot/modules/msg/vo/MsgRedisVO.java | 49 + .../controller/ProjectsController.java | 298 +++++ .../controller/TbContractController.java | 242 ++++ .../controller/TbVehicleCheckController.java | 272 +++++ .../TbVehicleCheckDetailController.java | 133 +++ .../TbVehicleCheckProjectController.java | 94 ++ .../projects/entity/ProjectUserRel.java | 73 ++ .../entity/ProjectVehicleBindLog.java | 76 ++ .../modules/projects/entity/Projects.java | 150 +++ .../modules/projects/entity/TbContract.java | 196 ++++ .../projects/entity/TbContractVehicle.java | 101 ++ .../projects/entity/TbVehicleCheck.java | 257 +++++ .../projects/entity/TbVehicleCheckDetail.java | 140 +++ .../entity/TbVehicleCheckProject.java | 89 ++ .../projects/mapper/ProjectUserRelMapper.java | 19 + .../mapper/ProjectVehicleBindLogMapper.java | 19 + .../projects/mapper/ProjectsMapper.java | 44 + .../projects/mapper/TbContractMapper.java | 20 + .../mapper/TbContractVehicleMapper.java | 7 + .../mapper/TbVehicleCheckDetailMapper.java | 16 + .../projects/mapper/TbVehicleCheckMapper.java | 16 + .../mapper/TbVehicleCheckProjectMapper.java | 16 + .../mapper/xml/ProjectUserRelMapper.xml | 6 + .../xml/ProjectVehicleBindLogMapper.xml | 4 + .../projects/mapper/xml/ProjectsMapper.xml | 52 + .../projects/mapper/xml/TbContractMapper.xml | 11 + .../mapper/xml/TbContractVehicleMapper.xml | 4 + .../mapper/xml/TbVehicleCheckDetailMapper.xml | 5 + .../mapper/xml/TbVehicleCheckMapper.xml | 5 + .../xml/TbVehicleCheckProjectMapper.xml | 5 + .../service/IProjectUserRelService.java | 19 + .../IProjectVehicleBindLogService.java | 35 + .../projects/service/IProjectsService.java | 66 ++ .../projects/service/ITbContractService.java | 37 + .../service/ITbContractVehicleService.java | 14 + .../service/ITbVehicleCheckDetailService.java | 31 + .../ITbVehicleCheckProjectService.java | 21 + .../service/ITbVehicleCheckService.java | 25 + .../impl/ProjectUserRelServiceImpl.java | 20 + .../ProjectVehicleBindLogServiceImpl.java | 54 + .../service/impl/ProjectsServiceImpl.java | 508 ++++++++ .../service/impl/TbContractServiceImpl.java | 344 ++++++ .../impl/TbContractVehicleServiceImpl.java | 49 + .../impl/TbVehicleCheckDetailServiceImpl.java | 178 +++ .../TbVehicleCheckProjectServiceImpl.java | 81 ++ .../impl/TbVehicleCheckServiceImpl.java | 299 +++++ .../modules/projects/vo/TbVehicleCheckVo.java | 217 ++++ .../modules/projects/vo/VehicleTypeVO.java | 13 + .../AccidentInfoStatisController.java | 103 ++ .../AnnualInspectionInfoStatisController.java | 79 ++ .../statis/controller/BusinessController.java | 102 ++ .../controller/ProjectStatisController.java | 73 ++ .../controller/RepairStatisController.java | 133 +++ .../TbInsuranceStatisController.java | 145 +++ .../controller/UpkeepStatisController.java | 132 +++ .../controller/VehicleAnalysisController.java | 202 ++++ .../controller/VehicleRentalController.java | 78 ++ .../controller/VehicleStatisController.java | 74 ++ .../controller/ViolationStatisController.java | 113 ++ .../WeighbridgeStatisController.java | 79 ++ .../service/AccidentInfoStatisService.java | 14 + .../AnnualInspectionInfoStatisService.java | 14 + .../statis/service/BusinessService.java | 14 + .../service/InsuranceRecordService.java | 12 + .../statis/service/ProjectStatisService.java | 15 + .../statis/service/RepairStatisService.java | 32 + .../statis/service/UpkeepStatisService.java | 33 + .../statis/service/VehicleRentalService.java | 9 + .../statis/service/VehicleStatisService.java | 24 + .../service/ViolationStatisService.java | 25 + .../impl/AccidentInfoStatisServiceImpl.java | 101 ++ ...AnnualInspectionInfoStatisServiceImpl.java | 141 +++ .../service/impl/BusinessServiceImpl.java | 239 ++++ .../impl/InsuranceRecordServiceImpl.java | 98 ++ .../impl/ProjectStatisServiceImpl.java | 169 +++ .../service/impl/RepairStatisServiceImpl.java | 193 ++++ .../service/impl/UpkeepStatisServiceImpl.java | 172 +++ .../impl/VehicleRentalServiceImpl.java | 286 +++++ .../impl/VehicleStatisServiceImpl.java | 648 +++++++++++ .../impl/ViolationStatisServiceImpl.java | 111 ++ .../statis/vo/AccidentInfoStatisVo.java | 37 + .../boot/modules/statis/vo/AlarmTrendVO.java | 18 + .../vo/AnnualInspectionInfoStatisVo.java | 52 + .../modules/statis/vo/BusinessStatisVo.java | 18 + .../boot/modules/statis/vo/ColumnItemVO.java | 11 + .../boot/modules/statis/vo/ColumnItemVo2.java | 11 + .../modules/statis/vo/DriverAnalysisVO.java | 65 ++ .../modules/statis/vo/InsuranceStatisVo.java | 68 ++ .../modules/statis/vo/ProjectStatisVo.java | 42 + .../boot/modules/statis/vo/RepairBoardVO.java | 16 + .../modules/statis/vo/RepairStatisVO.java | 53 + .../boot/modules/statis/vo/SafetyDataVO.java | 13 + .../boot/modules/statis/vo/StatisParamVO.java | 55 + .../boot/modules/statis/vo/UpkeepBoardVO.java | 17 + .../modules/statis/vo/UpkeepStatisVO.java | 48 + .../modules/statis/vo/VehicleAnalysisVO.java | 91 ++ .../modules/statis/vo/VehicleRentalVo.java | 91 ++ .../modules/statis/vo/VehicleStatisVo.java | 85 ++ .../statis/vo/ViolationRecordStatisVO.java | 48 + .../statis/vo/WeighbridgeStatisVo.java | 64 ++ .../system/controller/LoginController.java | 270 +++++ .../controller/SysDepartController.java | 292 +++++ .../system/controller/SysDictController.java | 221 ++++ .../controller/SysDictItemController.java | 147 +++ .../system/controller/SysLogController.java | 101 ++ .../controller/SysPermissionController.java | 429 +++++++ .../system/controller/SysRoleController.java | 299 +++++ .../system/controller/SysUserController.java | 419 +++++++ .../system/entity/InnerUserProject.java | 36 + .../system/entity/LoginTimesValidate.java | 64 ++ .../boot/modules/system/entity/SysDepart.java | 107 ++ .../boot/modules/system/entity/SysDict.java | 67 ++ .../modules/system/entity/SysDictItem.java | 65 ++ .../boot/modules/system/entity/SysLog.java | 89 ++ .../modules/system/entity/SysPermission.java | 106 ++ .../boot/modules/system/entity/SysRole.java | 67 ++ .../system/entity/SysRolePermission.java | 38 + .../boot/modules/system/entity/SysUser.java | 158 +++ .../modules/system/entity/SysUserDepart.java | 44 + .../modules/system/entity/SysUserRole.java | 39 + .../system/mapper/SysDepartMapper.java | 20 + .../system/mapper/SysDictItemMapper.java | 16 + .../modules/system/mapper/SysDictMapper.java | 36 + .../modules/system/mapper/SysLogMapper.java | 16 + .../system/mapper/SysPermissionMapper.java | 32 + .../modules/system/mapper/SysRoleMapper.java | 23 + .../mapper/SysRolePermissionMapper.java | 16 + .../system/mapper/SysUserDepartMapper.java | 16 + .../modules/system/mapper/SysUserMapper.java | 25 + .../system/mapper/SysUserRoleMapper.java | 16 + .../system/mapper/xml/SysDepartMapper.xml | 13 + .../system/mapper/xml/SysDictItemMapper.xml | 5 + .../system/mapper/xml/SysDictMapper.xml | 58 + .../system/mapper/xml/SysLogMapper.xml | 5 + .../system/mapper/xml/SysPermissionMapper.xml | 32 + .../system/mapper/xml/SysRoleMapper.xml | 23 + .../mapper/xml/SysRolePermissionMapper.xml | 5 + .../system/mapper/xml/SysUserDepartMapper.xml | 5 + .../system/mapper/xml/SysUserMapper.xml | 126 ++ .../system/mapper/xml/SysUserRoleMapper.xml | 5 + .../system/service/ISysDepartService.java | 28 + .../system/service/ISysDictItemService.java | 16 + .../system/service/ISysDictService.java | 36 + .../system/service/ISysLogService.java | 16 + .../system/service/ISysPermissionService.java | 35 + .../service/ISysRolePermissionService.java | 19 + .../system/service/ISysRoleService.java | 34 + .../system/service/ISysUserDepartService.java | 16 + .../system/service/ISysUserRoleService.java | 16 + .../system/service/ISysUserService.java | 71 ++ .../service/LoginTimesValidateService.java | 36 + .../service/impl/SysDepartServiceImpl.java | 60 + .../service/impl/SysDictItemServiceImpl.java | 20 + .../service/impl/SysDictServiceImpl.java | 126 ++ .../service/impl/SysLogServiceImpl.java | 20 + .../impl/SysPermissionServiceImpl.java | 126 ++ .../impl/SysRolePermissionServiceImpl.java | 78 ++ .../service/impl/SysRoleServiceImpl.java | 68 ++ .../impl/SysUserDepartServiceImpl.java | 20 + .../service/impl/SysUserRoleServiceImpl.java | 20 + .../service/impl/SysUserServiceImpl.java | 352 ++++++ .../authc/CustomShiroFilterFactoryBean.java | 75 ++ .../modules/system/shiro/authc/JwtToken.java | 28 + .../system/shiro/authc/ShiroRealm.java | 203 ++++ .../system/shiro/authc/aop/JwtFilter.java | 112 ++ .../shiro/authc/aop/ResourceCheckFilter.java | 68 ++ .../modules/system/shiro/vo/DefContants.java | 7 + .../modules/system/shiro/vo/ResponseBean.java | 42 + .../modules/system/shiro/vo/UserBean.java | 14 + .../modules/system/util/AesEncryptUtil.java | 101 ++ .../system/util/GciDataAutorUtils.java | 87 ++ .../gci/boot/modules/system/util/JwtUtil.java | 340 ++++++ .../modules/system/util/PasswordUtil.java | 207 ++++ .../modules/system/util/QsEncodeUtil.java | 170 +++ .../modules/system/util/RandImageUtil.java | 140 +++ .../boot/modules/system/vo/ApiTokenModel.java | 35 + .../gci/boot/modules/system/vo/DictModel.java | 42 + .../boot/modules/system/vo/LimitRequest.java | 17 + .../gci/boot/modules/system/vo/LoginUser.java | 94 ++ .../modules/system/vo/SysDepartTreeModel.java | 64 ++ .../boot/modules/system/vo/SysLoginModel.java | 55 + .../system/vo/SysPermissionDataRuleModel.java | 144 +++ .../modules/system/vo/SysPermissionTree.java | 334 ++++++ .../modules/system/vo/SysUserCacheInfo.java | 67 ++ .../gci/boot/modules/system/vo/TreeModel.java | 186 +++ .../task/customer/SchedulePlanTask.java | 33 + .../modules/task/gps/GisGpsAnalysisTask.java | 104 ++ .../task/gps/GisGpsStatisticsTask.java | 32 + .../task/gps/GisSpeedingThresholdTask.java | 34 + .../task/gps/SpeedingAndFenceAlarmTask.java | 46 + .../vehicles/AnnualInspectionRemindTask.java | 32 + .../gci/boot/modules/test/TestController.java | 117 ++ .../com/gci/boot/modules/test/TestVO.java | 9 + .../controller/BacklogController.java | 51 + .../vehicles/controller/RepairController.java | 518 +++++++++ .../controller/TbAccidentInfoController.java | 169 +++ .../TbAnnualInspectionInfoController.java | 322 ++++++ .../TbAnnualInspectionRemindController.java | 156 +++ .../TbConsumablesTemplateController.java | 145 +++ .../TbConsumablesTemplatePartController.java | 190 +++ .../TbCustomizedTemplateController.java | 144 +++ .../TbCustomizedTemplatePartController.java | 90 ++ .../controller/TbInsuranceController.java | 390 +++++++ .../TbInsuranceRecordController.java | 190 +++ .../TbInsuranceRemindController.java | 144 +++ .../TbRefuelChargeRecordController.java | 244 ++++ .../TbViolationRecordController.java | 378 ++++++ .../controller/UpKeepBillController.java | 354 ++++++ .../controller/UpKeepPlanController.java | 283 +++++ .../controller/UpKeepRuleController.java | 184 +++ .../vehicles/entity/TbAccidentInfo.java | 230 ++++ .../entity/TbAccidentInsuranceInfo.java | 174 +++ .../vehicles/entity/TbAccidentProgress.java | 108 ++ .../entity/TbAnnualInspectionInfo.java | 254 ++++ .../entity/TbAnnualInspectionRemind.java | 110 ++ .../entity/TbConsumablesTemplate.java | 86 ++ .../entity/TbConsumablesTemplateOutPart.java | 116 ++ .../entity/TbConsumablesTemplatePart.java | 179 +++ .../vehicles/entity/TbCustomizedTemplate.java | 80 ++ .../entity/TbCustomizedTemplatePart.java | 100 ++ .../modules/vehicles/entity/TbInsurance.java | 328 ++++++ .../vehicles/entity/TbInsuranceRecord.java | 290 +++++ .../vehicles/entity/TbInsuranceRemind.java | 214 ++++ .../vehicles/entity/TbRefuelChargeRecord.java | 232 ++++ .../vehicles/entity/TbRepairAssign.java | 94 ++ .../vehicles/entity/TbRepairCheck.java | 93 ++ .../modules/vehicles/entity/TbRepairInfo.java | 168 +++ .../vehicles/entity/TbRepairOffer.java | 125 ++ .../vehicles/entity/TbUpkeepAssign.java | 79 ++ .../modules/vehicles/entity/TbUpkeepBill.java | 208 ++++ .../vehicles/entity/TbUpkeepCheck.java | 90 ++ .../vehicles/entity/TbUpkeepOffer.java | 121 ++ .../modules/vehicles/entity/TbUpkeepPlan.java | 286 +++++ .../vehicles/entity/TbUpkeepPlanCheck.java | 90 ++ .../modules/vehicles/entity/TbUpkeepRule.java | 143 +++ .../vehicles/entity/TbViolationRecord.java | 210 ++++ .../modules/vehicles/enums/BacklogEnum.java | 62 + .../vehicles/enums/BacklogTabEnum.java | 47 + .../enums/RepairStatusChangeEvent.java | 123 ++ .../enums/RepairStatusEnumDriver.java | 84 ++ .../enums/RepairStatusEnumEmployee.java | 84 ++ .../RepairStatusEnumEmployeeAndLeader.java | 84 ++ .../enums/RepairStatusEnumLeader.java | 84 ++ .../enums/RepairStatusEnumRepair.java | 84 ++ .../RepairStatusEnumRepairAndDriver.java | 84 ++ .../enums/UpkeepPlanStatusEnumEmployee.java | 78 ++ .../enums/UpkeepPlanStatusEnumLeader.java | 78 ++ .../enums/UpkeepStatusChangeEvent.java | 98 ++ .../UpkeepStatusEnumEmployeeAndLeader.java | 82 ++ .../enums/UpkeepStatusEnumRepair.java | 77 ++ .../vehicles/mapper/TbAccidentInfoMapper.java | 34 + .../mapper/TbAccidentInsuranceInfoMapper.java | 16 + .../mapper/TbAccidentProgressMapper.java | 21 + .../mapper/TbAnnualInspectionInfoMapper.java | 42 + .../TbAnnualInspectionRemindMapper.java | 21 + .../mapper/TbConsumablesTemplateMapper.java | 22 + .../TbConsumablesTemplateOutPartMapper.java | 7 + .../TbConsumablesTemplatePartMapper.java | 16 + .../mapper/TbCustomizedTemplateMapper.java | 22 + .../TbCustomizedTemplatePartMapper.java | 16 + .../vehicles/mapper/TbInsuranceMapper.java | 37 + .../mapper/TbInsuranceRecordMapper.java | 39 + .../mapper/TbInsuranceRemindMapper.java | 16 + .../mapper/TbRefuelChargeRecordMapper.java | 22 + .../vehicles/mapper/TbRepairAssignMapper.java | 7 + .../vehicles/mapper/TbRepairCheckMapper.java | 7 + .../vehicles/mapper/TbRepairInfoMapper.java | 85 ++ .../vehicles/mapper/TbRepairOfferMapper.java | 29 + .../vehicles/mapper/TbUpkeepAssignMapper.java | 8 + .../vehicles/mapper/TbUpkeepBillMapper.java | 74 ++ .../vehicles/mapper/TbUpkeepCheckMapper.java | 7 + .../vehicles/mapper/TbUpkeepOfferMapper.java | 8 + .../mapper/TbUpkeepPlanCheckMapper.java | 8 + .../vehicles/mapper/TbUpkeepPlanMapper.java | 25 + .../vehicles/mapper/TbUpkeepRuleMapper.java | 7 + .../mapper/TbViolationRecordMapper.java | 76 ++ .../mapper/xml/TbAccidentInfoMapper.xml | 203 ++++ .../xml/TbAccidentInsuranceInfoMapper.xml | 5 + .../mapper/xml/TbAccidentProgressMapper.xml | 12 + .../xml/TbAnnualInspectionInfoMapper.xml | 345 ++++++ .../xml/TbAnnualInspectionRemindMapper.xml | 30 + .../xml/TbConsumablesTemplateMapper.xml | 37 + .../TbConsumablesTemplateOutPartMapper.tld | 5 + .../xml/TbConsumablesTemplatePartMapper.xml | 5 + .../mapper/xml/TbCustomizedTemplateMapper.xml | 37 + .../xml/TbCustomizedTemplatePartMapper.xml | 5 + .../vehicles/mapper/xml/TbInsuranceMapper.xml | 158 +++ .../mapper/xml/TbInsuranceRecordMapper.xml | 71 ++ .../mapper/xml/TbInsuranceRemindMapper.xml | 5 + .../mapper/xml/TbRefuelChargeRecordMapper.xml | 21 + .../mapper/xml/TbRepairAssignMapper.xml | 5 + .../mapper/xml/TbRepairCheckMapper.xml | 5 + .../mapper/xml/TbRepairInfoMapper.xml | 385 +++++++ .../mapper/xml/TbRepairOfferMapper.xml | 66 ++ .../mapper/xml/TbUpkeepAssignMapper.xml | 5 + .../mapper/xml/TbUpkeepBillMapper.xml | 296 +++++ .../mapper/xml/TbUpkeepCheckMapper.xml | 5 + .../mapper/xml/TbUpkeepOfferMapper.xml | 5 + .../mapper/xml/TbUpkeepPlanCheckMapper.xml | 5 + .../mapper/xml/TbUpkeepPlanMapper.xml | 92 ++ .../mapper/xml/TbUpkeepRuleMapper.xml | 5 + .../mapper/xml/TbViolationRecordMapper.xml | 173 +++ .../vehicles/query/AccidentInfoQuery.java | 55 + .../query/AnnualInspectionInfoQuery.java | 38 + .../query/AnnualInspectionRemindQuery.java | 47 + .../query/ConsumablesTemplateQuery.java | 22 + .../query/CustomizedTemplateQuery.java | 22 + .../vehicles/service/BacklogService.java | 20 + .../vehicles/service/CommonService.java | 7 + .../service/IRepairUpkeepImportService.java | 28 + .../service/ITbAccidentInfoService.java | 28 + .../ITbAccidentInsuranceInfoService.java | 16 + .../service/ITbAccidentProgressService.java | 16 + .../ITbAnnualInspectionInfoService.java | 38 + .../ITbAnnualInspectionRemindService.java | 52 + .../ITbConsumablesTemplateOutPartService.java | 7 + .../ITbConsumablesTemplatePartService.java | 45 + .../ITbConsumablesTemplateService.java | 34 + .../ITbCustomizedTemplatePartService.java | 16 + .../service/ITbCustomizedTemplateService.java | 29 + .../service/ITbInsuranceRecordService.java | 19 + .../service/ITbInsuranceRemindService.java | 26 + .../vehicles/service/ITbInsuranceService.java | 38 + .../service/ITbRefuelChargeRecordService.java | 25 + .../service/ITbRepairAssignService.java | 7 + .../service/ITbRepairCheckService.java | 7 + .../service/ITbRepairInfoService.java | 43 + .../service/ITbRepairOfferService.java | 7 + .../service/ITbUpkeepAssignService.java | 8 + .../service/ITbUpkeepBillService.java | 47 + .../service/ITbUpkeepCheckService.java | 7 + .../service/ITbUpkeepOfferService.java | 8 + .../service/ITbUpkeepPlanCheckService.java | 8 + .../service/ITbUpkeepPlanService.java | 39 + .../service/ITbUpkeepRuleService.java | 7 + .../service/ITbViolationRecordService.java | 52 + .../service/impl/BacklogServiceImpl.java | 304 +++++ .../service/impl/CommonServiceImpl.java | 105 ++ .../impl/RepairUpkeepImportServiceImpl.java | 641 +++++++++++ .../impl/TbAccidentInfoServiceImpl.java | 250 ++++ .../TbAccidentInsuranceInfoServiceImpl.java | 20 + .../impl/TbAccidentProgressServiceImpl.java | 20 + .../TbAnnualInspectionInfoServiceImpl.java | 309 +++++ .../TbAnnualInspectionRemindServiceImpl.java | 240 ++++ ...ConsumablesTemplateOutPartServiceImpl.java | 11 + .../TbConsumablesTemplatePartServiceImpl.java | 270 +++++ .../TbConsumablesTemplateServiceImpl.java | 132 +++ .../TbCustomizedTemplatePartServiceImpl.java | 20 + .../impl/TbCustomizedTemplateServiceImpl.java | 134 +++ .../impl/TbInsuranceRecordServiceImpl.java | 107 ++ .../impl/TbInsuranceRemindServiceImpl.java | 216 ++++ .../service/impl/TbInsuranceServiceImpl.java | 324 ++++++ .../impl/TbRefuelChargeRecordServiceImpl.java | 186 +++ .../impl/TbRepairAssignServiceImpl.java | 16 + .../impl/TbRepairCheckServiceImpl.java | 16 + .../service/impl/TbRepairInfoServiceImpl.java | 596 ++++++++++ .../impl/TbRepairOfferServiceImpl.java | 13 + .../impl/TbUpkeepAssignServiceImpl.java | 13 + .../service/impl/TbUpkeepBillServiceImpl.java | 604 ++++++++++ .../impl/TbUpkeepCheckServiceImpl.java | 13 + .../impl/TbUpkeepOfferServiceImpl.java | 16 + .../impl/TbUpkeepPlanCheckServiceImpl.java | 16 + .../service/impl/TbUpkeepPlanServiceImpl.java | 501 ++++++++ .../service/impl/TbUpkeepRuleServiceImpl.java | 16 + .../impl/TbViolationRecordServiceImpl.java | 453 ++++++++ .../vehicles/vo/AttachmentDetailVO.java | 14 + .../modules/vehicles/vo/BacklogStatisVO.java | 13 + .../modules/vehicles/vo/CancelObjectVO.java | 25 + .../boot/modules/vehicles/vo/CancelVO.java | 13 + .../vehicles/vo/ConsumablesTemplateVo.java | 98 ++ .../vehicles/vo/CustomizedTemplateVo.java | 96 ++ .../vehicles/vo/InsuranceImportVO.java | 176 +++ .../modules/vehicles/vo/InsurancePriceVO.java | 13 + .../vehicles/vo/InsuranceRecordStatisVO.java | 56 + .../boot/modules/vehicles/vo/MessageVO.java | 28 + .../modules/vehicles/vo/MsgImportFailVO.java | 21 + .../modules/vehicles/vo/RegexTemplateVO.java | 9 + .../vehicles/vo/RepairDataEntryVO.java | 16 + .../modules/vehicles/vo/RepairDetailVO.java | 31 + .../modules/vehicles/vo/RepairImportVO.java | 122 ++ .../modules/vehicles/vo/RepairInfoListVO.java | 114 ++ .../modules/vehicles/vo/RepairObjectVO.java | 48 + .../vehicles/vo/TbInsuranceRemindVo.java | 214 ++++ .../vo/TbRefuelChargeRecordImportVo.java | 134 +++ .../vehicles/vo/TbRefuelChargeRecordVo.java | 208 ++++ .../vehicles/vo/UpkeepDataEntryVO.java | 16 + .../modules/vehicles/vo/UpkeepImportVO.java | 110 ++ .../modules/vehicles/vo/UpkeepInfoListVO.java | 141 +++ .../modules/vehicles/vo/UpkeepObjectVO.java | 45 + .../vehicles/vo/UpkeepPlanObjectVO.java | 38 + .../modules/vehicles/vo/VehicleInfoVO.java | 75 ++ .../modules/vehicles/vo/VehicleProjectVO.java | 16 + .../video/controller/VideoController.java | 195 ++++ .../modules/video/service/IVideoService.java | 70 ++ .../video/service/Impl/VideoServiceImpl.java | 510 ++++++++ .../gci/boot/modules/video/vo/ChannelVO.java | 19 + .../modules/video/vo/CutVideoListPageVO.java | 14 + .../boot/modules/video/vo/CutVideoListVO.java | 37 + .../modules/video/vo/CutVideoResultVO.java | 11 + .../boot/modules/video/vo/ResultDeviceVO.java | 65 ++ .../boot/modules/video/vo/VideoDeviceVO.java | 57 + .../boot/modules/video/vo/VideoPlayVO.java | 21 + .../properties/GciRedisCacheProperties.java | 35 + .../properties/GciSecurityProperties.java | 39 + src/main/resources/application-dev.yml | 103 ++ src/main/resources/application-prod.yml | 101 ++ src/main/resources/application-test.yml | 90 ++ src/main/resources/application.yml | 5 + .../excelTemplate/保养台账导入模板.xlsx | Bin 0 -> 11641 bytes .../resources/excelTemplate/保险导入模板.xlsx | Bin 0 -> 11964 bytes .../excelTemplate/加油充电登记导入模板.xlsx | Bin 0 -> 11801 bytes .../excelTemplate/司机档案导入模板.xlsx | Bin 0 -> 11795 bytes .../resources/excelTemplate/年检导入模板.xlsx | Bin 0 -> 12516 bytes .../excelTemplate/车辆作业导出模板.xlsx | Bin 0 -> 10012 bytes .../车辆作业综合分析周报导出模板.xlsx | Bin 0 -> 10208 bytes .../车辆作业综合分析日报导出模板.xlsx | Bin 0 -> 9977 bytes .../车辆作业综合分析月报导出模板.xlsx | Bin 0 -> 10204 bytes .../excelTemplate/车辆维修导入模板.xlsx | Bin 0 -> 11901 bytes .../excelTemplate/违章短信导入模板.xlsx | Bin 0 -> 8980 bytes .../excelTemplate/采购校验车导入.xlsx | Bin 0 -> 10708 bytes src/main/resources/logback-spring.xml | 42 + .../com/gci/boot/test/PermissionTest.java | 101 ++ src/updateSql/update-230915.sql | 22 + src/updateSql/update-230919.sql | 13 + src/updateSql/update-230921.sql | 127 ++ src/updateSql/update-230925.sql | 129 +++ src/updateSql/update-231007.sql | 29 + src/updateSql/update-231011.sql | 64 ++ src/updateSql/update-231014.sql | 160 +++ src/updateSql/update-231020.sql | 612 ++++++++++ src/updateSql/update-231024.sql | 5 + src/updateSql/update-231031.sql | 141 +++ src/updateSql/update-231106.sql | 36 + src/updateSql/update-231108.sql | 20 + src/updateSql/update-231109.sql | 44 + src/updateSql/update-231117-2.sql | 51 + src/updateSql/update-231117.sql | 4 + src/updateSql/update-240220.sql | 189 +++ src/updateSql/update-240307.sql | 21 + 862 files changed, 77421 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 readme.txt create mode 100644 src/main/java/com/gci/boot/GciApplication.java create mode 100644 src/main/java/com/gci/boot/annotation/Query/OrderQuery.java create mode 100644 src/main/java/com/gci/boot/annotation/Query/SelectQuery.java create mode 100644 src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java create mode 100644 src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java create mode 100644 src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java create mode 100644 src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java create mode 100644 src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java create mode 100644 src/main/java/com/gci/boot/annotation/permission/DataPermission.java create mode 100644 src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java create mode 100644 src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java create mode 100644 src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java create mode 100644 src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java create mode 100644 src/main/java/com/gci/boot/aspect/DataPermissionAspect.java create mode 100644 src/main/java/com/gci/boot/common/config/CancelConverter.java create mode 100644 src/main/java/com/gci/boot/common/config/DictConfig.java create mode 100644 src/main/java/com/gci/boot/common/config/LogConfig.java create mode 100644 src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java create mode 100644 src/main/java/com/gci/boot/common/dict/annotation/Dict.java create mode 100644 src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java create mode 100644 src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java create mode 100644 src/main/java/com/gci/boot/common/dict/excel/DictConverter.java create mode 100644 src/main/java/com/gci/boot/common/dict/excel/DictParser.java create mode 100644 src/main/java/com/gci/boot/common/dict/excel/EnumConverter.java create mode 100644 src/main/java/com/gci/boot/common/dict/excel/MyExcelDictHandleImpl.java create mode 100644 src/main/java/com/gci/boot/common/log/annotation/AddSysLog.java create mode 100644 src/main/java/com/gci/boot/common/log/aspect/SysLogAspect.java create mode 100644 src/main/java/com/gci/boot/common/query/SuperQueryGenerator.java create mode 100644 src/main/java/com/gci/boot/common/string/StringValidAspect.java create mode 100644 src/main/java/com/gci/boot/common/util/BeanUtilsCopy.java create mode 100644 src/main/java/com/gci/boot/common/util/CacheUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/CalcTool.java create mode 100644 src/main/java/com/gci/boot/common/util/ClassReflectionUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/CoordinateConverterUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/DateUtils.java create mode 100644 src/main/java/com/gci/boot/common/util/FormatUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/JsonUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/LambdaFunctionUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/LatLonPoint.java create mode 100644 src/main/java/com/gci/boot/common/util/LimitCheckUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/Lock.java create mode 100644 src/main/java/com/gci/boot/common/util/MD5Util.java create mode 100644 src/main/java/com/gci/boot/common/util/MinioUtils.java create mode 100644 src/main/java/com/gci/boot/common/util/ParamsCheckUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/QueryWrapperUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/RedisKey.java create mode 100644 src/main/java/com/gci/boot/common/util/RedisUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/SpringContextUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/SpringEnvironmentUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/SqlInjectionCheckUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/StringUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/ValidateUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/ValidatorUtil.java create mode 100644 src/main/java/com/gci/boot/common/util/ZipUtil.java create mode 100644 src/main/java/com/gci/boot/common/validated/ImportValidated.java create mode 100644 src/main/java/com/gci/boot/common/validated/SaveValidated.java create mode 100644 src/main/java/com/gci/boot/common/validated/UpdateValidated.java create mode 100644 src/main/java/com/gci/boot/common/vo/Result.java create mode 100644 src/main/java/com/gci/boot/config/MinioConfig.java create mode 100644 src/main/java/com/gci/boot/config/MyBatisPlusConfig.java create mode 100644 src/main/java/com/gci/boot/config/RedisConfig.java create mode 100644 src/main/java/com/gci/boot/config/ShiroConfig.java create mode 100644 src/main/java/com/gci/boot/config/TomcatConfig.java create mode 100644 src/main/java/com/gci/boot/config/WebMvcConfiguration.java create mode 100644 src/main/java/com/gci/boot/constant/CacheConstant.java create mode 100644 src/main/java/com/gci/boot/constant/CommonConstant.java create mode 100644 src/main/java/com/gci/boot/constant/DataBaseConstant.java create mode 100644 src/main/java/com/gci/boot/constant/DataPermissionConstant.java create mode 100644 src/main/java/com/gci/boot/constant/FileConstant.java create mode 100644 src/main/java/com/gci/boot/enums/AlarmCountType.java create mode 100644 src/main/java/com/gci/boot/enums/AlarmType.java create mode 100644 src/main/java/com/gci/boot/enums/EventCharacteristicsType.java create mode 100644 src/main/java/com/gci/boot/enums/EventType.java create mode 100644 src/main/java/com/gci/boot/enums/FileExtension.java create mode 100644 src/main/java/com/gci/boot/enums/VehicleGpsType.java create mode 100644 src/main/java/com/gci/boot/exception/GciBootException.java create mode 100644 src/main/java/com/gci/boot/interceptor/GciBootExceptionHandler.java create mode 100644 src/main/java/com/gci/boot/interceptor/MybatisDataPermissionInterceptor.java create mode 100644 src/main/java/com/gci/boot/interceptor/MybatisInterceptor.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/ExportController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbCustomerArchivesController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbCustomerFollowTemplateController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbExternalAddressBookController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbInspectionTemplateController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbInsuranceCompanyArchivesController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbRepairShopArchivesController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbVehicleCheckTemplateController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbVehicleCheckTemplateProjectController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbVehicleController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/controller/TbVehicleSupplierArchivesController.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbCustomerArchives.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbCustomerFollowTemplate.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbCustomerFollowTemplatePart.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbExternalAddressBook.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbInspectionTemplate.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbInspectionTemplateProject.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbInsuranceCompanyArchives.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbRepairShopArchives.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbVehicle.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbVehicleCheckTemplate.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbVehicleCheckTemplateProject.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/entity/TbVehicleSupplierArchives.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbCustomerArchivesMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbCustomerFollowTemplateMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbCustomerFollowTemplatePartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbExternalAddressBookMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbInspectionTemplateMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbInspectionTemplateProjectMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbInsuranceCompanyArchivesMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbRepairShopArchivesMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbVehicleCheckTemplateMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbVehicleCheckTemplateProjectMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbVehicleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/TbVehicleSupplierArchivesMapper.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbCustomerArchivesMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbCustomerFollowTemplateMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbCustomerFollowTemplatePartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbExternalAddressBookMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbInspectionTemplateMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbInspectionTemplateProjectMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbInsuranceCompanyArchivesMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbRepairShopArchivesMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbVehicleCheckTemplateMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbVehicleCheckTemplateProjectMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbVehicleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/mapper/xml/TbVehicleSupplierArchivesMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/basedata/query/ProjectVehicleListQuery.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbCustomerArchivesService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbCustomerFollowTemplatePartService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbCustomerFollowTemplateService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbExternalAddressBookService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbInspectionTemplateProjectService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbInspectionTemplateService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbInsuranceCompanyArchivesService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbRepairShopArchivesService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbVehicleCheckTemplateProjectService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbVehicleCheckTemplateService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbVehicleService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/ITbVehicleSupplierArchivesService.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbCustomerArchivesServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbCustomerFollowTemplatePartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbCustomerFollowTemplateServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbExternalAddressBookServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbInspectionTemplateProjectServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbInspectionTemplateServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbInsuranceCompanyArchivesServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbRepairShopArchivesServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbVehicleCheckTemplateProjectServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbVehicleCheckTemplateServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbVehicleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/service/impl/TbVehicleSupplierArchivesServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/basedata/vo/SupplierPageVO.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbCustomerFollowController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbCustomerFollowPartController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbCustomerOpinionController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbCustomerOpinionHandleController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbCustomerTrainingController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbInspectionTaskController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/controller/TbScheduledPlanController.java create mode 100644 src/main/java/com/gci/boot/modules/customer/dto/VehicleDto.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbCustomerFollow.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbCustomerFollowPart.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbCustomerOpinion.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbCustomerOpinionHandle.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbCustomerTraining.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbInspectionTask.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbInspectionTaskPart.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbInspectionTaskProject.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbInspectionTaskVehicle.java create mode 100644 src/main/java/com/gci/boot/modules/customer/entity/TbScheduledPlan.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbCustomerFollowMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbCustomerFollowPartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbCustomerOpinionHandleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbCustomerOpinionMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbCustomerTrainingMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbInspectionTaskMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbInspectionTaskPartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbInspectionTaskProjectMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbInspectionTaskVehicleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/TbScheduledPlanMapper.java create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbCustomerFollowMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbCustomerFollowPartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbCustomerOpinionHandleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbCustomerOpinionMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbCustomerTrainingMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbInspectionTaskMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbInspectionTaskPartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbInspectionTaskProjectMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbInspectionTaskVehicleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/mapper/xml/TbScheduledPlanMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/customer/query/CustomerTrainingQuery.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbCustomerFollowPartService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbCustomerFollowService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbCustomerOpinionHandleService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbCustomerOpinionService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbCustomerTrainingService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbInspectionTaskPartService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbInspectionTaskProjectService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbInspectionTaskService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbInspectionTaskVehicleService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/ITbScheduledPlanService.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbCustomerFollowPartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbCustomerFollowServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbCustomerOpinionHandleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbCustomerOpinionServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbCustomerTrainingServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbInspectionTaskPartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbInspectionTaskProjectServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbInspectionTaskServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbInspectionTaskVehicleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/service/impl/TbScheduledPlanServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/customer/vo/CustomerFollowVo.java create mode 100644 src/main/java/com/gci/boot/modules/customer/vo/InspectionTaskVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/controller/SafetyDataCenterController.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/controller/TbAssetCenterController.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/controller/TbBusinessCenterController.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/controller/VehiclesCenterController.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/mapper/VehiclesCenterMapper.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/mapper/xml/VehiclesCenterMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/ITbAssetCenterService.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/ITbBusinessCenterService.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/SafetyDataStatisticsService.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/VehiclesCenterService.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/impl/SafetyDataStatisticsServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/impl/TbAssetCenterImpl.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/impl/TbBusinessCenterServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/service/impl/VehiclesCenterServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/GisRoadMileVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/ProjectContractVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/ProjectSignInVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/RepairPayMonthVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/VehicleCenterVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/VehicleFaultAlarmVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/VehicleTotalVo.java create mode 100644 src/main/java/com/gci/boot/modules/dataview/vo/VehicleTypeVo.java create mode 100644 src/main/java/com/gci/boot/modules/demo/controller/CRUDDemoController.java create mode 100644 src/main/java/com/gci/boot/modules/demo/controller/ExcelDemoController.java create mode 100644 src/main/java/com/gci/boot/modules/demo/controller/RedisDemoController.java create mode 100644 src/main/java/com/gci/boot/modules/demo/entity/entity.java create mode 100644 src/main/java/com/gci/boot/modules/demo/generator/GciMybatisPlusCodeGenerator.java create mode 100644 src/main/java/com/gci/boot/modules/demo/utildemo/JsonUtilDemo.java create mode 100644 src/main/java/com/gci/boot/modules/driver/controller/TbDriverController.java create mode 100644 src/main/java/com/gci/boot/modules/driver/controller/TbDriverSignInController.java create mode 100644 src/main/java/com/gci/boot/modules/driver/entity/TbDriver.java create mode 100644 src/main/java/com/gci/boot/modules/driver/entity/TbDriverSignIn.java create mode 100644 src/main/java/com/gci/boot/modules/driver/mapper/TbDriverMapper.java create mode 100644 src/main/java/com/gci/boot/modules/driver/mapper/TbDriverSignInMapper.java create mode 100644 src/main/java/com/gci/boot/modules/driver/mapper/xml/TbDriverMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/driver/mapper/xml/TbDriverSignInMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/driver/service/ITbDriverService.java create mode 100644 src/main/java/com/gci/boot/modules/driver/service/ITbDriverSignInService.java create mode 100644 src/main/java/com/gci/boot/modules/driver/service/impl/TbDriverServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/driver/service/impl/TbDriverSignInServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/driver/vo/DriverImportVO.java create mode 100644 src/main/java/com/gci/boot/modules/driver/vo/DriverUserVo.java create mode 100644 src/main/java/com/gci/boot/modules/driver/vo/DriverWorkVO.java create mode 100644 src/main/java/com/gci/boot/modules/finance/controller/FinanceCalculateController.java create mode 100644 src/main/java/com/gci/boot/modules/finance/controller/VehicleCostController.java create mode 100644 src/main/java/com/gci/boot/modules/finance/entity/BaseFinance.java create mode 100644 src/main/java/com/gci/boot/modules/finance/entity/FinanceVehicleCost.java create mode 100644 src/main/java/com/gci/boot/modules/finance/entity/MeasureResult.java create mode 100644 src/main/java/com/gci/boot/modules/finance/entity/VehicleCost.java create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/BaseFinanceMapper.java create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/FinanceVehicleCostMapper.java create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/MeasureResultMapper.java create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/VehicleCostMapper.java create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/xml/BaseFinanceMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/xml/FinanceVehicleCostMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/xml/MeasureResultMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/finance/mapper/xml/VehicleCostMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/finance/service/IBaseFinanceService.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/IFinanceVehicleCostService.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/IMeasureResultService.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/IVehicleCostService.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/impl/BaseFinanceServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/impl/FinanceVehicleCostServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/impl/MeasureResultServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/finance/service/impl/VehicleCostServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/finance/vo/CalculateListVO.java create mode 100644 src/main/java/com/gci/boot/modules/finance/vo/CalculateParamVO.java create mode 100644 src/main/java/com/gci/boot/modules/finance/vo/CalculateResultObjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/finance/vo/CalculateResultVO.java create mode 100644 src/main/java/com/gci/boot/modules/finance/vo/DetailObjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/finance/vo/FinanceItemVO.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/GisGpsAnalysisController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/RefuelAlarmController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisActiveSafetyAlarmController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisChargeLogController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisFenceAlarmController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisFenceInfoController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisFencePlanController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisFenceVehicleController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisGpsController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisGpsStatisticsController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisRunningbusController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisSpeedingAlarmController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisSpeedingThresholdController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisStoppingAlarmController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/controller/TbGisVehicleFaultAlarmController.java create mode 100644 src/main/java/com/gci/boot/modules/gis/dto/EverydayMileCountDto.java create mode 100644 src/main/java/com/gci/boot/modules/gis/dto/VehicleFaultDto.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/GisAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/GisGpsAnalysis.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/GisRoadMileLog.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/RefuelAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisActiveSafetyAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisChargeLog.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisFenceAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisFenceInfo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisFencePlan.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisFenceVehicle.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisGps.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisGpsStatistics.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisRunningbus.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisSpeedingAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisSpeedingThreshold.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisStoppingAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/entity/TbGisVehicleFaultAlarm.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/GisGpsAnalysisMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/GisRoadMileLogMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/RefuelAlarmMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisActiveSafetyAlarmMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisChargeLogMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisFenceAlarmMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisFenceInfoMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisFencePlanMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisFenceVehicleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisGpsMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisGpsStatisticsMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisRunningbusMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisSpeedingAlarmMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisSpeedingThresholdMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisStoppingAlarmMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/TbGisVehicleFaultAlarmMapper.java create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/GisGpsAnalysisMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/GisRoadMileLogMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/RefuelAlarmMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisActiveSafetyAlarmMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisChargeLogMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceAlarmMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceInfoMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFencePlanMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceVehicleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsStatisticsMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisRunningbusMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingAlarmMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingThresholdMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisStoppingAlarmMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisVehicleFaultAlarmMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/gis/query/EverydayInfoQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/EverydayQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GisActiveSafetyQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GisChargeLogQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GisFenceAlarmQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GisSpeedingQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GisStoppingQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GisVehicleFaultQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/query/GpsHistoryQuery.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/GisRoadMileLogService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/GpsConsumerService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/IGisGpsAnalysisService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/IRefuelAlarmService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisActiveSafetyAlarmService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisChargeLogService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceAlarmService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceInfoService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisFencePlanService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceVehicleService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsStatisticsService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisRunningbusService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingAlarmService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingThresholdService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisStoppingAlarmService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/ITbGisVehicleFaultAlarmService.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/GisGpsAnalysisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/GisRoadMileLogServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/RefuelAlarmServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisActiveSafetyAlarmServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisChargeLogServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceAlarmServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceInfoServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFencePlanServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceVehicleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsStatisticsServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisRunningbusServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingAlarmServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingThresholdServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisStoppingAlarmServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/service/impl/TbGisVehicleFaultAlarmServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/EverydayGisVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/EverydayMileCountVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/FenceSpeedBeanVO.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/GisHistoryVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/GisProjectTreeVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/GisRedisVehicleVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/GisVehicleVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/PointListDTO.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/StatisGisVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/TimeSlotDTO.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/VehicleFaultVo.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/VehicleWorkVO.java create mode 100644 src/main/java/com/gci/boot/modules/gis/vo/WorkLineVo.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/controller/MonitorController.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/enums/DirectionEnum.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/enums/VehicleStatusEnum.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/service/IMonitorService.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/service/impl/MonitorServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/vo/AlarmCountVO.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/vo/OverallMonitorVO.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/vo/RunningbusVO.java create mode 100644 src/main/java/com/gci/boot/modules/monitor/vo/VehicleTreeVO.java create mode 100644 src/main/java/com/gci/boot/modules/msg/enums/RepairSenderEnum.java create mode 100644 src/main/java/com/gci/boot/modules/msg/enums/SenderTypeEnum.java create mode 100644 src/main/java/com/gci/boot/modules/msg/enums/UpkeepBillSenderEnum.java create mode 100644 src/main/java/com/gci/boot/modules/msg/enums/WorkOrderType.java create mode 100644 src/main/java/com/gci/boot/modules/msg/service/MsgPushService.java create mode 100644 src/main/java/com/gci/boot/modules/msg/service/impl/MsgPushServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/msg/vo/MsgRedisVO.java create mode 100644 src/main/java/com/gci/boot/modules/projects/controller/ProjectsController.java create mode 100644 src/main/java/com/gci/boot/modules/projects/controller/TbContractController.java create mode 100644 src/main/java/com/gci/boot/modules/projects/controller/TbVehicleCheckController.java create mode 100644 src/main/java/com/gci/boot/modules/projects/controller/TbVehicleCheckDetailController.java create mode 100644 src/main/java/com/gci/boot/modules/projects/controller/TbVehicleCheckProjectController.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/ProjectUserRel.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/ProjectVehicleBindLog.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/Projects.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/TbContract.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/TbContractVehicle.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheck.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckDetail.java create mode 100644 src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckProject.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/ProjectUserRelMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/ProjectVehicleBindLogMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/ProjectsMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/TbContractMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/TbContractVehicleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckDetailMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckProjectMapper.java create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectUserRelMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectVehicleBindLogMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectsMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractVehicleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckDetailMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckProjectMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/projects/service/IProjectUserRelService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/IProjectVehicleBindLogService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/IProjectsService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/ITbContractService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/ITbContractVehicleService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckDetailService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckProjectService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckService.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/ProjectUserRelServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/ProjectVehicleBindLogServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/ProjectsServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/TbContractServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/TbContractVehicleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckDetailServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckProjectServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/projects/vo/TbVehicleCheckVo.java create mode 100644 src/main/java/com/gci/boot/modules/projects/vo/VehicleTypeVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/AccidentInfoStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/AnnualInspectionInfoStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/BusinessController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/ProjectStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/RepairStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/TbInsuranceStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/UpkeepStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/VehicleAnalysisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/VehicleRentalController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/VehicleStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/ViolationStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/controller/WeighbridgeStatisController.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/AccidentInfoStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/AnnualInspectionInfoStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/BusinessService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/InsuranceRecordService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/ProjectStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/RepairStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/UpkeepStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/VehicleRentalService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/VehicleStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/ViolationStatisService.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/AccidentInfoStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/AnnualInspectionInfoStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/BusinessServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/InsuranceRecordServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/ProjectStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/RepairStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/UpkeepStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/VehicleRentalServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/VehicleStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/service/impl/ViolationStatisServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/AccidentInfoStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/AlarmTrendVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/AnnualInspectionInfoStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/BusinessStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVo2.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/DriverAnalysisVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/InsuranceStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/ProjectStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/RepairBoardVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/RepairStatisVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/SafetyDataVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/StatisParamVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/UpkeepBoardVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/UpkeepStatisVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/VehicleAnalysisVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/VehicleRentalVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/VehicleStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/ViolationRecordStatisVO.java create mode 100644 src/main/java/com/gci/boot/modules/statis/vo/WeighbridgeStatisVo.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/LoginController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysDepartController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysDictController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysDictItemController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysLogController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysPermissionController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysRoleController.java create mode 100644 src/main/java/com/gci/boot/modules/system/controller/SysUserController.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/InnerUserProject.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/LoginTimesValidate.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysDepart.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysDict.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysDictItem.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysLog.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysPermission.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysRole.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysRolePermission.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysUser.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysUserDepart.java create mode 100644 src/main/java/com/gci/boot/modules/system/entity/SysUserRole.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysDepartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysDictItemMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysDictMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysLogMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysPermissionMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysRoleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysRolePermissionMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysUserDepartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysUserMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/SysUserRoleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysDepartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictItemMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysLogMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysPermissionMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysRoleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysRolePermissionMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserDepartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserRoleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysDepartService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysDictItemService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysDictService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysLogService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysPermissionService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysRolePermissionService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysRoleService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysUserDepartService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysUserRoleService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/ISysUserService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/LoginTimesValidateService.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysDepartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysDictItemServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysDictServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysLogServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysPermissionServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysRolePermissionServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysRoleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysUserDepartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysUserRoleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/service/impl/SysUserServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/authc/CustomShiroFilterFactoryBean.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/authc/JwtToken.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/authc/ShiroRealm.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/authc/aop/JwtFilter.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/authc/aop/ResourceCheckFilter.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/vo/DefContants.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/vo/ResponseBean.java create mode 100644 src/main/java/com/gci/boot/modules/system/shiro/vo/UserBean.java create mode 100644 src/main/java/com/gci/boot/modules/system/util/AesEncryptUtil.java create mode 100644 src/main/java/com/gci/boot/modules/system/util/GciDataAutorUtils.java create mode 100644 src/main/java/com/gci/boot/modules/system/util/JwtUtil.java create mode 100644 src/main/java/com/gci/boot/modules/system/util/PasswordUtil.java create mode 100644 src/main/java/com/gci/boot/modules/system/util/QsEncodeUtil.java create mode 100644 src/main/java/com/gci/boot/modules/system/util/RandImageUtil.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/ApiTokenModel.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/DictModel.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/LimitRequest.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/LoginUser.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/SysDepartTreeModel.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/SysLoginModel.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/SysPermissionDataRuleModel.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/SysPermissionTree.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/SysUserCacheInfo.java create mode 100644 src/main/java/com/gci/boot/modules/system/vo/TreeModel.java create mode 100644 src/main/java/com/gci/boot/modules/task/customer/SchedulePlanTask.java create mode 100644 src/main/java/com/gci/boot/modules/task/gps/GisGpsAnalysisTask.java create mode 100644 src/main/java/com/gci/boot/modules/task/gps/GisGpsStatisticsTask.java create mode 100644 src/main/java/com/gci/boot/modules/task/gps/GisSpeedingThresholdTask.java create mode 100644 src/main/java/com/gci/boot/modules/task/gps/SpeedingAndFenceAlarmTask.java create mode 100644 src/main/java/com/gci/boot/modules/task/vehicles/AnnualInspectionRemindTask.java create mode 100644 src/main/java/com/gci/boot/modules/test/TestController.java create mode 100644 src/main/java/com/gci/boot/modules/test/TestVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/BacklogController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/RepairController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbAccidentInfoController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionInfoController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionRemindController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplateController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplatePartController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplateController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplatePartController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceRecordController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceRemindController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbRefuelChargeRecordController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/TbViolationRecordController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepBillController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepPlanController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepRuleController.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInfo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInsuranceInfo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentProgress.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionInfo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionRemind.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplate.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplateOutPart.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplatePart.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplate.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplatePart.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbInsurance.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRecord.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRemind.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbRefuelChargeRecord.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairAssign.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairCheck.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairInfo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairOffer.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepAssign.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepBill.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepCheck.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepOffer.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlan.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlanCheck.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepRule.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/entity/TbViolationRecord.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/BacklogEnum.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/BacklogTabEnum.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusChangeEvent.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumDriver.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployee.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployeeAndLeader.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumLeader.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepair.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepairAndDriver.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumEmployee.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumLeader.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusChangeEvent.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumEmployeeAndLeader.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumRepair.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInfoMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInsuranceInfoMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentProgressMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionInfoMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionRemindMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateOutPartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplatePartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplateMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplatePartMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRecordMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRemindMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbRefuelChargeRecordMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairAssignMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairCheckMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairInfoMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairOfferMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepAssignMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepBillMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepCheckMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepOfferMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanCheckMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepRuleMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/TbViolationRecordMapper.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInfoMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInsuranceInfoMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentProgressMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionInfoMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionRemindMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateOutPartMapper.tld create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplatePartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplateMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplatePartMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRecordMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRemindMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRefuelChargeRecordMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairAssignMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairCheckMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairInfoMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairOfferMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepAssignMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepBillMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepCheckMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepOfferMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanCheckMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepRuleMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbViolationRecordMapper.xml create mode 100644 src/main/java/com/gci/boot/modules/vehicles/query/AccidentInfoQuery.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionInfoQuery.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionRemindQuery.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/query/ConsumablesTemplateQuery.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/query/CustomizedTemplateQuery.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/BacklogService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/CommonService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/IRepairUpkeepImportService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInfoService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInsuranceInfoService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentProgressService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionInfoService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionRemindService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateOutPartService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplatePartService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplatePartService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplateService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRecordService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRemindService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbRefuelChargeRecordService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairAssignService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairCheckService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairInfoService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairOfferService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepAssignService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepBillService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepCheckService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepOfferService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanCheckService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepRuleService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/ITbViolationRecordService.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/BacklogServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/CommonServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/RepairUpkeepImportServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInfoServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInsuranceInfoServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentProgressServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionInfoServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionRemindServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateOutPartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplatePartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplatePartServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplateServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRecordServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRemindServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRefuelChargeRecordServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairAssignServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairCheckServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairInfoServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairOfferServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepAssignServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepBillServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepCheckServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepOfferServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanCheckServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepRuleServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/service/impl/TbViolationRecordServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/AttachmentDetailVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/BacklogStatisVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/CancelObjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/CancelVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/ConsumablesTemplateVo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/CustomizedTemplateVo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceImportVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/InsurancePriceVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceRecordStatisVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/MessageVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/MsgImportFailVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/RegexTemplateVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/RepairDataEntryVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/RepairDetailVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/RepairImportVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/RepairInfoListVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/RepairObjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/TbInsuranceRemindVo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordImportVo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordVo.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepDataEntryVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepImportVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepInfoListVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepObjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepPlanObjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/VehicleInfoVO.java create mode 100644 src/main/java/com/gci/boot/modules/vehicles/vo/VehicleProjectVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/controller/VideoController.java create mode 100644 src/main/java/com/gci/boot/modules/video/service/IVideoService.java create mode 100644 src/main/java/com/gci/boot/modules/video/service/Impl/VideoServiceImpl.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/ChannelVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/CutVideoListPageVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/CutVideoListVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/CutVideoResultVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/ResultDeviceVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/VideoDeviceVO.java create mode 100644 src/main/java/com/gci/boot/modules/video/vo/VideoPlayVO.java create mode 100644 src/main/java/com/gci/boot/properties/GciRedisCacheProperties.java create mode 100644 src/main/java/com/gci/boot/properties/GciSecurityProperties.java create mode 100644 src/main/resources/application-dev.yml create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/application-test.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/excelTemplate/保养台账导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/保险导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/加油充电登记导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/司机档案导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/年检导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/车辆作业导出模板.xlsx create mode 100644 src/main/resources/excelTemplate/车辆作业综合分析周报导出模板.xlsx create mode 100644 src/main/resources/excelTemplate/车辆作业综合分析日报导出模板.xlsx create mode 100644 src/main/resources/excelTemplate/车辆作业综合分析月报导出模板.xlsx create mode 100644 src/main/resources/excelTemplate/车辆维修导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/违章短信导入模板.xlsx create mode 100644 src/main/resources/excelTemplate/采购校验车导入.xlsx create mode 100644 src/main/resources/logback-spring.xml create mode 100644 src/test/java/com/gci/boot/test/PermissionTest.java create mode 100644 src/updateSql/update-230915.sql create mode 100644 src/updateSql/update-230919.sql create mode 100644 src/updateSql/update-230921.sql create mode 100644 src/updateSql/update-230925.sql create mode 100644 src/updateSql/update-231007.sql create mode 100644 src/updateSql/update-231011.sql create mode 100644 src/updateSql/update-231014.sql create mode 100644 src/updateSql/update-231020.sql create mode 100644 src/updateSql/update-231024.sql create mode 100644 src/updateSql/update-231031.sql create mode 100644 src/updateSql/update-231106.sql create mode 100644 src/updateSql/update-231108.sql create mode 100644 src/updateSql/update-231109.sql create mode 100644 src/updateSql/update-231117-2.sql create mode 100644 src/updateSql/update-231117.sql create mode 100644 src/updateSql/update-240220.sql create mode 100644 src/updateSql/update-240307.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c936be6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/ +*.iws +*.iml +*.ipr +rebel.xml + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store + +# Compiled class file +*.class + +# Log file +*.log +*.log.gz + +# flatten +.flattened-pom.xml + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar +target/ + +### temp ignore ### +*.cache +*.diff +*.patch +*.tmp +*.java~ +*.properties~ +*.xml~ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ac29e3f --- /dev/null +++ b/pom.xml @@ -0,0 +1,308 @@ + + 4.0.0 + com.gci.boot + cdenv-manage + 1.0.0-SNAPSHOT + jar + gci-boot-backend-demo Tapestry 5 Application + GCI-Boot3.0样例工程 + + + org.springframework.boot + spring-boot-starter-parent + 2.6.15 + + + + 1.0.0-SNAPSHOT + UTF-8 + 1.2.7 + 0.0.39 + 3.0.0-M5 + 3.8.1 + 1.8 + 1.8 + 5.8.20 + 3.4.2 + 3.5.1 + 2.3 + 3.3.2 + 3.0.0 + 2.6.15 + 2021.0.5 + 2021.1 + UTF-8 + 2.3.6.RELEASE + 1.1.1.RELEASE + 5.6.0 + 1.8 + 1.8 + 2.2.5 + 0.0.23 + 1.5.24 + 0.9.1 + 2.6.0 + 1.18.22 + 2.13.0 + 2.1.210 + 3.8.0 + 3.2.1 + 1.12.0 + 2.11.1 + 1.1.17 + 42.2.5 + 3.7.0 + 6.2.5.Final + 4.4.0 + + + + + gci-nexus + Releases + http://10.88.2.69:8081/nexus/content/repositories/releases/ + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis.plus.version} + + + + io.swagger + swagger-models + ${swagger.core.version} + + + io.swagger + swagger-annotations + ${swagger.core.version} + + + + org.springframework.boot + spring-boot-starter-web + + + cn.hutool + hutool-all + ${hutool.version} + + + org.apache.commons + commons-lang3 + + + org.projectlombok + lombok + ${lombok.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + org.springframework.boot + spring-boot-devtools + ${spring.boot.version} + true + + + org.springframework.boot + spring-boot-starter-aop + + + com.alibaba + easyexcel + ${easyexcel.version} + + + + org.apache.shiro + shiro-spring-boot-starter + ${shiro.version} + + + + org.springframework.boot + spring-boot-starter-cache + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.postgresql + postgresql + runtime + ${postgresql.version} + + + + com.auth0 + java-jwt + ${java.jwt.version} + + + + + + com.baomidou + mybatis-plus-generator + ${mybatis.plus.generator.version} + + + + org.apache.velocity + velocity-engine-core + ${velocity.version} + + + + org.freemarker + freemarker + + + + org.hibernate.validator + hibernate-validator + ${org.hibernate.validator.version} + + + io.minio + minio + 8.2.2 + + + org.aspectj + aspectjweaver + 1.9.7 + + + org.springframework.statemachine + spring-statemachine-core + 2.1.3.RELEASE + + + org.springframework.statemachine + spring-statemachine-redis + 1.2.9.RELEASE + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + 2.13.5 + + + cn.afterturn + easypoi-base + ${easypoi.version} + + + cn.afterturn + easypoi-web + ${easypoi.version} + + + cn.afterturn + easypoi-annotation + ${easypoi.version} + + + + + + dev + + dev + + + true + + + + test + + test + + + + prod + + prod + + + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + org.apache.maven.plugins + maven-resources-plugin + + + woff + woff2 + eot + ttf + svg + xls + xlsx + + + + + + + src/main/resources + true + + + src/main/java + + **/*.xml + **/*.json + **/*.ftl + + + + + diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..8178c76 --- /dev/null +++ b/readme.txt @@ -0,0 +1 @@ +readme diff --git a/src/main/java/com/gci/boot/GciApplication.java b/src/main/java/com/gci/boot/GciApplication.java new file mode 100644 index 0000000..49487be --- /dev/null +++ b/src/main/java/com/gci/boot/GciApplication.java @@ -0,0 +1,33 @@ +package com.gci.boot; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.scheduling.annotation.EnableScheduling; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +@SpringBootApplication +@EnableScheduling +@Slf4j +public class GciApplication { + + public static void main(String[] args) throws UnknownHostException { + ConfigurableApplicationContext application = SpringApplication.run(GciApplication.class, args); + Environment env = application.getEnvironment(); + String ip = InetAddress.getLocalHost().getHostAddress(); + String port = env.getProperty("server.port"); + String path = env.getProperty("server.servlet.context-path"); + log.info("\n----------------------------------------------------------\n\t" + + "Application Gci-Boot is running! Access URLs:\n\t" + + "Local: \t\thttp://localhost:" + port + path + "/\n\t" + + "External: \thttp://" + ip + ":" + port + path + "/\n\t" + + "swagger-ui: \thttp://" + ip + ":" + port + path + "/swagger-ui.html\n\t" + + "Doc: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" + + "----------------------------------------------------------"); + } + +} diff --git a/src/main/java/com/gci/boot/annotation/Query/OrderQuery.java b/src/main/java/com/gci/boot/annotation/Query/OrderQuery.java new file mode 100644 index 0000000..0beb661 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/Query/OrderQuery.java @@ -0,0 +1,27 @@ +package com.gci.boot.annotation.Query; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 用于构建排序 + * @author 24642 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface OrderQuery { + /** + * 排序顺序 + */ + int sort() default 0; + /** + * 排序规则 + */ + boolean IsAsc() default false; + /** + * 属性名 + */ + String PropName() default ""; +} diff --git a/src/main/java/com/gci/boot/annotation/Query/SelectQuery.java b/src/main/java/com/gci/boot/annotation/Query/SelectQuery.java new file mode 100644 index 0000000..aa35549 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/Query/SelectQuery.java @@ -0,0 +1,81 @@ +package com.gci.boot.annotation.Query; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 用于构建查询 + * @author 24642 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SelectQuery { + + /** + * 属性名 + */ + String PropName() default ""; + + + /** + * 查询类型 + */ + SelectType Type() default SelectType.LIKE; + + enum SelectType { + /** + * 等于 + */ + EQ, + /** + * 不等于 + */ + NE, + /** + * 大于 + */ + GT, + /** + * 大于等于 + */ + GE, + /** + * 小于 + */ + LT, + /** + * 小于等于 + */ + LE, + /** + * 列表中 + */ + IN, + /** + * 列表外 + */ + NOT_IN, + /** + * 区间内 + */ + BETWEEN, + /** + * 区间外 + */ + NOT_BETWEEN, + /** + * 模糊查询 + */ + LIKE, + /** + * 左模糊查询 + */ + LIKE_LEFT, + /** + * 右模糊查询 + */ + LIKE_RIGHT + } +} diff --git a/src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java b/src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java new file mode 100644 index 0000000..1f1d8c4 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/Query/handle/QueryGenerator.java @@ -0,0 +1,186 @@ +package com.gci.boot.annotation.Query.handle; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * @author 24642 + */ +@Slf4j +public class QueryGenerator { + private static final String COMMA = ","; + /** + * 生成查询语句 + * @param entity 数据库实体类 + * @param query 查询参数实体类或者数据库实体类 + * @return 生成的查询语句 + */ + public static LambdaQueryWrapper initQueryWrapper(Class entity, Q query) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (query == null) { + return queryWrapper.lambda(); + } + common(entity, query, queryWrapper,false); + return queryWrapper.lambda(); + } + + public static LambdaQueryWrapper initQueryWrapper(Class entity, Q query,Boolean ignoreOrder) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (query == null) { + return queryWrapper.lambda(); + } + common(entity, query, queryWrapper, ignoreOrder); + return queryWrapper.lambda(); + } + + private static void common(Class entity, Q query, QueryWrapper queryWrapper, boolean ignoreOrder) { + Field[] fields = ReflectUtil.getFields(query.getClass()); + ArrayList orderList = new ArrayList<>(); + for (Field field : fields) { + boolean accessible = field.isAccessible(); + //设置后操作速度更快 + field.setAccessible(true); + if (!ignoreOrder) { + if (field.isAnnotationPresent(OrderQuery.class)) { + orderList.add(field); + } + } + Object fieldValue = ReflectUtil.getFieldValue(query, field); + if (ObjectUtil.isEmpty(fieldValue)) { + continue; + } +// String simpleName = field.getType().getSimpleName(); + SelectQuery selectQuery = field.getAnnotation(SelectQuery.class); + + + if (selectQuery == null) { + continue; + } + String fieldName = StrUtil.toUnderlineCase(!"".equals(selectQuery.PropName()) ? selectQuery.PropName() : field.getName()); + Class type = field.getType(); +// SFunction function = LambdaFunctionUtil.getFunctionField(entity, fieldName); + switch (selectQuery.Type()) { + case EQ: + queryWrapper.eq(fieldName,fieldValue); + break; + case NE: + queryWrapper.ne(fieldName,fieldValue); + break; + case GT: + queryWrapper.gt(fieldName,fieldValue); + break; + case GE: + queryWrapper.ge(fieldName,fieldValue); + break; + case LT: + queryWrapper.lt(fieldName,fieldValue); + break; + case LE: + queryWrapper.le(fieldName,fieldValue); + break; + case IN: + if (List.class.equals(type)) { + queryWrapper.in(fieldName, (List)fieldValue); + } else if (String.class.equals(type)) { + Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName)); + String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA); + List split = StrUtil.split(replace, COMMA); + if (!o.getType().equals(String.class)) { + queryWrapper.in(fieldName,Convert.toNumberArray(split)); + } + queryWrapper.in(fieldName,split); + } + break; + case NOT_IN: + if (List.class.equals(type)) { + queryWrapper.notIn(fieldName, (List)fieldValue); + } else if (String.class.equals(type)) { + Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName)); + String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA); + List split = StrUtil.split(replace, COMMA); + if (!o.getType().equals(String.class)) { + queryWrapper.notIn(fieldName,Convert.toNumberArray(split)); + } + queryWrapper.notIn(fieldName,split); + } + break; + case BETWEEN: + if (List.class.equals(type)) { + if (((List)fieldValue).size()<2) { + break; + } + queryWrapper.between(fieldName, ((List)fieldValue).get(0),((List)fieldValue).get(1)); + } else if (String.class.equals(type)) { + Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName)); + String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA); + List split = StrUtil.split(replace, COMMA); + if (split.size()<2) { + break; + } + if (!o.getType().equals(String.class)) { + Number[] numbers = Convert.toNumberArray(split); + queryWrapper.between(fieldName,numbers[0],numbers[1]); + } + queryWrapper.between(fieldName,split.get(0),split.get(1)); + } + break; + case NOT_BETWEEN: + if (List.class.equals(type)) { + if (((List)fieldValue).size()<2) { + break; + } + queryWrapper.notBetween(fieldName, ((List)fieldValue).get(0),((List)fieldValue).get(1)); + } else if (String.class.equals(type)) { + Field o = ReflectUtil.getField(entity, StrUtil.toCamelCase(fieldName)); + String replace = StrUtil.join(",",fieldValue).replace(",,", COMMA); + List split = StrUtil.split(replace, COMMA); + if (split.size()<2) { + break; + } + if (!o.getType().equals(String.class)) { + Number[] numbers = Convert.toNumberArray(split); + queryWrapper.notBetween(fieldName,numbers[0],numbers[1]); + } + queryWrapper.notBetween(fieldName,split.get(0),split.get(1)); + } + break; + case LIKE: + queryWrapper.like(fieldName,fieldValue); + break; + case LIKE_LEFT: + queryWrapper.likeLeft(fieldName,fieldValue); + break; + case LIKE_RIGHT: + queryWrapper.likeRight(fieldName,fieldValue); + break; + default: + break; + } + //恢复原样 + field.setAccessible(accessible); + } + if (!ignoreOrder) { + if (ObjectUtil.isNotEmpty(orderList)) { + orderList.sort(Comparator.comparingInt(f->f.getAnnotation(OrderQuery.class).sort())); + for (Field field : orderList) { + OrderQuery orderQuery = field.getAnnotation(OrderQuery.class); + String fieldName = StrUtil.toUnderlineCase(!"".equals(orderQuery.PropName()) ? orderQuery.PropName() : field.getName()); +// SFunction function = LambdaFunctionUtil.getFunctionField(entity, fieldName); + queryWrapper.orderBy(true,orderQuery.IsAsc(),fieldName); + } + } + } + } +} diff --git a/src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java b/src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java new file mode 100644 index 0000000..4e38d75 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/fileUrl/FileUrl.java @@ -0,0 +1,23 @@ +package com.gci.boot.annotation.fileUrl; + +import com.gci.boot.annotation.repeat.handle.TableRepeatHandle; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author 24642 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface FileUrl { + /** + * 文件前缀 没有的话就是默认取value + * @return + */ + String value() default ""; +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java b/src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java new file mode 100644 index 0000000..1a9eb9c --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/fileUrl/handle/FileUrlHandle.java @@ -0,0 +1,57 @@ +package com.gci.boot.annotation.fileUrl.handle; + + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import org.springframework.beans.factory.annotation.Value; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.List; + +/** + * @author 24642 + */ +public class FileUrlHandle extends JsonDeserializer { + @Value("${minio.fileUrl}") + private String fileUrl; + @Value("${minio.minioUrl}") + private String minioUrl; + + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + String inFileUrl; + HttpServletRequest request = SpringContextUtil.getHttpServletRequest(); + String header = request.getHeader(CommonConstant.IS_INNER); + if (Convert.toBool(header,false)) { + inFileUrl = minioUrl; + } else { + inFileUrl = fileUrl; + } + String text = jsonParser.getText(); + if (StrUtil.isBlank(text)) { + return text; + } + List split = StrUtil.split(text, StrUtil.COMMA); + for (int i = 0; i < split.size(); i++) { + String s = split.get(i); + if (StrUtil.isBlank(s)) { + throw new GciBootException("上传文件地址错误!"); + } else { + boolean contains = StrUtil.contains(s, inFileUrl); + if (!contains) { + throw new GciBootException("上传文件地址未包括域名和端口!"); + } + split.set(i,StrUtil.removeAll(s,inFileUrl)); + } + } + return StrUtil.join(StrUtil.COMMA,split); + } +} diff --git a/src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java b/src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java new file mode 100644 index 0000000..7698c30 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/importHandler/ExcelTypeHandler.java @@ -0,0 +1,95 @@ +package com.gci.boot.annotation.importHandler; + +import lombok.Data; + + +import java.util.List; +import java.util.Map; + +@Data +public class ExcelTypeHandler { + /** + * 校验类型 + * 1-数据库重复校验(excel校验也用这个) + * 2-单独字段校验是否在数据内(是否有权限之类的) + * 3-联合检验(当对应校验字段为指定值时其他字段不能为空) + */ + private String type; + + /** + * 对应校验字段 + */ + private List fields; + + /** + * 校验字段指定值 + */ + private Map specifiedValue; + + /** + * 其他字段 + */ + private List others; + /** + * 校验字段是否共同校验 + */ + private boolean needAll; + /** + * 数据集合 + */ + private List record; + /** + * 自定义校验信息 + */ + private String errorMsg; + + /** + * 数据库重复校验(excel校验也用这个) + * 这个校验感觉有问题 还是注解优先 + * @param fields + * @param needAll + * @param record + * @param errorMsg + * @return + */ + public ExcelTypeHandler(List fields, boolean needAll, List record, String errorMsg) { + this.type = "1"; + this.fields = fields; + this.needAll = needAll; + this.record = record; + this.errorMsg = errorMsg; + } + + /** + * 单独字段校验是否在数据内(是否有权限之类的) + * @param fields + * @param record + * @param errorMsg + */ + public ExcelTypeHandler(List fields, List record, String errorMsg) { + this.type = "2"; + this.fields = fields; + this.record = record; + this.errorMsg = errorMsg; + } + + /** + * 联合检验(当对应校验字段为指定值时其他字段不能为空) + * @param fields + * @param specifiedValue + * @param others + * @param needAll + * @param record + * @param errorMsg + */ + public ExcelTypeHandler(List fields, Map specifiedValue, List others, boolean needAll, List record, String errorMsg) { + this.type = "3"; + this.fields = fields; + this.specifiedValue = specifiedValue; + this.others = others; + this.needAll = needAll; + this.record = record; + this.errorMsg = errorMsg; + } + +} diff --git a/src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java b/src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java new file mode 100644 index 0000000..cb9417d --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/importHandler/MyExcelVerifyHandler.java @@ -0,0 +1,179 @@ +package com.gci.boot.annotation.importHandler; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Component; + +import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHandlerResult; +import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; + +@Component +public class MyExcelVerifyHandler implements IExcelVerifyHandler { + + private final ThreadLocal> threadLocal = new ThreadLocal<>(); + private List list; + private Map> map; + + public ThreadLocal> getThreadLocal() { + return threadLocal; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + if (!list.isEmpty()) { + this.map = list.stream().collect(Collectors.groupingBy(ExcelTypeHandler::getType)); + } + } + + @Override + public ExcelVerifyHandlerResult verifyHandler(T t) { + Class aClass = t.getClass(); + + return getExcelVerifyHandlerResult(t); + + } + + private ExcelVerifyHandlerResult getExcelVerifyHandlerResult(T t) { + + List objects = threadLocal.get(); + if (objects == null) { + objects = new ArrayList<>(); + } + ArrayList errorMsg = new ArrayList<>(); + + List first = map.get("1"); + if (first != null) { + for (ExcelTypeHandler excelTypeHandler : first) { + // 获取需要检验的字段 + List fields = excelTypeHandler.getFields(); + + // 获取数据 + List record = excelTypeHandler.getRecord(); + + // 是否需要共同校验 + boolean needAll = excelTypeHandler.isNeedAll(); + if (record != null) { + boolean recordAnyMatch = record.stream().anyMatch(i -> { + if (needAll) { + // 共同校验数据 + boolean allMatch = true; + for (String field : fields) { + boolean equal = ObjectUtil.equal(BeanUtil.getFieldValue(i, field), + BeanUtil.getFieldValue(t, field)); + if (!equal) { + allMatch = false; + } + } + return allMatch; + } else { + for (String field : fields) { + boolean equal = ObjectUtil.equal(BeanUtil.getFieldValue(i, field), + BeanUtil.getFieldValue(t, field)); + if (equal) { + return true; + } + } + return false; + } + }); + + if (recordAnyMatch) { + errorMsg.add(excelTypeHandler.getErrorMsg()); + } + } + + // excel内校验 + List inExcel = new ArrayList<>(); + objects.forEach(e -> { + if (needAll) { + // 共同校验数据 + boolean allMatch = true; + for (String field : fields) { + boolean equal = + ObjectUtil.equal(BeanUtil.getFieldValue(e, field), BeanUtil.getFieldValue(t, field)); + if (!equal) { + allMatch = false; + } + } + if (allMatch) { + inExcel.add("与原始excel" + BeanUtil.getFieldValue(e, "rowNum") + "行" + + excelTypeHandler.getErrorMsg()); + } + } else { + for (String field : fields) { + boolean equal = + ObjectUtil.equal(BeanUtil.getFieldValue(e, field), BeanUtil.getFieldValue(t, field)); + if (equal) { + inExcel.add("与原始excel" + BeanUtil.getFieldValue(e, "rowNum") + "行" + + excelTypeHandler.getErrorMsg()); + } + } + } + }); + if (!inExcel.isEmpty()) { + errorMsg.addAll(inExcel); + } + } + } + + objects.add(t); + threadLocal.set(objects); + + List second = map.get("2"); + if (second != null) { + for (ExcelTypeHandler excelTypeHandler : second) { + // 需要校验的字段 + List fields = excelTypeHandler.getFields(); + // 获取数据 + List record = excelTypeHandler.getRecord(); + for (String field : fields) { + Object fieldValue = BeanUtil.getFieldValue(t, field); + if (ObjectUtil.isNotEmpty(fieldValue)) { + boolean contains = record.contains(fieldValue); + // 不包含就报错 + if (!contains) { + errorMsg.add(excelTypeHandler.getErrorMsg()); + } + } + } + } + } + List third = map.get("3"); + if (third != null) { + for (ExcelTypeHandler excelTypeHandler : third) { + List fields = excelTypeHandler.getFields(); + Map specifiedValueMap = excelTypeHandler.getSpecifiedValue(); + for (String field : fields) { + boolean equals = ObjectUtil.equals(BeanUtil.getFieldValue(t, field), specifiedValueMap.get(field)); + if (equals) { + List others = excelTypeHandler.getOthers(); + for (String other : others) { + boolean empty = ObjectUtil.isEmpty(BeanUtil.getFieldValue(t, other)); + if (empty) { + errorMsg.add(excelTypeHandler.getErrorMsg()); + break; + } + } + } + } + } + } + + if (errorMsg.isEmpty()) { + return new ExcelVerifyHandlerResult(true); + } else { + errorMsg.add(0,"当前行为原始excel"+BeanUtil.getFieldValue(t, "rowNum") + "行"); + return new ExcelVerifyHandlerResult(false, StrUtil.join(";", errorMsg)); + } + } +} diff --git a/src/main/java/com/gci/boot/annotation/permission/DataPermission.java b/src/main/java/com/gci/boot/annotation/permission/DataPermission.java new file mode 100644 index 0000000..5ceae45 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/permission/DataPermission.java @@ -0,0 +1,36 @@ +package com.gci.boot.annotation.permission; + +import java.lang.annotation.*; + +/** + * 数据权限注解 + * @Author taoyan + * @Date 2019年4月11日 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE,ElementType.METHOD}) +@Documented +public @interface DataPermission { + /** + * 默认字段暂时不用 + * @return + */ + String value() default ""; + + + /** + * 存放作为过滤条件的字段名称:表名.projectId,createBy,repairShop或(createBy,repairShop) + */ + String item() default "projectId"; + + /** + * 指定sqlId + * @return + */ + String[] sqlIds() default {}; + + /** + * 以逗号隔开的字符串包容 + */ + boolean stringIn() default false; + } \ No newline at end of file diff --git a/src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java b/src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java new file mode 100644 index 0000000..7559b66 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/repeat/FieldRepeat.java @@ -0,0 +1,25 @@ +package com.gci.boot.annotation.repeat; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 需要结合@TableRepeat使用 + * @author 24642 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface FieldRepeat { + /** + * 属性名 + */ + String PropName() default ""; + + /** + * 不重复关联属性 --未完成 + */ + String other() default ""; + String message() default "你所输入的内容已存在"; +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java b/src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java new file mode 100644 index 0000000..ce41ab8 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/repeat/TableRepeat.java @@ -0,0 +1,23 @@ +package com.gci.boot.annotation.repeat; + +import com.gci.boot.annotation.repeat.handle.TableRepeatHandle; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author 24642 + */ +@Target({ElementType.TYPE}) +@Constraint(validatedBy = TableRepeatHandle.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface TableRepeat { + Class aClass() ; + String message() default ""; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java new file mode 100644 index 0000000..af3d155 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatHandle.java @@ -0,0 +1,27 @@ +package com.gci.boot.annotation.repeat.handle; + +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import org.apache.poi.ss.formula.functions.T; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +/** + * @author 24642 + */ +public class TableRepeatHandle implements ConstraintValidator { + private Class cClass; + /** + * + */ + @Override + public void initialize(TableRepeat constraintAnnotation) { + this.cClass = (Class) constraintAnnotation.aClass(); + } + + @Override + public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) { + return TableRepeatUtils.fieldRepeat(o,cClass,constraintValidatorContext); + } +} diff --git a/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java new file mode 100644 index 0000000..14d9cb8 --- /dev/null +++ b/src/main/java/com/gci/boot/annotation/repeat/handle/TableRepeatUtils.java @@ -0,0 +1,84 @@ +package com.gci.boot.annotation.repeat.handle; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.common.util.LambdaFunctionUtil; +import com.gci.boot.common.util.SpringContextUtil; +import org.apache.poi.ss.formula.functions.T; + +import javax.validation.ConstraintValidatorContext; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; + +/** + * @author 24642 + */ +public class TableRepeatUtils { + + public static boolean fieldRepeat(Object o, Class cClass, ConstraintValidatorContext context) { + HashMap stringObjectHashMap = new HashMap<>(); + SFunction sFunction = null; + Object idValue = null; + //去除默认的提示消息 + context.disableDefaultConstraintViolation(); + String message = ""; + Field[] fields = ReflectUtil.getFields(cClass); + if (ObjectUtil.isEmpty(fields)) { + return true; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + for (Field field : fields) { + queryWrapper.clear(); + boolean accessible = field.isAccessible(); + //设置后操作速度更快 + field.setAccessible(true); + Object fieldValue = ReflectUtil.getFieldValue(o, field); + if (ObjectUtil.isEmpty(fieldValue)) { + continue; + } + TableId annotation = field.getAnnotation(TableId.class); + if (null != annotation && ObjectUtil.isNotEmpty(fieldValue)) { + sFunction = LambdaFunctionUtil.getFunctionField(cClass,field.getName()); + idValue = fieldValue; + } + FieldRepeat fieldRepeat = field.getAnnotation(FieldRepeat.class); + if (null == fieldRepeat) { + continue; + } + String fieldName = !"".equals(fieldRepeat.PropName()) ? fieldRepeat.PropName() : field.getName(); + queryWrapper.eq(LambdaFunctionUtil.getFunctionField(cClass,fieldName),fieldValue); + if (ObjectUtil.isNotEmpty(sFunction)) { + queryWrapper.ne(sFunction,idValue); + } + String other = fieldRepeat.other(); + if (StrUtil.isNotBlank(other)) { + List split = StrUtil.split(other, ','); + for (String s : split) { + Object orDefault = stringObjectHashMap.getOrDefault(s, null); + if (orDefault == null) { + orDefault = ReflectUtil.getFieldValue(o,s); + } + if (ObjectUtil.isNotEmpty(orDefault)) { + stringObjectHashMap.put(s,orDefault); + queryWrapper.eq(LambdaFunctionUtil.getFunctionField(cClass,s),orDefault); + } + } + } + int count = ((IService) SpringContextUtil.getBean(StrUtil.lowerFirst(cClass.getSimpleName()) + "ServiceImpl")).count(queryWrapper); + if (count >0) { + message = fieldRepeat.message(); + context.buildConstraintViolationWithTemplate(message).addConstraintViolation(); + return false; + } + field.setAccessible(accessible); + } + return true; + } +} diff --git a/src/main/java/com/gci/boot/aspect/DataPermissionAspect.java b/src/main/java/com/gci/boot/aspect/DataPermissionAspect.java new file mode 100644 index 0000000..3113488 --- /dev/null +++ b/src/main/java/com/gci/boot/aspect/DataPermissionAspect.java @@ -0,0 +1,164 @@ +package com.gci.boot.aspect; + +import cn.hutool.core.util.StrUtil; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.constant.DataPermissionConstant; +import com.gci.boot.modules.basedata.entity.TbRepairShopArchives; +import com.gci.boot.modules.basedata.service.ITbRepairShopArchivesService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.vo.LoginUser; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; +import java.util.List; + +/** + * 数据权限切面处理类 + * 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息 + * @Date 2019年4月10日 + * @Version: 1.0 + */ +@Aspect +@Component +@Slf4j +public class DataPermissionAspect { + + @Autowired + private IProjectsService projectsService; + @Autowired + private ISysRoleService sysRoleService; + @Autowired + private ITbRepairShopArchivesService tbRepairShopArchivesService; + + @Pointcut("@annotation(com.gci.boot.annotation.permission.DataPermission)") + public void pointCut() { + + } + + @Around("pointCut()") + public Object arround(ProceedingJoinPoint point) throws Throwable{ + HttpServletRequest request = SpringContextUtil.getHttpServletRequest(); + String requestPath = request.getRequestURI().substring(request.getContextPath().length()); + String requestMethod = request.getMethod(); + requestPath = filterUrl(requestPath); + log.info("DataPermissionAspect拦截请求 >> "+requestPath+";请求类型 >> "+requestMethod); + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + DataPermission pd = method.getAnnotation(DataPermission.class); + String item = pd.item(); + //处理特定的数据权限:按照项目projectId列表过滤 + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser==null || StringUtils.isEmpty(sysUser.getId())){ + throw new RuntimeException("用户未登录"); + } + //获取角色:为判断超级管理员准备 + List listRole = sysRoleService.getRoleByUserId(sysUser.getId()); + if(CollectionUtils.isEmpty(listRole)){ + //角色配置为空 + throw new RuntimeException("角色配置为空"); + } + StringBuilder sbRole = new StringBuilder(); + listRole.forEach(lRole -> { + sbRole.append(","+lRole.getRoleCode()); + }); + String strRole = sbRole.toString(); + + String sqlConditon = null; + if(item.contains("projectId")){ + //判断用户身份:1_普通部门,2_维修厂,3_司机,4_客户公司其他人员,0、其他身份,并根据身份获取授权的项目列表 + List listProjectIds = projectsService.queryProjectListOfUser(); + //超级管理员角色需放通 + if(strRole.contains("PM0000")){ + return point.proceed(); + } + if(CollectionUtils.isEmpty(listProjectIds)){ + //项目清单为空,说明没有任何项目权限,禁止查看视频监控、司机管理等项目类列表 + sqlConditon = "1 != 1"; + }else{ + //组装项目id条件 + sqlConditon = buildProjectIds(item,listProjectIds,pd.stringIn()); + } + request.setAttribute(DataPermissionConstant.DATA_PERMISSION_CONDITION, sqlConditon); + request.setAttribute(DataPermissionConstant.DATA_PERMISSION_SQL_ID, pd.sqlIds()); + } + return point.proceed(); + } + + private String buildProjectIds(String item, List listProjectIds, boolean stringIn){ + + String tableName = item.substring(0,item.lastIndexOf(".")); + + StringBuilder sb = new StringBuilder(); + if (stringIn) { + sb.append("string_to_array(").append(tableName).append(".project_id,',') &&"); + sb.append("string_to_array('").append(StrUtil.join(StrUtil.COMMA, listProjectIds)).append("',',')"); + return sb.toString(); + } else { + sb.append(tableName+".project_id in ("); + listProjectIds.forEach(id -> { + sb.append("'"+id+"',"); + }); + String res = sb.substring(0, sb.length() - 1); + + return res+")"; + } + } + + private String buildCreateBy(String item,String username){ + String tableName = item.substring(0,item.lastIndexOf(".")); + StringBuilder sb = new StringBuilder(); + sb.append(tableName+".create_by='").append(username).append("'"); + return sb.toString(); + } + + private String buildRepairShop(String item,String userId){ + String res = null; + String tableName = item.substring(0,item.lastIndexOf(".")); + List list = tbRepairShopArchivesService.getRepairShopByUserId(userId); + if(CollectionUtils.isEmpty(list)){ + return "1 != 1"; + } + StringBuilder sb = new StringBuilder(); + sb.append(tableName+".repair_shop in ("); + list.forEach(shop -> { + sb.append("'"+shop.getId()+"',"); + }); + res = sb.substring(0, sb.length() - 1); + return res+")"; + } + + /** + * 过滤url + * @param requestPath + * @return + */ + private String filterUrl(String requestPath){ + String url = ""; + if(requestPath != null && !requestPath.equals("") && !requestPath.equals("null")){ + url = requestPath.replace("\\", "/"); + url = requestPath.replace("//", "/"); + if(url.indexOf("//")>=0){ + url = filterUrl(url); + } + /*if(url.startsWith("/")){ + url=url.substring(1); + }*/ + } + return url; + } + +} diff --git a/src/main/java/com/gci/boot/common/config/CancelConverter.java b/src/main/java/com/gci/boot/common/config/CancelConverter.java new file mode 100644 index 0000000..2b7e966 --- /dev/null +++ b/src/main/java/com/gci/boot/common/config/CancelConverter.java @@ -0,0 +1,56 @@ +package com.gci.boot.common.config; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.converters.ReadConverterContext; +import com.alibaba.excel.converters.WriteConverterContext; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.data.WriteCellData; + +/** + * 状态字符串处理 + * + */ +public class CancelConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + //对象属性类型 + return Integer.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + //CellData属性类型 + return CellDataTypeEnum.STRING; + } + + @Override + public Integer convertToJavaData(ReadConverterContext context) throws Exception { + //CellData转对象属性 + String cellStr = context.getReadCellData().getStringValue(); + if (StrUtil.isEmpty(cellStr)) return null; + if ("正常".equals(cellStr)) { + return 0; + } else if ("作废".equals(cellStr)) { + return 1; + } else { + return null; + } + } + + @Override + public WriteCellData convertToExcelData(WriteConverterContext context) throws Exception { + //对象属性转CellData + Integer cellValue = context.getValue(); + if (cellValue == null) { + return new WriteCellData<>(""); + } + if (cellValue == 0) { + return new WriteCellData<>("正常"); + } else if (cellValue == 1) { + return new WriteCellData<>("作废"); + } else { + return new WriteCellData<>(""); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/common/config/DictConfig.java b/src/main/java/com/gci/boot/common/config/DictConfig.java new file mode 100644 index 0000000..06096d9 --- /dev/null +++ b/src/main/java/com/gci/boot/common/config/DictConfig.java @@ -0,0 +1,14 @@ +package com.gci.boot.common.config; + +import com.gci.boot.common.dict.aspect.DictAspect; +import com.gci.boot.modules.system.service.ISysDictService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DictConfig { + @Bean + public DictAspect dictAspect(ISysDictService dictService){ + return new DictAspect(dictService); + } +} diff --git a/src/main/java/com/gci/boot/common/config/LogConfig.java b/src/main/java/com/gci/boot/common/config/LogConfig.java new file mode 100644 index 0000000..1b55c04 --- /dev/null +++ b/src/main/java/com/gci/boot/common/config/LogConfig.java @@ -0,0 +1,16 @@ +package com.gci.boot.common.config; + +import com.gci.boot.common.log.aspect.SysLogAspect; +import com.gci.boot.modules.system.service.ISysLogService; +import com.gci.boot.modules.system.service.ISysUserService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LogConfig { + + @Bean + public SysLogAspect sysLogAspect(ISysLogService sysLogService, ISysUserService sysUserService) { + return new SysLogAspect(sysLogService, sysUserService); + } +} diff --git a/src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java b/src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java new file mode 100644 index 0000000..53dccec --- /dev/null +++ b/src/main/java/com/gci/boot/common/config/UtilsInitializeConfig.java @@ -0,0 +1,35 @@ +package com.gci.boot.common.config; + +import com.gci.boot.common.util.CacheUtil; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.common.util.SpringEnvironmentUtil; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.data.redis.core.RedisTemplate; + +@Configuration +public class UtilsInitializeConfig { + @Bean + public SpringContextUtil.Initializer springContextUtilInitializer() { + return new SpringContextUtil.Initializer(); + } + + @Bean + public SpringEnvironmentUtil.Initializer springEnvironmentUtilInitializer() { + return new SpringEnvironmentUtil.Initializer(); + } + + @Bean + public RedisUtil redisUtilInitializer() { + return new RedisUtil(); + } + + @Bean + public CacheUtil cacheUtilInitializer() { + return new CacheUtil(); + } +} diff --git a/src/main/java/com/gci/boot/common/dict/annotation/Dict.java b/src/main/java/com/gci/boot/common/dict/annotation/Dict.java new file mode 100644 index 0000000..e3179f2 --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/annotation/Dict.java @@ -0,0 +1,25 @@ +package com.gci.boot.common.dict.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Dict { + /** + * 方法描述: 字典编码,如果指定了dictTable,则是字典项的值 + */ + String dicCode(); + + /** + * 方法描述: 字典文本 + */ + String dicText() default ""; + + /** + * 数据字典表 + */ + String dictTable() default ""; +} diff --git a/src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java b/src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java new file mode 100644 index 0000000..bdc67eb --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/annotation/ExcelEnum.java @@ -0,0 +1,12 @@ +package com.gci.boot.common.dict.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelEnum { + String value() default ""; +} diff --git a/src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java b/src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java new file mode 100644 index 0000000..0831837 --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/aspect/DictAspect.java @@ -0,0 +1,251 @@ +package com.gci.boot.common.dict.aspect; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.util.ClassReflectionUtil; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.service.ISysDictService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Value; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Field; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 字典解析切面 + */ +@Aspect +@Slf4j +@RequiredArgsConstructor +public class DictAspect { + private final ISysDictService dictService; + private static final ThreadLocal> dateFormatHolder = new ThreadLocal(); + @Value("${minio.fileUrl}") + private String fileUrl; + @Value("${minio.minioUrl}") + private String minioUrl; + + private static String delFlag = "delFlag"; + + // 定义切点Pointcut + @Pointcut("execution(public * com.gci.boot.modules..*.*Controller.*(..))") + public void excudeService() { + } + + @Around("excudeService()") + public Object doAround(ProceedingJoinPoint pjp) throws Throwable { + long time1 = System.currentTimeMillis(); + Object result = pjp.proceed(); + long time2 = System.currentTimeMillis(); + log.debug("获取JSON数据 耗时:" + (time2 - time1) + "ms"); + long start = System.currentTimeMillis(); + result = this.parseDictText(result); + long end = System.currentTimeMillis(); + log.debug("解析注入JSON数据 耗时" + (end - start) + "ms"); + return result; + } + + private Object parseDictText(Object result) { + if (result instanceof Result) { + Object rslt = ((Result) result).getResult(); + ((Result) result).setResult(parseDictText(rslt)); + return result; + } + + try { + if (result == null) { + return null; + } + + Object record; + if (result instanceof IPage) { + List items = new ArrayList(); + Iterator iterator = ((IPage) result).getRecords().iterator(); + + while (iterator.hasNext()) { + record = iterator.next(); + items.add(this.parseObject(record)); + } + + return ((IPage) result).setRecords(items); + } else if (result instanceof List) { + List items = new ArrayList(); + Iterator iterator = ((List) result).iterator(); + + while (iterator.hasNext()) { + record = iterator.next(); + items.add(this.parseObject(record)); + } + + return items; + } else if (result instanceof Map) { + Map items = new LinkedHashMap(); + ((Map) result).forEach((k, v) -> + items.put(k, this.parseObject(v)) + ); + return items; + } else { + return parseObject(result); + } + } catch (Exception e) { + log.error("字典标识转换失败", e); + } + dateFormatHolder.remove(); + return result; + } + + /** + * 翻译对象 + * + * @param rslt + * @return + */ + private Object parseObject(Object rslt) { + if(rslt == null){ + return null; + }else if (rslt instanceof List) { + return parseDictText(rslt); + } else if (rslt instanceof Map) { + return parseDictText(rslt); + //基本类型不处理 + }else if (rslt.getClass().isPrimitive() || rslt.getClass().getName().startsWith("java.")) { + return rslt; + } + + Map map = BeanUtil.beanToMap(rslt); + List fields = ClassReflectionUtil.getAllFields(rslt.getClass()); + boolean hasDelFlag = false; + for (Field field : fields) { + if(delFlag.equals(field.getName())) { + hasDelFlag = true; + break; + } + } + for (Field field : fields) { + boolean accessible = field.isAccessible(); + field.setAccessible(true); + if (field.isAnnotationPresent(Dict.class)) { + Dict dictAno = field.getAnnotation(Dict.class); + String code = dictAno.dicCode(); + String text = dictAno.dicText(); + String table = dictAno.dictTable(); + String key = String.valueOf(map.get(field.getName())); + + //翻译字典值对应的txt + String textValue = translateDictValue(code, text, table, key,hasDelFlag); + + log.debug(" 字典Val : " + textValue); + log.debug(" __翻译字典字段__ " + field.getName() + CommonConstant.DICT_TEXT_SUFFIX + ": " + textValue); + map.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue); + } else if (field.isAnnotationPresent(FileUrl.class)) { + String inFileUrl; + HttpServletRequest request = SpringContextUtil.getHttpServletRequest(); + String header = request.getHeader(CommonConstant.IS_INNER); + if (Convert.toBool(header,false)) { + inFileUrl = minioUrl; + } else { + inFileUrl = fileUrl; + } + //文件url补充前缀 + String value = Convert.toStr(map.get(field.getName())); + if (StrUtil.isNotBlank(value)) { + List split = StrUtil.split(value, StrUtil.COMMA); + for (int i = 0; i < split.size(); i++) { + String s = split.get(i); + split.set(i,URLUtil.completeUrl(inFileUrl,s)); + } + map.put(field.getName(),StrUtil.join(StrUtil.COMMA,split)); + } + } else if (field.getType().getName().equals("java.util.Date") && field.isAnnotationPresent(JsonFormat.class)) { + //date类型默认转换string格式化日期 + Object d = map.get(field.getName()); + if (d instanceof Date) { + JsonFormat jsonFormat = field.getAnnotation(JsonFormat.class); + DateFormat dateFormat; + if (StringUtils.isNotBlank(jsonFormat.pattern())) { + dateFormat = getDateFormat(jsonFormat.pattern()); + } else { + dateFormat = getDateFormat("yyyy-MM-dd HH:mm:ss"); + } + map.put(field.getName(), dateFormat.format((Date) d)); + } + }else { + Object o = map.get(field.getName()); + map.put(field.getName(), parseObject(o)); + } + field.setAccessible(accessible); + } + return map; + } + + /** + * 翻译字典文本 + * + * @param code + * @param text + * @param table + * @param key + * @return 字典文本 + */ + private String translateDictValue(String code, String text, String table, String key,boolean hasDelFlag) { + if (StringUtils.isBlank(key)) { + return null; + } + List keys = Arrays.asList(key.split(",")); + String textValue; + if (!StringUtils.isEmpty(table)) { + log.debug("--DictAspect------dicTable=" + table + " ,dicText= " + text + " ,dicCode=" + code); + textValue = keys.stream().map(String::trim).filter(k -> k.length() > 0) + .map(k -> dictService.queryTableDictTextByKey(table, text, code, k,hasDelFlag)) + .filter(StringUtils::isNotBlank) + .collect(Collectors.joining(",")); + } else { + textValue = keys.stream().map(String::trim).filter(k -> k.length() > 0) + .map(k -> dictService.queryDictTextByKey(code, k)) + .filter(StringUtils::isNotBlank) + .collect(Collectors.joining(",")); + } + return StringUtils.isNotBlank(textValue) ? textValue : null; + } + + + + /** + * SimpleDateFormat不是线程安全的,每个线程都要使用一个新的实例 + * + * @param pattern + * @return + */ + private DateFormat getDateFormat(String pattern) { + Map dateFormatMap = dateFormatHolder.get(); + if (dateFormatMap == null) { + dateFormatMap = new HashMap<>(); + dateFormatHolder.set(dateFormatMap); + } + DateFormat dateFormat = dateFormatMap.get(pattern); + if (dateFormat == null) { + dateFormat = new SimpleDateFormat(pattern); + dateFormatMap.put(pattern, dateFormat); + } + return dateFormat; + } +} diff --git a/src/main/java/com/gci/boot/common/dict/excel/DictConverter.java b/src/main/java/com/gci/boot/common/dict/excel/DictConverter.java new file mode 100644 index 0000000..6f1fe87 --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/excel/DictConverter.java @@ -0,0 +1,147 @@ +package com.gci.boot.common.dict.excel; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.constant.CacheConstant; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +public class DictConverter implements Converter { + + private static DictParser dictParser; + private static CacheManager cacheManager; + + public DictConverter() { + dictParser = SpringContextUtil.getBean(DictParser.class); + cacheManager = SpringContextUtil.getBean(CacheManager.class); + } + + @Override + public Class supportJavaTypeKey() { + return Converter.super.supportJavaTypeKey(); + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { + try { + if (StringUtils.isBlank(cellData.getStringValue())) { + return null; + } + Field field = contentProperty.getField(); + if (field.isAnnotationPresent(Dict.class)) { + Dict dictAnno = field.getAnnotation(Dict.class); + String val; + List keys = Arrays.asList(cellData.getStringValue().split(",")); + if (StringUtils.isNotBlank(dictAnno.dictTable())) { + val = keys.stream().map(String::trim).filter(k->k.length()>0) + .map(k -> dictParser.queryTableDictValueByText(dictAnno.dictTable(), dictAnno.dicText(), dictAnno.dicCode(), k)) + .collect(Collectors.joining(",")); + } else { + val = keys.stream().map(String::trim).filter(k->k.length()>0) + .map(k -> dictParser.queryDictValueByText(dictAnno.dicCode(), k)) + .collect(Collectors.joining(",")); + } + if (Integer.class.getName().equals(field.getType().getName())) { + return Integer.parseInt(val); + } + if("null".equals(val)) { + val = ""; + } + return val; + } + } catch (Exception e) { + log.error("", e); + } + return null; + } + + @Override + public WriteCellData convertToExcelData(Object value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { + try { + if (value == null || value.toString().trim().length() == 0) { + return new WriteCellData<>(""); + } + Field field = contentProperty.getField(); + if (field.isAnnotationPresent(Dict.class)) { + Dict dictAnno = field.getAnnotation(Dict.class); + List keys = Arrays.asList(value.toString().split(",")); + String val; + if (StringUtils.isNotBlank(dictAnno.dictTable())) { + val = keys.stream().map(String::trim).filter(k->k.length()>0) + .map(k -> getTableDictTextByKey(dictAnno, k)) + .collect(Collectors.joining(",")); + } else { + val = keys.stream().map(String::trim).filter(k->k.length()>0) + .map(k -> getDictTextByKey(dictAnno, k)) + .collect(Collectors.joining(",")); + } + if("null".equals(val)) { + val = ""; + } + return new WriteCellData<>(val); + } + } catch (Exception e) { + log.error("", e); + } + return new WriteCellData<>(value.toString()); + } + + private String getDictTextByKey(Dict dictAnno, String k) { + Cache cache = cacheManager.getCache(CacheConstant.SYS_DICT_CACHE); + String cacheKey = dictAnno.dicCode() + ":" + k; + if (ObjectUtil.isNotNull(cache)) { + Cache.ValueWrapper valueWrapper = cache.get(cacheKey); + if (ObjectUtil.isNotNull(valueWrapper)) { + return Convert.toStr(valueWrapper.get()); + } + } + String sqlValue = dictParser.queryDictTextByKey(dictAnno.dicCode(), k); + if (ObjectUtil.isNotNull(cache)) { + if (StrUtil.isNotBlank(sqlValue)) { + cache.put(cacheKey,sqlValue); + } + } + return sqlValue; + } + + private String getTableDictTextByKey(Dict dictAnno, String k) { + Cache cache = cacheManager.getCache(CacheConstant.SYS_DICT_TABLE_CACHE); + String cacheKey = dictAnno.dictTable() + ":" + dictAnno.dicCode() + ":" + k + ":" + false; + if (ObjectUtil.isNotNull(cache)) { + Cache.ValueWrapper valueWrapper = cache.get(cacheKey); + if (ObjectUtil.isNotNull(valueWrapper)) { + return Convert.toStr(valueWrapper.get()); + } + } + String sqlValue = dictParser.queryTableDictTextByKey(dictAnno.dictTable(), dictAnno.dicText(), dictAnno.dicCode(), k); + if (ObjectUtil.isNotNull(cache)) { + if (StrUtil.isNotBlank(sqlValue)) { + cache.put(cacheKey,sqlValue); + } + } + return sqlValue; + } + +} diff --git a/src/main/java/com/gci/boot/common/dict/excel/DictParser.java b/src/main/java/com/gci/boot/common/dict/excel/DictParser.java new file mode 100644 index 0000000..cebf18b --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/excel/DictParser.java @@ -0,0 +1,11 @@ +package com.gci.boot.common.dict.excel; + +public interface DictParser { + String queryTableDictTextByKey(String table, String text, String code, String key); + + String queryDictTextByKey(String code, String key); + + String queryDictValueByText(String code, String key); + + String queryTableDictValueByText(String table, String text, String code, String key); +} diff --git a/src/main/java/com/gci/boot/common/dict/excel/EnumConverter.java b/src/main/java/com/gci/boot/common/dict/excel/EnumConverter.java new file mode 100644 index 0000000..340514b --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/excel/EnumConverter.java @@ -0,0 +1,85 @@ +package com.gci.boot.common.dict.excel; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; +import com.gci.boot.common.dict.annotation.ExcelEnum; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class EnumConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return Converter.super.supportJavaTypeKey(); + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public Object convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { + try { + Field field = contentProperty.getField(); + if(field.isAnnotationPresent(ExcelEnum.class)){ + ExcelEnum enumAnno = field.getAnnotation(ExcelEnum.class); + Map enumMap = getEnumMap(enumAnno.value(), false); + Class type = field.getType(); + String value = enumMap.get(cellData.getStringValue()); + if(Integer.class.getName().equals(type.getName())) { + return Integer.parseInt(value); + }else{ + return value; + } + } + } catch (Exception e) { + log.error("", e); + } + return null; + } + + @Override + public WriteCellData convertToExcelData(Object value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { + try { + Field field = contentProperty.getField(); + if(field.isAnnotationPresent(ExcelEnum.class)){ + ExcelEnum enumAnno = field.getAnnotation(ExcelEnum.class); + Map enumMap = getEnumMap(enumAnno.value(), true); + return new WriteCellData<>(enumMap.get(value.toString())); + } + } catch (Exception e) { + log.error("枚举转换出错", e); + } + return new WriteCellData<>(value.toString()); + } + + + private Map getEnumMap(String enumStr, boolean valueKey){ + Map result = new HashMap<>(); + if(StringUtils.isBlank(enumStr)){ + return result; + } + String[] es = enumStr.split(","); + for(String e : es){ + String[] k = e.trim().split("_"); + if(k.length < 2){ + continue; + } + if(valueKey) { + result.put(k[0], k[1]); + }else{ + result.put(k[1], k[0]); + } + } + return result; + } +} diff --git a/src/main/java/com/gci/boot/common/dict/excel/MyExcelDictHandleImpl.java b/src/main/java/com/gci/boot/common/dict/excel/MyExcelDictHandleImpl.java new file mode 100644 index 0000000..03c06b2 --- /dev/null +++ b/src/main/java/com/gci/boot/common/dict/excel/MyExcelDictHandleImpl.java @@ -0,0 +1,114 @@ +package com.gci.boot.common.dict.excel; + +import cn.afterturn.easypoi.handler.inter.IExcelDictHandler; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.system.service.impl.SysDictServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author 24642 + */ +@Slf4j +@Component +public class MyExcelDictHandleImpl implements IExcelDictHandler { + @Autowired + private SysDictServiceImpl sysDictService; + private static SysDictServiceImpl sysDictDetailMapper; + @Autowired + private CacheManager cacheManager; + private static CacheManager cacheManagerMapper; + + @PostConstruct + public void init() { + sysDictDetailMapper = this.sysDictService; + cacheManagerMapper = cacheManager; + } + /** + * 导出 + * @param dict 字典key + * @param o 对象 + * @param propName 属性名 + * @param value 属性值 + * @return 翻译后字典值 + */ + @Override + public String toName(String dict, Object o, String propName, Object value) { + if (ObjectUtil.isEmpty(value)) { + return StrUtil.EMPTY; + } + List keys = Arrays.asList(Convert.toStr(value).split(",")); + //支持一下表字典 + if (dict.contains(StrUtil.COMMA)) { + List split = StrUtil.split(dict, StrUtil.COMMA); + if (split.size() != 3) { + throw new GciBootException("字典值错误!"); + } else { + // table text code + String collect = keys.stream().map(String::trim).filter(k -> k.length() > 0) + .map(k -> getTableDictTextByKey(split, k)) + .collect(Collectors.joining(",")); + return StrUtil.isNotBlank(collect) && !StrUtil.NULL.equals(collect) ? collect : StrUtil.EMPTY; + } + } else { + String collect = keys.stream().map(String::trim).filter(k -> k.length() > 0) + .map(k -> getDictTextByKey(dict, k)) + .collect(Collectors.joining(",")); + return StrUtil.isNotBlank(collect) && !StrUtil.NULL.equals(collect) ? collect : StrUtil.EMPTY; + } + } + + private String getTableDictTextByKey(List split, String k) { + Cache cache = cacheManagerMapper.getCache(CacheConstant.SYS_DICT_TABLE_CACHE); + String cacheKey = split.get(0) + ":" + split.get(2) + ":" + k + ":" + false; + if (ObjectUtil.isNotNull(cache)) { + Cache.ValueWrapper valueWrapper = cache.get(cacheKey); + if (ObjectUtil.isNotNull(valueWrapper)) { + return Convert.toStr(valueWrapper.get()); + } + } + String sqlValue = sysDictDetailMapper.queryTableDictTextByKey(split.get(0), split.get(1), split.get(2), k); + if (ObjectUtil.isNotNull(cache)) { + if (StrUtil.isNotBlank(sqlValue)) { + cache.put(cacheKey,sqlValue); + } + } + return sqlValue; + } + + private String getDictTextByKey(String dict, String k) { + Cache cache = cacheManagerMapper.getCache(CacheConstant.SYS_DICT_CACHE); + String cacheKey = dict + ":" + k; + if (ObjectUtil.isNotNull(cache)) { + Cache.ValueWrapper valueWrapper = cache.get(cacheKey); + if (ObjectUtil.isNotNull(valueWrapper)) { + return Convert.toStr(valueWrapper.get()); + } + } + String sqlValue = sysDictDetailMapper.queryDictTextByKey(dict, k); + if (ObjectUtil.isNotNull(cache)) { + if (StrUtil.isNotBlank(sqlValue)) { + cache.put(cacheKey,sqlValue); + } + } + return sqlValue; + } + + @Override + public String toValue(String dict, Object o, String s1, Object o1) { + return null; + } +} diff --git a/src/main/java/com/gci/boot/common/log/annotation/AddSysLog.java b/src/main/java/com/gci/boot/common/log/annotation/AddSysLog.java new file mode 100644 index 0000000..ab44011 --- /dev/null +++ b/src/main/java/com/gci/boot/common/log/annotation/AddSysLog.java @@ -0,0 +1,40 @@ +package com.gci.boot.common.log.annotation; + +import com.gci.boot.constant.CommonConstant; + +import java.lang.annotation.*; + +/** + * 系统日志注解 + * + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AddSysLog { + + /** + * 日志内容 + * + * @return + */ + String value() default ""; + + /** + * 日志类型 + * + * @return 1:登录日志;2:操作日志; + */ + int logType() default CommonConstant.LOG_TYPE_OP; + + /** + * 操作日志类型 + * + * @return (1查询,2添加,3修改,4删除,5导入,6导出) + */ + int operateType() default 0; + /** + * 日志来源 + */ + String logSource() default "PC"; +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/common/log/aspect/SysLogAspect.java b/src/main/java/com/gci/boot/common/log/aspect/SysLogAspect.java new file mode 100644 index 0000000..2aad992 --- /dev/null +++ b/src/main/java/com/gci/boot/common/log/aspect/SysLogAspect.java @@ -0,0 +1,212 @@ +package com.gci.boot.common.log.aspect; + +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.entity.SysLog; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.service.ISysLogService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.LoginUser; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.web.servlet.ShiroHttpServletRequest; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.LocalVariableTableParameterNameDiscoverer; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Aspect +@Slf4j +@RequiredArgsConstructor +public class SysLogAspect { + private final ISysLogService sysLogService; + private final ISysUserService sysUserService; + + @Pointcut("@annotation(com.gci.boot.common.log.annotation.AddSysLog)") + public void logPointCut() { + + } + + @Around("logPointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + long beginTime = System.currentTimeMillis(); + //执行方法 + Object result = point.proceed(); + //执行时长(毫秒) + long time = System.currentTimeMillis() - beginTime; + if(sysUser == null) { + sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + } + //保存日志 + try { + saveSysLog(point, time, sysUser); + } catch (Exception e) { + log.error("写入系统日志失败", e); + } + + return result; + } + + private void saveSysLog(ProceedingJoinPoint joinPoint, long time, LoginUser sysUser) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + + SysLog sysLog = new SysLog(); + AddSysLog sysLogAnno = method.getAnnotation(AddSysLog.class); + if(sysLogAnno != null){ + //注解上的描述,操作日志内容 + sysLog.setLogContent(sysLogAnno.value()); + sysLog.setLogType(sysLogAnno.logType()); + sysLog.setLogSource(sysLogAnno.logSource()); + } + + //请求的方法名 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = signature.getName(); + sysLog.setMethod(className + "." + methodName + "()"); + + + //设置操作类型 + if (sysLog.getLogType() == CommonConstant.LOG_TYPE_OP) { + sysLog.setOperateType(getOperateType(methodName, sysLogAnno.operateType())); + } + + //获取request + HttpServletRequest request = SpringContextUtil.getHttpServletRequest(); + //请求的参数 + sysLog.setRequestParam(getReqestParams(request,joinPoint)); + + //设置IP地址 + sysLog.setIp(getIpAddr(request)); + + sysLog.setRequestUrl(request.getRequestURI()); + + sysLog.setRequestType(request.getMethod()); + + //获取登录用户信息 + if(sysUser!=null){ + sysLog.setUserid(sysUser.getUsername()); + sysLog.setUsername(sysUser.getRealname()); + }else{ + if(StringUtils.isNotBlank(sysLog.getRequestParam())) { + List maps = JsonUtil.json2List(sysLog.getRequestParam(), Map.class); + if (maps != null && maps.size() > 0) { + Object username = maps.get(0).get("username"); + if (username != null) { + sysLog.setUserid(username.toString()); + SysUser user = sysUserService.getByUsername(sysLog.getUserid()); + if(user != null){ + sysLog.setUsername(user.getRealname()); + } + } + } + } + } + //耗时 + sysLog.setCostTime(time); + sysLog.setCreateTime(new Date()); + //保存系统日志 + sysLogService.save(sysLog); + } + /** + * 获取操作类型 + */ + private int getOperateType(String methodName,int operateType) { + if (operateType > 0) { + return operateType; + } + if (methodName.startsWith("list") || methodName.startsWith("page")) { + return CommonConstant.OPERATE_TYPE_QUERY; + } + if (methodName.startsWith("add") || methodName.startsWith("insert") || methodName.startsWith("save")) { + return CommonConstant.OPERATE_TYPE_INSERT; + } + if (methodName.startsWith("edit") || methodName.startsWith("update")) { + return CommonConstant.OPERATE_TYPE_UPDATE; + } + if (methodName.startsWith("delete") || methodName.startsWith("remove") ) { + return CommonConstant.OPERATE_TYPE_DELETE; + } + if (methodName.startsWith("import")) { + return CommonConstant.OPERATE_TYPE_IMPORT; + } + if (methodName.startsWith("export")) { + return CommonConstant.OPERATE_TYPE_EXPORT; + } + return CommonConstant.OPERATE_TYPE_QUERY; + } + + /** + * @Description: 获取请求参数 + * @author: scott + * @date: 2020/4/16 0:10 + * @param request: request + * @param joinPoint: joinPoint + * @Return: java.lang.String + */ + private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) { + String httpMethod = request.getMethod(); + String params = ""; + if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod)) { + // HttpServletRequest类型转Json异常 + Object[] paramsArray = Arrays.stream(joinPoint.getArgs()) + .filter(p -> !p.getClass().equals(ShiroHttpServletRequest.class)).toArray(); + + params = JsonUtil.object2Json(paramsArray); + } else { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + // 请求的方法参数值 + Object[] args = joinPoint.getArgs(); + // 请求的方法参数名称 + LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); + String[] paramNames = u.getParameterNames(method); + if (args != null && paramNames != null) { + for (int i = 0; i < args.length; i++) { + params += " " + paramNames[i] + ": " + args[i]; + } + } + } + return params; + } + + public static String getIpAddr(HttpServletRequest request) { + String ip = null; + try { + ip = request.getHeader("x-forwarded-for"); + if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } catch (Exception e) { + log.error("IP ERROR ", e); + } + return ip; + } +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/common/query/SuperQueryGenerator.java b/src/main/java/com/gci/boot/common/query/SuperQueryGenerator.java new file mode 100644 index 0000000..ecc849c --- /dev/null +++ b/src/main/java/com/gci/boot/common/query/SuperQueryGenerator.java @@ -0,0 +1,4 @@ +package com.gci.boot.common.query; + +public class SuperQueryGenerator { +} diff --git a/src/main/java/com/gci/boot/common/string/StringValidAspect.java b/src/main/java/com/gci/boot/common/string/StringValidAspect.java new file mode 100644 index 0000000..0b5b584 --- /dev/null +++ b/src/main/java/com/gci/boot/common/string/StringValidAspect.java @@ -0,0 +1,170 @@ +package com.gci.boot.common.string; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.api.R; +import com.gci.boot.common.util.JsonUtil; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 特殊字符切面 + */ +@Aspect +@Slf4j +@Component("stringValidAspect") +public class StringValidAspect { + + @Value("${string.specialChar}") + private String specialChar; + + @Pointcut("execution(public * com.gci.boot.modules..*.*Controller.*edit*(..)) " + + " && !execution(public * com.gci.boot.modules.driver.controller.TbDriverController.edit(..)) " + + " && !execution(public * com.gci.boot.modules.system.controller.SysUserController.edit(..)) " + + " && !execution(public * com.gci.boot.modules.projects.controller.TbContractController.edit(..)) " + + " && !execution(public * com.gci.boot.modules.system.controller.SysPermissionController.edit(..))" + + " && !execution(public * com.gci.boot.modules.gis.controller.TbGisFencePlanController.edit(..))") + public void excudeServiceEdit() { + } + + @Before("excudeServiceEdit()") + public Object doBeforeEdit(JoinPoint joinPoint) throws Throwable { + Object[] args = joinPoint.getArgs(); + if(Objects.nonNull(args) && args.length>0){ + checkArgs(args); + } + return null; + } + + @Pointcut("execution(public * com.gci.boot.modules..*.*Controller.*add*(..)) " + + " && !execution(public * com.gci.boot.modules.driver.controller.TbDriverController.add(..)) " + + " && !execution(public * com.gci.boot.modules.system.controller.SysUserController.add(..)) "+ + " && !execution(public * com.gci.boot.modules.projects.controller.TbContractController.add(..)) " + + " && !execution(public * com.gci.boot.modules.system.controller.SysPermissionController.add(..)) " + + " && !execution(public * com.gci.boot.modules.gis.controller.TbGisFencePlanController.add(..))") + public void excudeServiceAdd() { + } + + @Before("excudeServiceAdd()") + public Object doBeforeAdd(JoinPoint joinPoint) throws Throwable { + Object[] args = joinPoint.getArgs(); + if(Objects.nonNull(args) && args.length>0){ + checkArgs(args); + } + return null; + } + + + public void checkArgs(Object[] args) throws Exception { + for (Object arg : args) { + // 集合校验 + if (arg instanceof Collection) { + checkCollection((Collection) arg); + } + // 实体对象校验 + if (arg instanceof Object) { + Class clazz = arg.getClass(); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { + checkObject(arg, field); + } + } + // 字符串类型校验 + if (arg instanceof String) { + checkString((String) arg); + } + } + } + + public void checkString(String arg) { + //todo 校验字符串 + if(Objects.nonNull(arg) && arg.length() > 0){ + boolean isAllSpaces = true; + for (int i = 0; i < arg.length(); i++) { + if (!Character.isWhitespace(arg.charAt(i))) { + isAllSpaces = false; + break; + } + } + if(isAllSpaces){ + throw new RuntimeException("输入的字符串存在全为空格,请修改!"); + } + } + if(StrUtil.isNotBlank(arg)){ + log.info("String type:" + arg); + Pattern p = Pattern.compile(specialChar); + Matcher m = p.matcher(arg); + if (m.find()) { + StringBuilder specialCharacters = new StringBuilder(); + do { + specialCharacters.append(m.group()); + } while (m.find()); + throw new RuntimeException("输入的字符串: "+ arg +" 包含特殊字符:" + specialCharacters.toString()+ " ,请修改!"); + } + } + } + + public void checkObject(Object object, Field field) throws Exception { + log.info(field.getGenericType().toString()); + + if (field.getGenericType().toString().equals("class java.lang.String")) { + Method m = object.getClass().getMethod("get" + getMethodName(field.getName())); + String val = (String) m.invoke(object); + if (val != null) { + checkString(val); + } + } else if (field.getGenericType().toString().startsWith("class com.gci.boot.modules")) { + // 对嵌套对象进行校验 + Method m = object.getClass().getMethod("get" + getMethodName(field.getName())); + Object val = m.invoke(object); + if (val != null) { + Field[] nestedFields = val.getClass().getDeclaredFields(); + for (Field nestedField : nestedFields) { + checkObject(val, nestedField); + } + } + } else if (field.getGenericType().toString().startsWith("java.util.List")) { + // 对嵌套集合进行校验 + Method m = object.getClass().getMethod("get" + getMethodName(field.getName())); + Object fieldValue = m.invoke(object); + checkCollection((Collection) fieldValue); + } + + } + + public void checkCollection(Collection arg) throws Exception { + Collection collectionParam = (Collection) arg; + if (CollectionUtils.isNotEmpty(collectionParam)) { + List listParam = Arrays.asList(collectionParam.toArray()); + Class clazz = listParam.get(0).getClass(); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Object listValue : listParam) { + for (Field field : declaredFields) { + checkObject(listValue, field); + } + } + } + return; + } + + // 把一个字符串的第一个字母大写、效率是最高的 get方法是驼峰命名的 因此要这样做 + private static String getMethodName(String fildeName) throws Exception { + byte[] items = fildeName.getBytes(); + items[0] = (byte) ((char) items[0] - 'a' + 'A'); + return new String(items); + } + +} diff --git a/src/main/java/com/gci/boot/common/util/BeanUtilsCopy.java b/src/main/java/com/gci/boot/common/util/BeanUtilsCopy.java new file mode 100644 index 0000000..52c7da6 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/BeanUtilsCopy.java @@ -0,0 +1,181 @@ +package com.gci.boot.common.util; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +/** + * Bean 工具类 + * @author + * + */ +public class BeanUtilsCopy { + + /** Bean方法名中属性名开始的下标 */ + private static final int BEAN_METHOD_PROP_INDEX = 3; + + /** * 匹配getter方法的正则表达式 */ + private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); + + /** * 匹配setter方法的正则表达式 */ + private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); + + /** + * Bean属性复制工具方法。 + * + * @param dest 目标对象 + * @param src 源对象 + */ + public static void copyBeanProp(Object dest, Object src) + { + List destSetters = getSetterMethods(dest); + List srcGetters = getGetterMethods(src); + try + { + for (Method setter : destSetters) + { + for (Method getter : srcGetters) + { + if (isMethodPropEquals(setter.getName(), getter.getName()) + && setter.getParameterTypes()[0].equals(getter.getReturnType())) + { + setter.invoke(dest, getter.invoke(src)); + } + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * 获取对象的setter方法。 + * + * @param obj 对象 + * @return 对象的setter方法列表 + */ + public static List getSetterMethods(Object obj) + { + // setter方法列表 + List setterMethods = new ArrayList(); + + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + + // 查找setter方法 + + for (Method method : methods) + { + Matcher m = SET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 1)) + { + setterMethods.add(method); + } + } + // 返回setter方法列表 + return setterMethods; + } + + /** + * 获取对象的getter方法。 + * + * @param obj 对象 + * @return 对象的getter方法列表 + */ + + public static List getGetterMethods(Object obj) + { + // getter方法列表 + List getterMethods = new ArrayList(); + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + // 查找getter方法 + for (Method method : methods) + { + Matcher m = GET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 0)) + { + getterMethods.add(method); + } + } + // 返回getter方法列表 + return getterMethods; + } + + /** + * 检查Bean方法名中的属性名是否相等。
+ * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 + * + * @param m1 方法名1 + * @param m2 方法名2 + * @return 属性名一样返回true,否则返回false + */ + + public static boolean isMethodPropEquals(String m1, String m2) + { + return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); + } + + + /** + * Bean属性复制工具方法。跳过某些字段 + * + * @param dest 目标对象 + * @param src 源对象 + */ + public static void copyBeanProp(Object dest, Object src,List filter) + { + for(int i= 0;i destSetters = getSetterMethods(dest); + List srcGetters = getGetterMethods(src); + try + { + for (Method setter : destSetters) + { + //跳过某些字段 + if(filter.contains(setter.getName().toLowerCase())) { + continue; + } + for (Method getter : srcGetters) + { + if (isMethodPropEquals(setter.getName(), getter.getName()) + && setter.getParameterTypes()[0].equals(getter.getReturnType())) + { + setter.invoke(dest, getter.invoke(src)); + } + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Bean属性复制工具方法。跳过id,创建时间等字段 + * + * @param dest 目标对象 + * @param src 源对象 + */ + public static void copyBeanPropFilterId(Object dest, Object src) + { + List filter = new ArrayList<>(); + filter.add("id"); + filter.add("createBy"); + filter.add("createTime"); + filter.add("updateBy"); + filter.add("updateTime"); + filter.add("sysOrgCode"); + filter.add("tenantId"); + copyBeanProp(dest,src,filter); + } + +} + diff --git a/src/main/java/com/gci/boot/common/util/CacheUtil.java b/src/main/java/com/gci/boot/common/util/CacheUtil.java new file mode 100644 index 0000000..87763f5 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/CacheUtil.java @@ -0,0 +1,43 @@ +package com.gci.boot.common.util; + +import org.springframework.beans.BeansException; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +public final class CacheUtil implements ApplicationContextAware{ + + private static CacheManager cacheManager; + + public static T get(String cacheName, String key, Class cls) { + Cache cache = cacheManager.getCache(cacheName); + Cache.ValueWrapper valueWrapper = cache.get(key); + if(valueWrapper == null || valueWrapper.get() == null){ + return null; + } + return cls.cast(valueWrapper.get()); + } + + public static Object get(String cacheName, String key) { + Cache cache = cacheManager.getCache(cacheName); + Cache.ValueWrapper valueWrapper = cache.get(key); + return valueWrapper.get(); + } + + public static void put(String cacheName, String key, Object value) { + Cache cache = cacheManager.getCache(cacheName); + cache.put(key, value); + } + + public static void evit(String cacheName, String key) { + Cache cache = cacheManager.getCache(cacheName); + cache.evict(key); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + CacheUtil.cacheManager = applicationContext.getBean(CacheManager.class); + } + +} diff --git a/src/main/java/com/gci/boot/common/util/CalcTool.java b/src/main/java/com/gci/boot/common/util/CalcTool.java new file mode 100644 index 0000000..5b727d7 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/CalcTool.java @@ -0,0 +1,18 @@ +package com.gci.boot.common.util; + +/** + * @author lyz + * @date 2023/10/31 17:55 + */ +public class CalcTool { + + public static double getDistance(double p_FirstLongitude,double p_FirstLatitude, + double p_SecondLongitude,double p_SecondLatitude) { + double distance = 6366707.01949329* Math.acos( + Math.sin(p_FirstLatitude*0.0174532925199444)*Math.sin(p_SecondLatitude*0.0174532925199444)+ + Math.cos(p_FirstLatitude*0.0174532925199444)*Math.cos(p_SecondLatitude*0.0174532925199444)* + Math.cos((p_FirstLongitude-p_SecondLongitude)*0.0174532925199444) + ); + return (distance+(distance*0.2))/1000.0; + } +} diff --git a/src/main/java/com/gci/boot/common/util/ClassReflectionUtil.java b/src/main/java/com/gci/boot/common/util/ClassReflectionUtil.java new file mode 100644 index 0000000..ced1611 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/ClassReflectionUtil.java @@ -0,0 +1,27 @@ +package com.gci.boot.common.util; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class ClassReflectionUtil { + public static List getAllFields(Class clazz) { + List fieldList = new ArrayList<>(); + while (clazz != null && !"java.lang.Object".equals(clazz.getName())) { + fieldList.addAll(Arrays.asList(clazz.getDeclaredFields())); + clazz = clazz.getSuperclass(); + } + return fieldList; + } + + public static List getAllMethods(Class clazz) { + List methodList = new ArrayList<>(); + while (clazz != null && !"java.lang.Object".equals(clazz.getName())) { + methodList.addAll(Arrays.asList(clazz.getDeclaredMethods())); + clazz = clazz.getSuperclass(); + } + return methodList; + } +} diff --git a/src/main/java/com/gci/boot/common/util/CoordinateConverterUtil.java b/src/main/java/com/gci/boot/common/util/CoordinateConverterUtil.java new file mode 100644 index 0000000..54cd0d1 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/CoordinateConverterUtil.java @@ -0,0 +1,139 @@ +package com.gci.boot.common.util; + +import java.math.BigDecimal; + +/** + * @Author: lyz + * @Description: 经纬度转换 + * @Date: 2021-04-20 14:10 + * @version: v1.0 + * @Modified by: + **/ +public class CoordinateConverterUtil +{ + /** + *赤道半径 + */ + private final static double EARTH_RADIUS = 6378137.0; + + /** + * PI + */ + private final static double PI = Math.PI; + + /** + * e2 + */ + private final static double EE = 0.00669342162296594323; + + + /** + * GCJ-02 to WGS-84 即高德坐标转换成gps坐标 + * @param latitude + * @param longitude + * @return + */ + public static LatLonPoint toGPSPoint(double latitude, double longitude) { + LatLonPoint dev = calDev(latitude, longitude); + double retLat = latitude - dev.getLatitude(); + double retLon = longitude - dev.getLongitude(); + for (int i = 0; i < 1; i++) { + dev = calDev(retLat, retLon); + retLat = latitude - dev.getLatitude(); + retLon = longitude - dev.getLongitude(); + } + retLat = new BigDecimal(retLat).setScale(6,BigDecimal.ROUND_HALF_UP).doubleValue(); + retLon = new BigDecimal(retLon).setScale(6,BigDecimal.ROUND_HALF_UP).doubleValue(); + return new LatLonPoint(retLat, retLon); + } + /** + * WGS-84 to GCJ-02 即gps坐标转成高德坐标 + * @param latitude + * @param longitude + * @return + */ + public static LatLonPoint toWGSPoint(double latitude, double longitude){ + LatLonPoint dev = calDev(latitude, longitude); + double retLat = latitude + dev.getLatitude(); + double retLon = longitude + dev.getLongitude(); + retLat = new BigDecimal(retLat).setScale(6,BigDecimal.ROUND_HALF_UP).doubleValue(); + retLon = new BigDecimal(retLon).setScale(6,BigDecimal.ROUND_HALF_UP).doubleValue(); + return new LatLonPoint(retLat, retLon); + } + + /** + * 计算偏差 + * @param wgLat + * @param wgLon + * @return + */ + private static LatLonPoint calDev(double wgLat, double wgLon) { + if (isOutOfChina(wgLat, wgLon)) { + return new LatLonPoint(0, 0); + } + double dLat = calLat(wgLon - 105.0, wgLat - 35.0); + double dLon = calLon(wgLon - 105.0, wgLat - 35.0); + double radLat = wgLat / 180.0 * PI; + double magic = Math.sin(radLat); + magic = 1 - EE * magic * magic; + double sqrtMagic = Math.sqrt(magic); + dLat = (dLat * 180.0) / ((EARTH_RADIUS * (1 - EE)) / (magic * sqrtMagic) * PI); + dLon = (dLon * 180.0) / (EARTH_RADIUS / sqrtMagic * Math.cos(radLat) * PI); + return new LatLonPoint(dLat, dLon); + } + + /** + * 判断坐标是否在国外 纬度 3.86~53.55, 经度 73.66~135.05 + * @param lat + * @param lon + * @return + */ + private static boolean isOutOfChina(double lat, double lon) { + if (lon < 73.66 || lon > 135.05){ + return true; + } + if (lat < 3.86 || lat > 53.55){ + return true; + } + return false; + } + + /** + * 计算纬度 + * @param x + * @param y + * @return + */ + private static double calLat(double x, double y) { + double resultLat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + + 0.2 * Math.sqrt(Math.abs(x)); + resultLat += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0; + resultLat += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0; + resultLat += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0; + return resultLat; + } + + /** + * 计算经度 + * @param x + * @param y + * @return + */ + private static double calLon(double x, double y) { + double resultLon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 + * Math.sqrt(Math.abs(x)); + resultLon += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0; + resultLon += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0; + resultLon += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 + * PI)) * 2.0 / 3.0; + return resultLon; + } + + public static void main(String[] args){ + LatLonPoint point = new LatLonPoint(29.623759D,104.543263D); + System.out.println("gps坐标:经度:"+point.getLongitude()+" 纬度:"+point.getLatitude()); + LatLonPoint point1 = CoordinateConverterUtil.toWGSPoint(point.getLatitude(),point.getLongitude()); + System.out.println("高德坐标:经度:"+point1.getLongitude()+" 纬度:"+point1.getLatitude()); + } + +} diff --git a/src/main/java/com/gci/boot/common/util/DateUtils.java b/src/main/java/com/gci/boot/common/util/DateUtils.java new file mode 100644 index 0000000..523716a --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/DateUtils.java @@ -0,0 +1,956 @@ +package com.gci.boot.common.util; + +import java.beans.PropertyEditorSupport; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.Period; +import java.time.ZoneId; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.springframework.util.StringUtils; + +/** + * 类描述:时间操作定义类 + * + * @Author: 张代浩 + * @Date:2012-12-8 12:15:03 + * @Version 1.0 + */ +public class DateUtils extends PropertyEditorSupport { + + // 连字符:hyphens(默认格式) + public static final String HYPHENS_DATE = "yyyy-MM-dd"; + public static final String HYPHENS_DATETIME = "yyyy-MM-dd HH:mm:ss"; + public static final String HYPHENS_DATETIME_DETAIL = "yyyy-MM-dd HH:mm:ss SSS"; + public static final String HYPHENS_TIME = "HH:mm:ss"; + public static final String HYPHENS_TIME2 = "HH:mm"; + + + public static final String HYPHENS_DATETIME2 = "yyyyMMddHHmmss"; + + public static final String HYPHENS_DATETIME4 = "yyyyMMddHHmmssSS"; + + public static final String HYPHENS_DATE2 = "yyyyMMdd"; + + public static final String HYPHENS_MONTH = "yyyy-MM"; + + public static final String HYPHENS_MONTH2 = "yyyyMM"; + + public static final String HYPHENS_TIME3 = "MMddHHmmss"; + + public static final String HYPHENS_DATETIME3 = "MM月dd日 HH:mm"; + + public static final String HYPHENS_MONTH3 = "MM-dd"; + + public static final String HYPHENS_YEAR = "yyyy"; + + public static final String HYPHENS_MONTH4 = "M/d"; + + public static ThreadLocal date_sdf = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyy-MM-dd"); + } + }; + public static ThreadLocal yyyyMMdd = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyyMMdd"); + } + }; + public static ThreadLocal date_sdf_wz = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyy年MM月dd日"); + } + }; + public static ThreadLocal time_sdf = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm"); + } + }; + public static ThreadLocal yyyymmddhhmmss = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyyMMddHHmmss"); + } + }; + public static ThreadLocal short_time_sdf = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("HH:mm"); + } + }; + public static ThreadLocal datetimeFormat = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + } + }; + + // 以毫秒表示的时间 + private static final long DAY_IN_MILLIS = 24 * 3600 * 1000; + private static final long HOUR_IN_MILLIS = 3600 * 1000; + private static final long MINUTE_IN_MILLIS = 60 * 1000; + private static final long SECOND_IN_MILLIS = 1000; + + // 指定模式的时间格式 + private static SimpleDateFormat getSDFormat(String pattern) { + return new SimpleDateFormat(pattern); + } + + /** + * 当前日历,这里用中国时间表示 + * + * @return 以当地时区表示的系统当前日历 + */ + public static Calendar getCalendar() { + return Calendar.getInstance(); + } + + /** + * 指定毫秒数表示的日历 + * + * @param millis 毫秒数 + * @return 指定毫秒数表示的日历 + */ + public static Calendar getCalendar(long millis) { + Calendar cal = Calendar.getInstance(); + // --------------------cal.setTimeInMillis(millis); + cal.setTime(new Date(millis)); + return cal; + } + + // //////////////////////////////////////////////////////////////////////////// + // getDate + // 各种方式获取的Date + // //////////////////////////////////////////////////////////////////////////// + + /** + * 当前日期 + * + * @return 系统当前时间 + */ + public static Date getDate() { + return new Date(); + } + + /** + * 指定毫秒数表示的日期 + * + * @param millis 毫秒数 + * @return 指定毫秒数表示的日期 + */ + public static Date getDate(long millis) { + return new Date(millis); + } + + /** + * 时间戳转换为字符串 + * + * @param time + * @return + */ + public static String timestamptoStr(Timestamp time) { + Date date = null; + if (null != time) { + date = new Date(time.getTime()); + } + return date2Str(date_sdf.get()); + } + + public static Date convertLocalDateTimeToDate(LocalDateTime localDateTime){ + Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); + return Date.from(instant); + } + + public static LocalDateTime convertDateToLocalDateTime(Date date){ + Instant instant = date.toInstant(); + return instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + } + + /** + * 字符串转换时间戳 + * + * @param str + * @return + */ + public static Timestamp str2Timestamp(String str) { + Date date = str2Date(str, date_sdf.get()); + return new Timestamp(date.getTime()); + } + + /** + * 字符串转换成日期 + * + * @param str + * @param sdf + * @return + */ + public static Date str2Date(String str, SimpleDateFormat sdf) { + if (null == str || "".equals(str)) { + return null; + } + Date date = null; + try { + date = sdf.parse(str); + return date; + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 日期转换为字符串 + * + * @param date_sdf 日期格式 + * @return 字符串 + */ + public static String date2Str(SimpleDateFormat date_sdf) { + Date date = getDate(); + if (null == date) { + return null; + } + return date_sdf.format(date); + } + + /** + * 格式化时间 + * + * @param date + * @param format + * @return + */ + public static String dateformat(String date, String format) { + SimpleDateFormat sformat = new SimpleDateFormat(format); + Date _date = null; + try { + _date = sformat.parse(date); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return sformat.format(_date); + } + + /** + * 日期转换为字符串 + * + * @param date 日期 + * @param date_sdf 日期格式 + * @return 字符串 + */ + public static String date2Str(Date date, SimpleDateFormat date_sdf) { + if (null == date) { + return null; + } + return date_sdf.format(date); + } + + /** + * 日期转换为字符串 + * + * @param format 日期格式 + * @return 字符串 + */ + public static String getDate(String format) { + Date date = new Date(); + if (null == date) { + return null; + } + SimpleDateFormat sdf = new SimpleDateFormat(format); + return sdf.format(date); + } + + /** + * 指定毫秒数的时间戳 + * + * @param millis 毫秒数 + * @return 指定毫秒数的时间戳 + */ + public static Timestamp getTimestamp(long millis) { + return new Timestamp(millis); + } + + /** + * 以字符形式表示的时间戳 + * + * @param time 毫秒数 + * @return 以字符形式表示的时间戳 + */ + public static Timestamp getTimestamp(String time) { + return new Timestamp(Long.parseLong(time)); + } + + /** + * 系统当前的时间戳 + * + * @return 系统当前的时间戳 + */ + public static Timestamp getTimestamp() { + return new Timestamp(System.currentTimeMillis()); + } + + /** + * 当前时间,格式 yyyy-MM-dd HH:mm:ss + * + * @return 当前时间的标准形式字符串 + */ + public static String now() { + return datetimeFormat.get().format(getCalendar().getTime()); + } + + /** + * 指定日期的时间戳 + * + * @param date 指定日期 + * @return 指定日期的时间戳 + */ + public static Timestamp getTimestamp(Date date) { + return new Timestamp(date.getTime()); + } + + /** + * 指定日历的时间戳 + * + * @param cal 指定日历 + * @return 指定日历的时间戳 + */ + public static Timestamp getCalendarTimestamp(Calendar cal) { + // ---------------------return new Timestamp(cal.getTimeInMillis()); + return new Timestamp(cal.getTime().getTime()); + } + + public static Timestamp gettimestamp() { + Date dt = new Date(); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String nowTime = df.format(dt); + Timestamp buydate = Timestamp.valueOf(nowTime); + return buydate; + } + + // //////////////////////////////////////////////////////////////////////////// + // getMillis + // 各种方式获取的Millis + // //////////////////////////////////////////////////////////////////////////// + + /** + * 系统时间的毫秒数 + * + * @return 系统时间的毫秒数 + */ + public static long getMillis() { + return System.currentTimeMillis(); + } + + /** + * 指定日历的毫秒数 + * + * @param cal 指定日历 + * @return 指定日历的毫秒数 + */ + public static long getMillis(Calendar cal) { + // --------------------return cal.getTimeInMillis(); + return cal.getTime().getTime(); + } + + /** + * 指定日期的毫秒数 + * + * @param date 指定日期 + * @return 指定日期的毫秒数 + */ + public static long getMillis(Date date) { + return date.getTime(); + } + + /** + * 指定时间戳的毫秒数 + * + * @param ts 指定时间戳 + * @return 指定时间戳的毫秒数 + */ + public static long getMillis(Timestamp ts) { + return ts.getTime(); + } + + // //////////////////////////////////////////////////////////////////////////// + // formatDate + // 将日期按照一定的格式转化为字符串 + // //////////////////////////////////////////////////////////////////////////// + + /** + * 默认方式表示的系统当前日期,具体格式:年-月-日 + * + * @return 默认日期按“年-月-日“格式显示 + */ + public static String formatDate() { + return date_sdf.get().format(getCalendar().getTime()); + } + + /** + * 默认方式表示的系统当前日期,具体格式:yyyy-MM-dd HH:mm:ss + * + * @return 默认日期按“yyyy-MM-dd HH:mm:ss“格式显示 + */ + public static String formatDateTime() { + return datetimeFormat.get().format(getCalendar().getTime()); + } + + /** + * 获取时间字符串 + */ + public static String getDataString(SimpleDateFormat formatstr) { + return formatstr.format(getCalendar().getTime()); + } + + /** + * 指定日期的默认显示,具体格式:年-月-日 + * + * @param cal 指定的日期 + * @return 指定日期按“年-月-日“格式显示 + */ + public static String formatDate(Calendar cal) { + return date_sdf.get().format(cal.getTime()); + } + + /** + * 指定日期的默认显示,具体格式:年-月-日 + * + * @param date 指定的日期 + * @return 指定日期按“年-月-日“格式显示 + */ + public static String formatDate(Date date) { + return date_sdf.get().format(date); + } + + /** + * 指定毫秒数表示日期的默认显示,具体格式:年-月-日 + * + * @param millis 指定的毫秒数 + * @return 指定毫秒数表示日期按“年-月-日“格式显示 + */ + public static String formatDate(long millis) { + return date_sdf.get().format(new Date(millis)); + } + + /** + * 默认日期按指定格式显示 + * + * @param pattern 指定的格式 + * @return 默认日期按指定格式显示 + */ + public static String formatDate(String pattern) { + return getSDFormat(pattern).format(getCalendar().getTime()); + } + + /** + * 指定日期按指定格式显示 + * + * @param cal 指定的日期 + * @param pattern 指定的格式 + * @return 指定日期按指定格式显示 + */ + public static String formatDate(Calendar cal, String pattern) { + return getSDFormat(pattern).format(cal.getTime()); + } + + /** + * 指定日期按指定格式显示 + * + * @param date 指定的日期 + * @param pattern 指定的格式 + * @return 指定日期按指定格式显示 + */ + public static String formatDate(Date date, String pattern) { + return getSDFormat(pattern).format(date); + } + + // //////////////////////////////////////////////////////////////////////////// + // formatTime + // 将日期按照一定的格式转化为字符串 + // //////////////////////////////////////////////////////////////////////////// + + /** + * 默认方式表示的系统当前日期,具体格式:年-月-日 时:分 + * + * @return 默认日期按“年-月-日 时:分“格式显示 + */ + public static String formatTime() { + return time_sdf.get().format(getCalendar().getTime()); + } + + /** + * 指定毫秒数表示日期的默认显示,具体格式:年-月-日 时:分 + * + * @param millis 指定的毫秒数 + * @return 指定毫秒数表示日期按“年-月-日 时:分“格式显示 + */ + public static String formatTime(long millis) { + return time_sdf.get().format(new Date(millis)); + } + + /** + * 指定日期的默认显示,具体格式:年-月-日 时:分 + * + * @param cal 指定的日期 + * @return 指定日期按“年-月-日 时:分“格式显示 + */ + public static String formatTime(Calendar cal) { + return time_sdf.get().format(cal.getTime()); + } + + /** + * 指定日期的默认显示,具体格式:年-月-日 时:分 + * + * @param date 指定的日期 + * @return 指定日期按“年-月-日 时:分“格式显示 + */ + public static String formatTime(Date date) { + return time_sdf.get().format(date); + } + + // //////////////////////////////////////////////////////////////////////////// + // formatShortTime + // 将日期按照一定的格式转化为字符串 + // //////////////////////////////////////////////////////////////////////////// + + /** + * 默认方式表示的系统当前日期,具体格式:时:分 + * + * @return 默认日期按“时:分“格式显示 + */ + public static String formatShortTime() { + return short_time_sdf.get().format(getCalendar().getTime()); + } + + /** + * 指定毫秒数表示日期的默认显示,具体格式:时:分 + * + * @param millis 指定的毫秒数 + * @return 指定毫秒数表示日期按“时:分“格式显示 + */ + public static String formatShortTime(long millis) { + return short_time_sdf.get().format(new Date(millis)); + } + + /** + * 指定日期的默认显示,具体格式:时:分 + * + * @param cal 指定的日期 + * @return 指定日期按“时:分“格式显示 + */ + public static String formatShortTime(Calendar cal) { + return short_time_sdf.get().format(cal.getTime()); + } + + /** + * 指定日期的默认显示,具体格式:时:分 + * + * @param date 指定的日期 + * @return 指定日期按“时:分“格式显示 + */ + public static String formatShortTime(Date date) { + return short_time_sdf.get().format(date); + } + + // //////////////////////////////////////////////////////////////////////////// + // parseDate + // parseCalendar + // parseTimestamp + // 将字符串按照一定的格式转化为日期或时间 + // //////////////////////////////////////////////////////////////////////////// + + /** + * 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间 + * + * @param src 将要转换的原始字符窜 + * @param pattern 转换的匹配格式 + * @return 如果转换成功则返回转换后的日期 + * @throws ParseException + */ + public static Date parseDate(String src, String pattern) throws ParseException { + return getSDFormat(pattern).parse(src); + + } + + /** + * 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间 + * + * @param src 将要转换的原始字符窜 + * @param pattern 转换的匹配格式 + * @return 如果转换成功则返回转换后的日期 + * @throws ParseException + */ + public static Calendar parseCalendar(String src, String pattern) throws ParseException { + + Date date = parseDate(src, pattern); + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + return cal; + } + + public static String formatAddDate(String src, String pattern, int amount) throws ParseException { + Calendar cal; + cal = parseCalendar(src, pattern); + cal.add(Calendar.DATE, amount); + return formatDate(cal); + } + + /** + * 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间 + * + * @param src 将要转换的原始字符窜 + * @param pattern 转换的匹配格式 + * @return 如果转换成功则返回转换后的时间戳 + * @throws ParseException + */ + public static Timestamp parseTimestamp(String src, String pattern) throws ParseException { + Date date = parseDate(src, pattern); + return new Timestamp(date.getTime()); + } + + // //////////////////////////////////////////////////////////////////////////// + // dateDiff + // 计算两个日期之间的差值 + // //////////////////////////////////////////////////////////////////////////// + + /** + * 计算两个时间之间的差值,根据标志的不同而不同 + * + * @param flag 计算标志,表示按照年/月/日/时/分/秒等计算 + * @param calSrc 减数 + * @param calDes 被减数 + * @return 两个日期之间的差值 + */ + public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) { + + long millisDiff = getMillis(calSrc) - getMillis(calDes); + + if (flag == 'y') { + return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR)); + } + + if (flag == 'd') { + return (int) (millisDiff / DAY_IN_MILLIS); + } + + if (flag == 'h') { + return (int) (millisDiff / HOUR_IN_MILLIS); + } + + if (flag == 'm') { + return (int) (millisDiff / MINUTE_IN_MILLIS); + } + + if (flag == 's') { + return (int) (millisDiff / SECOND_IN_MILLIS); + } + + return 0; + } + + /** + * String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd + * HH:mm:ss“ * @param text String类型的时间值 + */ + @Override + public void setAsText(String text) throws IllegalArgumentException { + if (StringUtils.hasText(text)) { + try { + if (text.indexOf(":") == -1 && text.length() == 10) { + setValue(DateUtils.date_sdf.get().parse(text)); + } else if (text.indexOf(":") > 0 && text.length() == 19) { + setValue(DateUtils.datetimeFormat.get().parse(text)); + } else { + throw new IllegalArgumentException("Could not parse date, date format is error "); + } + } catch (ParseException ex) { + IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage()); + iae.initCause(ex); + throw iae; + } + } else { + setValue(null); + } + } + + public static int getYear() { + GregorianCalendar calendar = new GregorianCalendar(); + calendar.setTime(getDate()); + return calendar.get(Calendar.YEAR); + } + + + /** + * 获取一天开始时间 + * @param date + * @return + */ + public static Date getDayStart(Date date) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return c.getTime(); + } + + /** + * 获取一天结束时间 + * @return + */ + public static Date getDayEnd(Date date) { + if(date==null){ + return null; + } + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.set(Calendar.HOUR_OF_DAY, 23); + c.set(Calendar.MINUTE, 59); + c.set(Calendar.SECOND, 59); + c.set(Calendar.MILLISECOND, 0); + return c.getTime(); + } + + public static Date getToday() { + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return c.getTime(); + } + + /** + * 月份加减,可传负数 + * @param date + * @param day + * @return + */ + public static Date addMonth(Date date, int count) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.MONTH, count); + return c.getTime(); + } + + /** + * 日期加减,可传负数 + * @param date + * @param day + * @return + */ + public static Date addDay(Date date, int day) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.DATE, day); + return c.getTime(); + } + + /** + * 分钟加减,可传负数 + * @param date + * @param day + * @return + */ + public static Date addMinute(Date date, int min) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.MINUTE, min); + return c.getTime(); + } + + /** + * 小时加减,可传负数 + * @param date + * @param day + * @return + */ + public static Date addHours(Date date, int count) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.HOUR_OF_DAY, count); + return c.getTime(); + } + + /** + * 年加减,可传负数 + * @param date + * @param day + * @return + */ + public static Date addYear(Date date, int count) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.YEAR, count); + return c.getTime(); + } + + public static int compareTo(Date date1,Date date2) { + if(date1!=null&&date2!=null) { + return date1.compareTo(date2); + } + if(date1==null) { + return -1; + } + if(date2==null) { + return 1; + } + return 0; + } + + /** + * 获取相差天数 + * @param start + * @param end + * @return + */ + public static int differentDays(Date start,Date end) + { + int days = (int) ((end.getTime() - start.getTime()) / (1000*3600*24)); + return days; + } + + //获取当某月第一天: + public static Date getFirstDayForMonth(Date date) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.MONTH, 0); + c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天 + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return c.getTime(); + } + + + //获取当某月最后一天 + public static Date getLastDayForMonth(Date date,int type) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH)); + if(type==2) { + c.set(Calendar.HOUR_OF_DAY, 23); + c.set(Calendar.MINUTE, 59); + c.set(Calendar.SECOND, 59); + c.set(Calendar.MILLISECOND, 0); + }else { + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + } + return c.getTime(); + } + + + public static LocalDate convertDateToLocalDate(Date date){ + Instant instant = date.toInstant(); + return instant.atZone(ZoneId.systemDefault()).toLocalDate(); + } + + /** + * 获取月份差值 + * @param start + * @param end + * @return + */ + public static int differentMonth(Date start,Date end) { + LocalDate date1 = convertDateToLocalDate(start); + LocalDate date2 = convertDateToLocalDate(end); + Period period = Period.between(date1, date2); + int totalMonths = period.getYears() * 12 + period.getMonths(); + return totalMonths; + } + + // 获取季度的三个月份 + public static String[] getQuarter(Date date) { + LocalDate current = convertDateToLocalDate(date); + int year = current.getYear(); + int quarter = (current.getMonthValue() - 1) / 3 + 1; + + // 计算季度的三个月份 + String[] months = new String[3]; + for (int i = 0; i < months.length; i++) { + int month = quarter * 3 - 3 + i + 1; + if (month > 12) { + month -= 12; + months[i] = (year - 1) + "-"; + } else { + //prevMonths[i] = year + "-Q" + prevQuarter; + months[i] = year + "-"; + } + months[i] += String.format("%02d", month); + } + return months; + } + + public static String[] getQuarterDate(Date date) { + LocalDate current = convertDateToLocalDate(date); + int year = current.getYear(); + int quarter = (current.getMonthValue() - 1) / 3 + 1; + + // 计算季度的三个月份 + String[] months = new String[3]; + for (int i = 0; i < months.length; i++) { + int month = quarter * 3 - 3 + i + 1; + if (month > 12) { + month -= 12; + months[i] = (year - 1) + "-"; + } else { + months[i] = year + "-"; + } + months[i] += String.format("%02d", month) + "-01"; + } + return months; + } + + public static Date getFirstDayForYear(Date date) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.YEAR)); + c.set(Calendar.MONTH, 0); + c.set(Calendar.DAY_OF_MONTH, 1); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return c.getTime(); + } + + + //获取当某月最后一天 + public static Date getLastDayForNextMonth(Date date,int mouth,int type) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.MONTH, mouth); + c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH)); + if(type==2) { + c.set(Calendar.HOUR_OF_DAY, 23); + c.set(Calendar.MINUTE, 59); + c.set(Calendar.SECOND, 59); + c.set(Calendar.MILLISECOND, 0); + }else { + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + } + return c.getTime(); + } + + +} + diff --git a/src/main/java/com/gci/boot/common/util/FormatUtil.java b/src/main/java/com/gci/boot/common/util/FormatUtil.java new file mode 100644 index 0000000..80d0fc1 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/FormatUtil.java @@ -0,0 +1,92 @@ +package com.gci.boot.common.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.util.Date; + +/** + * @author lyz + * @date 2023/10/10 10:09 + */ +public class FormatUtil { + + public static void main(String[] args) { + String jsonString = "[{\"controllerTemperature\":\"39\",\"dcBusCurrent\":\"1001.2000122070312\",\"inputVoltage\":\"408.0\",\"number\":1,\"rpm\":40531,\"status\":\"1\",\"temperature\":\"34\",\"torque\":\"10.0\"},{\"controllerTemperature\":\"39\",\"dcBusCurrent\":\"1001.2000122070312\",\"inputVoltage\":\"408.0\",\"number\":1,\"rpm\":40531,\"status\":\"3\",\"temperature\":\"34\",\"torque\":\"10.0\"}]"; + + String updatedJsonString = replaceStatusValues("status",jsonString); + + System.out.println(updatedJsonString); + } + + public static String replaceStatusValues(String key,String jsonString) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode arrayNode = objectMapper.readTree(jsonString); + + for (JsonNode motorNode : arrayNode) { + String currentStatus = motorNode.get(key).asText(); + String newStatus = calculateNewStatus(currentStatus); + ((ObjectNode) motorNode).put(key, newStatus); + } + return objectMapper.writeValueAsString(arrayNode); + } catch (Exception e) { + e.printStackTrace(); + return jsonString; + } + } + + private static String calculateNewStatus(String currentStatus) { + // 根据实际情况计算新的status值 + switch (currentStatus) { + case "1": + return "正常"; + case "0": + return "异常"; + default: + return "未知"; + } + } + + /** + * 格式化两个时间之间的差值 + * @param startTime + * @param endTime + * @return + */ + public static String formattedTimeDifference(Date startTime, Date endTime){ + if(startTime == null){ + return "未知"; + } + // 如果endTime为空,则使用当前时间作为endTime + if (endTime == null) { + endTime = new Date(); + } + long timeDifferenceInMillis = endTime.getTime() - startTime.getTime(); + long seconds = timeDifferenceInMillis / 1000; + long minutes = seconds / 60; + long hours = minutes / 60; + long remainingMinutes = minutes % 60; + long remainingSeconds = seconds % 60; + String formattedTimeDifference = String.format("%d时%d分%d秒", hours, remainingMinutes, remainingSeconds); + return formattedTimeDifference; + } + + public static String convertToMonthDescription(String input) { + try { + int monthNumber = Integer.parseInt(input); + String[] monthDescriptions = { + "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月" + }; + // 检查输入的月份是否在有效范围内 + if (monthNumber >= 1 && monthNumber <= 12) { + return monthDescriptions[monthNumber - 1]; + } else { + return input; + } + } catch (NumberFormatException e) { + return input; + } + } +} diff --git a/src/main/java/com/gci/boot/common/util/JsonUtil.java b/src/main/java/com/gci/boot/common/util/JsonUtil.java new file mode 100644 index 0000000..fa6d685 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/JsonUtil.java @@ -0,0 +1,233 @@ +package com.gci.boot.common.util; + +import cn.hutool.json.JSONNull; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; +import org.apache.poi.ss.formula.functions.T; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +/** + * JSON转换工具 + * + * @author chenzw + * @date 2021/12/9 + */ +public class JsonUtil { + + /** 默认日期时间格式 */ + public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + /** 默认日期格式 */ + public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; + + /** 默认时间格式 */ + public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss"; + + public static class JsonNullSerizlizer extends JsonSerializer { + + @Override + public void serialize(JSONNull jsonNull, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { + jsonGenerator.writeNull(); + } + + } + + private static final ObjectMapper MAPPER; + private static final ObjectMapper ALL_MAPPER; + static { + MAPPER = initMapper(); + ALL_MAPPER = initMapper(); + ALL_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS); + } + + private static ObjectMapper initMapper(){ + ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT)); + mapper.enable(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL); + mapper.disable(SerializationFeature.FAIL_ON_SELF_REFERENCES); + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalDateTime.class, + new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))); + javaTimeModule.addSerializer(LocalDate.class, + new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))); + javaTimeModule.addSerializer(LocalTime.class, + new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))); + javaTimeModule.addDeserializer(LocalDateTime.class, + new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))); + javaTimeModule.addDeserializer(LocalDate.class, + new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))); + javaTimeModule.addDeserializer(LocalTime.class, + new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))); + mapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule()); + + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(JSONNull.class, new JsonNullSerizlizer()); + mapper.registerModule(simpleModule); + + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return mapper; + } + public static byte[] object2JsonBytes(Object obj) { + // 把对象转换成JSON + String json = object2Json(obj); + try { + return json.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + // 将 POJO 转成JSON字符串,只处理非空字段 + public static String object2Json(Object obj) { + try { + return MAPPER.writeValueAsString(obj); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将 POJO 转成JSON字符串,处理全部字段 + public static String object2JsonAll(Object obj) { + try { + return ALL_MAPPER.writeValueAsString(obj); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将 POJO 转成JSON字符串,只处理非空字段,格式美化 + public static String object2JsonPretty(Object obj) { + try { + return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将 POJO 转成JSON字符串,处理全部字段,格式美化 + public static String object2JsonAllPretty(Object obj) { + try { + return ALL_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将JSON字符串转成 Map + public static Map json2Map(String json) { + try { + return MAPPER.readValue(json, Map.class); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将POJO对象转Map + public static Map object2Map(Object obj) { + try { + return MAPPER.convertValue(obj, Map.class); + } catch (IllegalArgumentException e) { + return null; + } + } + + // 将POJO对象转Map + public static Map object2MapAll(Object obj) { + try { + return ALL_MAPPER.convertValue(obj, Map.class); + } catch (IllegalArgumentException e) { + return null; + } + } + + public static T jsonBytes2Object(byte[] bytes, Class tClass) { + // 尽量把对象转换成JSON保存更稳妥 + try { + String json = new String(bytes, "UTF-8"); + T t = json2Object(json, tClass); + return t; + } + catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + // 将JSON字符串转成 POJO对象 + public static T json2Object(String json, Class tClass) { + try { + return MAPPER.readValue(json, tClass); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将JSON字符串转成List + public static List json2List(String json, Class tClass) { + try { + return MAPPER.readValue(json, MAPPER.getTypeFactory().constructParametricType(List.class, tClass)); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + // 将JSON字符串转成元素为Map的List + public static List json2MapList(String json) { + return JsonUtil.json2List(json, Map.class); + } + + // 将JSON字符串转成 POJO对象 + public static T map2Object(Map map, Class tClass) { + try { + return MAPPER.readValue(MAPPER.writeValueAsString(map), tClass); + } + catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + public static ObjectMapper getMapper() { + return MAPPER; + } + +} diff --git a/src/main/java/com/gci/boot/common/util/LambdaFunctionUtil.java b/src/main/java/com/gci/boot/common/util/LambdaFunctionUtil.java new file mode 100644 index 0000000..905bc69 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/LambdaFunctionUtil.java @@ -0,0 +1,41 @@ +package com.gci.boot.common.util; + +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import lombok.extern.slf4j.Slf4j; + +import java.lang.invoke.CallSite; +import java.lang.invoke.LambdaMetafactory; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Field; + +@Slf4j +public class LambdaFunctionUtil { + private static final int FLAG_SERIALIZABLE = 1; + + public static SFunction getFunctionField(Class entityClass, String filedName) { + Field field = ReflectUtil.getField(entityClass, filedName); + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType methodType = MethodType.methodType(field.getType(), entityClass); + final CallSite site; + if (StrUtil.isEmpty(filedName)){ + filedName = field.getName(); + } + String getFunName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1); + try { + site = LambdaMetafactory.altMetafactory(lookup, + "invoke", + MethodType.methodType(SFunction.class), + methodType, + lookup.findVirtual(entityClass, getFunName, MethodType.methodType(field.getType())), + methodType, FLAG_SERIALIZABLE); + SFunction func = (SFunction) site.getTarget().invokeExact(); + return func; + } catch (Throwable e) { + log.error("根据字段获取sfunc异常:{},{}", e.getMessage(), e); + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/common/util/LatLonPoint.java b/src/main/java/com/gci/boot/common/util/LatLonPoint.java new file mode 100644 index 0000000..8f731b6 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/LatLonPoint.java @@ -0,0 +1,39 @@ +package com.gci.boot.common.util; + +/** + * @Author: lyz + * @Description: TODO:(用一句话描述该文件做什么) + * @Date: 2021-04-20 14:26 + * @version: v1.0 + * @Modified by: + **/ +public class LatLonPoint +{ + private double longitude ; + + private double latitude; + + public LatLonPoint() { + } + + public LatLonPoint(double latitude, double longitude) { + this.longitude = longitude; + this.latitude = latitude; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } +} diff --git a/src/main/java/com/gci/boot/common/util/LimitCheckUtil.java b/src/main/java/com/gci/boot/common/util/LimitCheckUtil.java new file mode 100644 index 0000000..823b3b4 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/LimitCheckUtil.java @@ -0,0 +1,68 @@ +package com.gci.boot.common.util; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.system.vo.LimitRequest; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; + +@Component +public class LimitCheckUtil { + /** + * 接口每日限制次数 + */ + private static int limitCount = 10; + + public static void putNeedCheck(String username, String token) { + Object o = RedisUtil.get(CacheConstant.LIMIT_USERNAME + username); + if (ObjectUtil.isNotEmpty(o)) { + //清空用户登录Token缓存 + RedisUtil.del(CommonConstant.PREFIX_USER_TOKEN + o); + } + RedisUtil.set(CacheConstant.LIMIT_USERNAME + username,token); + } + + public static void check(HttpServletRequest request, String username, String token) { + if (token != null) { + Object u = RedisUtil.get(CacheConstant.LIMIT_USERNAME + username); + if (ObjectUtil.isEmpty(u)) { + return; + } else { + if (!u.equals(token)) { + return; + } + } + } + DateTime today = new DateTime(); + String uri = request.getRequestURI(); + String pre = CacheConstant.LIMIT_REQUEST + username + ":" + uri; + Object o = RedisUtil.get(pre); + if (ObjectUtil.isEmpty(o)) { + LimitRequest limitRequest = new LimitRequest(); + limitRequest.setCount(1); + limitRequest.setTime(today.toDateStr()); + RedisUtil.set(pre, JSONUtil.toJsonStr(limitRequest)); + } else { + LimitRequest limitRequest = JSONUtil.toBean(JSONUtil.toJsonStr(o), LimitRequest.class); + String time = limitRequest.getTime(); + if (time.equals(today.toDateStr())) { + //是同一天的话看看次数 + if (limitRequest.getCount() >= limitCount) { + throw new GciBootException(uri+"超过每日请求次数限制" + limitCount +"次"); + } else { + limitRequest.setCount(limitRequest.getCount() + 1); + } + } else { + limitRequest.setTime(today.toDateStr()); + limitRequest.setCount(1); + } + RedisUtil.set(pre,JSONUtil.toJsonStr(limitRequest)); + } + } +} diff --git a/src/main/java/com/gci/boot/common/util/Lock.java b/src/main/java/com/gci/boot/common/util/Lock.java new file mode 100644 index 0000000..0e5dae7 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/Lock.java @@ -0,0 +1,40 @@ +package com.gci.boot.common.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Component +public class Lock { + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + public int getLock(String lockKey, String lockValue){ + boolean n = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue); + if(n){ + stringRedisTemplate.expire(lockKey, 180, TimeUnit.SECONDS); + return 1; + }else{ + return 0; + } + } + + public void delLock(String lockKey, String lockValue){ + String value = stringRedisTemplate.opsForValue().get(lockKey); + if(lockValue.equals(value)){ + stringRedisTemplate.delete(lockKey); + } + } + + public String getUniqueNum(){ + String uuid = UUID.randomUUID().toString(); + String timestamp = System.currentTimeMillis()+""; + return uuid+"-"+timestamp; + } + + + +} diff --git a/src/main/java/com/gci/boot/common/util/MD5Util.java b/src/main/java/com/gci/boot/common/util/MD5Util.java new file mode 100644 index 0000000..56e04e8 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/MD5Util.java @@ -0,0 +1,43 @@ +package com.gci.boot.common.util; + +import java.security.MessageDigest; + +public class MD5Util { + + public static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++){ + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) { + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)) { + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + } else { + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + } catch (Exception exception) { + } + return resultString; + } + + private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; + +} diff --git a/src/main/java/com/gci/boot/common/util/MinioUtils.java b/src/main/java/com/gci/boot/common/util/MinioUtils.java new file mode 100644 index 0000000..7e13074 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/MinioUtils.java @@ -0,0 +1,748 @@ +package com.gci.boot.common.util; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +import cn.hutool.core.convert.Convert; +import com.gci.boot.constant.CommonConstant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.io.FileTypeUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import io.minio.BucketExistsArgs; +import io.minio.CopyObjectArgs; +import io.minio.CopySource; +import io.minio.GetBucketPolicyArgs; +import io.minio.GetObjectArgs; +import io.minio.GetPresignedObjectUrlArgs; +import io.minio.ListObjectsArgs; +import io.minio.MakeBucketArgs; +import io.minio.MinioClient; +import io.minio.ObjectWriteResponse; +import io.minio.PutObjectArgs; +import io.minio.RemoveBucketArgs; +import io.minio.RemoveObjectArgs; +import io.minio.Result; +import io.minio.StatObjectArgs; +import io.minio.UploadObjectArgs; +import io.minio.http.Method; +import io.minio.messages.Bucket; +import io.minio.messages.DeleteObject; +import io.minio.messages.Item; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import sun.misc.BASE64Decoder; + +import javax.servlet.http.HttpServletRequest; + +/** + * MinIO工具类 + * + */ +@Slf4j +@Component +public class MinioUtils { + @Autowired + private MinioClient minioClient; + @Value("${minio.bucketName}") + private String bucketName; + @Value("${minio.fileUrl}") + private String fileUrl; + @Value("${minio.minioUrl}") + private String minioUrl; + private final String bizPath = "common"; + private final String contentType = "application/octet-stream"; + private final String noStorage = "Storage backend has reached its minimum free disk threshold. Please delete a few objects to proceed."; + + + /****************************** Operate Bucket Start ******************************/ + + /** + * 启动SpringBoot容器的时候初始化Bucket + * 如果没有Bucket则创建 + * + * @param bucketName + */ + @SneakyThrows(Exception.class) + private void createBucket(String bucketName) { + if (!bucketExists(bucketName)) { + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); + } + } + + /** + * 判断Bucket是否存在,true:存在,false:不存在 + * + * @param bucketName + * @return + */ + @SneakyThrows(Exception.class) + public boolean bucketExists(String bucketName) { + return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); + } + + /** + * 获得Bucket的策略 + * + * @param bucketName + * @return + */ + @SneakyThrows(Exception.class) + public String getBucketPolicy(String bucketName) { + return minioClient.getBucketPolicy(GetBucketPolicyArgs + .builder() + .bucket(bucketName) + .build()); + } + + /** + * 获得所有Bucket列表 + * + * @return + */ + @SneakyThrows(Exception.class) + public List getAllBuckets() { + return minioClient.listBuckets(); + } + + /** + * 根据bucketName获取其相关信息 + * + * @param bucketName + * @return + */ + @SneakyThrows(Exception.class) + public Optional getBucket(String bucketName) { + return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst(); + } + + /** + * 根据bucketName删除Bucket,true:删除成功; false:删除失败,文件或已不存在 + * + * @param bucketName + * @throws Exception + */ + @SneakyThrows(Exception.class) + public void removeBucket(String bucketName) { + minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } + + /****************************** Operate Bucket End ******************************/ + + + /****************************** Operate Files Start ******************************/ + + /** + * 判断文件是否存在 + * + * @param bucketName + * @param objectName + * @return + */ + public boolean isObjectExist(String bucketName, String objectName) { + boolean exist = true; + try { + minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); + } catch (Exception e) { + log.error("[Minio工具类]>>>> 判断文件是否存在, 异常:", e); + exist = false; + } + return exist; + } + + /** + * 判断文件夹是否存在 + * + * @param bucketName + * @param objectName + * @return + */ + public boolean isFolderExist(String bucketName, String objectName) { + boolean exist = false; + try { + Iterable> results = minioClient.listObjects( + ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build()); + for (Result result : results) { + Item item = result.get(); + if (item.isDir() && objectName.equals(item.objectName())) { + exist = true; + } + } + } catch (Exception e) { + log.error("[Minio工具类]>>>> 判断文件夹是否存在,异常:", e); + exist = false; + } + return exist; + } + + /** + * 根据文件前置查询文件 + * + * @param bucketName 存储桶 + * @param prefix 前缀 + * @param recursive 是否使用递归查询 + * @return MinioItem 列表 + */ + @SneakyThrows(Exception.class) + public List getAllObjectsByPrefix(String bucketName, + String prefix, + boolean recursive) { + List list = new ArrayList<>(); + Iterable> objectsIterator = minioClient.listObjects( + ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build()); + if (objectsIterator != null) { + for (Result o : objectsIterator) { + Item item = o.get(); + list.add(item); + } + } + return list; + } + + /** + * 获取文件流 + * + * @param bucketName 存储桶 + * @param objectName 文件名 + * @return 二进制流 + */ + @SneakyThrows(Exception.class) + public InputStream getObject(String bucketName, String objectName) { + return minioClient.getObject( + GetObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .build()); + } + + /** + * 断点下载 + * + * @param bucketName 存储桶 + * @param objectName 文件名称 + * @param offset 起始字节的位置 + * @param length 要读取的长度 + * @return 二进制流 + */ + @SneakyThrows(Exception.class) + public InputStream getObject(String bucketName, String objectName, long offset, long length) { + return minioClient.getObject( + GetObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .offset(offset) + .length(length) + .build()); + } + + /** + * 获取路径下文件列表 + * + * @param bucketName 存储桶 + * @param prefix 文件名称 + * @param recursive 是否递归查找,false:模拟文件夹结构查找 + * @return 二进制流 + */ + public Iterable> listObjects(String bucketName, String prefix, boolean recursive) { + return minioClient.listObjects( + ListObjectsArgs.builder() + .bucket(bucketName) + .prefix(prefix) + .recursive(recursive) + .build()); + } + + /** + * 使用MultipartFile进行文件上传 + * + * @param bucketName 存储桶 + * @param file 文件名 + * @param objectName 对象名 + * @param contentType 类型 + * @return + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse uploadFile(String bucketName, MultipartFile file, String objectName, String contentType) { + InputStream inputStream = file.getInputStream(); + return minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .contentType(contentType) + .stream(inputStream, inputStream.available(), -1) + .build()); + } + + /** + * 使用MultipartFile进行文件上传 + * + * @param file 文件 + * @param fileSuffixList 需要校验的文件列表 + * @return + */ + @SneakyThrows(Exception.class) + public String uploadFileValid(MultipartFile file,List fileSuffixList) { + createBucket(bucketName); + + InputStream inputStream = file.getInputStream(); + BufferedInputStream bufferedInputStream = IoUtil.toBuffered(inputStream); + + bufferedInputStream.mark(0); + String fileContentType = file.getContentType(); + String type = FileTypeUtil.getType(bufferedInputStream,file.getOriginalFilename()); + if (!fileSuffixList.contains(type)) { + bufferedInputStream.close(); + throw new GciBootException("上传失败,文件类型不在"+fileSuffixList.toString()+"中!"); + } + bufferedInputStream.reset(); + + String name = file.getOriginalFilename(); + int typeIndex = name.lastIndexOf("."); + String fileType = ""; + if(typeIndex>0) { + fileType = name.substring(typeIndex); + name = name.substring(0, typeIndex); + } + String s = RandomUtil.randomNumbers(10); + String afterBizPath = bizPath + StrUtil.SLASH + new DateTime().toString(DatePattern.NORM_MONTH_PATTERN); + String objectName = afterBizPath + "/" + name + "_" + s + fileType; + try { + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .contentType(fileContentType) + .stream(bufferedInputStream, bufferedInputStream.available(), -1) + .build()); + } catch (Exception e) { + e.printStackTrace(); + log.error("文件上传报错:{}",e.getMessage()); + if (e.getMessage().equals(noStorage)) { + throw new GciBootException("minio内存不足,无法上传!请联系管理员!"); + } else { + throw new GciBootException("minio上传出现未知异常,请联系管理员!"); + } + } finally { + bufferedInputStream.close(); + } + return getRelFileUrl() + bucketName + "/" + objectName; + } + + /** + * 使用MultipartFile进行文件上传 + * + * @param file 文件 + * @param fileSuffixList 需要校验的文件列表 + * @return + */ + @SneakyThrows(Exception.class) + public String uploadFileValidNotIn(MultipartFile file,List fileSuffixList) { + createBucket(bucketName); + + InputStream inputStream = file.getInputStream(); + BufferedInputStream bufferedInputStream = IoUtil.toBuffered(inputStream); + + bufferedInputStream.mark(0); + String fileContentType = file.getContentType(); + String type = FileTypeUtil.getType(bufferedInputStream,file.getOriginalFilename()); + if (fileSuffixList.contains(type)) { + bufferedInputStream.close(); + throw new GciBootException("上传失败,文件类型不能在"+fileSuffixList.toString()+"中!"); + } + bufferedInputStream.reset(); + + String name = file.getOriginalFilename(); + int typeIndex = name.lastIndexOf("."); + String fileType = ""; + if(typeIndex>0) { + fileType = name.substring(typeIndex); + name = name.substring(0, typeIndex); + } + String s = RandomUtil.randomNumbers(10); + String afterBizPath = bizPath + StrUtil.SLASH + new DateTime().toString(DatePattern.NORM_MONTH_PATTERN); + String objectName = afterBizPath + "/" + name + "_" + s + fileType; + + try { + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .contentType(fileContentType) + .stream(bufferedInputStream, bufferedInputStream.available(), -1) + .build()); + } catch (Exception e) { + e.printStackTrace(); + log.error("文件上传报错:{}",e.getMessage()); + if (e.getMessage().equals(noStorage)) { + throw new GciBootException("minio内存不足,无法上传!请联系管理员!"); + } else { + throw new GciBootException("minio上传出现未知异常,请联系管理员!"); + } + } finally { + bufferedInputStream.close(); + } + return getRelFileUrl() + bucketName + "/" + objectName; + } + + /** + * 使用MultipartFile进行文件上传 + * + * @param file 文件 + * @param fileSuffixList 需要校验的文件列表 + * @return + */ + @SneakyThrows(Exception.class) + public AttachmentDetailVO uploadFileV2Valid(MultipartFile file, List fileSuffixList) { + createBucket(bucketName); + + InputStream inputStream = file.getInputStream(); + BufferedInputStream bufferedInputStream = IoUtil.toBuffered(inputStream); + + bufferedInputStream.mark(0); + String fileContentType = file.getContentType(); + String type = FileTypeUtil.getType(bufferedInputStream,file.getOriginalFilename()); + if (!fileSuffixList.contains(type)) { + bufferedInputStream.close(); + throw new GciBootException("上传失败,文件类型不在"+fileSuffixList.toString()+"中!"); + } + bufferedInputStream.reset(); + + String name = file.getOriginalFilename(); + int typeIndex = name.lastIndexOf("."); + String fileType = ""; + if(typeIndex>0) { + fileType = name.substring(typeIndex); + name = name.substring(0, typeIndex); + } + String s = RandomUtil.randomNumbers(10); + String afterBizPath = bizPath + StrUtil.SLASH + new DateTime().toString(DatePattern.NORM_MONTH_PATTERN); + String objectName = afterBizPath + "/" + name + "_" + s + fileType; + + try { + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .contentType(fileContentType) + .stream(bufferedInputStream, bufferedInputStream.available(), -1) + .build()); + } catch (Exception e) { + e.printStackTrace(); + log.error("文件上传报错:{}",e.getMessage()); + if (e.getMessage().equals(noStorage)) { + throw new GciBootException("minio内存不足,无法上传!请联系管理员!"); + } else { + throw new GciBootException("minio上传出现未知异常,请联系管理员!"); + } + } finally { + bufferedInputStream.close(); + } + + AttachmentDetailVO vo = new AttachmentDetailVO(); + vo.setFileUrl(getRelFileUrl() + bucketName + "/" + objectName); + vo.setFileName(name); + vo.setFileType(type); + return vo; + } + + /** + * 图片上传 + * @param bucketName + * @param imageBase64 + * @param imageName + * @return + */ + public ObjectWriteResponse uploadImage(String bucketName, String imageBase64, String imageName) { + if (!StrUtil.isEmpty(imageBase64)) { + InputStream in = base64ToInputStream(imageBase64); + String newName = System.currentTimeMillis() + "_" + imageName + ".jpg"; + String year = String.valueOf(new Date().getYear()); + String month = String.valueOf(new Date().getMonth()); + return uploadFile(bucketName, year + "/" + month + "/" + newName, in); + + } + return null; + } + + public static InputStream base64ToInputStream(String base64) { + ByteArrayInputStream stream = null; + try { + byte[] bytes = new BASE64Decoder().decodeBuffer(base64.trim()); + stream = new ByteArrayInputStream(bytes); + } catch (Exception e) { + e.printStackTrace(); + } + return stream; + } + + + /** + * 上传本地文件 + * + * @param bucketName 存储桶 + * @param objectName 对象名称 + * @param fileName 本地文件路径 + * @return + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse uploadFile(String bucketName, String objectName, String fileName) { + return minioClient.uploadObject( + UploadObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .filename(fileName) + .build()); + } + + /** + * 通过流上传文件 + * + * @param bucketName 存储桶 + * @param objectName 文件对象 + * @param inputStream 文件流 + * @return + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) { + return minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .stream(inputStream, inputStream.available(), -1) + .build()); + } + + /** + * 创建文件夹或目录 + * + * @param bucketName 存储桶 + * @param objectName 目录路径 + * @return + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse createDir(String bucketName, String objectName) { + return minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .stream(new ByteArrayInputStream(new byte[]{}), 0, -1) + .build()); + } + + /** + * 获取文件信息, 如果抛出异常则说明文件不存在 + * + * @param bucketName 存储桶 + * @param objectName 文件名称 + * @return + */ + @SneakyThrows(Exception.class) + public String getFileStatusInfo(String bucketName, String objectName) { + return minioClient.statObject( + StatObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .build()).toString(); + } + + /** + * 拷贝文件 + * + * @param bucketName 存储桶 + * @param objectName 文件名 + * @param srcBucketName 目标存储桶 + * @param srcObjectName 目标文件名 + */ + @SneakyThrows(Exception.class) + public ObjectWriteResponse copyFile(String bucketName, String objectName, String srcBucketName, String srcObjectName) { + return minioClient.copyObject( + CopyObjectArgs.builder() + .source(CopySource.builder().bucket(bucketName).object(objectName).build()) + .bucket(srcBucketName) + .object(srcObjectName) + .build()); + } + + /** + * 删除文件 + * + * @param bucketName 存储桶 + * @param objectName 文件名称 + */ + @SneakyThrows(Exception.class) + public void removeFile(String bucketName, String objectName) { + minioClient.removeObject( + RemoveObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .build()); + } + + /** + * 批量删除文件 + * + * @param bucketName 存储桶 + * @param keys 需要删除的文件列表 + * @return + */ + public void removeFiles(String bucketName, List keys) { + List objects = new LinkedList<>(); + keys.forEach(s -> { + objects.add(new DeleteObject(s)); + try { + removeFile(bucketName, s); + } catch (Exception e) { + log.error("[Minio工具类]>>>> 批量删除文件,异常:", e); + } + }); + } + + /** + * 获取文件外链 + * + * @param bucketName 存储桶 + * @param objectName 文件名 + * @param expires 过期时间 <=7 秒 (外链有效时间(单位:秒)) + * @return url + */ + @SneakyThrows(Exception.class) + public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) { + GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build(); + return minioClient.getPresignedObjectUrl(args); + } + + /** + * 获得文件外链 + * + * @param bucketName + * @param objectName + * @return url + */ + @SneakyThrows(Exception.class) + public String getPresignedObjectUrl(String bucketName, String objectName) { + GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() + .bucket(bucketName) + .object(objectName) + .method(Method.GET).build(); + return minioClient.getPresignedObjectUrl(args); + } + + /** + * 将URLDecoder编码转成UTF8 + * + * @param str + * @return + * @throws UnsupportedEncodingException + */ + public String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException { + String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25"); + return URLDecoder.decode(url, "UTF-8"); + } + + + /** + * @param file 文件 + * @param fileSuffixList 需要校验的文件列表 + * @return + */ + @SneakyThrows(Exception.class) + public String uploadFileValid(File file,List fileSuffixList) { + createBucket(bucketName); + + InputStream inputStream = new FileInputStream(file); + BufferedInputStream bufferedInputStream = IoUtil.toBuffered(inputStream); + + bufferedInputStream.mark(0); + String type = FileTypeUtil.getType(bufferedInputStream,file.getName()); + if (!fileSuffixList.contains(type)) { + bufferedInputStream.close(); + throw new GciBootException("上传失败,文件类型不在"+fileSuffixList.toString()+"中!"); + } + bufferedInputStream.reset(); + + String name = file.getName(); + int typeIndex = name.lastIndexOf("."); + String fileType = ""; + if(typeIndex>0) { + fileType = name.substring(typeIndex); + name = name.substring(0, typeIndex); + } + String s = RandomUtil.randomNumbers(10); + String afterBizPath = bizPath + StrUtil.SLASH + new DateTime().toString(DatePattern.NORM_MONTH_PATTERN); + String objectName = afterBizPath + "/" + name + "_" + s + fileType; + try { + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + //.contentType(type) + .stream(bufferedInputStream, bufferedInputStream.available(), -1) + .build()); + } catch (Exception e) { + e.printStackTrace(); + log.error("文件上传报错:{}",e.getMessage()); + if (e.getMessage().equals(noStorage)) { + throw new GciBootException("minio内存不足,无法上传!请联系管理员!"); + } else { + throw new GciBootException("minio上传出现未知异常,请联系管理员!"); + } + } finally { + bufferedInputStream.close(); + } + return getRelFileUrl() + bucketName + "/" + objectName; + } + + public void checkType(MultipartFile file,List fileSuffixList) { + boolean nopass = false; + try { + InputStream inputStream = file.getInputStream(); + BufferedInputStream bufferedInputStream = IoUtil.toBuffered(inputStream); + + bufferedInputStream.mark(0); + String type = FileTypeUtil.getType(bufferedInputStream,file.getName()); + if (!fileSuffixList.contains(type)) { + nopass = true; + } + bufferedInputStream.close(); + + } catch (Exception e) { + throw new GciBootException("文件上传失败!"); + } + if(nopass) { + throw new GciBootException("上传失败,文件类型不在"+fileSuffixList.toString()+"中!"); + } + } + + private String getRelFileUrl() { + String inFileUrl; + HttpServletRequest request = SpringContextUtil.getHttpServletRequest(); + String header = request.getHeader(CommonConstant.IS_INNER); + if (Convert.toBool(header,false)) { + inFileUrl = minioUrl; + } else { + inFileUrl = fileUrl; + } + return inFileUrl; + } +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/common/util/ParamsCheckUtil.java b/src/main/java/com/gci/boot/common/util/ParamsCheckUtil.java new file mode 100644 index 0000000..d500909 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/ParamsCheckUtil.java @@ -0,0 +1,282 @@ +package com.gci.boot.common.util; + +import com.gci.boot.exception.GciBootException; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +/** + * 参数校验工具 + */ +@Slf4j +public final class ParamsCheckUtil { + + public static void assertTrue(boolean expr, String msg) { + if (!expr) { + throw new GciBootException(msg); + } + } + + public static void assertNotNull(Object val, String msg) { + if (val == null) { + throw new GciBootException(msg); + } + } + + public static void assertNotBlank(Object val, String msg) { + if (val == null || val.toString().trim().length() == 0) { + throw new GciBootException(msg); + } + } + + public static void assertDateBefore(boolean condition, Date date, Date right, String msg) { + if (!condition) { + return; + } + if (date != null && right != null && date.after(right)) { + throw new GciBootException(msg); + } + } + + public static void assertDateAfter(boolean condition, Date date, Date left, String msg) { + if (!condition) { + return; + } + if (date != null && left != null && date.before(left)) { + throw new GciBootException(msg); + } + } + + public static void assertDateBefore(Date date, Date right, String msg) { + assertDateBefore(true, date, right, msg); + } + + public static void assertDateAfter(Date date, Date left, String msg) { + assertDateAfter(true, date, left, msg); + } + + public static ParamsAssert paramsAssert() { + return new ParamsAssert(); + } + + public static ParamsCheck paramsCheck() { + return new ParamsCheck(); + } + + + @AllArgsConstructor + @Data + private static class ValueCheck { + private Object val; + private String msg; + } + + @AllArgsConstructor + @Data + private static class DateCheck { + private Date date; + private Date leftDate; + private Date rightDate; + private String dateName; + private String leftDateName; + private String rightDateName; + private String message; + + } + + public static class ParamsAssert { + + private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + public ParamsAssert() { + } + + + public ParamsAssert datePattern(String pattern) { + this.dateFormat = new SimpleDateFormat(pattern); + return this; + } + + public ParamsAssert isTrue(boolean val, String msg) { + assertTrue(val, msg); + return this; + } + public ParamsAssert notNull(boolean condition, Object val, String msg) { + if (!condition) { + return this; + } + assertNotNull(val, msg); + return this; + } + + public ParamsAssert notBlank(boolean condition, Object val, String msg) { + if (!condition) { + return this; + } + assertNotBlank(val, msg); + return this; + } + + + public ParamsAssert dateBefore(boolean condition, Date date, Date rightDate, String dateName, String rightDateName) { + assertDateBefore(condition, date, rightDate, String.format("%s【%s】不能晚于%s【%s】", dateName, dateFormat.format(date), rightDateName, dateFormat.format(rightDate))); + return this; + } + + public ParamsAssert dateAfter(boolean condition, Date date, Date leftDate, String dateName, String leftDateName) { + assertDateAfter(condition, date, leftDate, String.format("%s【%s】不能早于%s【%s】", dateName, dateFormat.format(date), leftDateName, dateFormat.format(leftDate))); + return this; + } + + public ParamsAssert notNull(Object val, String msg) { + return notNull(true, val, msg); + } + + public ParamsAssert notBlank(Object val, String msg) { + return notBlank(true, val, msg); + } + + + public ParamsAssert dateBefore(Date date, Date rightDate, String dateName, String rightDateName) { + return dateBefore(true, date, rightDate, dateName, rightDateName); + } + + public ParamsAssert dateAfter(Date date, Date leftDate, String dateName, String leftDateName) { + return dateAfter(true, date, leftDate, dateName, leftDateName); + } + } + + public static class ParamsCheck { + private List nnVals; + private List nbVals; + private List dates; + + private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + public ParamsCheck() { + } + + private void notNullInit() { + nnVals = new ArrayList<>(); + } + + private void notBlankInit() { + nbVals = new ArrayList<>(); + } + + private void dateInit() { + dates = new ArrayList<>(); + } + + public ParamsCheck datePattern(String pattern) { + this.dateFormat = new SimpleDateFormat(pattern); + return this; + } + + public ParamsCheck notNull(boolean condition, Object val, String msg) { + if (!condition) { + return this; + } + if (nnVals == null) { + notNullInit(); + } + nnVals.add(new ValueCheck(val, msg)); + return this; + } + + public ParamsCheck notBlank(boolean condition, Object val, String msg) { + if (!condition) { + return this; + } + if (nbVals == null) { + notBlankInit(); + } + nbVals.add(new ValueCheck(val, msg)); + return this; + } + + + public ParamsCheck dateBefore(boolean condition, Date date, Date rightDate, String dateName, String rightDateName) { + if (!condition) { + return this; + } + if (dates == null) { + dateInit(); + } + dates.add(new DateCheck(date, null, rightDate, dateName, null, rightDateName, null)); + return this; + } + + public ParamsCheck dateAfter(boolean condition, Date date, Date leftDate, String dateName, String leftDateName) { + if (!condition) { + return this; + } + if (dates == null) { + dateInit(); + } + dates.add(new DateCheck(date, leftDate, null, dateName, leftDateName, null, null)); + return this; + } + + public ParamsCheck notNull(Object val, String nameOrMsg) { + return notNull(true, val, nameOrMsg); + } + + public ParamsCheck notBlank(Object val, String nameOrMsg) { + return notBlank(true, val, nameOrMsg); + } + + + public ParamsCheck dateBefore(Date date, Date rightDate, String dateName, String rightDateName) { + return dateBefore(true, date, rightDate, dateName, rightDateName); + } + + public ParamsCheck dateAfter(Date date, Date leftDate, String dateName, String leftDateName) { + return dateAfter(true, date, leftDate, dateName, leftDateName); + } + + private ParamsCheck doAssert() { + Optional.ofNullable(nnVals).ifPresent(vals -> { + vals.forEach(v -> { + assertNotBlank(v.getVal(), v.getMsg()); + }); + vals.clear(); + }); + Optional.ofNullable(nbVals).ifPresent(vals -> { + vals.forEach(v -> { + assertNotBlank(v.getVal(), v.getMsg()); + }); + vals.clear(); + }); + + Optional.ofNullable(dates).ifPresent(ds -> { + ds.forEach(d -> { + if (d.getDate()!=null && d.getRightDate() != null) { + assertDateBefore(d.getDate(), d.getRightDate(), String.format("【%s[%s]】不能晚于【%s[%s]】", d.getDateName(), dateFormat.format(d.getDate()), d.getRightDateName(), dateFormat.format(d.getRightDate()))); + } else if (d.getDate()!=null && d.getLeftDate() != null) { + assertDateAfter(d.getDate(), d.getLeftDate(), String.format("【%s[%s]】不能早于【%s[%s]】", d.getDateName(), dateFormat.format(d.getDate()), d.getLeftDateName(), dateFormat.format(d.getLeftDate()))); + } + }); + ds.clear(); + }); + return this; + } + + public String doCheck() { + try { + doAssert(); + } catch (GciBootException e) { + return e.getMessage(); + } + return null; + } + + } +} diff --git a/src/main/java/com/gci/boot/common/util/QueryWrapperUtil.java b/src/main/java/com/gci/boot/common/util/QueryWrapperUtil.java new file mode 100644 index 0000000..f71e71f --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/QueryWrapperUtil.java @@ -0,0 +1,566 @@ +package com.gci.boot.common.util; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.AnnotationUtils; + +import java.beans.Introspector; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.stream.IntStream; + +@Slf4j +public final class QueryWrapperUtil { + enum Operation{ + EQ, + NE, + GE, + LE, + GT, + LT, + LK, + LLK, + RLK, + IN, + NI, + NU, + NN; + } + + public static Builder builder(){ + return new Builder<>(); + } + + public static class Builder{ + + //<列名, 操作类型> + private Map opMap = new HashMap<>(); + //<列名, 替换名> + private Map columnReplace = new HashMap<>(); + //<排序列名, 替换名> + private Map orderColumnReplace = new HashMap<>(); + //<[列名,表名]> + private List orderColumns; + //<表名, 忽略的列> + private Map> ignoreColumns; + //排序 + private List orders; + //<表名, 别名> + private Map tableAlias; + //<字段名, 表名> + Map columnTableRelations; + //默认操作 + private Operation defaultOp = Operation.EQ; + + public Builder columnReplace(String column, String replace){ + columnReplace.put(StringUtils.camelToUnderline(column), replace); + return (Builder) this; + } + + public Builder columnReplace(SFunction func, String replace){ + columnReplace.put(getFieldName(func), replace); + return (Builder) this; + } + + public Builder orderColumnReplace(SFunction func, String replace){ + orderColumnReplace.put(getFieldName(func), replace); + return (Builder) this; + } + + public Builder orderColumnReplace(String column, String replace){ + orderColumnReplace.put(StringUtils.camelToUnderline(column), replace); + return (Builder) this; + } + + private Builder table(String tableName, String tableAlia){ + if(StringUtils.isBlank(tableName) || StringUtils.isBlank(tableAlia)){ + return (Builder) this; + } + if(this.tableAlias == null){ + tableAlias = new HashMap<>(); + } + tableAlias.put(StringUtils.camelToUnderline(tableName), tableAlia); + return (Builder) this; + } + + public Builder table(Class clazz, String tableAlia){ + if(clazz == null){ + return (Builder) this; + } + if(columnTableRelations == null){ + columnTableRelations = new HashMap<>(); + } + registerColumnTableRelations(clazz, columnTableRelations); + return table(getTableName(clazz), tableAlia); + } + + public Builder table(Class clazz){ + if(clazz == null){ + return (Builder) this; + } + if(columnTableRelations == null){ + columnTableRelations = new HashMap<>(); + } + registerColumnTableRelations(clazz, columnTableRelations); + return (Builder) this; + } + + private String getTableName(Class clazz){ + TableName tableAnno = AnnotationUtils.findAnnotation(clazz, TableName.class); + if(tableAnno != null){ + return tableAnno.value(); + }else{ + return StringUtils.camelToUnderline(clazz.getSimpleName()); + } + } + + private String getFuncTableName(SFunction func){ + Class funcClass = getFuncClass(func); + if(funcClass == null){ + return null; + } + return getTableName(funcClass); + } + + + public Builder ignoreColumn(Class clazz, String column){ + return ignoreColumn(getTableName(clazz), column); + } + + public Builder ignoreColumn(String tableName, String column){ + if(ignoreColumns == null){ + ignoreColumns = new HashMap<>(); + } + Set igCols = ignoreColumns.get(tableName); + if(igCols == null){ + igCols = new HashSet<>(); + ignoreColumns.put(tableName, igCols); + } + igCols.add(StringUtils.camelToUnderline(column)); + return (Builder) this; + } + + public Builder ignoreColumn(SFunction func){ + return ignoreColumn(getFuncClass(func), getFieldName(func)); + } + + public Builder eq(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.EQ); + return (Builder) this; + } + + public Builder ne(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.NE); + return (Builder) this; + } + public Builder ge(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.GE); + return (Builder) this; + } + public Builder le(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.LE); + return (Builder) this; + } + + public Builder gt(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.GT); + return (Builder) this; + } + public Builder lt(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.LT); + return (Builder) this; + } + public Builder like(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.LK); + return (Builder) this; + } + public Builder likeLeft(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.LLK); + return (Builder) this; + } + public Builder likeRight(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.RLK); + return (Builder) this; + } + public Builder in(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.IN); + return (Builder) this; + } + public Builder notIn(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.NI); + return (Builder) this; + } + public Builder isNull(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.NU); + return (Builder) this; + } + + public Builder isNotNull(String column){ + opMap.put(StringUtils.camelToUnderline(column), Operation.NN); + return (Builder) this; + } + + + //lambda表达式表示列 + public Builder eq(SFunction func){ + return eq(getFieldName(func)); + } + + public Builder ne(SFunction func){ + return ne(getFieldName(func)); + } + public Builder ge(SFunction func){ + return ge(getFieldName(func)); + } + public Builder le(SFunction func){ + return le(getFieldName(func)); + } + + public Builder gt(SFunction func){ + return gt(getFieldName(func)); + } + public Builder lt(SFunction func){ + return lt(getFieldName(func)); + } + public Builder like(SFunction func){ + return like(getFieldName(func)); + } + public Builder likeLeft(SFunction func){ + return likeLeft(getFieldName(func)); + } + public Builder likeRight(SFunction func){ + return likeRight(getFieldName(func)); + } + public Builder in(SFunction func){ + return in(getFieldName(func)); + } + public Builder notIn(SFunction func){ + return notIn(getFieldName(func)); + } + public Builder isNull(SFunction func){ + return isNull(getFieldName(func)); + } + + public Builder isNotNull(SFunction func){ + return isNotNull(getFieldName(func)); + } + + + public Builder orderColums(String columns){ + if(StringUtils.isBlank(columns)){ + return (Builder) this; + } + return orderColums(columns.split(",")); + } + + public Builder orders(String orders){ + if(StringUtils.isBlank(orders)){ + return (Builder) this; + } + return orders(orders.split(",")); + } + + public Builder orderColums(String[] columns){ + if(orderColumns == null){ + orderColumns = new ArrayList<>(); + } + Arrays.asList(columns).forEach(col->{ + orderColumns.add(new String[]{StringUtils.camelToUnderline(col), null}); + }); + return (Builder) this; + } + + public Builder orders(String[] orders){ + if(this.orders == null){ + this.orders = new ArrayList<>(); + } + this.orders.addAll(Arrays.asList(orders)); + return (Builder) this; + } + + public Builder orderByAsc(String tableName, String column){ + if(orderColumns == null){ + orderColumns = new ArrayList<>(); + } + + orderColumns.add(new String[]{StringUtils.camelToUnderline(column), tableName}); + + if(this.orders == null){ + this.orders = new ArrayList<>(); + } + this.orders.add("ASC"); + return (Builder) this; + } + + public Builder orderByAsc(String column){ + return orderByAsc(null, column); + } + + public Builder orderByAsc(SFunction func){ + String table = getFuncTableName(func); + String column = getFieldName(func); + return orderByAsc(table, column); + } + + public Builder orderByDesc(String column){ + return orderByDesc(null, column); + } + public Builder orderByDesc(SFunction func){ + String table = getFuncTableName(func); + String column = getFieldName(func); + return orderByDesc(table, column); + } + + public Builder orderByDesc(String tableName, String column){ + if(orderColumns == null){ + orderColumns = new ArrayList<>(); + } + + orderColumns.add(new String[]{StringUtils.camelToUnderline(column), tableName}); + + if(this.orders == null){ + this.orders = new ArrayList<>(); + } + this.orders.add("DESC"); + return (Builder) this; + } + + public QueryWrapper buildFromObject(Object... objects){ + return buildFromObject(null, objects); + } + + public QueryWrapper buildFromObject(QueryWrapper wrapper, Object... objects){ + if(wrapper == null){ + wrapper = new QueryWrapper(); + } + if(objects == null || objects.length == 0){ + return wrapper; + } + Class[] entityClasses = new Class[objects.length]; + try { + for(int i=0; i < objects.length; i++) { + Object entity = objects[i]; + entityClasses[i] = entity.getClass(); + List fields = ClassReflectionUtil.getAllFields(entity.getClass()); + String tableName = getTableName(entity.getClass()); + for (Field f : fields) { + //跳过常量和静态变量 + if (Modifier.isFinal(f.getModifiers()) || Modifier.isStatic(f.getModifiers())) { + continue; + } + String k = f.getName(); + String colName = StringUtils.camelToUnderline(k); + //跳过忽略字段 + if(ignoreColumns != null) { + Set igCols = ignoreColumns.get(tableName); + if (igCols != null && igCols.contains(colName)) { + continue; + } + } + //处理别名 + String columnName = useAliaIfExists(colName, tableName); + //获取值 + boolean accessible = f.isAccessible(); + f.setAccessible(true); + Object v = f.get(entity); + f.setAccessible(accessible); + //设置wrapper + setWrapper(wrapper, columnName, v, opMap.getOrDefault(colName, defaultOp)); + } + } + setWrapperOrder(wrapper, orderColumns, orders, columnTableRelations); + return wrapper; + } catch (Exception e) { + log.error("", e); + return wrapper; + } + } + + public QueryWrapper buildFromMap( Map map){ + return buildFromMap(null, map); + } + + public QueryWrapper buildFromMap(QueryWrapper wrapper, Map map){ + if(wrapper == null){ + wrapper = new QueryWrapper(); + } + if(map == null || map.size() == 0){ + return wrapper; + } + + try { + Set keys = map.keySet(); + for (String k : keys) { + String colName = StringUtils.camelToUnderline(k); + String tableName = columnTableRelations.get(colName); + //跳过忽略字段 + if(ignoreColumns != null) { + Set igCols = ignoreColumns.get(tableName); + if (igCols != null && igCols.contains(colName)) { + continue; + } + } + //处理别名 + String columnName = useAliaIfExists(colName, tableName); + //获取值 + Object v = map.get(k); + //设置wrapper + setWrapper(wrapper, columnName, v, opMap.getOrDefault(colName, defaultOp)); + } + setWrapperOrder(wrapper, orderColumns, orders, columnTableRelations); + return wrapper; + } catch (Exception e) { + log.error("", e); + return wrapper; + } + } + + private Map registerColumnTableRelations( Class cls, Map columnTableRelations){ + if(columnTableRelations == null){ + columnTableRelations = new HashMap<>(); + } + List fields = ClassReflectionUtil.getAllFields(cls); + String tableName = getTableName(cls); + for(Field f : fields){ + String col = StringUtils.camelToUnderline(f.getName()); + if(!columnTableRelations.containsKey(col)){ + columnTableRelations.put(col, tableName); + } + } + return columnTableRelations; + } + + /** + * 如果设置了列名替换,直接使用替换的列 + * 如果没有设置列名替换,添加表别名 + */ + private String useAliaIfExists(String colName, String tableName){ + String columnName = columnReplace.get(colName); + if (columnName == null) { + String tableAlia = null; + if(tableAlias != null) { + tableAlia = tableAlias.get(tableName); + } + if (tableAlia != null) { + columnName = tableAlia + "." + colName; + } else { + columnName = colName; + } + } + return columnName; + } + + //设置查询条件 + private void setWrapper(QueryWrapper wrapper, String columnName, Object v, Operation op){ + columnName = StringUtils.camelToUnderline(columnName); + if(v == null){ + if(Operation.NU.equals(op)){ + wrapper.isNull(columnName); + }else if(Operation.NN.equals(op)){ + wrapper.isNotNull(columnName); + } + return; + } + + if(Operation.EQ.equals(op)){ + wrapper.eq(columnName, v); + }else if(Operation.NE.equals(op)){ + wrapper.ne(columnName, v); + }else if(Operation.GE.equals(op)){ + wrapper.ge(columnName, v); + }else if(Operation.LE.equals(op)){ + wrapper.le(columnName, v); + }else if(Operation.GT.equals(op)){ + wrapper.gt(columnName, v); + }else if(Operation.LT.equals(op)){ + wrapper.lt(columnName, v); + }else if(Operation.LK.equals(op)){ + wrapper.like(columnName, v); + }else if(Operation.LLK.equals(op)){ + wrapper.likeLeft(columnName, v); + }else if(Operation.RLK.equals(op)){ + wrapper.likeRight(columnName, v); + }else if(Operation.IN.equals(op)){ + wrapper.in(columnName, v); + }else if(Operation.NI.equals(op)){ + wrapper.notIn(columnName, v); + }else if(Operation.NU.equals(op)){ + wrapper.isNull(columnName); + }else if(Operation.NN.equals(op)){ + wrapper.isNotNull(columnName); + } + } + + //设置排序 + private void setWrapperOrder(QueryWrapper wrapper, List columns, List orders, Map columnTableRelations){ + if(columns == null || columns.size() == 0){ + return; + } + IntStream.range(0, columns.size()).forEach(i->{ + String[] colAndTable = columns.get(i); + if(colAndTable[1] == null && columnTableRelations != null){ + colAndTable[1] = columnTableRelations.get(colAndTable[0]); + } + String c = useAliaIfExists(colAndTable[0], colAndTable[1]); + if(orders == null||orders.size() <= i){ + wrapper.orderByAsc(c); + }else{ + if("ASC".equalsIgnoreCase(orders.get(i))){ + wrapper.orderByAsc(c); + }else{ + wrapper.orderByDesc(c); + } + } + }); + } + } + + //根据lambda表达式获取字段名 + public static String getFieldName(SFunction func){ + try { + Method method = func.getClass().getDeclaredMethod("writeReplace"); + method.setAccessible(true); + SerializedLambda serializedLambda = (SerializedLambda) method.invoke(func); + String getterMethodName = serializedLambda.getImplMethodName(); + String fieldName = Introspector.decapitalize(getterMethodName.replace("get", "")); + return fieldName; + } catch (Exception e) { + return null; + } + } + + //根据lambda表达式获取列名 + public static String getColumnName(SFunction func){ + String fieldName = getFieldName(func); + if(fieldName != null){ + return StringUtils.camelToUnderline(fieldName); + } + return null; + } + + /** + * 根据lambda表达式获取类 + * @param func + * @return + * @param + */ + public static Class getFuncClass(SFunction func){ + try { + Method method = func.getClass().getDeclaredMethod("writeReplace"); + boolean accessible = method.isAccessible(); + method.setAccessible(true); + SerializedLambda serializedLambda = (SerializedLambda) method.invoke(func); + method.setAccessible(accessible); + String className = serializedLambda.getImplClass().replace("/", "."); + return Class.forName(className); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/com/gci/boot/common/util/RedisKey.java b/src/main/java/com/gci/boot/common/util/RedisKey.java new file mode 100644 index 0000000..2907ebb --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/RedisKey.java @@ -0,0 +1,22 @@ +package com.gci.boot.common.util; + +public class RedisKey { + + /** + * 围栏告警、超速告警实体对象推业务平台 + */ + public static final String FENCE_SPEED_ALARM_BEAN = "FENCE_SPEED_ALARM"; + + /** + * 围栏生成的车辆告警记录得分 + */ + public static final String FENCE_VEHICLE_SCORE = "fence:vehicle:score"; + /** + * 车机异常的 是否有异常 + */ + public static final String VEHICLE_IS_FAULT_ALARM = "vehicle:is:alarm:"; + /** + * 该项目轨迹回放和作业采用什么数据 true为32960 false为808 默认无数据也为808 + */ + public static final String PROJECT_GIS_SOURCE = "project:gisSource:"; +} diff --git a/src/main/java/com/gci/boot/common/util/RedisUtil.java b/src/main/java/com/gci/boot/common/util/RedisUtil.java new file mode 100644 index 0000000..a97fa49 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/RedisUtil.java @@ -0,0 +1,640 @@ +package com.gci.boot.common.util; + +import org.springframework.context.SmartLifecycle; +import org.springframework.data.redis.core.*; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +public final class RedisUtil implements SmartLifecycle{ + + private static RedisTemplate redisTemplate; + + // bean初始化完毕后,会按getPhase()方法返回值从小到大依次执行 + // 实现SmartLifecycle的bean的start方法 + @Override + public void start() { + redisTemplate = SpringContextUtil.getBean("redisTemplate", RedisTemplate.class); + } + + /* + * 默认实现是Integer.MAX_VALUE + * WebServerStartStopLifecycle的phase为Integer.MAX_VALUE-1 这里取0,在webserver启动前执行start() + */ + @Override + public int getPhase() { + return 0; + } + + @Override + public void stop() { + + } + @Override + public boolean isRunning() { + return false; + } + + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public static boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public static long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public static boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public static void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 删除缓存 + * + * @param list 传多个 + */ + @SuppressWarnings("unchecked") + public static void multiDel(Collection list) { + redisTemplate.delete(list); + } + + // ============================String============================= + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public static Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + public static List multiGet(Collection list) { + return redisTemplate.opsForValue().multiGet(list); + } + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public static Set getScan(String key) { +//批量查询需要统计的数据 + return redisTemplate.execute((RedisCallback>) connection -> { + Set keysTmp = new HashSet<>(); + + Cursor cursor = connection + .scan( + ScanOptions.scanOptions() + .match(key) + //count参数在翻译的中文文档中说是返回的数量,但实际应该是每次遍历的哈希槽数量 + .count(10000L) + .build()); + + while (cursor.hasNext()) { + keysTmp.add(new String(cursor.next())); + } + + return keysTmp; + }); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public static boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public static boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 批量放入普通缓存 + * @param map 多个键值 + * @return 是否成功 + */ + public static boolean multiSet(Map map) { + try { + redisTemplate.opsForValue().multiSet(map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * + * @param key 键 + * @param delta 要增加几(大于0) + * @return + */ + public static long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public static long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + // ================================Map================================= + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public static Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public static Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public static boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public static boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public static boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public static boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public static void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public static boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public static double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public static double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public static Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public static boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public static long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) { + expire(key, time); + } + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public static long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public static long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public static List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public static long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public static Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public static boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public static boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public static boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public static boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public static long lRemove(String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } +} diff --git a/src/main/java/com/gci/boot/common/util/SpringContextUtil.java b/src/main/java/com/gci/boot/common/util/SpringContextUtil.java new file mode 100644 index 0000000..95da6a7 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/SpringContextUtil.java @@ -0,0 +1,94 @@ +package com.gci.boot.common.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; + +/** + * spring上下文工具 + * + * @author chenzw + * @date 2023/8/14 + */ +public final class SpringContextUtil { + + private static ApplicationContext applicationContext; + + /** + * 初始化,注入ApplicationContext对象 + */ + public static class Initializer implements ApplicationContextAware { + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextUtil.applicationContext = applicationContext; + } + + } + + // 获取applicationContext + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + // 通过name获取 Bean. + public static Object getBean(String name) { + return getApplicationContext().getBean(name); + + } + + // 通过name获取 Bean. + public static Object getBean(String name, Object... params) { + return getApplicationContext().getBean(name, params); + } + + // 通过class获取Bean. + public static T getBean(Class clazz) { + return getApplicationContext().getBean(clazz); + } + + // 通过name,以及Clazz返回指定的Bean + public static T getBean(String name, Class clazz) { + return getApplicationContext().getBean(name, clazz); + } + + // 判断bean是否是prototype. + public static boolean isPrototype(String name) { + return getApplicationContext().isPrototype(name); + } + + public static Class getType(String name) { + return getApplicationContext().getType(name); + } + + public static String[] getBeanNamesForType(Class c) { + return getApplicationContext().getBeanNamesForType(c); + } + + + /** + * 获取HttpServletRequest + */ + public static HttpServletRequest getHttpServletRequest() { + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if(requestAttributes != null) { + return requestAttributes.getRequest(); + } + return null; + } + + public static String getDomain(){ + HttpServletRequest request = getHttpServletRequest(); + StringBuffer url = request.getRequestURL(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString(); + } + + public static String getOrigin(){ + HttpServletRequest request = getHttpServletRequest(); + return request.getHeader("Origin"); + } +} diff --git a/src/main/java/com/gci/boot/common/util/SpringEnvironmentUtil.java b/src/main/java/com/gci/boot/common/util/SpringEnvironmentUtil.java new file mode 100644 index 0000000..4436096 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/SpringEnvironmentUtil.java @@ -0,0 +1,37 @@ +package com.gci.boot.common.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; + +/** + * spring上下文工具 + * + * @author chenzw + * @date 2023/8/14 + */ +public final class SpringEnvironmentUtil { + + private static Environment environment; + + /** + * 初始化,注入ApplicationContext对象 + */ + public static class Initializer implements EnvironmentAware { + + @Override + public void setEnvironment(Environment environment) { + SpringEnvironmentUtil.environment = environment; + } + } + + public String getProperty(String propName){ + return environment.getProperty(propName); + } +} diff --git a/src/main/java/com/gci/boot/common/util/SqlInjectionCheckUtil.java b/src/main/java/com/gci/boot/common/util/SqlInjectionCheckUtil.java new file mode 100644 index 0000000..710c0a0 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/SqlInjectionCheckUtil.java @@ -0,0 +1,32 @@ +package com.gci.boot.common.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * sql注入检查 + * @author chenzw + * @date 2022/3/30 + */ +public final class SqlInjectionCheckUtil { + + private static Pattern pattern = Pattern.compile( + "\\b(and|exec|insert|select|drop|grant|alter|delete|update|count|chr|mid|master|truncate|char|declare|or)\\b|(;|\\+|'|%)"); + public static boolean containsSqlInjection(Object obj) { + if(obj == null){ + return false; + } + Matcher matcher = pattern.matcher(obj.toString().toLowerCase()); + return matcher.find(); + } + + public static boolean containsSqlInjection(String... sql){ + for(String s : sql){ + if(containsSqlInjection(s)){ + return true; + } + } + return false; + } + +} diff --git a/src/main/java/com/gci/boot/common/util/StringUtil.java b/src/main/java/com/gci/boot/common/util/StringUtil.java new file mode 100644 index 0000000..fd250f2 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/StringUtil.java @@ -0,0 +1,74 @@ +package com.gci.boot.common.util; + +import cn.hutool.core.util.StrUtil; +import com.gci.boot.constant.CommonConstant; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; + +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Slf4j +public class StringUtil { + + public static String checkString(String arg, Integer length) { + if(StrUtil.isBlank(arg)){ + return "不能为空!"; + } + String temp = arg.replace(" ",""); + if(StrUtil.isBlank(temp)){ + return "不能为空!"; + } + if(StrUtil.isNotBlank(arg)){ + Pattern p = Pattern.compile(CommonConstant.SPECIAL_CHAR); + Matcher m = p.matcher(arg); + if (m.find()) { + StringBuilder specialCharacters = new StringBuilder(); + do { + specialCharacters.append(m.group()); + } while (m.find()); + return "输入的字符串: "+ arg +" 包含特殊字符:" + specialCharacters.toString()+ " ,请修改!"; + } + if(length != 0){ + if(arg.length() > length){ + return "长度不能超过" + length + "字符!"; + } + } + } + return null; + } + + public static String checkString2(String arg, Integer length) { + if(Objects.nonNull(arg) && arg.length() > 0){ + boolean isAllSpaces = true; + for (int i = 0; i < arg.length(); i++) { + if (!Character.isWhitespace(arg.charAt(i))) { + isAllSpaces = false; + break; + } + } + if(isAllSpaces){ + return "不能全为空格!"; + } + } + + if(StrUtil.isNotBlank(arg)){ + Pattern p = Pattern.compile(CommonConstant.SPECIAL_CHAR); + Matcher m = p.matcher(arg); + if (m.find()) { + StringBuilder specialCharacters = new StringBuilder(); + do { + specialCharacters.append(m.group()); + } while (m.find()); + return "输入的字符串: "+ arg +" 包含特殊字符:" + specialCharacters.toString()+ " ,请修改!"; + } + if(length != 0){ + if(arg.length() > length){ + return "长度不能超过" + length + "字符!"; + } + } + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/common/util/ValidateUtil.java b/src/main/java/com/gci/boot/common/util/ValidateUtil.java new file mode 100644 index 0000000..f02b364 --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/ValidateUtil.java @@ -0,0 +1,22 @@ +package com.gci.boot.common.util; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author 24642 + */ +public class ValidateUtil { + public static String valid(T t,Class ...groups) { + ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); + Validator validator = validatorFactory.getValidator(); + Set> validate = validator.validate(t, groups); + + return validate.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(" ")); + } +} diff --git a/src/main/java/com/gci/boot/common/util/ValidatorUtil.java b/src/main/java/com/gci/boot/common/util/ValidatorUtil.java new file mode 100644 index 0000000..864f5db --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/ValidatorUtil.java @@ -0,0 +1,420 @@ +package com.gci.boot.common.util; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.gci.boot.constant.CommonConstant; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.lang.annotation.*; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Slf4j +public class ValidatorUtil { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface NotEmpty { + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface PhoneNumber { + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface IDCard { + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface DateValue { + String format() default "yyyy-MM-dd"; + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface NotEmptyByField { + String field() default ""; + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface NumericValue { + double minValue() default Double.MIN_VALUE; + double maxValue() default Double.MAX_VALUE; + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface NumericValueWithOutEqual { + double minValue() default Double.MIN_VALUE; + double maxValue() default Double.MAX_VALUE; + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface IntValue { + double minValue() default Double.MIN_VALUE; + double maxValue() default Double.MAX_VALUE; + String message() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface StrMaxLength { + int strMaxLength() default 0; + String message() default ""; + String fieldNameCN() default ""; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface CollectionStr { + String collectionStr() default ""; + String message() default ""; + } + + public static class ValidationError { + private String fieldName; + private String message; + + public ValidationError(String fieldName, String message) { + this.fieldName = fieldName; + this.message = message; + } + + public String getFieldName() { + return fieldName; + } + + public String getMessage() { + return message; + } + } + + public static List validate(T entity) { + List errors = new ArrayList<>(); + Class clazz = entity.getClass(); + Field[] fields = clazz.getDeclaredFields(); + + for (Field field : fields) { + field.setAccessible(true); + + try { + Object value = field.get(entity); + String fieldName = field.getName(); + + if (field.isAnnotationPresent(NotEmpty.class)) { + NotEmpty annotation = field.getAnnotation(NotEmpty.class); + String message = annotation.message(); + if (isEmpty(value)) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "字段不能为空" : message)); + } + } + if (field.isAnnotationPresent(StrMaxLength.class)) { + StrMaxLength annotation = field.getAnnotation(StrMaxLength.class); + int strLength = annotation.strMaxLength(); + String message = annotation.message(); + String fieldNameCN = annotation.fieldNameCN(); + if (!isEmpty(value)) { + //补充一个非法字符的校验 + Pattern p = Pattern.compile(CommonConstant.SPECIAL_CHAR); + Matcher m = p.matcher(value.toString()); + if (m.find()) { + StringBuilder specialCharacters = new StringBuilder(); + do { + specialCharacters.append(m.group()); + } while (m.find()); + errors.add(new ValidationError(fieldName, fieldNameCN + "包含特殊字符:" + specialCharacters.toString())); + } + + if(value.toString().length() > strLength){ + errors.add(new ValidationError(fieldName, message.isEmpty() ? "字段长度不能超过" + strLength : message)); + } + } + } + + if (field.isAnnotationPresent(PhoneNumber.class)) { + PhoneNumber annotation = field.getAnnotation(PhoneNumber.class); + String message = annotation.message(); + if (!isEmpty(value) && !isPhoneNumber(value.toString())) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "手机号格式错误" : message)); + } + } + + if (field.isAnnotationPresent(DateValue.class)) { + DateValue annotation = field.getAnnotation(DateValue.class); + String format = annotation.format(); + String message = annotation.message(); + if (!isEmpty(value) && !isValidDate(value.toString(), format)) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "日期格式错误,应为" + format : message)); + } + } + + if (field.isAnnotationPresent(NumericValue.class)) { + NumericValue annotation = field.getAnnotation(NumericValue.class); + double minValue = annotation.minValue(); + double maxValue = annotation.maxValue(); + String message = annotation.message(); + if (!isEmpty(value) && !isNumeric(value.toString())) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "数值格式错误" : message)); + }else{ + if (!isEmpty(value) && !isInRange(value.toString(), minValue, maxValue)) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "数值超出范围,应在" + minValue + "和" + maxValue + "之间" : message)); + } + } + } + + if (field.isAnnotationPresent(NumericValueWithOutEqual.class)) { + NumericValueWithOutEqual annotation = field.getAnnotation(NumericValueWithOutEqual.class); + double minValue = annotation.minValue(); + double maxValue = annotation.maxValue(); + String message = annotation.message(); + if (!isEmpty(value) && !isNumeric(value.toString())) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "数值格式错误" : message)); + }else{ + if (!isEmpty(value) && !isInRangeWithOutEqual(value.toString(), minValue, maxValue)) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "数值超出范围,应在" + minValue + "和" + maxValue + "之间" : message)); + } + } + } + + if (field.isAnnotationPresent(IntValue.class)) { + IntValue annotation = field.getAnnotation(IntValue.class); + double minValue = annotation.minValue(); + double maxValue = annotation.maxValue(); + String message = annotation.message(); + if (!isEmpty(value) && !isInt(value.toString())) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "数值格式错误" : message)); + }else{ + if (!isEmpty(value) && !isInRange(value.toString(), minValue, maxValue)) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "数值超出范围,应在" + minValue + "和" + maxValue + "之间" : message)); + } + } + } + + if (field.isAnnotationPresent(CollectionStr.class)) { + CollectionStr annotation = field.getAnnotation(CollectionStr.class); + String message = annotation.message(); + String collectionStr = annotation.collectionStr(); + if (!isEmpty(value)) { + if(StrUtil.isNotBlank(collectionStr)){ + List list = Arrays.asList(collectionStr.toString().split(",")); + if(CollectionUtil.isNotEmpty(list) && !list.contains(value)){ + errors.add(new ValidationError(fieldName, message.isEmpty() ? "字段值应该为" + list : message)); + } + } + } + } + + if (field.isAnnotationPresent(IDCard.class)) { + IDCard annotation = field.getAnnotation(IDCard.class); + String message = annotation.message(); + if (!isEmpty(value) && !isIDCardNumber(value.toString())) { + errors.add(new ValidationError(fieldName, message.isEmpty() ? "身份证号码格式错误" : message)); + } + } + + if (field.isAnnotationPresent(NotEmptyByField.class)) { + NotEmptyByField annotation = field.getAnnotation(NotEmptyByField.class); + String message = annotation.message(); + String byFieldName = annotation.field(); + Field byField = Arrays.stream(fields).filter(f->{ + return f.getName().equals(byFieldName); + }).findFirst().orElse(null); + Object byFieldValue = Objects.isNull(byField)?"":byField.get(entity); + if(Objects.equals(byFieldValue,"是")&&isEmpty(value)){ + errors.add(new ValidationError(fieldName, message.isEmpty() ? "字段不能为空" : message)); + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + errors.add(new ValidationError("数据行", "数据行校验异常:" +e.getMessage())); + } + } + + return errors; + } + + private static boolean isEmpty(Object value) { + return value == null || value.toString().isEmpty(); + } + + private static boolean isPhoneNumber(String value) { + return value.matches("^1[3456789]\\d{9}$"); + } + + private static boolean isIDCardNumber(String value) { + return value.matches("^((\\d{17}[0-9Xx])|(\\d{15}))$"); + } + + private static boolean isValidDate(String value, String format) { + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + try { + Date date = dateFormat.parse(value); + return value.equals(dateFormat.format(date)); + } catch (ParseException e) { + return false; + } + } + + private static boolean isNumeric(String value) { + return value.matches("-?\\d+(\\.\\d+)?"); + } + + private static boolean isInt(String value) { + try { + int intValue = Integer.parseInt(value); + return (intValue >= Integer.MIN_VALUE && intValue <= Integer.MAX_VALUE); + } catch (NumberFormatException e) { + return false; + } + } + private static boolean isInRange(String value, double minValue, double maxValue) { + try { + double num = Double.parseDouble(value); + return num >= minValue && num <= maxValue; + } catch (NumberFormatException e) { + return false; + } + } + + private static boolean isInRangeWithOutEqual(String value, double minValue, double maxValue) { + try { + double num = Double.parseDouble(value); + return num > minValue && num < maxValue; + } catch (NumberFormatException e) { + return false; + } + } + + public static Map> findDuplicates(List list, String... fields) { + Map> duplicatesMap = new HashMap<>(); + for (int i = 0; i < list.size(); i++) { + T current = list.get(i); + StringBuilder keyBuilder = new StringBuilder(); + for (String field : fields) { + try { + keyBuilder.append(current.getClass().getMethod("get" + capitalize(field)).invoke(current)); + } catch (Exception e) { + e.printStackTrace(); + } + } + String key = keyBuilder.toString(); + if (duplicatesMap.containsKey(key)) { + duplicatesMap.get(key).add(i + 1); + } else { + List indexList = new ArrayList<>(); + indexList.add(i + 1); + duplicatesMap.put(key, indexList); + } + } + //删除不重复的记录 + List keysToRemove = new ArrayList<>(); + for (Map.Entry> entry : duplicatesMap.entrySet()) { + if (entry.getValue().size() == 1) { + keysToRemove.add(entry.getKey()); + } + } + for (String key : keysToRemove) { + duplicatesMap.remove(key); + } + return duplicatesMap; + } + private static String capitalize(String str) { + if (str == null || str.isEmpty()) { + return str; + } + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + + public static void deleteFile(String filePath) { + try { + Path path = Paths.get(filePath); + Files.deleteIfExists(path); + log.info("文件删除成功: {}",filePath); + } catch (IOException e) { + e.printStackTrace(); + log.info("文件删除失败: {}",filePath); + } + } + + public static void trimStringFields(Object obj) { + Class clazz = obj.getClass(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + try { + field.setAccessible(true); + Object value = field.get(obj); + if (value instanceof String) { + String strValue = (String) value; + if (StrUtil.isNotBlank(strValue)) { + field.set(obj, strValue.trim()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static boolean allFieldsAreNullInList(List list) { + for (T obj : list) { + if (!allFieldsAreNull(obj)) { + // 只要有一个对象的字段不为null,就返回false + return false; + } + } + // 如果所有对象的字段都为null,返回true + return true; + } + //判断对象全部字段是否为null + private static boolean allFieldsAreNull(Object obj) { + Class clazz = obj.getClass(); + Field[] fields = clazz.getDeclaredFields(); + + for (Field field : fields) { + field.setAccessible(true); + try { + if (field.get(obj) != null) { + // 只要有一个字段不为null,就返回false + return false; + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + // 如果所有字段都为null,返回true + return true; + } + // 校验文件是否为Excel格式 + public static boolean isExcelFile(MultipartFile file) { + try { + Workbook workbook = WorkbookFactory.create(file.getInputStream()); + return true; + } catch (Exception e) { + return false; + } + } +} diff --git a/src/main/java/com/gci/boot/common/util/ZipUtil.java b/src/main/java/com/gci/boot/common/util/ZipUtil.java new file mode 100644 index 0000000..21e6c6f --- /dev/null +++ b/src/main/java/com/gci/boot/common/util/ZipUtil.java @@ -0,0 +1,50 @@ +package com.gci.boot.common.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import lombok.extern.slf4j.Slf4j; + +/** + * 生成压缩包 + * @author admin + * + */ +@Slf4j +public class ZipUtil { + + /** * 解压缩ZIP文件 * @param zipFile ZIP文件 * @param destDir 目标路径 */ + public static void unzip(InputStream zipFile, String dest) { + File destDir = new File(dest); + byte[] buffer = new byte[1024]; + try (ZipInputStream zis = new ZipInputStream(zipFile,Charset.forName("GBK"))) { + ZipEntry entry = zis.getNextEntry(); + while (entry != null) { + File file = new File(destDir, entry.getName()); + if (entry.isDirectory()) { + file.mkdirs(); + } else { + File parent = file.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + try (FileOutputStream fos = new FileOutputStream(file)) { + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + } + } + entry = zis.getNextEntry(); + } + } catch (IOException e) { + log.error("解压文件出错", e); + } + } + +} diff --git a/src/main/java/com/gci/boot/common/validated/ImportValidated.java b/src/main/java/com/gci/boot/common/validated/ImportValidated.java new file mode 100644 index 0000000..c0edef5 --- /dev/null +++ b/src/main/java/com/gci/boot/common/validated/ImportValidated.java @@ -0,0 +1,7 @@ +package com.gci.boot.common.validated; + +/** + * 导入校验分组无实际作用 + */ +public interface ImportValidated { +} diff --git a/src/main/java/com/gci/boot/common/validated/SaveValidated.java b/src/main/java/com/gci/boot/common/validated/SaveValidated.java new file mode 100644 index 0000000..5c36bf1 --- /dev/null +++ b/src/main/java/com/gci/boot/common/validated/SaveValidated.java @@ -0,0 +1,8 @@ +package com.gci.boot.common.validated; + +/** + * 无实际作用,仅提供给校验分组 + * @author 24642 + */ +public interface SaveValidated { +} diff --git a/src/main/java/com/gci/boot/common/validated/UpdateValidated.java b/src/main/java/com/gci/boot/common/validated/UpdateValidated.java new file mode 100644 index 0000000..f398c50 --- /dev/null +++ b/src/main/java/com/gci/boot/common/validated/UpdateValidated.java @@ -0,0 +1,7 @@ +package com.gci.boot.common.validated; +/** + * 无实际作用,仅提供给校验分组 + * @author 24642 + */ +public interface UpdateValidated { +} diff --git a/src/main/java/com/gci/boot/common/vo/Result.java b/src/main/java/com/gci/boot/common/vo/Result.java new file mode 100644 index 0000000..ded189e --- /dev/null +++ b/src/main/java/com/gci/boot/common/vo/Result.java @@ -0,0 +1,120 @@ +package com.gci.boot.common.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.http.HttpStatus; + +import java.io.Serializable; + +/** + * 接口返回数据格式 + * + * @author scott + * @email jeecgos@163.com + * @date 2019年1月19日 + */ +@Data +@ApiModel(value = "接口返回对象", description = "接口返回对象") +public class Result implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 成功标志 + */ + @ApiModelProperty(value = "成功标志") + private boolean success = true; + + /** + * 返回处理消息 + */ + @ApiModelProperty(value = "返回处理消息") + private String message = "操作成功!"; + + /** + * 返回代码 + */ + @ApiModelProperty(value = "返回代码") + private Integer code = 0; + + /** + * 返回数据对象 data + */ + @ApiModelProperty(value = "返回数据对象") + private T result; + + /** + * 时间戳 + */ + @ApiModelProperty(value = "时间戳") + private long timestamp = System.currentTimeMillis(); + + public Result() { + + } + + public Result success(String message) { + this.message = message; + this.code = HttpStatus.OK.value(); + this.success = true; + return this; + } + + public static Result ok() { + Result r = new Result<>(); + r.setSuccess(true); + r.setCode(HttpStatus.OK.value()); + r.setMessage("成功"); + return r; + } + + public static Result ok(String msg) { + Result r = new Result<>(); + r.setSuccess(true); + r.setCode(HttpStatus.OK.value()); + r.setMessage(msg); + return r; + } + + public static Result ok(T data) { + Result r = new Result<>(); + r.setSuccess(true); + r.setCode(HttpStatus.OK.value()); + r.setResult(data); + return r; + } + + public static Result error(String msg) { + return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg); + } + + public static Result error(int code, String msg) { + Result r = new Result<>(); + r.setCode(code); + r.setMessage(msg); + r.setSuccess(false); + return r; + } + + public Result error500(String message) { + this.message = message; + this.code = HttpStatus.INTERNAL_SERVER_ERROR.value(); + this.success = false; + return this; + } + + /** + * 无权限访问返回结果 + */ + public static Result noauth(String msg) { + return error(HttpStatus.NON_AUTHORITATIVE_INFORMATION.value(), msg); + } + + /** + * 无权限访问返回结果 + */ + public static Result unauthorized(String msg) { + return error(HttpStatus.UNAUTHORIZED.value(), msg); + } +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/config/MinioConfig.java b/src/main/java/com/gci/boot/config/MinioConfig.java new file mode 100644 index 0000000..4c7b6e2 --- /dev/null +++ b/src/main/java/com/gci/boot/config/MinioConfig.java @@ -0,0 +1,25 @@ +package com.gci.boot.config; + +import io.minio.MinioClient; +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +public class MinioConfig { + @Value("${minio.minioUrl}") + private String minioUrl; + @Value("${minio.minioName}") + private String minioName; + @Value("${minio.minioPass}") + private String minioPass; + + @Bean + public MinioClient getMinioClient() { + return MinioClient.builder() + .endpoint(minioUrl) + .credentials(minioName,minioPass).build(); + } +} diff --git a/src/main/java/com/gci/boot/config/MyBatisPlusConfig.java b/src/main/java/com/gci/boot/config/MyBatisPlusConfig.java new file mode 100644 index 0000000..9ba7922 --- /dev/null +++ b/src/main/java/com/gci/boot/config/MyBatisPlusConfig.java @@ -0,0 +1,32 @@ +package com.gci.boot.config; + +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; +import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize; +import com.gci.boot.interceptor.MybatisInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@MapperScan(value = { "com.gci.boot.modules.**.mapper*" }) +@Configuration +public class MyBatisPlusConfig { + /** + * 分页拦截器 + */ + @Bean + public PaginationInterceptor paginationInterceptor() { + PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); + // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false + // paginationInterceptor.setOverflow(false); + // 设置最大单页限制数量,默认 500 条,-1 不受限制 + // paginationInterceptor.setLimit(500); + // 开启 count 的 join 优化,只针对部分 left join + paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); + return paginationInterceptor; + } + + @Bean + public MybatisInterceptor mybatisInterceptor(){ + return new MybatisInterceptor(); + } +} diff --git a/src/main/java/com/gci/boot/config/RedisConfig.java b/src/main/java/com/gci/boot/config/RedisConfig.java new file mode 100644 index 0000000..25fcc37 --- /dev/null +++ b/src/main/java/com/gci/boot/config/RedisConfig.java @@ -0,0 +1,105 @@ +package com.gci.boot.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gci.boot.properties.GciRedisCacheProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.*; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +@EnableCaching +@Configuration +@EnableConfigurationProperties(GciRedisCacheProperties.class) +public class RedisConfig { + @Autowired + private GciRedisCacheProperties redisCacheProperties; + + /** + * RedisTemplate配置 + * + * @param lettuceConnectionFactory + * @return + */ + @Bean + public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { + // 设置序列化 + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + // 配置redisTemplate + RedisTemplate redisTemplate = new RedisTemplate(); + redisTemplate.setConnectionFactory(lettuceConnectionFactory); + RedisSerializer stringSerializer = new StringRedisSerializer(); + redisTemplate.setKeySerializer(stringSerializer);// key序列化 + redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化 + redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化 + redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化 + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + /** + * 缓存配置管理器 + * + * @param factory + * @return + */ + @Bean + public CacheManager cacheManager(LettuceConnectionFactory factory) { + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); + //设置默认的缓存过期时间 + if(redisCacheProperties.getDefaultTtl() > 0){ + config = config.entryTtl(Duration.ofMillis(redisCacheProperties.getDefaultTtl())); + } + if(StringUtils.hasText(redisCacheProperties.getDefaultKeyPrefix())){ + config = config.prefixCacheNameWith(redisCacheProperties.getDefaultKeyPrefix()); + } + config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); + + RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager + // 写入加锁 + .builder(RedisCacheWriter.lockingRedisCacheWriter(factory)) + // 使用默认缓存配置 + .cacheDefaults(config) + .transactionAware(); + /* 自定义配置缓存的超时时间*/ + if(redisCacheProperties.getKeys().size()>0){ + Map map = new HashMap<>(); + for(Map.Entry e : redisCacheProperties.getKeys().entrySet()){ + RedisCacheConfiguration keyConfig = RedisCacheConfiguration.defaultCacheConfig(); + if(e.getValue().getTtl()>0){ + keyConfig = keyConfig.entryTtl(Duration.ofMillis(e.getValue().getTtl())); + } + if(!e.getValue().isCacheNullValues()){ + keyConfig = keyConfig.disableCachingNullValues(); + } + if(StringUtils.hasText(e.getValue().getPrefix())){ + keyConfig = keyConfig.prefixCacheNameWith(e.getValue().getPrefix()); + } + map.put(e.getKey(), keyConfig); + } + builder.withInitialCacheConfigurations(map); + } + RedisCacheManager cacheManager = builder.build(); + return cacheManager; + } +} diff --git a/src/main/java/com/gci/boot/config/ShiroConfig.java b/src/main/java/com/gci/boot/config/ShiroConfig.java new file mode 100644 index 0000000..0100941 --- /dev/null +++ b/src/main/java/com/gci/boot/config/ShiroConfig.java @@ -0,0 +1,142 @@ +package com.gci.boot.config; + +import com.gci.boot.modules.system.shiro.authc.ShiroRealm; +import com.gci.boot.modules.system.util.JwtUtil; +import com.gci.boot.properties.GciSecurityProperties; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.shiro.authc.CustomShiroFilterFactoryBean; +import com.gci.boot.modules.system.shiro.authc.aop.JwtFilter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; +import org.apache.shiro.mgt.DefaultSubjectDAO; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.filter.InvalidRequestFilter; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; + +import javax.servlet.Filter; +import java.util.*; + +/** + * @author: Scott + * @date: 2018/2/7 + * @description: shiro 配置类 + */ + +@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") +@Slf4j +@Configuration +@EnableConfigurationProperties(GciSecurityProperties.class) +public class ShiroConfig { + + + @Autowired + private GciSecurityProperties gciSecurityProperties; + + /** + * Filter Chain定义说明 + * + * 1、一个URL可以配置多个Filter,使用逗号分隔 + * 2、当设置多个过滤器时,全部验证通过,才视为通过 + * 3、部分过滤器可指定参数,如perms,roles + */ + @Bean + public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { + CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean(); + shiroFilterFactoryBean.setSecurityManager(securityManager); + // 拦截器 + Map filterChainDefinitionMap = new LinkedHashMap(); + String excludeUrls = gciSecurityProperties.getShiro().getExcludeUrls(); + + if(StringUtils.isNotBlank(excludeUrls)){ + String[] permissionUrl = excludeUrls.split(","); + for(String url : permissionUrl){ + /* + 添加shiro的内置过滤器 + anon:无需认证就可以访问 + authc:必须认证才可以访问 + user:必须有“记住我”功能才能使用 + perms:拥有对某个资源的权限才能访问 + role:拥有某个角色权限才能访问 + */ + filterChainDefinitionMap.put(url,"anon"); + } + } + + // 添加自己的过滤器并且取名为jwt + Map filterMap = new HashMap(1); + filterMap.put("jwt", new JwtFilter()); + shiroFilterFactoryBean.setFilters(filterMap); + // + + + + + + + + + + + + + + SELECT + vehicle_type, + AVG(power_consume/road_mile) AS average_energy + FROM + public.tb_gis_road_mile_log + WHERE + start_time >= #{startTime} AND end_time <= #{endTime} + and road_mile > 0 and power_consume > 0 + GROUP BY + vehicle_type + ORDER BY + average_energy DESC; + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/RefuelAlarmMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/RefuelAlarmMapper.xml new file mode 100644 index 0000000..c514289 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/RefuelAlarmMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisActiveSafetyAlarmMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisActiveSafetyAlarmMapper.xml new file mode 100644 index 0000000..13c858f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisActiveSafetyAlarmMapper.xml @@ -0,0 +1,33 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisChargeLogMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisChargeLogMapper.xml new file mode 100644 index 0000000..4c48774 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisChargeLogMapper.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceAlarmMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceAlarmMapper.xml new file mode 100644 index 0000000..9a6707e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceAlarmMapper.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceInfoMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceInfoMapper.xml new file mode 100644 index 0000000..d258665 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFencePlanMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFencePlanMapper.xml new file mode 100644 index 0000000..f2553c5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFencePlanMapper.xml @@ -0,0 +1,34 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceVehicleMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceVehicleMapper.xml new file mode 100644 index 0000000..7a295d8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisFenceVehicleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsMapper.xml new file mode 100644 index 0000000..67bf25c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsStatisticsMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsStatisticsMapper.xml new file mode 100644 index 0000000..804c028 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisGpsStatisticsMapper.xml @@ -0,0 +1,45 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisRunningbusMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisRunningbusMapper.xml new file mode 100644 index 0000000..a77ef66 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisRunningbusMapper.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingAlarmMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingAlarmMapper.xml new file mode 100644 index 0000000..bcfde91 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingAlarmMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingThresholdMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingThresholdMapper.xml new file mode 100644 index 0000000..edf6f81 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisSpeedingThresholdMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisStoppingAlarmMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisStoppingAlarmMapper.xml new file mode 100644 index 0000000..cb14664 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisStoppingAlarmMapper.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisVehicleFaultAlarmMapper.xml b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisVehicleFaultAlarmMapper.xml new file mode 100644 index 0000000..bcb526c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/mapper/xml/TbGisVehicleFaultAlarmMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/gis/query/EverydayInfoQuery.java b/src/main/java/com/gci/boot/modules/gis/query/EverydayInfoQuery.java new file mode 100644 index 0000000..db346b1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/EverydayInfoQuery.java @@ -0,0 +1,28 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.validated.SaveValidated; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * @author 24642 + */ +@Data +public class EverydayInfoQuery { + /** + * 车牌号 + */ + private String numberPlate; + /** + * 日期 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "日期不能为空!",groups = {SaveValidated.class}) + private Date time; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/EverydayQuery.java b/src/main/java/com/gci/boot/modules/gis/query/EverydayQuery.java new file mode 100644 index 0000000..75cae62 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/EverydayQuery.java @@ -0,0 +1,50 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @author 24642 + */ +@Data +public class EverydayQuery { + /** + * 项目Id + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String projectId; + /** + * 车牌号 + */ + @SelectQuery + @OrderQuery(sort = 2) + private String numberPlate; + /** + * 车辆种类 + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleType; + /** + * 车辆品牌 + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleBrand; + /** + * 时间区间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "ownDate") + @OrderQuery(PropName = "startTime",sort = 1) + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private List time; + /** + * 统计期间类型 1-日 2-周 3-月 + */ + private String statisType; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GisActiveSafetyQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GisActiveSafetyQuery.java new file mode 100644 index 0000000..3980d23 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GisActiveSafetyQuery.java @@ -0,0 +1,59 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class GisActiveSafetyQuery { + + @ApiModelProperty("项目ID") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgasa.projectId") + private String projectId; + + @ApiModelProperty("车牌号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tgasa.plateNumber") + private String plateNumber; + + @ApiModelProperty("一级类型") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgasa.primaryType") + private Integer primaryType; + + @ApiModelProperty("事件类型") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgasa.eventType") + private String eventType; + + @OrderQuery(sort = 1,PropName = "tgasa.alertEndTime") + private Date alertEndTime; + + /** + * 时间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "tgasa.alertStartTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private List time; + + + @ApiModelProperty("车辆品牌") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleBrand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tv.vehicleModel") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + + @ApiModelProperty("所属车商") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.dealer") + private String dealer; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GisChargeLogQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GisChargeLogQuery.java new file mode 100644 index 0000000..369cd2a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GisChargeLogQuery.java @@ -0,0 +1,49 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class GisChargeLogQuery { + @ApiModelProperty("项目ID") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgcl.projectId") + private String projectId; + + @ApiModelProperty("车牌号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tgcl.numberPlate") + private String plateNumber; + + @OrderQuery(sort = 1,PropName = "tgcl.endTime") + private Date endTime; + + /** + * 时间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "tgcl.startTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private List time; + + @ApiModelProperty("车辆品牌") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleBrand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tv.vehicleModel") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + + @ApiModelProperty("所属车商") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.dealer") + private String dealer; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GisFenceAlarmQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GisFenceAlarmQuery.java new file mode 100644 index 0000000..e59c05c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GisFenceAlarmQuery.java @@ -0,0 +1,48 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class GisFenceAlarmQuery { + @ApiModelProperty("项目ID") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgfa.projectId") + private String projectId; + + @ApiModelProperty("车牌号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tgfa.plateNumber") + private String plateNumber; + + @OrderQuery(sort = 1,PropName = "tgfa.endTime") + private Date endTime; + /** + * 时间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "startTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private List time; + + @ApiModelProperty("车辆品牌") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleBrand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tv.vehicleModel") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + + @ApiModelProperty("所属车商") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.dealer") + private String dealer; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GisSpeedingQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GisSpeedingQuery.java new file mode 100644 index 0000000..2c5fa42 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GisSpeedingQuery.java @@ -0,0 +1,49 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class GisSpeedingQuery { + @ApiModelProperty("项目ID") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgsa.projectId") + private String projectId; + + @ApiModelProperty("车牌号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tgsa.plateNumber") + private String plateNumber; + + @OrderQuery(sort = 1,PropName = "tgsa.endTime") + private Date endTime; + + /** + * 时间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "tgsa.startTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private List time; + + @ApiModelProperty("车辆品牌") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleBrand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tv.vehicleModel") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + + @ApiModelProperty("所属车商") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.dealer") + private String dealer; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GisStoppingQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GisStoppingQuery.java new file mode 100644 index 0000000..bdb1bfa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GisStoppingQuery.java @@ -0,0 +1,51 @@ +package com.gci.boot.modules.gis.query; + +import java.util.Date; +import java.util.List; + +import org.springframework.format.annotation.DateTimeFormat; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class GisStoppingQuery { + @ApiModelProperty("项目ID") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgsa.projectId") + private String projectId; + + @ApiModelProperty("车牌号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tgsa.plateNumber") + private String plateNumber; + + @OrderQuery(sort = 1,PropName = "tgsa.endTime") + private Date endTime; + + /** + * 时间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "tgsa.startTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private List time; + + @ApiModelProperty("车辆品牌") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleBrand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tv.vehicleModel") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + + @ApiModelProperty("所属车商") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.dealer") + private String dealer; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GisVehicleFaultQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GisVehicleFaultQuery.java new file mode 100644 index 0000000..5dff5fb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GisVehicleFaultQuery.java @@ -0,0 +1,56 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class GisVehicleFaultQuery { + @ApiModelProperty("项目ID") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgvfa.projectId") + private String projectId; + + @ApiModelProperty("车牌号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tgvfa.plateNumber") + private String plateNumber; + @ApiModelProperty("vin码") + @SelectQuery(PropName = "tgvfa.vinCode") + private String vinCode; + @ApiModelProperty("故障码") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tgvfa.faultType") + private String faultType; + + @OrderQuery(sort = 1) + private Date alarmEndTime; + + /** + * 时间 + */ + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "tgvfa.alarmStartTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private List time; + + + @ApiModelProperty("车辆品牌") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleBrand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tv.vehicleModel") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + + @ApiModelProperty("所属车商") + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.dealer") + private String dealer; +} diff --git a/src/main/java/com/gci/boot/modules/gis/query/GpsHistoryQuery.java b/src/main/java/com/gci/boot/modules/gis/query/GpsHistoryQuery.java new file mode 100644 index 0000000..dab274a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/query/GpsHistoryQuery.java @@ -0,0 +1,36 @@ +package com.gci.boot.modules.gis.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.validated.SaveValidated; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.Date; +import java.util.List; + +/** + * @author 24642 + */ +@Data +public class GpsHistoryQuery { + @NotBlank(message = "车牌号不能为空!",groups = {SaveValidated.class}) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String plateNumber; + + @Size(min = 2,max = 2,message = "查询时间必须包括起止时间!") + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "gpsTime") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @NotNull(message = "查询时间范围不能为空!",groups = {SaveValidated.class}) + List time; + + @ApiModelProperty("gps采集时间") + @OrderQuery(IsAsc = true) + private Date gpsTime; +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/GisRoadMileLogService.java b/src/main/java/com/gci/boot/modules/gis/service/GisRoadMileLogService.java new file mode 100644 index 0000000..d3d404e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/GisRoadMileLogService.java @@ -0,0 +1,39 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.dataview.vo.GisRoadMileVo; +import com.gci.boot.modules.gis.entity.GisRoadMileLog; +import com.gci.boot.modules.gis.entity.TbGisChargeLog; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 行驶里程能耗记录表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface GisRoadMileLogService extends IService { + + /** + * 查询能耗信息 + * @param startTime + * @param endTime + * @return + */ + List countByTime(Date startTime,Date endTime); + + + /** + * 将支持三电的gps数据转换计算成行驶里程和耗电量 + */ + void coverGpsToRoadMile(TbVehicle vehicle, Date startTime, Date endTime); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/GpsConsumerService.java b/src/main/java/com/gci/boot/modules/gis/service/GpsConsumerService.java new file mode 100644 index 0000000..928fb98 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/GpsConsumerService.java @@ -0,0 +1,89 @@ +package com.gci.boot.modules.gis.service; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.gci.boot.common.util.RedisKey; +import com.gci.boot.modules.gis.entity.TbGisFenceAlarm; +import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm; +import com.gci.boot.modules.gis.vo.FenceSpeedBeanVO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@Service +public class GpsConsumerService{ + + @Autowired + private ITbGisSpeedingAlarmService speedingAlarmService; + @Autowired + private ITbGisFenceAlarmService fenceAlarmService; + + @Autowired + private StringRedisTemplate redisTemplate; + + //数据入库 + public void saveHandle(FenceSpeedBeanVO vo){ + if(1 == vo.getType()){ + //围栏告警 + TbGisFenceAlarm fenceAlarm = JSONUtil.toBean(vo.getData(),TbGisFenceAlarm.class); + LambdaQueryWrapper fenceQuery = new LambdaQueryWrapper<>(); + fenceQuery.eq(TbGisFenceAlarm::getPlateNumber,fenceAlarm.getPlateNumber()); + //围栏id标识。新增和完结告警必传围栏id。 车辆掉线时自动任务推送不传围栏id。处理该车所有的未结束围栏告警。 + if(StringUtils.isNotBlank(fenceAlarm.getFenceId())){ + fenceQuery.eq(TbGisFenceAlarm::getFenceId,fenceAlarm.getFenceId()); + } + fenceQuery.isNull(TbGisFenceAlarm::getEndTime); + List list = fenceAlarmService.list(fenceQuery); + //类型为开始 且该车辆 该围栏并没有正在进行中的告警记录,则说明是新增,否则不新增 + if(vo.getFlag() == 1 && list.isEmpty()){ + fenceAlarm.setStartTime(fenceAlarm.getAlarmTime()); + fenceAlarmService.save(fenceAlarm); + } + //类型为结束的,则说明是修改 + if(vo.getFlag() == 2){ + for(TbGisFenceAlarm one:list){ + //判断是否为-结束->找到开始的记录,更新结束信息 + fenceAlarm.setEndTime(fenceAlarm.getAlarmTime()); + fenceAlarmService.updateById(one); + // TODO: 2023/10/18 屏蔽自动关闭逻辑,无数据产生不需要删除 +// redisTemplate.opsForZSet().remove(RedisKey.FENCE_VEHICLE_SCORE,one.getPlateNumber()+"-"+one.getId()+"-"+one.getFenceId()); + } + } + }else if(2 == vo.getType()){ + //超速告警 + TbGisSpeedingAlarm speedingAlarm = JSONUtil.toBean(vo.getData(),TbGisSpeedingAlarm.class); + LambdaQueryWrapper speedQuery = new LambdaQueryWrapper<>(); + speedQuery.eq(TbGisSpeedingAlarm::getPlateNumber,speedingAlarm.getPlateNumber()) + .isNull(TbGisSpeedingAlarm::getEndTime); + TbGisSpeedingAlarm one = speedingAlarmService.getOne(speedQuery); + if(vo.getFlag() == 1){ + //判断是否为-开始->插入一条 + if(Objects.isNull(one)){ + speedingAlarmService.save(speedingAlarm); + } + }else if(vo.getFlag() == 2){ + //判断是否为-结束->找到开始的记录,更新结束信息 + if(Objects.nonNull(one)){ + one.setEndLat(speedingAlarm.getEndLat()); + one.setEndLon(speedingAlarm.getEndLon()); + one.setEndTime(speedingAlarm.getEndTime()); + one.setSpeed(speedingAlarm.getSpeed()); + one.setAverageSpeed(speedingAlarm.getAverageSpeed()); + speedingAlarmService.updateById(one); + } + } + } + } + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/IGisGpsAnalysisService.java b/src/main/java/com/gci/boot/modules/gis/service/IGisGpsAnalysisService.java new file mode 100644 index 0000000..e58b44d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/IGisGpsAnalysisService.java @@ -0,0 +1,65 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.gis.entity.GisGpsAnalysis; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.vo.StatisGisVo; +import com.gci.boot.modules.gis.vo.VehicleWorkVO; +import com.gci.boot.modules.gis.query.EverydayQuery; +import com.gci.boot.modules.gis.vo.EverydayGisVo; +import com.gci.boot.modules.gis.vo.EverydayMileCountVo; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 车辆gps轨迹信息表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface IGisGpsAnalysisService extends IService { + + /** + * + *时间段内车辆gps数据分析 + * + * @param vehicle + * @param startTime + * @param endTime + */ + void gpsDataAnalysisByVehicle(TbVehicle vehicle, Date startTime, Date endTime,boolean isEic); + + void gpsDataAnalysisByVehicleBy808(TbVehicle vehicle, Date startTime, Date endTime); + + List gpsTime(TbVehicle vehicle, Date startTime, Date endTime); + + /** + * 车辆作业分析 + * @param page + * @param query + * @return + */ + IPage everydayGis(Page page, EverydayQuery query); + + /** + * 车辆作业统计 + * @param query + * @return + */ + EverydayMileCountVo everydayMileCount(EverydayQuery query); + /** + * 查询指定车辆在某段时间内的作业信息 + * @param numberplates + * @param startTime + * @param endTime + * @return + */ + List findAnalysisByTimeAndVehicle(List numberplates,Date startTime,Date endTime); + + IPage statisGis(Page page, EverydayQuery query); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/IRefuelAlarmService.java b/src/main/java/com/gci/boot/modules/gis/service/IRefuelAlarmService.java new file mode 100644 index 0000000..dfb76db --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/IRefuelAlarmService.java @@ -0,0 +1,11 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.entity.RefuelAlarm; + +public interface IRefuelAlarmService extends IService { + IPage pageBuild(Page page, RefuelAlarm lambdaQueryWrapper); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisActiveSafetyAlarmService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisActiveSafetyAlarmService.java new file mode 100644 index 0000000..9bf8b89 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisActiveSafetyAlarmService.java @@ -0,0 +1,36 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.gis.entity.TbGisActiveSafetyAlarm; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.statis.vo.AlarmTrendVO; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 主动安全故障记录表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface ITbGisActiveSafetyAlarmService extends IService { + /** + * 构建返回 + */ + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); + + /** + * 查询某地时间内的所有告警记录 + * @param startTime + * @param endTime + * @return + */ + List findListByTime(Date startTime,Date endTime); + + List findTrendListByTime(Date startTime, Date endTime); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisChargeLogService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisChargeLogService.java new file mode 100644 index 0000000..415b3a1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisChargeLogService.java @@ -0,0 +1,23 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.gis.entity.TbGisChargeLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 充电记录表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface ITbGisChargeLogService extends IService { + + /** + * 补充数据 + */ + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceAlarmService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceAlarmService.java new file mode 100644 index 0000000..ca4d76a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceAlarmService.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.gis.entity.TbGisFenceAlarm; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 围栏告警记录表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface ITbGisFenceAlarmService extends IService { + + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceInfoService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceInfoService.java new file mode 100644 index 0000000..7d1c0e0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceInfoService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.gis.service; + +import com.gci.boot.modules.gis.entity.TbGisFenceInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 围栏信息表 服务类 + *

+ * + * @author 2464 + * @since 2023-08-30 + */ +public interface ITbGisFenceInfoService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisFencePlanService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFencePlanService.java new file mode 100644 index 0000000..3962d97 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFencePlanService.java @@ -0,0 +1,81 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.gis.entity.TbGisFenceInfo; +import com.gci.boot.modules.gis.entity.TbGisFencePlan; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.vo.GisProjectTreeVo; +import com.gci.boot.modules.gis.vo.GisVehicleVo; + +import java.util.List; + +/** + *

+ * 围栏方案表 服务类 + *

+ * + * @author 2464 + * @since 2023-08-30 + */ +public interface ITbGisFencePlanService extends IService { + + /** + * 保存 方案及信息 + */ + void saveItem(TbGisFencePlan tbGisFencePlan); + + /** + * 编辑 方案及信息 + */ + void updateItem(TbGisFencePlan tbGisFencePlan); + + /** + * 保存 关联车辆 + */ + void saveVehicle(GisVehicleVo vo); + + /** + * 删除关联车辆 + */ + void delVehicle(GisVehicleVo vo); + + /** + * 启用方案 + * @param id + */ + void isValid(String id); + + /** + * 禁用方案 + * @param id + */ + void unValid(String id); + + /** + * 获取方案内车辆列表 + * @param id + * @param page + * @return + */ + Page getPlanVehicleList(String id, Page page); + + /** + * 获取项目内车辆列表 + * @param id + * @return + */ + List getProjectVehicleList(String id); + + /** + * 获取方案内围栏列表 + * @param id + * @return + */ + List getPlanFenceInfoList(String id); + + /** + * 手动更新全部围栏信息 + */ + void updateAll(); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceVehicleService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceVehicleService.java new file mode 100644 index 0000000..4bbba0a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisFenceVehicleService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.gis.service; + +import com.gci.boot.modules.gis.entity.TbGisFenceVehicle; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 围栏关联车辆信息表 服务类 + *

+ * + * @author 2464 + * @since 2023-08-30 + */ +public interface ITbGisFenceVehicleService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsService.java new file mode 100644 index 0000000..8be1392 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsService.java @@ -0,0 +1,31 @@ +package com.gci.boot.modules.gis.service; + +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.gis.entity.TbGisGps; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.query.GpsHistoryQuery; +import com.gci.boot.modules.gis.vo.GisHistoryVo; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface ITbGisGpsService extends IService { + + /** + * 获取 + * @param vo + * @return + */ + List getGpsHistory(GpsHistoryQuery vo); + + List getGpsListByVehicleAndTime(TbVehicle vehicle, Date startTime, Date endTime,int recordSource); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsStatisticsService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsStatisticsService.java new file mode 100644 index 0000000..3d81557 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisGpsStatisticsService.java @@ -0,0 +1,27 @@ +package com.gci.boot.modules.gis.service; + +import com.gci.boot.modules.gis.entity.TbGisGpsStatistics; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆gps相关数据统计 服务类 + *

+ * + * @author 2464 + * @since 2023-10-31 + */ +public interface ITbGisGpsStatisticsService extends IService { + + /** + * 生成方法 + * @param time + */ + void init(String time); + + /** + * 生成方法 + */ + void gen (); + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisRunningbusService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisRunningbusService.java new file mode 100644 index 0000000..989f5f2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisRunningbusService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.gis.service; + +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆实时信息表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface ITbGisRunningbusService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingAlarmService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingAlarmService.java new file mode 100644 index 0000000..7637248 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingAlarmService.java @@ -0,0 +1,34 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.statis.vo.AlarmTrendVO; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 超速记录表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +public interface ITbGisSpeedingAlarmService extends IService { + + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); + + /** + * 查询某地时间内的所有告警记录 + * @param startTime + * @param endTime + * @return + */ + List findListByTime(Date startTime, Date endTime); + + List findTrendListByTime(Date startTime, Date endTime); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingThresholdService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingThresholdService.java new file mode 100644 index 0000000..261efc0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisSpeedingThresholdService.java @@ -0,0 +1,42 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.entity.TbGisSpeedingThreshold; + +/** + *

+ * 超速阈值设置 服务类 + *

+ * + * @author 2464 + * @since 2023-12-25 + */ +public interface ITbGisSpeedingThresholdService extends IService { + + void saveItem(TbGisSpeedingThreshold tbGisSpeedingThreshold); + + void updateItem(TbGisSpeedingThreshold tbGisSpeedingThreshold); + + /** + * 作废 + * @param id + */ + void cancel(String id); + + /** + * 恢复 + * @param id + */ + void unCancel(String id); + + /** + * 删除 + * @param id + */ + void removeItem(String id); + + /** + * 重新计算数据 + */ + void rel(); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisStoppingAlarmService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisStoppingAlarmService.java new file mode 100644 index 0000000..6ba07d3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisStoppingAlarmService.java @@ -0,0 +1,15 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.entity.TbGisStoppingAlarm; + +/** + * @author 24642 + */ +public interface ITbGisStoppingAlarmService extends IService { + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/ITbGisVehicleFaultAlarmService.java b/src/main/java/com/gci/boot/modules/gis/service/ITbGisVehicleFaultAlarmService.java new file mode 100644 index 0000000..9f236f1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/ITbGisVehicleFaultAlarmService.java @@ -0,0 +1,44 @@ +package com.gci.boot.modules.gis.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.gis.entity.TbGisVehicleFaultAlarm; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.gis.vo.VehicleFaultVo; +import com.gci.boot.modules.statis.vo.AlarmTrendVO; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 车辆车机故障异常记录表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-09 + */ +public interface ITbGisVehicleFaultAlarmService extends IService { + + /** + * 统计查询 + * @param projectId + * @return + */ + List countFault(String projectId); + + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); + + /** + * 查询某地时间内的所有告警记录 + * @param startTime + * @param endTime + * @return + */ + List findListByTime(Date startTime, Date endTime); + + List findTrendListByTime(Date startTime, Date endTime); + + void close(String ids, String remark); +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/GisGpsAnalysisServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/GisGpsAnalysisServiceImpl.java new file mode 100644 index 0000000..47fc16a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/GisGpsAnalysisServiceImpl.java @@ -0,0 +1,853 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.Week; +import cn.hutool.core.lang.Segment; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.PageUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.util.CalcTool; +import com.gci.boot.enums.VehicleGpsType; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.gis.dto.EverydayMileCountDto; +import com.gci.boot.modules.gis.entity.GisGpsAnalysis; +import com.gci.boot.modules.gis.entity.TbGisGps; +import com.gci.boot.modules.gis.mapper.GisGpsAnalysisMapper; +import com.gci.boot.modules.gis.query.EverydayQuery; +import com.gci.boot.modules.gis.service.IGisGpsAnalysisService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.gis.service.ITbGisGpsService; +import com.gci.boot.modules.gis.vo.StatisGisVo; +import com.gci.boot.modules.gis.vo.VehicleWorkVO; +import com.gci.boot.modules.gis.vo.EverydayGisVo; +import com.gci.boot.modules.gis.vo.EverydayMileCountVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 车辆gps轨迹信息表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class GisGpsAnalysisServiceImpl extends ServiceImpl implements IGisGpsAnalysisService { + + @Autowired + private ITbGisGpsService tbGisGpsService; + @Autowired + private GisGpsAnalysisMapper gisGpsAnalysisMapper; + + @Override + public void gpsDataAnalysisByVehicle(TbVehicle vehicle, Date startTime, Date endTime,boolean isEic) { + + int recordSource = isEic?2:1; + List gpsList = tbGisGpsService.getGpsListByVehicleAndTime(vehicle,startTime,endTime,recordSource); + + if(isEic){ + //删除掉脏数据 + gpsList.removeIf(gps -> Objects.isNull(gps.getAcc()) || Objects.isNull(gps.getSpeed()) + || Objects.isNull(gps.getTotalMileage()) || gps.getTotalMileage().compareTo(BigDecimal.ZERO)<=0); + }else{ + //删除掉脏数据 + gpsList.removeIf(gps -> Objects.isNull(gps.getAcc()) || Objects.isNull(gps.getSpeed())); + } + // 初始化分段的数据 + List segments = new ArrayList<>(); + List result = new ArrayList<>(); + //如果是福龙马的,暂时特殊处理。 + if(vehicle.getVehicleBrand().equals("3")){ + segments = genAnalysisFuLongMa(gpsList,vehicle,isEic); + result = mergeGisData(segments,isEic); + }else{ + segments = genAnalysisNormal(gpsList,vehicle,isEic); + result = mergeGisData(segments,isEic); + } +// segments = genAnalysisNormal(gpsList,vehicle); + // TODO: 2023/10/28 暂时屏蔽观察数据 +// segments.removeIf(s->Objects.isNull(s.getEndTime())); + this.saveBatch(result, 500); + } + + @Override + public void gpsDataAnalysisByVehicleBy808(TbVehicle vehicle, Date startTime, Date endTime) { + List gpsList = tbGisGpsService.getGpsListByVehicleAndTime(vehicle,startTime,endTime,1); + //删除掉脏数据 + gpsList.removeIf(gps -> Objects.isNull(gps.getAcc()) || Objects.isNull(gps.getSpeed())); + // 初始化分段的数据 + List segments = new ArrayList<>(); + //如果是福龙马的,暂时特殊处理。 + if(vehicle.getVehicleBrand().equals("3")){ + segments = genAnalysisFuLongMa(gpsList,vehicle,false); + }else{ + segments = genAnalysisNormal(gpsList,vehicle,false); + } +// segments = genAnalysisNormal(gpsList,vehicle); + // TODO: 2023/10/28 暂时屏蔽观察数据 +// segments.removeIf(s->Objects.isNull(s.getEndTime())); + List result = mergeGisData(segments,false); + this.saveBatch(result, 500); + } + + @Override + public List gpsTime(TbVehicle vehicle, Date startTime, Date endTime) { + List gpsList = tbGisGpsService.getGpsListByVehicleAndTime(vehicle,startTime,endTime,2); + //删除掉脏数据 + gpsList.removeIf(gps -> Objects.isNull(gps.getAcc()) || Objects.isNull(gps.getSpeed()) + || Objects.isNull(gps.getTotalMileage())|| gps.getTotalMileage().compareTo(BigDecimal.ZERO)<=0); + // 初始化分段的数据 + List segments = genAnalysis(gpsList,vehicle); + segments.removeIf(s->s.getRecordType()==3); + segments.sort(Comparator.comparing(GisGpsAnalysis::getStartTime)); + return segments; + } + + private boolean isDriving(TbGisGps gps){ + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0; + } + + private List genAnalysis(List gpsList,TbVehicle vehicle){ + List segments = new ArrayList<>(); + GisGpsAnalysis currentSegment = null; + for (TbGisGps gps : gpsList) { + // 根据规则判断记录类型 + int recordType; + if(isDriving(gps)){ + recordType = VehicleGpsType.Driving_Work.getValue(); + //如果为空 或者 原来的为停靠,则需新增 + if(currentSegment == null || currentSegment.getRecordType() == VehicleGpsType.Stopped_Work.getValue()){ + Optional option = segments.stream().filter(r->{ + return r.getRecordType()==VehicleGpsType.Driving_Work.getValue(); + }).reduce((first,second)->second); + if(option.isPresent()){ + GisGpsAnalysis lastDriverObj = option.get(); + long diff = gps.getGpsTime().getTime() - lastDriverObj.getEndTime().getTime(); + if(diff < 20*60*1000){ + updateSegment(lastDriverObj,vehicle, gps,true); + }else{ + currentSegment = createSegment(gps, vehicle,recordType,true); + segments.add(currentSegment); + } + }else{ + currentSegment = createSegment(gps, vehicle,recordType,true); + segments.add(currentSegment); + } + }else{ + updateSegment(currentSegment,vehicle, gps,true); + } + }else{ + recordType = VehicleGpsType.Stopped_Work.getValue(); + //如果原来的不为空 且 为行驶,且当前记录gps跟原来的差距小于20分钟;则追加,否则新曾一条 + if(currentSegment != null && currentSegment.getRecordType() == VehicleGpsType.Driving_Work.getValue()){ + long diff = gps.getGpsTime().getTime() - currentSegment.getStartTime().getTime(); + if(diff < 20*60*1000){ + // 更新现有GPS分析数据段 + currentSegment.setEndTime(gps.getGpsTime()); + //得到时长(s) + Long duration = DateUtil.betweenMs(currentSegment.getEndTime(),currentSegment.getStartTime())/1000; + currentSegment.setDuration(duration); + }else{ + currentSegment = createSegment(gps, vehicle,recordType,true); + segments.add(currentSegment); + } + }else if(currentSegment != null && currentSegment.getRecordType() == VehicleGpsType.Stopped_Work.getValue()){ + // 更新现有GPS分析数据段 + currentSegment.setEndTime(gps.getGpsTime()); + //得到时长(s) + Long duration = DateUtil.betweenMs(currentSegment.getEndTime(),currentSegment.getStartTime())/1000; + currentSegment.setDuration(duration); + } else if(currentSegment == null){ + currentSegment = createSegment(gps, vehicle,recordType,true); + segments.add(currentSegment); + } + } + } + return segments; + } + + @Override + public List findAnalysisByTimeAndVehicle(List numberplates, Date startTime, Date endTime) { + return gisGpsAnalysisMapper.findAnalysisByTimeAndVehicle(numberplates,startTime,endTime); + } + + @Override + public IPage statisGis(Page page, EverydayQuery query) { + checkTime(query); + ArrayList statisGisVoArrayList = new ArrayList<>(); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(GisGpsAnalysis.class, query); + List list = list(lambdaQueryWrapper); + for (GisGpsAnalysis gisGpsAnalysis : list) { + Date ownDate = gisGpsAnalysis.getOwnDate(); + if ("1".equals(query.getStatisType())) { + gisGpsAnalysis.setStatisTime(DateUtil.formatDate(ownDate)); + } else if ("2".equals(query.getStatisType())) { + int week = DateUtil.dateNew(ownDate).setFirstDayOfWeek(Week.MONDAY).weekOfYear(); + int year = DateUtil.year(ownDate); + gisGpsAnalysis.setStatisTime(StrUtil.format("{}年第{}周",year,week)); + } else if ("3".equals(query.getStatisType())) { + gisGpsAnalysis.setStatisTime(DateUtil.format(ownDate, "yyyy-MM")); + } else { + gisGpsAnalysis.setStatisTime(DateUtil.formatDate(ownDate)); + } + } + Map>> collect = list.stream().collect(Collectors.groupingBy(GisGpsAnalysis::getStatisTime, Collectors.groupingBy(GisGpsAnalysis::getNumberPlate))); + for (Map.Entry>> dateMapEntry : collect.entrySet()) { + for (Map.Entry> stringListEntry : dateMapEntry.getValue().entrySet()) { + //上次日期 + Date date = null; + Integer days = 0; + List value = stringListEntry.getValue(); + GisGpsAnalysis first = value.get(0); + StatisGisVo statisGisVo = new StatisGisVo(); + statisGisVo.setProjectId(first.getProjectId()); + statisGisVo.setPlateNumber(first.getNumberPlate()); + statisGisVo.setVehicleType(first.getVehicleType()); + statisGisVo.setVehicleBrand(first.getVehicleBrand()); + statisGisVo.setVehicleModel(first.getVehicleModel()); + statisGisVo.setStatisTime(first.getStatisTime()); + if ("1".equals(query.getStatisType())) { + statisGisVo.setRequiredAttendanceDays(1); + } else if ("2".equals(query.getStatisType())) { + statisGisVo.setRequiredAttendanceDays(7); + } else if ("3".equals(query.getStatisType())) { + statisGisVo.setRequiredAttendanceDays(DateUtil.lengthOfMonth(DateUtil.month(first.getOwnDate())+1,DateUtil.isLeapYear(DateUtil.year(first.getOwnDate())))); + } else { + statisGisVo.setRequiredAttendanceDays(1); + } + //行驶里程 + BigDecimal totalMile = BigDecimal.ZERO; + //作业里程 + BigDecimal workMile = BigDecimal.ZERO; + //行驶时间 + BigDecimal totalTime = BigDecimal.ZERO; + //作业时间 + BigDecimal workTime = BigDecimal.ZERO; + //行驶作业时间 + BigDecimal travelWorkTime = BigDecimal.ZERO; + //停靠作业时长 + BigDecimal stopWorkTime = BigDecimal.ZERO; + //平均行驶速度 + BigDecimal avgSpeed; + //平均作业速度 + BigDecimal avgWorkSpeed; + //在线时长 + BigDecimal onlineTime = BigDecimal.ZERO; + //通电停靠时长 + BigDecimal onlineStopTime = BigDecimal.ZERO; + for (GisGpsAnalysis gisGpsAnalysis : value) { + if (date == null) { + date = gisGpsAnalysis.getOwnDate(); + days = days + 1; + } + if (!DateUtil.isSameDay(gisGpsAnalysis.getOwnDate(),date)) { + date = gisGpsAnalysis.getOwnDate(); + days = days + 1; + } + BigDecimal duration = BigDecimal.valueOf(gisGpsAnalysis.getDuration()); + //计算在线时长 + onlineTime = onlineTime.add(duration); + if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Driving_Not_Work.getValue()) { + //行驶未作业 + //计算行驶里程 + totalMile = totalMile.add(gisGpsAnalysis.getMile()); + //计算行驶时长 + totalTime = totalTime.add(duration); + } else if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Driving_Work.getValue()) { + //行驶作业 + //计算行驶里程 + totalMile = totalMile.add(gisGpsAnalysis.getMile()); + //计算行驶时长 + totalTime = totalTime.add(duration); + //计算作业里程 + workMile = workMile.add(gisGpsAnalysis.getMile()); + //计算作业时长 + workTime = workTime.add(duration); + //计算行驶作业时长 + travelWorkTime = travelWorkTime.add(duration); + } else if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Stopped_Work.getValue()) { + //停靠作业 + //计算作业里程 + workMile = workMile.add(gisGpsAnalysis.getMile()); + //计算作业时长 + workTime = workTime.add(duration); + //计算停靠作业时长 + stopWorkTime = stopWorkTime.add(duration); + } else if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Stopped_NOT_Work.getValue()) { + //停靠未作业 + onlineStopTime = onlineStopTime.add(duration); + } + } + if (totalTime.compareTo(BigDecimal.ZERO)>0) { + avgSpeed = NumberUtil.div(totalMile,NumberUtil.div(totalTime,3600)).setScale(2,BigDecimal.ROUND_HALF_UP); + statisGisVo.setAvgSpeed(avgSpeed); + } + if (travelWorkTime.compareTo(BigDecimal.ZERO)>0) { + avgWorkSpeed = NumberUtil.div(workMile,NumberUtil.div(workTime,3600)).setScale(2,BigDecimal.ROUND_HALF_UP); + statisGisVo.setAvgWorkSpeed(avgWorkSpeed); + } + statisGisVo.setTotalMile(totalMile.setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setWorkMile(workMile.setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setTotalTime(NumberUtil.div(totalTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setWorkTime(NumberUtil.div(workTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setTravelWorkTime(NumberUtil.div(travelWorkTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setStopWorkTime(NumberUtil.div(stopWorkTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setOnlineTime(NumberUtil.div(onlineTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setOnlineStopTime(NumberUtil.div(onlineStopTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + statisGisVo.setActualAttendanceDays(days); + statisGisVo.setNotAttendanceDays(statisGisVo.getRequiredAttendanceDays() - statisGisVo.getActualAttendanceDays()); + if (statisGisVo.getWorkMile().compareTo(BigDecimal.ZERO)>0&&statisGisVo.getTotalMile().compareTo(BigDecimal.ZERO)>0) { + statisGisVo.setMileEfficiency(NumberUtil.mul(NumberUtil.div(statisGisVo.getWorkMile(),statisGisVo.getTotalMile()),100).setScale(2,BigDecimal.ROUND_HALF_UP)); + } + if (statisGisVo.getWorkTime().compareTo(BigDecimal.ZERO)>0&&statisGisVo.getOnlineTime().compareTo(BigDecimal.ZERO)>0) { + statisGisVo.setTimeEfficiency(NumberUtil.mul(NumberUtil.div(statisGisVo.getWorkTime(),statisGisVo.getOnlineTime()),100).setScale(2,BigDecimal.ROUND_HALF_UP)); + } + statisGisVoArrayList.add(statisGisVo); + } + } + statisGisVoArrayList.sort(Comparator.comparing(StatisGisVo::getStatisTime).reversed()); + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(statisGisVoArrayList.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(statisGisVoArrayList.size()); + page.setPages(totalPage); + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > statisGisVoArrayList.size()) { + endIndex = statisGisVoArrayList.size(); + } + page.setRecords(statisGisVoArrayList.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } + + private List genAnalysisFuLongMa(List gpsList,TbVehicle vehicle,boolean isEic){ + List segments = new ArrayList<>(); + GisGpsAnalysis currentSegment = null; +// List handleWorkList = processGpsData(gpsList); + for (TbGisGps gps : gpsList) { + // 根据规则判断记录类型 + int recordType; + if (isDrivingWorkFlm(gps)) { + recordType = VehicleGpsType.Driving_Work.getValue(); + } else if (isDrivingNotWorkFlm(gps)) { + recordType = VehicleGpsType.Driving_Not_Work.getValue(); + } else if (isStoppedWorkFlm(gps)) { + recordType = VehicleGpsType.Stopped_Work.getValue(); + } else if (isStoppedNotWorkFlm(gps)){ + recordType = VehicleGpsType.Stopped_NOT_Work.getValue(); + }else{ + continue; + } + if (currentSegment == null || recordType != currentSegment.getRecordType()) { + // 如果当前分段为空或者记录类型不同,创建新的分段 + currentSegment = createSegment(gps, vehicle,recordType,isEic); + segments.add(currentSegment); + } else { + // 否则,将当前GPS数据添加到当前分段 + updateSegment(currentSegment,vehicle, gps,isEic); + } + } + return segments; + } + + private List genAnalysisNormal(List gpsList,TbVehicle vehicle,boolean isEic){ + List segments = new ArrayList<>(); + GisGpsAnalysis currentSegment = null; + for (TbGisGps gps : gpsList) { + // 根据规则判断记录类型 + int recordType; + if (isDrivingWork(gps)) { + recordType = VehicleGpsType.Driving_Work.getValue(); + } else if (isDrivingNotWork(gps)) { + recordType = VehicleGpsType.Driving_Not_Work.getValue(); + } else if (isStoppedWork(gps)) { + recordType = VehicleGpsType.Stopped_Work.getValue(); + } else if (isStoppedNotWork(gps)){ + recordType = VehicleGpsType.Stopped_NOT_Work.getValue(); + }else{ + continue; + } + if (currentSegment == null || recordType != currentSegment.getRecordType()) { + // 如果当前分段为空或者记录类型不同,创建新的分段 + currentSegment = createSegment(gps, vehicle,recordType,isEic); + segments.add(currentSegment); + } else { + // 否则,将当前GPS数据添加到当前分段 + updateSegment(currentSegment,vehicle, gps,isEic); + } + } + return segments; + } + /** + * 行驶作业 点火且速度大于0 + * + * @param gps + * @return + */ + private boolean isDrivingWork(TbGisGps gps) { + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0 && isWorking(gps); + } + + /** + * 行驶未作业 点火、速度大于0、且未作业 + * + * @param gps + * @return + */ + private boolean isDrivingNotWork(TbGisGps gps) { + // 根据规则判断是否为“行驶未作业” + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0 && !isWorking(gps); + } + + + /** + * 停靠作业 点火 速度小于等于0 且在作业 或者 熄火 且在作业 + * + * @param gps + * @return + */ + private boolean isStoppedWork(TbGisGps gps) { + return (gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) <= 0 && isWorking(gps)) || (gps.getAcc() == 0 && isWorking(gps)); + } + + /** + * 停靠未作业 点火 速度小于等于0 且未作业 或者 熄火 且未作业 + * + * @param gps + * @return + */ + private boolean isStoppedNotWork(TbGisGps gps) { + return (gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) <= 0 && !isWorking(gps)) || (gps.getAcc() == 0 && !isWorking(gps)); + } + + private GisGpsAnalysis createSegment(TbGisGps gps,TbVehicle vehicle, int recordType,boolean isEic) { + // 创建新的GPS分析数据段 + GisGpsAnalysis segment = new GisGpsAnalysis(); + + segment.setProjectId(vehicle.getProjectId()); + segment.setVehicleBrand(vehicle.getVehicleBrand()); + segment.setVehicleModel(vehicle.getVehicleModel()); + segment.setVehicleType(vehicle.getVehicleType()); + segment.setNumberPlate(gps.getPlateNumber()); + segment.setOwnDate(gps.getGpsTime()); + segment.setStartTime(gps.getGpsTime()); + segment.setRecordType(recordType); + segment.setStartMile(gps.getTotalMileage()); + segment.setStartSoc(gps.getStateOfCharge()); + segment.setCreateTime(new Date()); + segment.setMile(BigDecimal.ZERO); + if(!isEic){ + segment.setLon(gps.getLon()); + segment.setLat(gps.getLat()); + segment.setMile(BigDecimal.ZERO); + } + updateSegment(segment,vehicle,gps,isEic); + // 设置其他属性 + return segment; + } + + private void updateSegment(GisGpsAnalysis segment,TbVehicle vehicle, TbGisGps gps,boolean isEic) { + // 更新现有GPS分析数据段 + segment.setEndTime(gps.getGpsTime()); + //得到时长(s) + Long duration = DateUtil.betweenMs(segment.getEndTime(),segment.getStartTime())/1000; + segment.setDuration(duration); + //如果为eic,则直接取里程,为808则计算里程 + if(isEic){ + Integer batteryCapacity = ObjectUtil.isEmpty(vehicle.getBatteryCapacity()) ? 0 : vehicle.getBatteryCapacity(); + //里程 + segment.setEndMile(gps.getTotalMileage()); + BigDecimal mile = segment.getEndMile().subtract(segment.getStartMile()); + segment.setMile(mile); + //soc + if(ObjectUtil.isNotEmpty(gps.getStateOfCharge())){ + segment.setEndSoc(gps.getStateOfCharge()); + double hour = Convert.toDouble(duration/3600); + BigDecimal sub = NumberUtil.sub(segment.getStartSoc(), segment.getEndSoc()); + BigDecimal div = NumberUtil.div(sub, 100); + BigDecimal mul = NumberUtil.mul(div, batteryCapacity); + if (hour > 0) { + segment.setPowerConsume(NumberUtil.div(mul,hour,2)); + } + } + segment.setBatteryCapacity(new BigDecimal(batteryCapacity)); + }else{ + double distance = CalcTool.getDistance(segment.getLon().doubleValue(),segment.getLat().doubleValue(),gps.getLon().doubleValue(),gps.getLat().doubleValue()); + if(segment.getDuration()>0 && distance /segment.getDuration() < 0.055 ){ + segment.setMile(segment.getMile().add(new BigDecimal(distance))); + segment.setLon(gps.getLon()); + segment.setLat(gps.getLat()); + } + } + } + + public static List processGpsData(List gpsDataList) { + if (gpsDataList == null || gpsDataList.isEmpty()) { + return new ArrayList<>(); + } + List processedList = new ArrayList<>(); + int isWork = 0; + Date workStartTime = null; + boolean withinWork = false; + long timeThreshold = 1 * 60 * 1000; + for (TbGisGps currentData : gpsDataList) { + if (currentData.getSpeed().compareTo(new BigDecimal(2)) >= 0 && currentData.getSpeed().compareTo(new BigDecimal(20)) <= 0) { + if (isWork == 0) { + if(!withinWork){ + workStartTime = currentData.getGpsTime(); + withinWork = true; + }else{ + long timeDifference = currentData.getGpsTime().getTime() - workStartTime.getTime(); + if(timeDifference >= timeThreshold){ + isWork = 1; + } + } + } + } else { + if (isWork == 1) { + long timeDifference = currentData.getGpsTime().getTime() - workStartTime.getTime(); + if (timeDifference >= timeThreshold) { + isWork = 0; + withinWork = false; + } + } + } + currentData.setIsWork(isWork); + processedList.add(currentData); + } + return processedList; + } + + private boolean isWorking(TbGisGps gps) { + return Objects.nonNull(gps.getIsWork()) && gps.getIsWork() == 1; +// // 增加一个次数变量来跟踪连续行驶的时间 +// int consecutiveDrivingTimeInSeconds = 0; +// boolean isWorking = false; +// +// // 检查GPS数据是否满足条件 +// if (gps.getAcc() % 2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0) { +// // 如果已经在作业状态,增加连续行驶时间 +// if (isWorking) { +// consecutiveDrivingTimeInSeconds++; +// } else { +// // 否则,将状态设置为作业状态,并将时间重置为1 +// isWorking = true; +// consecutiveDrivingTimeInSeconds = 1; +// } +// +// // 检查连续行驶时间是否达到2分钟 +// if (consecutiveDrivingTimeInSeconds >= 120) { +// // 检查速度是否在2-20码之间 +// if (gps.getSpeed().compareTo(new BigDecimal(2)) >= 0 && gps.getSpeed().compareTo(new BigDecimal(20)) <= 0) { +// // 符合作业条件 +// return true; +// } +// } +// } else { +// // 如果不满足条件,将状态重置为非作业状态 +// isWorking = false; +// consecutiveDrivingTimeInSeconds = 0; +// } +// return false; + } + + /** + * 行驶作业 点火且速度大于0 + * + * @param gps + * @return + */ + private boolean isDrivingWorkFlm(TbGisGps gps) { + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0 && isWorking(gps); + } + + /** + * 行驶未作业 点火、速度大于0、且未作业 + * + * @param gps + * @return + */ + private boolean isDrivingNotWorkFlm(TbGisGps gps) { + // 根据规则判断是否为“行驶未作业” + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0 && !isWorking(gps); + } + + + /** + * 停靠作业 点火 速度小于等于0 且在作业 或者 熄火 且在作业 + * + * @param gps + * @return + */ + private boolean isStoppedWorkFlm(TbGisGps gps) { + return (gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) <= 0 && isWorking(gps)) || (gps.getAcc() == 0 && isWorking(gps)); + } + + /** + * 停靠未作业 点火 速度小于等于0 且未作业 或者 熄火 且未作业 + * + * @param gps + * @return + */ + private boolean isStoppedNotWorkFlm(TbGisGps gps) { + return (gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) <= 0 && !isWorking(gps)) || (gps.getAcc() == 0 && !isWorking(gps)); + } + + + @Override + public IPage everydayGis(Page page, EverydayQuery query) { + checkTime(query); + ArrayList gisVoArrayList = new ArrayList<>(); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(GisGpsAnalysis.class, query); + List list = list(lambdaQueryWrapper); + Map>> collect1 = list.stream().collect(Collectors.groupingBy(GisGpsAnalysis::getOwnDate, Collectors.groupingBy(GisGpsAnalysis::getNumberPlate))); + + for (Map.Entry>> dateMapEntry : collect1.entrySet()) { + for (Map.Entry> stringListEntry : dateMapEntry.getValue().entrySet()) { + String key = stringListEntry.getKey(); + List value = stringListEntry.getValue(); + GisGpsAnalysis first = value.get(0); + EverydayGisVo everydayGisVo = new EverydayGisVo(); + everydayGisVo.setProjectId(first.getProjectId()); + everydayGisVo.setPlateNumber(first.getNumberPlate()); + everydayGisVo.setVehicleType(first.getVehicleType()); + everydayGisVo.setVehicleBrand(first.getVehicleBrand()); + everydayGisVo.setVehicleModel(first.getVehicleModel()); + everydayGisVo.setStatisTime(DateUtil.formatDate(first.getOwnDate())); + //行驶里程 + BigDecimal totalMile = BigDecimal.ZERO; + //作业里程 + BigDecimal workMile = BigDecimal.ZERO; + //行驶时间 + BigDecimal totalTime = BigDecimal.ZERO; + //作业时间 + BigDecimal workTime = BigDecimal.ZERO; + //行驶作业时间 + BigDecimal travelWorkTime = BigDecimal.ZERO; + //停靠作业时长 + BigDecimal stopWorkTime = BigDecimal.ZERO; + //平均行驶速度 + BigDecimal avgSpeed; + //平均作业速度 + BigDecimal avgWorkSpeed; + //作业开始时间 + Date workStartTime = null; + //作业结束时间 + Date workEndTime = null; + //在线时长 + BigDecimal onlineTime = BigDecimal.ZERO; + //通电停靠时长 + BigDecimal onlineStopTime = BigDecimal.ZERO; + for (GisGpsAnalysis gisGpsAnalysis : value) { + BigDecimal duration = BigDecimal.valueOf(gisGpsAnalysis.getDuration()); + //计算在线时长 + onlineTime = onlineTime.add(duration); + if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Driving_Not_Work.getValue()) { + //行驶未作业 + //计算行驶里程 + totalMile = totalMile.add(gisGpsAnalysis.getMile()); + //计算行驶时长 + totalTime = totalTime.add(duration); + } else if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Driving_Work.getValue()) { + //行驶作业 + //计算行驶里程 + totalMile = totalMile.add(gisGpsAnalysis.getMile()); + //计算行驶时长 + totalTime = totalTime.add(duration); + //计算作业里程 + workMile = workMile.add(gisGpsAnalysis.getMile()); + //计算作业时长 + workTime = workTime.add(duration); + //计算行驶作业时长 + travelWorkTime = travelWorkTime.add(duration); + //计算作业开始时间 + if (workStartTime == null || workStartTime.after(gisGpsAnalysis.getStartTime())) { + workStartTime = gisGpsAnalysis.getStartTime(); + } + //计算作业结束时间 + if (gisGpsAnalysis.getEndTime() != null) { + if (workEndTime == null || workEndTime.before(gisGpsAnalysis.getEndTime())) { + workEndTime = gisGpsAnalysis.getEndTime(); + } + } + } else if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Stopped_Work.getValue()) { + //停靠作业 + //计算作业里程 + workMile = workMile.add(gisGpsAnalysis.getMile()); + //计算作业时长 + workTime = workTime.add(duration); + //计算停靠作业时长 + stopWorkTime = stopWorkTime.add(duration); + //计算作业开始时间 + if (workStartTime == null || workStartTime.after(gisGpsAnalysis.getStartTime())) { + workStartTime = gisGpsAnalysis.getStartTime(); + } + //计算作业结束时间 + if (gisGpsAnalysis.getEndTime() != null) { + if (workEndTime == null || workEndTime.before(gisGpsAnalysis.getEndTime())) { + workEndTime = gisGpsAnalysis.getEndTime(); + } + } + } else if (gisGpsAnalysis.getRecordType() == VehicleGpsType.Stopped_NOT_Work.getValue()) { + //停靠未作业 + onlineStopTime = onlineStopTime.add(duration); + } + } + if (totalTime.compareTo(BigDecimal.ZERO)>0) { + avgSpeed = NumberUtil.div(totalMile,NumberUtil.div(totalTime,3600)).setScale(2,BigDecimal.ROUND_HALF_UP); + everydayGisVo.setAvgSpeed(avgSpeed); + } + if (travelWorkTime.compareTo(BigDecimal.ZERO)>0) { + avgWorkSpeed = NumberUtil.div(workMile,NumberUtil.div(workTime,3600)).setScale(2,BigDecimal.ROUND_HALF_UP); + everydayGisVo.setAvgWorkSpeed(avgWorkSpeed); + } + everydayGisVo.setTotalMile(totalMile.setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setWorkMile(workMile.setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setTotalTime(NumberUtil.div(totalTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setWorkTime(NumberUtil.div(workTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setTravelWorkTime(NumberUtil.div(travelWorkTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setStopWorkTime(NumberUtil.div(stopWorkTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setWorkStartTime(workStartTime); + everydayGisVo.setWorkEndTime(workEndTime); + everydayGisVo.setOnlineTime(NumberUtil.div(onlineTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + everydayGisVo.setOnlineStopTime(NumberUtil.div(onlineStopTime,3600).setScale(2,BigDecimal.ROUND_HALF_UP)); + gisVoArrayList.add(everydayGisVo); + } + } + gisVoArrayList.sort(Comparator.comparing(EverydayGisVo::getStatisTime)); + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(gisVoArrayList.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(gisVoArrayList.size()); + page.setPages(totalPage); + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > gisVoArrayList.size()) { + endIndex = gisVoArrayList.size(); + } + page.setRecords(gisVoArrayList.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } + + + private static List mergeGisData(List inputList,boolean isEic) { + if (inputList == null || inputList.isEmpty()) { + return inputList; + } + List mergedList = new ArrayList<>(); + GisGpsAnalysis previousData = null; + + for (GisGpsAnalysis currentData : inputList) { + if (previousData == null) { + previousData = currentData; + } else { + if (areMergable(previousData, currentData,isEic)) { + mergeData(previousData, currentData,isEic); + } else { + mergedList.add(previousData); + previousData = currentData; + } + } + } + if (previousData != null) { + mergedList.add(previousData); + } + return mergedList; + } + + private static long calculateTimeDifferenceInMinutes(Date startTime, Date endTime) { + long timeDifference = endTime.getTime() - startTime.getTime(); + return timeDifference / (1000 * 60); + } + + private static boolean areMergable(GisGpsAnalysis previousData, GisGpsAnalysis currentData,boolean isEic) { + if(isEic){ + return (!previousData.getRecordType().equals(currentData.getRecordType()) && currentData.getDuration() < 120 && + (currentData.getRecordType() == 3 || currentData.getRecordType() == 4) && + calculateTimeDifferenceInMinutes(previousData.getEndTime(), currentData.getStartTime()) <= 2) + || (previousData.getRecordType().equals(currentData.getRecordType()) && calculateTimeDifferenceInMinutes(previousData.getEndTime(), currentData.getStartTime()) <= 5 ); + }else{ + return (!previousData.getRecordType().equals(currentData.getRecordType()) && currentData.getDuration() < 120 && + calculateTimeDifferenceInMinutes(previousData.getEndTime(), currentData.getStartTime()) <= 2) + || (previousData.getRecordType().equals(currentData.getRecordType()) && calculateTimeDifferenceInMinutes(previousData.getEndTime(), currentData.getStartTime()) <= 5 ); + } + } + + private static void mergeData(GisGpsAnalysis previousData, GisGpsAnalysis currentData,boolean isEic) { + previousData.setEndTime(currentData.getEndTime()); + + Long duration = DateUtil.betweenMs(previousData.getEndTime(),previousData.getStartTime())/1000; + previousData.setDuration(duration); + if(isEic){ + previousData.setEndMile(currentData.getEndMile()); + BigDecimal totalMileage = previousData.getEndMile().subtract(previousData.getStartMile()); + previousData.setMile(totalMileage); + }else{ + previousData.setMile(previousData.getMile().add(currentData.getMile())); + } + +// previousData.setRecordType(currentData.getRecordType()); + + if(ObjectUtil.isAllNotEmpty(previousData.getEndSoc(),currentData.getEndSoc())){ + previousData.setEndSoc(currentData.getEndSoc()); + } + if(ObjectUtil.isAllNotEmpty(previousData.getPowerConsume(),currentData.getPowerConsume())){ + BigDecimal totalPowerConsume = previousData.getPowerConsume().add(currentData.getPowerConsume()); + previousData.setPowerConsume(totalPowerConsume); + }else{ + previousData.setPowerConsume(previousData.getPowerConsume()); + } + } + + private void checkTime(EverydayQuery query) { + List time = query.getTime(); + if (ObjectUtil.isNotEmpty(time)) { + if (time.size()!=2) { + throw new GciBootException("查询必须包括起止时间!"); + } else { + if (time.get(0).after(time.get(1))) { + throw new GciBootException("查询开始时间需要大于结束时间!"); + } else { + if (DateUtil.between(time.get(0),time.get(1), DateUnit.DAY) > 30) { + throw new GciBootException("查询间隔不能超过30天!"); + } + } + } + } else { + throw new GciBootException("查询起止时间不能为空!"); + } + } + + @Override + public EverydayMileCountVo everydayMileCount(EverydayQuery query) { + checkTime(query); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(GisGpsAnalysis.class, query,true); + List everydayMileCountDtoList = gisGpsAnalysisMapper.everydayMileCount(lambdaQueryWrapper,query); + BigDecimal totalMile = everydayMileCountDtoList.stream().filter(i ->i.getRecordType() == VehicleGpsType.Driving_Work.getValue() || i.getRecordType() == VehicleGpsType.Driving_Not_Work.getValue()).map(EverydayMileCountDto::getSum).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal workMile = everydayMileCountDtoList.stream().filter(i -> i.getRecordType() == VehicleGpsType.Driving_Work.getValue() || i.getRecordType() == VehicleGpsType.Stopped_Work.getValue()).map(EverydayMileCountDto::getSum).reduce(BigDecimal.ZERO, BigDecimal::add); + EverydayMileCountVo vo = new EverydayMileCountVo(); + vo.setTotalMile(totalMile); + vo.setWorkMile(workMile); + return vo; + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/GisRoadMileLogServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/GisRoadMileLogServiceImpl.java new file mode 100644 index 0000000..eac5f19 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/GisRoadMileLogServiceImpl.java @@ -0,0 +1,255 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.BetweenFormatter; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.util.CoordinateConverterUtil; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.LatLonPoint; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.dataview.vo.GisRoadMileVo; +import com.gci.boot.modules.gis.entity.GisRoadMileLog; +import com.gci.boot.modules.gis.entity.TbGisChargeLog; +import com.gci.boot.modules.gis.entity.TbGisGps; +import com.gci.boot.modules.gis.mapper.GisRoadMileLogMapper; +import com.gci.boot.modules.gis.mapper.TbGisChargeLogMapper; +import com.gci.boot.modules.gis.service.GisRoadMileLogService; +import com.gci.boot.modules.gis.service.ITbGisChargeLogService; +import com.gci.boot.modules.gis.service.ITbGisGpsService; +import com.gci.boot.modules.gis.vo.GisHistoryVo; +import com.gci.boot.modules.gis.vo.PointListDTO; +import com.gci.boot.modules.gis.vo.TimeSlotDTO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 行驶里程能耗记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class GisRoadMileLogServiceImpl extends ServiceImpl implements GisRoadMileLogService { + + @Autowired + private ISysDictService sysDictService; + + @Autowired + private GisRoadMileLogMapper gisRoadMileLogMapper; + + @Autowired + private ITbGisGpsService tbGisGpsService; + + @Autowired + private ITbVehicleService vehicleService; + @Value("${gps.timeCut}") + private Long timeCut; + + @Override + public List countByTime(Date startTime, Date endTime) { + List modelList = sysDictService.queryDictItemsByCode("vehicle_type"); + List dbList = gisRoadMileLogMapper.countByTime(startTime, endTime); + List resultList = modelList.stream().map(a -> { + GisRoadMileVo vo = new GisRoadMileVo(); + vo.setVehicleType(a.getValue()); + vo.setVehicleTypeName(a.getText()); + BigDecimal averageEnergy = dbList.stream().filter(db -> { + return db.getVehicleType().equals(a.getValue()); + }).map(db -> { + return db.getAverageEnergy(); + }).findFirst().orElse(new BigDecimal(0)); + vo.setAverageEnergy(averageEnergy.setScale(4, BigDecimal.ROUND_HALF_UP)); + return vo; + }).collect(Collectors.toList()); + resultList.sort(Comparator.comparing(GisRoadMileVo::getAverageEnergy).reversed()); + return resultList; + } + + @Override + public void coverGpsToRoadMile(TbVehicle vehicle, Date startTime, Date endTime) { + Integer batteryCapacity = ObjectUtil.isEmpty(vehicle.getBatteryCapacity()) ? 0 : vehicle.getBatteryCapacity(); + //构建gps数据记录查询 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbGisGps::getPlateNumber, vehicle.getPlateNumber()); + queryWrapper.between(TbGisGps::getGpsTime, startTime, endTime); + queryWrapper.eq(TbGisGps::getIsValid, 1); + queryWrapper.orderByAsc(TbGisGps::getGpsTime); + List gpsList = tbGisGpsService.list(queryWrapper); + //只取三电记录的gps数据 + List list = gpsList.stream().filter(g -> g.getRecordSource().equals(2)).collect(Collectors.toList()); + if(list.isEmpty()){ + return; + } + List> lists =groupByStatusAndTime(list); + List logs = new ArrayList<>(); + if (ObjectUtil.isNotEmpty(lists)) { + for (List tbGisGps : lists) { + if (ObjectUtil.isEmpty(tbGisGps)) { + continue; + } + + + TbGisGps startGisGps = tbGisGps.get(0); + TbGisGps endGisGps = tbGisGps.get(tbGisGps.size() - 1); + + Date startGisGpsGpsTime = startGisGps.getGpsTime(); + Date endGisGpsGpsTime = endGisGps.getGpsTime(); + BigDecimal startGisGpsTotalMileage = startGisGps.getTotalMileage(); + BigDecimal endGisGpsTotalMileage = endGisGps.getTotalMileage(); + + + if (startGisGpsTotalMileage.compareTo(endGisGpsTotalMileage) == 0) { + continue; + } + + Integer startGisGpsStateOfCharge = startGisGps.getStateOfCharge(); + Integer endGisGpsStateOfCharge = endGisGps.getStateOfCharge(); + + String day = DateUtil.format(startGisGpsGpsTime, "yyyy-MM-dd"); + + GisRoadMileLog log = new GisRoadMileLog(); + log.setNumberPlate(vehicle.getPlateNumber()); + log.setProjectId(vehicle.getProjectId()); + log.setProjectName(""); + log.setVehicleBrand(vehicle.getVehicleBrand()); + log.setVehicleModel(vehicle.getVehicleModel()); + log.setVehicleType(vehicle.getVehicleType()); + log.setVinCode(vehicle.getVinCode()); + log.setStartTime(startGisGpsGpsTime); + log.setEndTime(endGisGpsGpsTime); + log.setOwnDate(day); + log.setCreateTime(new Date()); + + if (ObjectUtil.isAllNotEmpty(startGisGpsTotalMileage, endGisGpsTotalMileage)) { + log.setRoadMile((NumberUtil.sub(endGisGpsTotalMileage, startGisGpsTotalMileage))); + } + if (ObjectUtil.isAllNotEmpty(startGisGpsStateOfCharge,endGisGpsStateOfCharge, batteryCapacity)) { +// double hour = betweenHour(startGisGpsGpsTime, endGisGpsGpsTime); + BigDecimal sub = NumberUtil.sub(startGisGpsStateOfCharge, endGisGpsStateOfCharge); + BigDecimal div = NumberUtil.div(sub, 100); + BigDecimal mul = NumberUtil.mul(div, batteryCapacity); + log.setPowerConsume(mul); + // TODO: 2023/11/22 不需要处理小时。记录这段时间总的耗电量即可 +// if (hour > 0) { +// log.setPowerConsume(NumberUtil.div(mul,hour,2)); +// } + } + logs.add(log); + } + } + if(!logs.isEmpty()){ + this.saveBatch(logs); + } + } + + private List> groupByStatusAndTime(List list) { + // 创建一个空的结果列表 + List> result = new ArrayList<>(); + // 创建一个临时的子列表,用于存放符合条件的元素 + List subList = new ArrayList<>(); + // 创建速度缓存的 + ArrayList timeList = new ArrayList<>(); + // 遍历输入列表中的每个元素 + for (int i = 0; i < list.size(); i++) { + // 获取当前元素 + TbGisGps current = list.get(i); + // 获取当前状态 1-点火 0-熄火 + int currentStatus = current.getCurrentStatus(); + current.setCerStatus(currentStatus); + if(current.getChargeStatus() != 3){ + continue; + } + // 点火状态时 + if (currentStatus == 1) { + //临时列表为空或者上一个也是点火状态 + if (subList.isEmpty() || subList.get(subList.size() - 1).getCerStatus() == currentStatus) { + if (!subList.isEmpty()) { + TbGisGps tbGisGps = subList.get(subList.size() - 1); + //如果超过了间隔就截断 + long between = DateUtil.between(tbGisGps.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + timeList = new ArrayList<>(); + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + } + } + //没速度先缓存到时间缓存列表里面 + if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) == 0) { + timeList.add(current); + } else { + //有速度判断一下是否抛弃数据 + if (!timeList.isEmpty()) { + TbGisGps last = timeList.get(0); + //当前的速度不为零时 超过了设置时间 + long between = DateUtil.between(last.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + //清空速度缓存 + timeList = new ArrayList<>(); + //结束临时列表 + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + } else { + //新数据上来了 并且没有超过设置时间 + //将时间缓存加入临时列表 + subList.addAll(timeList); + //清空时间缓存 + timeList = new ArrayList<>(); + } + } + subList.add(current); + } + } + } else if (currentStatus == 0) { + //熄火状态时 + //临时列表不为空 + if (!subList.isEmpty()&¤t.getTotalMileage().compareTo(subList.get(subList.size()-1).getTotalMileage())==1) { + //时间缓存不为空 + if (!timeList.isEmpty()) { + timeList = new ArrayList<>(); + } + //加入结束点 +// subList.add(current); + result.add(subList); + //新建临时列表 + subList = new ArrayList<>(); + } + } + } + // 遍历结束后,判断临时列表是否为空 + if (!subList.isEmpty()) { + result.add(subList); + } + // 返回结果列表 + return result; + } + + private double betweenHour(Date startTime,Date endTime) { + return Convert.toDouble(DateUtil.betweenMs(startTime, endTime)) / 3600000; + } + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/RefuelAlarmServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/RefuelAlarmServiceImpl.java new file mode 100644 index 0000000..52e94f2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/RefuelAlarmServiceImpl.java @@ -0,0 +1,133 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Segment; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.PageUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.gis.entity.RefuelAlarm; +import com.gci.boot.modules.gis.mapper.RefuelAlarmMapper; +import com.gci.boot.modules.gis.service.IRefuelAlarmService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.vehicles.entity.TbRefuelChargeRecord; +import com.gci.boot.modules.vehicles.service.ITbRefuelChargeRecordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author 24642 + */ +@Service +public class RefuelAlarmServiceImpl extends ServiceImpl implements IRefuelAlarmService { + + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbRefuelChargeRecordService recordService; + @Autowired + private ITbVehicleService vehicleService; + + @Override + public IPage pageBuild(Page page,RefuelAlarm query) { + List recordList = new ArrayList<>(); + List allProjectListOfUser = projectsService.queryAllProjectListOfUser(); + if (allProjectListOfUser.isEmpty()) { + return page; + } + if (StrUtil.isNotBlank(query.getProjectId())) { + if (!allProjectListOfUser.contains(query.getProjectId())) { + return page; + } else { + allProjectListOfUser.clear(); + allProjectListOfUser.add(query.getProjectId()); + } + } + + List vehicles = vehicleService.list(new LambdaQueryWrapper() + .like(StrUtil.isNotBlank(query.getPlateNumber()),TbVehicle::getPlateNumber,query.getPlateNumber()) + .eq(StrUtil.isNotBlank(query.getVehicleType()),TbVehicle::getVehicleType,query.getVehicleType()) + .like(StrUtil.isNotBlank(query.getFrameNumber()),TbVehicle::getFrameNumber,query.getFrameNumber())); + if (vehicles.isEmpty()) { + return page; + } + List plateNumbers = vehicles.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList()); + List list = recordService.list(new LambdaQueryWrapper() + .eq(TbRefuelChargeRecord::getRefuelType, '1') + .in(TbRefuelChargeRecord::getProjectId,allProjectListOfUser) + .in(TbRefuelChargeRecord::getPlateNumber,plateNumbers) + .ge(ObjectUtil.isNotNull(query.getStartTime()),TbRefuelChargeRecord::getStartTime,query.getStartTime()) + .le(ObjectUtil.isNotNull(query.getEndTime()),TbRefuelChargeRecord::getEndTime,query.getEndTime()) + .isNotNull(TbRefuelChargeRecord::getStartTime) + .isNotNull(TbRefuelChargeRecord::getEndTime) + .orderByAsc(TbRefuelChargeRecord::getPlateNumber) + .orderByAsc(TbRefuelChargeRecord::getRecordDate) + .orderByAsc(TbRefuelChargeRecord::getStartTime) + ); + if (list.isEmpty()) { + return page; + } + Map>> stringMapMap = CollStreamUtil.groupBy2Key(list, TbRefuelChargeRecord::getPlateNumber, TbRefuelChargeRecord::getRecordDate); + Set>>> entries = stringMapMap.entrySet(); + for (Map.Entry>> entry : entries) { + Map> value = entry.getValue(); + Set>> entries1 = value.entrySet(); + for (Map.Entry> dateListEntry : entries1) { + List value1 = dateListEntry.getValue(); + if (value1.size() > 1) { + for (int i = 0; i < value1.size() -1; i++) { + TbRefuelChargeRecord cur = value1.get(i); + TbRefuelChargeRecord next = value1.get(i + 1); + + TbVehicle vehicle = vehicles.stream().filter(v -> v.getPlateNumber().equals(entry.getKey())).findFirst().orElse(null); + if (vehicle == null) { + continue; + } + + RefuelAlarm refuelAlarm = new RefuelAlarm(); + refuelAlarm.setStartTime(cur.getStartTime()); + refuelAlarm.setEndTime(next.getEndTime()); + refuelAlarm.setPlateNumber(vehicle.getPlateNumber()); + refuelAlarm.setVehicleType(vehicle.getVehicleType()); + refuelAlarm.setFrameNumber(vehicle.getFrameNumber()); + refuelAlarm.setVehicleModel(vehicle.getVehicleModel()); + refuelAlarm.setProjectId(cur.getProjectId()); + refuelAlarm.setAlarm(0); + recordList.add(refuelAlarm); + } + } + } + } + if (query.getAlarm() != null) { + recordList = recordList.stream().filter(r->r.getAlarm()!=null&&r.getAlarm().equals(query.getAlarm())).collect(Collectors.toList()); + } + recordList.sort(Comparator.comparing(RefuelAlarm::getStartTime).thenComparing(RefuelAlarm::getPlateNumber)); + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(recordList.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(recordList.size()); + page.setPages(totalPage); + if (page.getSize() == -1) { + page.setRecords(recordList); + return page; + } + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > recordList.size()) { + endIndex = recordList.size(); + } + page.setRecords(recordList.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisActiveSafetyAlarmServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisActiveSafetyAlarmServiceImpl.java new file mode 100644 index 0000000..94dc003 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisActiveSafetyAlarmServiceImpl.java @@ -0,0 +1,105 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.text.StrBuilder; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.enums.EventCharacteristicsType; +import com.gci.boot.enums.EventType; +import com.gci.boot.modules.gis.entity.TbGisActiveSafetyAlarm; +import com.gci.boot.modules.gis.mapper.TbGisActiveSafetyAlarmMapper; +import com.gci.boot.modules.gis.service.ITbGisActiveSafetyAlarmService; +import com.gci.boot.modules.statis.vo.AlarmTrendVO; +import com.gci.boot.modules.system.service.ISysDictService; +import org.aspectj.weaver.ast.Var; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; + +/** + *

+ * 主动安全故障记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class TbGisActiveSafetyAlarmServiceImpl extends ServiceImpl implements ITbGisActiveSafetyAlarmService { + + @Autowired + private TbGisActiveSafetyAlarmMapper tbGisActiveSafetyAlarmMapper; + @Autowired + private ISysDictService sysDictService; + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + Page alarmPage = tbGisActiveSafetyAlarmMapper.pageBuild(page, lambdaQueryWrapper); + List records = alarmPage.getRecords(); + if (ObjectUtil.isNotEmpty(records)) { + buildEventCharacteristics(records); + } + return alarmPage; + } + + @Override + public List findListByTime(Date startTime, Date endTime) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.between(TbGisActiveSafetyAlarm::getAlertStartTime,startTime, endTime); + List list = tbGisActiveSafetyAlarmMapper.selectList(queryWrapper); + return list; + } + + @Override + public List findTrendListByTime(Date startTime, Date endTime) { + return tbGisActiveSafetyAlarmMapper.findTrendListByTime(DateUtils.formatTime(startTime),DateUtils.formatTime(endTime)); + } + + /** + * 补充下描述 + * + * @param records + */ + private void buildEventCharacteristics(List records) { + EventCharacteristicsType[] values = EventCharacteristicsType.values(); + StrBuilder strBuilder = new StrBuilder(); + for (TbGisActiveSafetyAlarm record : records) { + strBuilder.clear(); + for (EventCharacteristicsType value : values) { + List eventTypeList = value.getEventTypeList(); + for (EventType eventType : eventTypeList) { + if (eventType.getDescription().equals(record.getEventName())) { + if (value.getDictCode() != null) { + if (StrUtil.isNotBlank(strBuilder)) { + strBuilder.append("/"); + } + String format = StrUtil.format(value.getDesc(), sysDictService.queryDictTextByKey(value.getDictCode(), String.valueOf(ReflectUtil.getFieldValue(record, value.getFieldName())))); + if (StrUtil.isNotBlank(format)) { + strBuilder.append(format); + } + } else { + if (StrUtil.isNotBlank(strBuilder)) { + strBuilder.append("/"); + } + String format = StrUtil.format(value.getDesc(), String.valueOf(ReflectUtil.getFieldValue(record, value.getFieldName()))); + if (StrUtil.isNotBlank(format)) { + strBuilder.append(format); + } + } + } + } + } + if (StrUtil.isNotBlank(strBuilder)) { + record.setEventCharacteristics(strBuilder.toString()); + } + } + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisChargeLogServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisChargeLogServiceImpl.java new file mode 100644 index 0000000..a6372d9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisChargeLogServiceImpl.java @@ -0,0 +1,41 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.date.BetweenFormatter; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.gis.entity.TbGisChargeLog; +import com.gci.boot.modules.gis.mapper.TbGisChargeLogMapper; +import com.gci.boot.modules.gis.service.ITbGisChargeLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + *

+ * 充电记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class TbGisChargeLogServiceImpl extends ServiceImpl implements ITbGisChargeLogService { + + @Autowired + private TbGisChargeLogMapper gisChargeLogMapper; + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + Page chargeLogPage = gisChargeLogMapper.pageBuild(page, lambdaQueryWrapper); + for (TbGisChargeLog record : chargeLogPage.getRecords()) { + if (ObjectUtil.isAllNotEmpty(record.getStartTime(),record.getEndTime())) { + String s = DateUtil.formatBetween(record.getStartTime(), record.getEndTime(), BetweenFormatter.Level.SECOND); + record.setDuration(s); + } + } + return chargeLogPage; + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceAlarmServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceAlarmServiceImpl.java new file mode 100644 index 0000000..a549137 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceAlarmServiceImpl.java @@ -0,0 +1,40 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.date.BetweenFormatter; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.util.FormatUtil; +import com.gci.boot.modules.gis.entity.TbGisFenceAlarm; +import com.gci.boot.modules.gis.mapper.TbGisFenceAlarmMapper; +import com.gci.boot.modules.gis.service.ITbGisFenceAlarmService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + *

+ * 围栏告警记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class TbGisFenceAlarmServiceImpl extends ServiceImpl implements ITbGisFenceAlarmService { + + @Autowired + private TbGisFenceAlarmMapper gisFenceAlarmMapper; + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + Page list = gisFenceAlarmMapper.pageBuild(page, lambdaQueryWrapper); + for (TbGisFenceAlarm record : list.getRecords()) { + String duration = FormatUtil.formattedTimeDifference(record.getStartTime(), record.getEndTime()); + record.setDuration(duration); + } + return list; + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceInfoServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceInfoServiceImpl.java new file mode 100644 index 0000000..9dceeb7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.gis.service.impl; + +import com.gci.boot.modules.gis.entity.TbGisFenceInfo; +import com.gci.boot.modules.gis.mapper.TbGisFenceInfoMapper; +import com.gci.boot.modules.gis.service.ITbGisFenceInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 围栏信息表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-08-30 + */ +@Service +public class TbGisFenceInfoServiceImpl extends ServiceImpl implements ITbGisFenceInfoService { + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFencePlanServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFencePlanServiceImpl.java new file mode 100644 index 0000000..126c151 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFencePlanServiceImpl.java @@ -0,0 +1,361 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.LatLonPoint; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.gis.entity.TbGisFenceInfo; +import com.gci.boot.modules.gis.entity.TbGisFencePlan; +import com.gci.boot.modules.gis.entity.TbGisFenceVehicle; +import com.gci.boot.modules.gis.mapper.TbGisFencePlanMapper; +import com.gci.boot.modules.gis.service.ITbGisFenceInfoService; +import com.gci.boot.modules.gis.service.ITbGisFencePlanService; +import com.gci.boot.modules.gis.service.ITbGisFenceVehicleService; +import com.gci.boot.modules.gis.vo.GisProjectTreeVo; +import com.gci.boot.modules.gis.vo.GisRedisVehicleVo; +import com.gci.boot.modules.gis.vo.GisVehicleVo; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 围栏方案表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-08-30 + */ +@Service +public class TbGisFencePlanServiceImpl extends ServiceImpl implements ITbGisFencePlanService { + + @Resource + private TbGisFencePlanMapper fencePlanMapper; + @Autowired + private ITbGisFenceInfoService fenceInfoService; + @Autowired + private ITbGisFenceVehicleService fenceVehicleService; + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbVehicleService vehicleService; + + @Override + public void saveItem(TbGisFencePlan tbGisFencePlan) { + checkTime(tbGisFencePlan); + String projectId = tbGisFencePlan.getProjectId(); + Projects byId = projectsService.getById(projectId); + if (BeanUtil.isEmpty(byId) || byId.getCancelFlag() == 1) { + throw new GciBootException("该项目不存在或者已经禁用,请重新选择项目!"); + } + save(tbGisFencePlan); + List gisFenceInfoList = tbGisFencePlan.getGisFenceInfoList(); + gisFenceInfoList.forEach(i -> { + i.setPlanId(tbGisFencePlan.getId()); + i.setPlanName(tbGisFencePlan.getName()); + }); + fenceInfoService.saveBatch(gisFenceInfoList); + findAndUpdateVehicleRedis(tbGisFencePlan.getId()); + } + + /** + * 校验时间先后 + * + * @param tbGisFencePlan + */ + private void checkTime(TbGisFencePlan tbGisFencePlan) { + String startTime = tbGisFencePlan.getStartTime(); + String endTime = tbGisFencePlan.getEndTime(); + DateTime start = DateUtil.parse(startTime); + DateTime end = DateUtil.parse(endTime); + if (tbGisFencePlan.getIsOvernight() == 0) { + if (DateUtil.between(start, end, DateUnit.MINUTE, false) < 0) { + throw new GciBootException("开始时间不能大于结束时间"); + } + } else { + long between = DateUtil.between(start, DateUtil.offset(end, DateField.DAY_OF_MONTH, 1), DateUnit.HOUR); + if (between > 24) { + throw new GciBootException("时间间隔不能超过24小时"); + } + } + } + + @Override + public void updateItem(TbGisFencePlan tbGisFencePlan) { + checkTime(tbGisFencePlan); + String projectId = tbGisFencePlan.getProjectId(); + Projects byId = projectsService.getById(projectId); + if (BeanUtil.isEmpty(byId) || byId.getCancelFlag() == 1) { + throw new GciBootException("该项目不存在或者已经禁用,请重新选择项目!"); + } + updateById(tbGisFencePlan); + //清空旧的在保存新的 + fenceInfoService.remove(new LambdaQueryWrapper().eq(TbGisFenceInfo::getPlanId, tbGisFencePlan.getId())); + List gisFenceInfoList = tbGisFencePlan.getGisFenceInfoList(); + gisFenceInfoList.forEach(i -> { + i.setPlanId(tbGisFencePlan.getId()); + i.setPlanName(tbGisFencePlan.getName()); + }); + fenceInfoService.saveBatch(gisFenceInfoList); + findAndUpdateVehicleRedis(tbGisFencePlan.getId()); + } + + @Override + public void saveVehicle(GisVehicleVo vo) { + checkVehicle(vo.getVehicleList()); + + saveFenceVehicle(vo); + } + + /** + * 检查是否已有车辆 + * + * @param vehicleList + */ + private void checkHadVehicle(GisVehicleVo vehicleList) { + LambdaQueryWrapper in = new LambdaQueryWrapper().in(TbGisFenceVehicle::getPlateNumber, vehicleList.getVehicleList()).eq(TbGisFenceVehicle::getPlanId,vehicleList.getPlanId()); + int count = fenceVehicleService.count(in); + if (count > 0) { + throw new GciBootException("已有对应关联车辆!"); + } + } + + @Override + public void delVehicle(GisVehicleVo vo) { + checkVehicle(vo.getVehicleList()); + delFenceVehicle(vo); + } + + @Override + public void isValid(String id) { + TbGisFencePlan gisFencePlan = getById(id); + + gisFencePlan.setIsValid(1); + updateById(gisFencePlan); + //车辆列表 + findAndUpdateVehicleRedis(id); + } + + /** + * 根据方案id更新车辆redis + * + * @param id + */ + private void findAndUpdateVehicleRedis(String id) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(TbGisFenceVehicle::getPlanId, id); + List gisFenceVehicleList = fenceVehicleService.list(wrapper); + if (ObjectUtil.isNotEmpty(gisFenceVehicleList)) { + updateVehicleRedis(gisFenceVehicleList); + } + } + + @Override + public void unValid(String id) { + TbGisFencePlan gisFencePlan = getById(id); + gisFencePlan.setIsValid(0); + updateById(gisFencePlan); + //车辆列表 + findAndUpdateVehicleRedis(id); + } + + @Override + public Page getPlanVehicleList(String id, Page page) { + List list = fenceVehicleService.list(new LambdaQueryWrapper().eq(TbGisFenceVehicle::getPlanId, id)); + if (ObjectUtil.isNotEmpty(list)) { + return vehicleService.page(page,new LambdaQueryWrapper().in(TbVehicle::getPlateNumber, list.stream().map(TbGisFenceVehicle::getPlateNumber).collect(Collectors.toList())).eq(TbVehicle::getCancelFlag, 0)); + } + return page; + } + + @Override + public List getProjectVehicleList(String id) { + TbGisFencePlan byId = getById(id); + List gisProjectTreeVos = new ArrayList<>(); + if (ObjectUtil.isEmpty(byId)) { + return gisProjectTreeVos; + } + List list = vehicleService.list(new LambdaQueryWrapper().eq(TbVehicle::getProjectId, byId.getProjectId()).eq(TbVehicle::getCancelFlag, 0)); + Map> collect = list.stream().collect(Collectors.groupingBy(TbVehicle::getProjectId)); + + if (ObjectUtil.isEmpty(collect)) { + return gisProjectTreeVos; + } + List projectsList = projectsService.list(new LambdaQueryWrapper().in(Projects::getId, collect.keySet()).eq(Projects::getCancelFlag,0)); + for (Projects projects : projectsList) { + GisProjectTreeVo gisProjectTreeVo = new GisProjectTreeVo(); + gisProjectTreeVo.setProjectId(projects.getId()); + gisProjectTreeVo.setProjectName(projects.getProjectName()); + gisProjectTreeVo.setVehicleList(collect.get(projects.getId())); + List list1 = fenceVehicleService.list(new LambdaQueryWrapper().eq(TbGisFenceVehicle::getPlanId, id)); + if (ObjectUtil.isNotEmpty(list1)){ + gisProjectTreeVo.setHadBind(list1.stream().map(TbGisFenceVehicle::getPlateNumber).collect(Collectors.toList())); + } + gisProjectTreeVos.add(gisProjectTreeVo); + } + return gisProjectTreeVos; + } + + @Override + public List getPlanFenceInfoList(String id) { + LambdaQueryWrapper eq = new LambdaQueryWrapper().eq(TbGisFenceInfo::getPlanId, id); + return fenceInfoService.list(eq); + } + + @Override + public void updateAll() { + List list = fenceVehicleService.list(); + delAllVehicleRedis(); + updateVehicleRedis(list); + } + + private void delAllVehicleRedis() { + Set scan = RedisUtil.getScan(CacheConstant.VEHICLE_FENCE_KEY + "*"); + RedisUtil.multiDel(scan); + } + + /** + * 删除车辆并更新redis数据 + */ + private void delFenceVehicle(GisVehicleVo vo) { + fenceVehicleService.remove(new LambdaQueryWrapper().eq(TbGisFenceVehicle::getPlanId, vo.getPlanId()).in(TbGisFenceVehicle::getPlateNumber, vo.getVehicleList())); +// delVehicleRedis(vo); + ArrayList gisVehicleVos = new ArrayList<>(); + List vehicleList = vo.getVehicleList(); + for (String s : vehicleList) { + TbGisFenceVehicle tbGisFenceVehicle = new TbGisFenceVehicle(); + tbGisFenceVehicle.setPlateNumber(s); + gisVehicleVos.add(tbGisFenceVehicle); + } + updateVehicleRedis(gisVehicleVos); + } + + /** + * 删除Redis数据 + */ + private void delVehicleRedis(GisVehicleVo vo) { + List vehicleList = vo.getVehicleList(); + for (String s : vehicleList) { + RedisUtil.del(CacheConstant.VEHICLE_FENCE_KEY + s); + } + } + + /** + * 新增车辆并同步redis数据 + */ + private void saveFenceVehicle(GisVehicleVo vo) { + List vehicleList = vo.getVehicleList(); + + List list = fenceVehicleService.list(new LambdaQueryWrapper().eq(TbGisFenceVehicle::getPlanId, vo.getPlanId())); + if (ObjectUtil.isNotEmpty(list)) { + vehicleList = CollUtil.subtractToList(vehicleList,list.stream().map(TbGisFenceVehicle::getPlateNumber).collect(Collectors.toList())); + } + if (vehicleList.size() == 0) { + return; + } + ArrayList gisVehicleVos = new ArrayList<>(); + List tbVehicleList = vehicleService.list(new LambdaQueryWrapper().in(TbVehicle::getPlateNumber, vehicleList).eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0)); + for (TbVehicle vehicle : tbVehicleList) { + TbGisFenceVehicle tbGisFenceVehicle = new TbGisFenceVehicle(); + tbGisFenceVehicle.setPlanId(vo.getPlanId()); + tbGisFenceVehicle.setPlateNumber(vehicle.getPlateNumber()); + gisVehicleVos.add(tbGisFenceVehicle); + tbGisFenceVehicle.setGpsNo(vehicle.getLocationTerminalId()); + } + fenceVehicleService.saveBatch(gisVehicleVos); + updateVehicleRedis(gisVehicleVos); + } + + /** + * 更新redis缓存数据 + * + * @param gisVehicleVos + */ + private void updateVehicleRedis(List gisVehicleVos) { + HashMap stringObjectHashMap = new HashMap<>(10); + //这辆车可能在多个方案内 + List gisFenceInfoList = fencePlanMapper.getGisFenceInfoList(gisVehicleVos.stream().map(TbGisFenceVehicle::getPlateNumber).collect(Collectors.toList())); + if (ObjectUtil.isNotEmpty(gisFenceInfoList)) { + for (GisRedisVehicleVo gisRedisVehicleVo : gisFenceInfoList) { + if (StrUtil.isBlank(gisRedisVehicleVo.getPlateNumber())) { + continue; + } + RedisUtil.del(CacheConstant.VEHICLE_FENCE_KEY + gisRedisVehicleVo.getPlateNumber()); + ArrayList latLonPoints = new ArrayList<>(); + JSONArray objects = JSONUtil.parseArray(gisRedisVehicleVo.getGeoJson()); + for (Object object : objects) { + LatLonPoint latLonPoint = new LatLonPoint(); + JSONArray objects1 = JSONUtil.parseArray(object); + latLonPoint.setLongitude(Convert.toDouble(objects1.get(0))); + latLonPoint.setLatitude(Convert.toDouble(objects1.get(1))); + latLonPoints.add(latLonPoint); + } + gisRedisVehicleVo.setCoordinateList(latLonPoints); + } + Map> collect = gisFenceInfoList.stream().filter(i->StrUtil.isNotBlank(i.getPlateNumber())).collect(Collectors.groupingBy(GisRedisVehicleVo::getPlateNumber)); + for (TbGisFenceVehicle gisVehicleVo : gisVehicleVos) { + String key = CacheConstant.VEHICLE_FENCE_KEY + gisVehicleVo.getPlateNumber(); + List gisRedisVehicleVos = collect.get(gisVehicleVo.getPlateNumber()); + if (ObjectUtil.isNotEmpty(gisRedisVehicleVos)) { + stringObjectHashMap.put(key, JsonUtil.object2Json(gisRedisVehicleVos)); + } + } + if (ObjectUtil.isNotEmpty(stringObjectHashMap)) { + RedisUtil.multiSet(stringObjectHashMap); + } + } + } + + + /** + * 检查车牌号是否正常 + * + * @param vehicleList + */ + private void checkVehicle(List vehicleList) { + StringBuilder stringBuilder = new StringBuilder(); + ArrayList strings = new ArrayList<>(); + for (String s : vehicleList) { + boolean plateNumber = ReUtil.isMatch("^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$", s); + if (!plateNumber) { + stringBuilder.append(s).append("格式错误!"); + } else { + strings.add(s); + } + } + if (ObjectUtil.isNotEmpty(strings)) { + List list = vehicleService.list(new LambdaQueryWrapper().in(TbVehicle::getPlateNumber, strings).eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0)); + if (list.size() != strings.size() || list == null) { + List subtract = CollUtil.subtractToList(strings, list.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList())); + stringBuilder.append(subtract).append("车辆不存在!"); + } + } + if (StrUtil.isNotBlank(stringBuilder)) { + throw new GciBootException(stringBuilder.toString()); + } + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceVehicleServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceVehicleServiceImpl.java new file mode 100644 index 0000000..a27cc28 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisFenceVehicleServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.gis.service.impl; + +import com.gci.boot.modules.gis.entity.TbGisFenceVehicle; +import com.gci.boot.modules.gis.mapper.TbGisFenceVehicleMapper; +import com.gci.boot.modules.gis.service.ITbGisFenceVehicleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 围栏关联车辆信息表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-08-30 + */ +@Service +public class TbGisFenceVehicleServiceImpl extends ServiceImpl implements ITbGisFenceVehicleService { + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsServiceImpl.java new file mode 100644 index 0000000..1da93b5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsServiceImpl.java @@ -0,0 +1,1021 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.BetweenFormatter; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.util.*; +import com.gci.boot.enums.VehicleGpsType; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.gis.entity.GisGpsAnalysis; +import com.gci.boot.modules.gis.entity.TbGisChargeLog; +import com.gci.boot.modules.gis.entity.TbGisGps; +import com.gci.boot.modules.gis.mapper.TbGisGpsMapper; +import com.gci.boot.modules.gis.query.GpsHistoryQuery; +import com.gci.boot.modules.gis.service.ITbGisChargeLogService; +import com.gci.boot.modules.gis.service.ITbGisGpsService; +import com.gci.boot.modules.gis.vo.GisHistoryVo; +import com.gci.boot.modules.gis.vo.PointListDTO; +import com.gci.boot.modules.gis.vo.TimeSlotDTO; +import com.gci.boot.modules.gis.vo.WorkLineVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +@Slf4j +public class TbGisGpsServiceImpl extends ServiceImpl implements ITbGisGpsService { + + @Autowired + private ITbVehicleService vehicleService; + @Autowired + private ITbGisChargeLogService chargeLogService; + @Value("${gps.timeCut}") + private Long timeCut; + @Autowired + private StringRedisTemplate redisTemplate; + @Override + public List getGpsHistory(GpsHistoryQuery vo) { + List time = vo.getTime(); + if (DateUtil.between(time.get(0), time.get(1), DateUnit.MS, false) < 0) { + throw new GciBootException("开始时间不能大于结束时间!"); + } +/* if (DateUtil.between(time.get(0), time.get(1), DateUnit.DAY, false) > 2) { + throw new GciBootException("开始时间和结束时间不能超过两天!"); + }*/ + + //返回给前端的list + List gisHistoryVos = new ArrayList<>(); + + TbVehicle one = vehicleService.getOne(new LambdaQueryWrapper().eq(TbVehicle::getPlateNumber, vo.getPlateNumber())); + Integer batteryCapacity = null; + if (ObjectUtil.isEmpty(one)) { + return gisHistoryVos; + } + if (ObjectUtil.isNotEmpty(one.getBatteryCapacity())) { + batteryCapacity = one.getBatteryCapacity(); + } + + + //是否三电 + boolean isEic = false; + if (Convert.toBool(redisTemplate.opsForValue().get(RedisKey.PROJECT_GIS_SOURCE + one.getProjectId()),false)) { + isEic = true; + } + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbGisGps.class, vo); + //在sql查询时直接排除异常数据 + lambdaQueryWrapper.eq(TbGisGps::getIsValid,1) + .isNotNull(TbGisGps::getLat) + .isNotNull(TbGisGps::getLon) + .ne(TbGisGps::getLon,0) + .ne(TbGisGps::getLat,0) + .eq(TbGisGps::getRecordSource,isEic ? 2 : 1); + List list = list(lambdaQueryWrapper); + if (ObjectUtil.isEmpty(list) && !isEic) { + isEic = true; + lambdaQueryWrapper.clear(); + lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbGisGps.class, vo); + lambdaQueryWrapper.eq(TbGisGps::getIsValid,1) + .isNotNull(TbGisGps::getLat) + .isNotNull(TbGisGps::getLon) + .ne(TbGisGps::getLon,0) + .ne(TbGisGps::getLat,0) + .eq(TbGisGps::getRecordSource, 2); + list = list(lambdaQueryWrapper); + } + + boolean finalIsEic = isEic; + list = list.stream().filter(g->{ + if (ObjectUtil.isAllNotEmpty(g.getAcc(),g.getSpeed())) { + //如果有只需要三电数据 + if (finalIsEic) { + if (g.getTotalMileage() == null || g.getTotalMileage().compareTo(BigDecimal.ZERO) <= 0) { + return false; + } + return g.getRecordSource().equals(2); + } + return true; + } else { + return false; + } + }).collect(Collectors.toList()); + + + + if (ObjectUtil.isEmpty(list)) { + return gisHistoryVos; + } + + + //行驶数据 + drivingDataV2(batteryCapacity, list,gisHistoryVos,isEic); + //充电数据 只查询结束时间在查询条件时间条件区间内 + powerData(vo,gisHistoryVos); + + //再排序两遍 + if (ObjectUtil.isNotEmpty(gisHistoryVos)) { + for (GisHistoryVo gisHistoryVo : gisHistoryVos) { + List timeSlot = gisHistoryVo.getTimeSlot(); + timeSlot.sort(Comparator.comparing(TimeSlotDTO::getSlotTime).reversed()); + } + } + gisHistoryVos.sort(Comparator.comparing(GisHistoryVo::getDayTime).reversed()); + return gisHistoryVos; + } + + @Override + public List getGpsListByVehicleAndTime(TbVehicle vehicle, Date startTime, Date endTime,int recordSource) { + //构建gps数据记录查询 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbGisGps::getPlateNumber, vehicle.getPlateNumber()); + queryWrapper.between(TbGisGps::getGpsTime, startTime, endTime); + // TODO: 2023/10/23 只查三电来源且有正确工作状态的数据 + queryWrapper.eq(TbGisGps::getRecordSource, recordSource); +// queryWrapper.and(wrapper -> { +// wrapper.eq(TbGisGps::getIsWork, 1).or().eq(TbGisGps::getIsWork, 0); +// }); + queryWrapper.eq(TbGisGps::getIsValid, 1); + queryWrapper.orderByAsc(TbGisGps::getGpsTime); + List gpsList = this.list(queryWrapper); + return gpsList; + } + + private void powerData(GpsHistoryQuery query, List gisHistoryVos) { + List time = query.getTime(); + List tbGisChargeLogs = chargeLogService.list(new LambdaQueryWrapper().eq(TbGisChargeLog::getNumberPlate,query.getPlateNumber()).between(TbGisChargeLog::getEndTime, time.get(0), time.get(1))); + if (ObjectUtil.isNotEmpty(tbGisChargeLogs)) { + for (TbGisChargeLog tbGisChargeLog : tbGisChargeLogs) { + Date startTime = tbGisChargeLog.getStartTime(); + Date endTime = tbGisChargeLog.getEndTime(); + + String day = DateUtil.format(startTime, "yyyy-MM-dd"); + DateTime dayTime = DateUtil.beginOfDay(startTime); + String startFormat = DateUtil.format(startTime, "HH:mm"); + String endFormat = DateUtil.format(endTime, "HH:mm"); + String formatBetween = DateUtil.formatBetween(startTime, endTime, BetweenFormatter.Level.MINUTE); + boolean sameDay = DateUtil.isSameDay(startTime, endTime); + + + TimeSlotDTO timeSlotDTO = new TimeSlotDTO(); + //充电 + timeSlotDTO.setType("power"); + timeSlotDTO.setSlotTime(startTime); + timeSlotDTO.setTimeCount(formatBetween); + timeSlotDTO.setIsOvernight(sameDay ? 0 : 1); + timeSlotDTO.setTimeRange(startFormat + " - " + endFormat); + timeSlotDTO.setChargedEnergy(tbGisChargeLog.getChargingEnergy()); + timeSlotDTO.setChargedEfficiency(tbGisChargeLog.getChargingEfficiency()); + + ArrayList pointListDTOS = new ArrayList<>(); + PointListDTO pointListDTO = new PointListDTO(); + ArrayList doubles = new ArrayList<>(); + doubles.add(tbGisChargeLog.getGdLon().doubleValue()); + doubles.add(tbGisChargeLog.getGdLat().doubleValue()); + pointListDTO.setLocation(doubles); + pointListDTOS.add(pointListDTO); + timeSlotDTO.setPointList(pointListDTOS); + GisHistoryVo gisHistoryVo = gisHistoryVos.stream().filter(gisHistoryVo1 -> gisHistoryVo1.getDay().equals(day)).findFirst().orElse(new GisHistoryVo()); + if (BeanUtil.isEmpty(gisHistoryVo)) { + gisHistoryVo.setDay(day); + gisHistoryVo.setDayTime(dayTime); + ArrayList timeSlotDTOS = new ArrayList<>(); + timeSlotDTOS.add(timeSlotDTO); + gisHistoryVo.setTimeSlot(timeSlotDTOS); + gisHistoryVos.add(gisHistoryVo); + } else { + gisHistoryVo.getTimeSlot().add(timeSlotDTO); + } + } + } + } + + private void drivingDataV2(Integer batteryCapacity, List list, List gisHistoryVos, boolean isEic) { + ArrayList dtoArrayList = new ArrayList<>(); + TimeSlotDTO timeSlotDTO = null; + for (TbGisGps gps : list) { + if (ObjectUtil.isEmpty(gps.getIsWork())) { + gps.setIsWork(0); + } + // 根据规则判断记录类型 + int recordType; + if (isDrivingWork(gps)) { + recordType = VehicleGpsType.Driving_Work.getValue(); + } else if (isDrivingNotWork(gps)) { + recordType = VehicleGpsType.Driving_Not_Work.getValue(); + } else if (isStoppedWork(gps)) { + recordType = VehicleGpsType.Stopped_Work.getValue(); + } else if (isStoppedNotWork(gps)){ + recordType = VehicleGpsType.Stopped_NOT_Work.getValue(); + }else{ + continue; + } + if (timeSlotDTO == null || recordType != timeSlotDTO.getRecordType()) { +// addTimeDTO(beforeMerge,timeSlotDTO); + // 如果当前分段为空或者记录类型不同,创建新的分段 + timeSlotDTO = createTimeDTO(gps,recordType,batteryCapacity,isEic); + dtoArrayList.add(timeSlotDTO); + } else { + // 否则,将当前GPS数据添加到当前分段 + if (DateUtil.between(timeSlotDTO.getEndTime(),gps.getGpsTime(),DateUnit.MINUTE,false) < 20) { + updateTimeDTO(timeSlotDTO, gps,batteryCapacity,isEic,true); + } else { + timeSlotDTO = createTimeDTO(gps,recordType,batteryCapacity,isEic); + dtoArrayList.add(timeSlotDTO); + } + } + } + if (!dtoArrayList.isEmpty()) { + mergeGisHistoryVo(gisHistoryVos,dtoArrayList,batteryCapacity,isEic); + } + } + + private void mergeGisHistoryVo(List gisHistoryVos, ArrayList beforeMerge, Integer batteryCapacity, boolean isEic) { + List afterMerge = new ArrayList<>(); + TimeSlotDTO pre = null; + for (TimeSlotDTO timeSlotDTO : beforeMerge) { +/* if (timeSlotDTO.getRecordType() == 3 || timeSlotDTO.getRecordType() == 4) { + continue; + }*/ + if (timeSlotDTO.getMileage().compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + if (pre == null) { + pre = timeSlotDTO; + } else { + if (areMergable(pre,timeSlotDTO,isEic)) { + mergeData(pre, timeSlotDTO,batteryCapacity,isEic); + } else { + afterMerge.add(timeSlotDTO); + pre = timeSlotDTO; + } + } + } +/* if (pre != null) { + afterMerge.add(pre); + }*/ + for (TimeSlotDTO timeSlotDTO : afterMerge) { + addTimeDTO(gisHistoryVos,timeSlotDTO); + } + } + + private void mergeData(TimeSlotDTO previousData, TimeSlotDTO currentData, Integer batteryCapacity, boolean isEic) { + previousData.setEndTime(currentData.getEndTime()); + if (!((previousData.getRecordType() == 4 && currentData.getRecordType() ==4) || + (previousData.getRecordType() == 3 && currentData.getRecordType() == 3))) { + previousData.setLogMerge(Boolean.TRUE); + } + Date startTime = previousData.getSlotTime(); + Date endTime = previousData.getEndTime(); + String startFormat = DateUtil.format(startTime, "HH:mm"); + String endFormat = DateUtil.format(endTime, "HH:mm"); + String formatBetween = DateUtil.formatBetween(startTime, endTime, BetweenFormatter.Level.MINUTE); + if (DateUtil.between(startTime, endTime, DateUnit.SECOND) < 60) { + formatBetween = "1分"; + } + boolean sameDay = DateUtil.isSameDay(startTime, endTime); + + previousData.setTimeRange(startFormat+ "-" +endFormat); + previousData.setTimeCount(formatBetween); + previousData.setIsOvernight(sameDay ? 0 : 1); + + if(isEic){ + previousData.setEndMile(currentData.getEndMile()); + BigDecimal totalMileage = previousData.getEndMile().subtract(previousData.getStartMile()); + previousData.setMileage(totalMileage); + if(ObjectUtil.isAllNotEmpty(previousData.getEndGisGpsStateOfCharge(),currentData.getEndGisGpsStateOfCharge())){ + if (previousData.getStartGisGpsStateOfCharge() > 0) { + previousData.setEndGisGpsStateOfCharge(currentData.getEndGisGpsStateOfCharge()); + Integer startGisGpsStateOfCharge = previousData.getStartGisGpsStateOfCharge(); + Integer endGisGpsStateOfCharge = previousData.getEndGisGpsStateOfCharge(); + + BigDecimal sub = NumberUtil.sub(startGisGpsStateOfCharge, endGisGpsStateOfCharge); + BigDecimal div = NumberUtil.div(sub, 100); + BigDecimal mul = NumberUtil.mul(div, batteryCapacity).setScale(2,BigDecimal.ROUND_HALF_UP); + + previousData.setPowerConsumption(mul); + } + } + }else{ + previousData.setMileage(previousData.getMileage().add(currentData.getMileage())); + } + BigDecimal mileage = previousData.getMileage(); + double between = betweenHour(startTime, endTime); + if (between > 0) { + previousData.setAverageSpeed(NumberUtil.div(mileage,between,2).doubleValue()); + } + List pointList = previousData.getPointList(); + pointList.addAll(currentData.getPointList()); + previousData.setPointList(pointList); + } + + private boolean areMergable(TimeSlotDTO previousData, TimeSlotDTO currentData, boolean isEic) { + if(isEic){ + return (calculateTimeDifferenceInMinutes(previousData.getEndTime(), currentData.getSlotTime()) <= 20 + && sameType(previousData,currentData)); + }else{ + return (calculateTimeDifferenceInMinutes(previousData.getEndTime(), currentData.getSlotTime()) <= 20 + && sameType(previousData,currentData)); + } + } + + /** + * 是否同类型段 + * @param previousData + * @param currentData + * @return + */ + private boolean sameType(TimeSlotDTO previousData, TimeSlotDTO currentData) { + if (previousData.getRecordType() == 1 || previousData.getRecordType() == 4) { + return currentData.getRecordType() == 1 || currentData.getRecordType() == 4; + } else if (previousData.getRecordType() == 2 || previousData.getRecordType() ==3) { + return currentData.getRecordType() == 2 || currentData.getRecordType() == 3; + } + return false; + } + + private void addTimeDTO(List gisHistoryVos, TimeSlotDTO timeSlotDTO) { + if (ObjectUtil.isNotEmpty(timeSlotDTO)) { + if (timeSlotDTO.getMileage().compareTo(BigDecimal.ZERO) == 0) { + return; + } + if ((!timeSlotDTO.getLogMerge()) && (timeSlotDTO.getRecordType() == 3 || timeSlotDTO.getRecordType() == 4)) { + return; + } + String day = DateUtil.format(timeSlotDTO.getSlotTime(), "yyyy-MM-dd"); + DateTime dayTime = DateUtil.beginOfDay(timeSlotDTO.getSlotTime()); + GisHistoryVo gisHistoryVo = gisHistoryVos.stream().filter(gisHistoryVo1 -> gisHistoryVo1.getDay().equals(day)).findFirst().orElse(new GisHistoryVo()); + if (BeanUtil.isEmpty(gisHistoryVo)) { + gisHistoryVo.setDay(day); + gisHistoryVo.setDayTime(dayTime); + ArrayList timeSlotDTOS = new ArrayList<>(); + timeSlotDTOS.add(timeSlotDTO); + gisHistoryVo.setTimeSlot(timeSlotDTOS); + gisHistoryVos.add(gisHistoryVo); + } else { + List timeSlot = gisHistoryVo.getTimeSlot(); + TimeSlotDTO timeSlotDTO1 = timeSlot.get(timeSlot.size() - 1); + List pointList = timeSlotDTO1.getPointList(); + PointListDTO pointListDTO = pointList.get(pointList.size() - 1); + timeSlotDTO.getPointList().add(0,pointListDTO); + timeSlot.add(timeSlotDTO); + } + } + } + + private TimeSlotDTO createTimeDTO(TbGisGps gps, int recordType, Integer batteryCapacity, boolean isEic) { + TimeSlotDTO timeSlotDTO = new TimeSlotDTO (); + if (recordType == 1 || recordType == 4) { + timeSlotDTO.setType("driving"); + } else { + timeSlotDTO.setType("working"); + } + timeSlotDTO.setSlotTime(gps.getGpsTime()); + timeSlotDTO.setEndTime(gps.getGpsTime()); + timeSlotDTO.setRecordType(recordType); + timeSlotDTO.setLogMerge(Boolean.FALSE); + ArrayList pointListDTOS = new ArrayList<>(); + pointListDTOS.add(buildPointListDTO(gps)); + timeSlotDTO.setPointList(pointListDTOS); + if (isEic) { + if (ObjectUtil.isNotEmpty(gps.getStateOfCharge())) { + timeSlotDTO.setStartGisGpsStateOfCharge(gps.getStateOfCharge()); + timeSlotDTO.setEndGisGpsStateOfCharge(gps.getStateOfCharge()); + } + timeSlotDTO.setStartMile(gps.getTotalMileage()); + } else { + timeSlotDTO.setMileage(BigDecimal.ZERO); + timeSlotDTO.setLon(gps.getLon()); + timeSlotDTO.setLat(gps.getLat()); + } + updateTimeDTO(timeSlotDTO, gps,batteryCapacity,isEic,false); + return timeSlotDTO; + } + + private void updateTimeDTO(TimeSlotDTO timeSlotDTO, TbGisGps gps, Integer batteryCapacity, boolean isEic, boolean needAdd) { + timeSlotDTO.setEndTime(gps.getGpsTime()); + + Date startTime = timeSlotDTO.getSlotTime(); + Date endTime = timeSlotDTO.getEndTime(); + String startFormat = DateUtil.format(startTime, "HH:mm"); + String endFormat = DateUtil.format(endTime, "HH:mm"); + String formatBetween = DateUtil.formatBetween(startTime, endTime, BetweenFormatter.Level.MINUTE); + boolean sameDay = DateUtil.isSameDay(startTime, endTime); + + timeSlotDTO.setTimeRange(startFormat+ "-" +endFormat); + timeSlotDTO.setTimeCount(formatBetween); + timeSlotDTO.setIsOvernight(sameDay ? 0 : 1); + + if (isEic) { + if (ObjectUtil.isAllNotEmpty(gps.getStateOfCharge(),batteryCapacity)) { + timeSlotDTO.setEndGisGpsStateOfCharge(gps.getStateOfCharge()); + Integer startGisGpsStateOfCharge = timeSlotDTO.getStartGisGpsStateOfCharge(); + Integer endGisGpsStateOfCharge = timeSlotDTO.getEndGisGpsStateOfCharge(); + + if (startGisGpsStateOfCharge > 0) { + BigDecimal sub = NumberUtil.sub(startGisGpsStateOfCharge, endGisGpsStateOfCharge); + BigDecimal div = NumberUtil.div(sub, 100); + BigDecimal mul = NumberUtil.mul(div, batteryCapacity).setScale(2,BigDecimal.ROUND_HALF_UP); + + timeSlotDTO.setPowerConsumption(mul); + } + + } + timeSlotDTO.setEndMile(gps.getTotalMileage()); + timeSlotDTO.setMileage(timeSlotDTO.getEndMile().subtract(timeSlotDTO.getStartMile())); + } else { + long duration = DateUtil.betweenMs(timeSlotDTO.getEndTime(),timeSlotDTO.getSlotTime())/1000; + double distance = CalcTool.getDistance(timeSlotDTO.getLon().doubleValue(),timeSlotDTO.getLat().doubleValue(),gps.getLon().doubleValue(),gps.getLat().doubleValue()); + if(duration>0 && distance /duration < 0.055 ){ + timeSlotDTO.setMileage(timeSlotDTO.getMileage().add(new BigDecimal(distance)).setScale(2,BigDecimal.ROUND_HALF_UP)); + timeSlotDTO.setLon(gps.getLon()); + timeSlotDTO.setLat(gps.getLat()); + } + } + + + BigDecimal mileage = timeSlotDTO.getMileage(); + double between = betweenHour(startTime, endTime); + if (between > 0) { + timeSlotDTO.setAverageSpeed(NumberUtil.div(mileage,between,2).doubleValue()); + } + if (needAdd) { + List pointList = timeSlotDTO.getPointList(); + pointList.add(buildPointListDTO(gps)); +// timeSlotDTO.setPointList(pointList); + } + } + + private void drivingData(Integer batteryCapacity, List list, List gisHistoryVos) { + List> lists = groupByStatusAndTime(list); + if (ObjectUtil.isNotEmpty(lists)) { + for (List tbGisGps : lists) { + if (ObjectUtil.isEmpty(tbGisGps)) { + continue; + } + TbGisGps startGisGps = tbGisGps.get(0); + TbGisGps endGisGps = tbGisGps.get(tbGisGps.size() - 1); + Date startGisGpsGpsTime = startGisGps.getGpsTime(); + Date endGisGpsGpsTime = endGisGps.getGpsTime(); + BigDecimal startGisGpsTotalMileage = startGisGps.getTotalMileage(); + BigDecimal endGisGpsTotalMileage = endGisGps.getTotalMileage(); + Integer startGisGpsStateOfCharge = startGisGps.getStateOfCharge(); + Integer endGisGpsStateOfCharge = endGisGps.getStateOfCharge(); + + String day = DateUtil.format(startGisGpsGpsTime, "yyyy-MM-dd"); + DateTime dayTime = DateUtil.beginOfDay(startGisGpsGpsTime); + String startFormat = DateUtil.format(startGisGpsGpsTime, "HH:mm"); + String endFormat = DateUtil.format(endGisGpsGpsTime, "HH:mm"); + String formatBetween = DateUtil.formatBetween(startGisGpsGpsTime, endGisGpsGpsTime, BetweenFormatter.Level.MINUTE); + boolean sameDay = DateUtil.isSameDay(startGisGpsGpsTime, endGisGpsGpsTime); + + TimeSlotDTO timeSlotDTO = new TimeSlotDTO(); + //行驶 + timeSlotDTO.setType("driving"); + timeSlotDTO.setSlotTime(startGisGpsGpsTime); + timeSlotDTO.setTimeCount(formatBetween); + timeSlotDTO.setIsOvernight(sameDay ? 0 : 1); + timeSlotDTO.setTimeRange(startFormat + " - " + endFormat); + + if (ObjectUtil.isAllNotEmpty(startGisGpsTotalMileage, endGisGpsTotalMileage)) { + if (startGisGpsTotalMileage.compareTo(endGisGpsTotalMileage) == 0) { + continue; + } + timeSlotDTO.setMileage(NumberUtil.sub(endGisGpsTotalMileage, startGisGpsTotalMileage)); + if (ObjectUtil.isAllNotEmpty(startGisGpsGpsTime,endGisGpsGpsTime)) { + BigDecimal mileage = timeSlotDTO.getMileage(); + double between = betweenHour(startGisGpsGpsTime, endGisGpsGpsTime); + if (between > 0) { + timeSlotDTO.setAverageSpeed(NumberUtil.div(mileage,between,2).doubleValue()); + } + } + } + if (ObjectUtil.isAllNotEmpty(startGisGpsStateOfCharge,endGisGpsStateOfCharge, batteryCapacity)) { + + BigDecimal sub = NumberUtil.sub(startGisGpsStateOfCharge, endGisGpsStateOfCharge); + BigDecimal div = NumberUtil.div(sub, 100); + BigDecimal mul = NumberUtil.mul(div, batteryCapacity).setScale(2,BigDecimal.ROUND_HALF_UP); + + timeSlotDTO.setPowerConsumption(mul); + + } + ArrayList pointListDTOS = new ArrayList<>(); + for (TbGisGps tbGisGp : tbGisGps) { + PointListDTO pointListDTO = buildPointListDTO(tbGisGp); + pointListDTOS.add(pointListDTO); + } + timeSlotDTO.setPointList(pointListDTOS); + + GisHistoryVo gisHistoryVo = gisHistoryVos.stream().filter(gisHistoryVo1 -> gisHistoryVo1.getDay().equals(day)).findFirst().orElse(new GisHistoryVo()); + if (BeanUtil.isEmpty(gisHistoryVo)) { + gisHistoryVo.setDay(day); + gisHistoryVo.setDayTime(dayTime); + ArrayList timeSlotDTOS = new ArrayList<>(); + timeSlotDTOS.add(timeSlotDTO); + gisHistoryVo.setTimeSlot(timeSlotDTOS); + gisHistoryVos.add(gisHistoryVo); + } else { + gisHistoryVo.getTimeSlot().add(timeSlotDTO); + } + } + } + } + + private PointListDTO buildPointListDTO(TbGisGps tbGisGp) { + PointListDTO pointListDTO = new PointListDTO(); + + BigDecimal lat = tbGisGp.getLat(); + BigDecimal lon = tbGisGp.getLon(); + LatLonPoint latLonPoint = CoordinateConverterUtil.toWGSPoint(lat.doubleValue(), lon.doubleValue()); + ArrayList doubles = new ArrayList<>(); + doubles.add(latLonPoint.getLongitude()); + doubles.add(latLonPoint.getLatitude()); + + pointListDTO.setLocation(doubles); + pointListDTO.setStateOfCharge(tbGisGp.getStateOfCharge()); + pointListDTO.setSpeed(tbGisGp.getSpeed()); + pointListDTO.setTotalMileage(tbGisGp.getTotalMileage()); + pointListDTO.setTotalVoltage(tbGisGp.getTotalVoltage()); + pointListDTO.setGpsTime(DateUtil.formatDateTime(tbGisGp.getGpsTime())); + pointListDTO.setAcc(tbGisGp.getAcc()); + pointListDTO.setDcStatus(tbGisGp.getDcStatus()); + pointListDTO.setOperatingMode(tbGisGp.getOperatingMode()); + pointListDTO.setIsWork(tbGisGp.getIsWork()); + return pointListDTO; + } + + private List> groupByStatusAndTime(List list) { + // 创建一个空的结果列表 + List> result = new ArrayList<>(); + // 如果输入列表为空,直接返回结果 + if (list == null || list.isEmpty()) { + return result; + } + // 创建一个临时的子列表,用于存放符合条件的元素 + List subList = new ArrayList<>(); + // 创建速度缓存的 + ArrayList timeList = new ArrayList<>(); + // 遍历输入列表中的每个元素 + for (int i = 0; i < list.size(); i++) { + // 获取当前元素 + TbGisGps current = list.get(i); + // 获取当前状态 1-点火 0-熄火 + int currentStatus = current.getCurrentStatus(); + current.setCerStatus(currentStatus); + // 点火状态时 + if (currentStatus == 1) { + //临时列表为空或者上一个也是点火状态 + if (subList.isEmpty() || subList.get(subList.size() - 1).getCerStatus() == currentStatus) { + //数据可能有缺失 + if (!subList.isEmpty()) { + TbGisGps tbGisGps = subList.get(subList.size() - 1); + //如果超过了间隔就截断 + long between = DateUtil.between(tbGisGps.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + timeList = new ArrayList<>(); + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + } + } + //没速度先缓存到时间缓存列表里面 + if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) == 0) { + timeList.add(current); + } else { + //有速度判断一下是否抛弃数据 + if (!timeList.isEmpty()) { + TbGisGps last = timeList.get(0); + //当前的速度不为零时 超过了设置时间 + long between = DateUtil.between(last.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + //清空速度缓存 + timeList = new ArrayList<>(); + //结束临时列表 + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + } else { + //新数据上来了 并且没有超过设置时间 + //将时间缓存加入临时列表 + subList.addAll(timeList); + //清空时间缓存 + timeList = new ArrayList<>(); + } + } + subList.add(current); + } + } else { + log.warn("出现了意料之外的情况,什么情况会到这里?list数据为:{}", JsonUtil.object2Json(list)); + } + } else if (currentStatus == 0) { + //熄火状态时 + //临时列表不为空 + if (!subList.isEmpty()) { + //时间缓存不为空 + if (!timeList.isEmpty()) { +// subList.addAll(timeList); + //不要时间缓存了 + timeList = new ArrayList<>(); + } + //加入结束点 +// subList.add(current); + result.add(subList); + //新建临时列表 + subList = new ArrayList<>(); + } + } + } + // 遍历结束后,判断临时列表是否为空 + if (!subList.isEmpty()) { + result.add(subList); + } + // 返回结果列表 + return result; + } + + private List> groupByStatusAndTimeV2(List list) { + // 创建一个空的结果列表 + List> result = new ArrayList<>(); + // 如果输入列表为空,直接返回结果 + if (list == null || list.isEmpty()) { + return result; + } + // 创建一个临时的子列表,用于存放符合条件的元素 + List subList = new ArrayList<>(); + // 创建速度为0或无效缓存的 + ArrayList speedList = new ArrayList<>(); + for (TbGisGps current : list) { + //1-点火 0-熄火 其他的为不正常数据 + int currentStatus = current.getCurrentStatus(); + current.setCerStatus(currentStatus); + if (currentStatus == 1) { + //点火状态时 + Integer chargeStatus = current.getChargeStatus(); + //没有充电的时候 + if (chargeStatus == null || chargeStatus == 3 || chargeStatus == 4) { + if (subList.isEmpty()) { + //临时列表为空是一定要加上的 + subList.add(current); + //速度缓存可能不为空都有要清空掉 + speedList = new ArrayList<>(); + } else { + //不为空需要判断一下是否能够加上数据 + if (ObjectUtil.isNotEmpty(current.getSpeed()) && current.getSpeed().compareTo(BigDecimal.ZERO) > 0) { + //有速度 + //判断是否可以加入缓存 + if (subList.isEmpty()) { + subList.add(current); + continue; + } else { + //和列表内的最后一条数据比较是否超过timeCut + //超过就不需要这条数据 + TbGisGps lastSub = subList.get(subList.size() - 1); + long between = DateUtil.between(lastSub.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + //超过说明需要结束临时列表 (速度缓存不需要加入 超过timeCut说明连最新一条数据都超过了,之前的数据肯定也是没速度的) + result.add(subList); + //清空 临时列表 速度缓存 + subList = new ArrayList<>(); + speedList= new ArrayList<>(); + continue; + } else { + //没超过说明需要加入中间的速度数据 + if (!speedList.isEmpty()) { + subList.addAll(speedList); + //清空速度缓存 + speedList= new ArrayList<>(); + } + subList.add(current); + continue; + } + } + } else if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) <= 0){ + //没速度 + //直接加入缓存 + speedList.add(current); + continue; + } + } + } else if (chargeStatus == 1 || chargeStatus ==2) { + //在充电 + //结束临时列表 + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + if (!speedList.isEmpty()) { + speedList = new ArrayList<>(); + } + } else { + //点火时 充电状态出现了异常数据 判断一下是否可以加入数据内 + if (subList.isEmpty()) { + continue; + } else { + //临时列表不为空的时候才考虑加不加进去 + TbGisGps lastSub = subList.get(subList.size() - 1); + long between = DateUtil.between(lastSub.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + //如果超过timeCut + //这条数据就不要了 + continue; + } else { + //未超过的话判断一下关键数据是否正常 + if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) < 0) { + //速度不正常 + //抛弃 + continue; + } +// if (ObjectUtil.isEmpty(current.get)) + //数据正常就加入到临时列表 + if (!speedList.isEmpty()) { + //速度缓存也加入 + subList.addAll(speedList); + //清空速度缓存 + speedList = new ArrayList<>(); + } + } + } + } + } else if (currentStatus == 0) { + //熄火时 + //speed就不要了 + speedList = new ArrayList<>(); + //结束缓存列表 + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + } else { + //异常状态时 + Integer chargeStatus = current.getChargeStatus(); + //没有充电的时候 + if (chargeStatus == null || chargeStatus == 3 || chargeStatus == 4) { + if (subList.isEmpty()) { + //临时列表为空是一定要加上的 + subList.add(current); + //速度缓存可能不为空都有要清空掉 + speedList = new ArrayList<>(); + } else { + //不为空需要判断一下是否能够加上数据 + if (ObjectUtil.isNotEmpty(current.getSpeed()) && current.getSpeed().compareTo(BigDecimal.ZERO) > 0) { + //有速度 + //判断是否可以加入缓存 + if (subList.isEmpty()) { + subList.add(current); + continue; + } else { + //和列表内的最后一条数据比较是否超过timeCut + //超过就不需要这条数据 + TbGisGps lastSub = subList.get(subList.size() - 1); + long between = DateUtil.between(lastSub.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + //超过说明需要结束临时列表 (速度缓存不需要加入 超过timeCut说明连最新一条数据都超过了,之前的数据肯定也是没速度的) + result.add(subList); + //清空 临时列表 速度缓存 + subList = new ArrayList<>(); + speedList= new ArrayList<>(); + continue; + } else { + //没超过说明需要加入中间的速度数据 + if (!speedList.isEmpty()) { + subList.addAll(speedList); + //清空速度缓存 + speedList= new ArrayList<>(); + } + subList.add(current); + } + } + } else if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) <= 0){ + //没速度 + //直接加入缓存 + speedList.add(current); + continue; + } + } + } else if (chargeStatus == 1 || chargeStatus ==2) { + //在充电 + //结束临时列表 + if (!subList.isEmpty()) { + result.add(subList); + subList = new ArrayList<>(); + } + if (!speedList.isEmpty()) { + speedList = new ArrayList<>(); + } + } else { + //异常时 充电状态出现了异常数据 判断一下是否可以加入数据内 + if (subList.isEmpty()) { + continue; + } else { + //临时列表不为空的时候才考虑加不加进去 + TbGisGps lastSub = subList.get(subList.size() - 1); + long between = DateUtil.between(lastSub.getGpsTime(), current.getGpsTime(), DateUnit.MINUTE, false); + if (between > timeCut) { + //如果超过timeCut + //这条数据就不要了 + continue; + } else { + //未超过的话判断一下关键数据是否正常 + if (ObjectUtil.isEmpty(current.getSpeed()) || current.getSpeed().compareTo(BigDecimal.ZERO) < 0) { + //速度不正常 + //抛弃 + continue; + } +// if (ObjectUtil.isEmpty(current.get)) + //数据正常就加入到临时列表 + if (!speedList.isEmpty()) { + //速度缓存也加入 + subList.addAll(speedList); + //清空速度缓存 + speedList = new ArrayList<>(); + } + } + } + } + } + } + return result; + } + + private List> groupByStatusAndTimeV3(List list) { + // 创建一个空的结果列表 + List> result = new ArrayList<>(); + // 如果输入列表为空,直接返回结果 + if (list == null || list.isEmpty()) { + return result; + } + // 创建一个临时的子列表,用于存放符合条件的元素 + List subList = new ArrayList<>(); + // 创建速度缓存的 + ArrayList timeList = new ArrayList<>(); + //全部缓存一波数据 + List> beforeResult = new ArrayList<>(); + // 遍历输入列表中的每个元素 + for (TbGisGps current : list) { + // 获取当前状态 1-点火 0-熄火 () + int currentStatus = current.getAcc() % 2; + current.setAcc(currentStatus); + if (DateUtil.format(current.getGpsTime(),"yyyy-MM-dd HH:mm").equals("2023-09-25 21:59")) { + System.out.println("1"); + } + //排除了空值还是会有异常值数据 也排除 + if (currentStatus < 0) { + continue; + } else if (current.getSpeed().compareTo(BigDecimal.ZERO) < 0) { + continue; + } + if (currentStatus == 1) { + //点火 + //点火有速度 + if (current.getSpeed().compareTo(BigDecimal.ZERO) > 0) { + if (!timeList.isEmpty()) { + //时间缓存的加入全部缓存 + beforeResult.add(timeList); + timeList = new ArrayList<>(); + } + subList.add(current); + } else { + //点火没速度 + if (!subList.isEmpty()) { + //有速度缓存的加入全部缓存 + beforeResult.add(subList); + subList = new ArrayList<>(); + } + timeList.add(current); + } + } else { + //熄火 + if (!timeList.isEmpty()) { + //时间缓存的加入全部缓存 + beforeResult.add(timeList); + timeList = new ArrayList<>(); + } + if (!subList.isEmpty()) { + //有速度缓存的加入全部缓存 + beforeResult.add(subList); + subList = new ArrayList<>(); + } + } + } + if (!timeList.isEmpty()) { + //时间缓存的加入全部缓存 + beforeResult.add(timeList); + } + if (!subList.isEmpty()) { + //有速度缓存的加入全部缓存 + beforeResult.add(subList); + } + beforeResult.sort(Comparator.comparing(o -> o.get(0).getGpsTime())); + // 返回结果列表 + for (List tbGisGps : beforeResult) { + TbGisGps beforeFirst = tbGisGps.get(0); + if (beforeFirst.getAcc() == 1 && beforeFirst.getSpeed().compareTo(BigDecimal.ZERO) > 0) { + result.add(tbGisGps); + } else { + Date startTime = beforeFirst.getGpsTime(); + Date endTime = tbGisGps.get(tbGisGps.size() - 1).getGpsTime(); + if (beforeFirst.getAcc() == 1 && beforeFirst.getSpeed().compareTo(BigDecimal.ZERO) == 0){ + if (!result.isEmpty()) { + List resultLast = result.get(result.size() - 1); + if (DateUtil.isOverlap(resultLast.get(0).getGpsTime(),resultLast.get(resultLast.size() - 1).getGpsTime(),startTime,startTime)) { + resultLast.addAll(tbGisGps); + resultLast.sort(Comparator.comparing(TbGisGps::getGpsTime)); + result.set(result.size() - 1, resultLast); + } else { + result.add(tbGisGps); + } + } + } else { + if (DateUtil.between(startTime, endTime, DateUnit.MINUTE, false) < timeCut) { + if (!result.isEmpty()) { + List resultLast = result.get(result.size() - 1); + resultLast.addAll(tbGisGps); + resultLast.sort(Comparator.comparing(TbGisGps::getGpsTime)); + result.set(result.size() - 1, resultLast); + } + } + } + } + } + return result; + } + /** + * 转换为小时 + */ + private double betweenHour(Date startTime,Date endTime) { + return Convert.toDouble(DateUtil.betweenMs(startTime, endTime)) / 3600000; + } + + /** + * 行驶作业 点火且速度大于0 + * + * @param gps + * @return + */ + private boolean isDrivingWork(TbGisGps gps) { + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0 && (gps.getIsWork() == 1); + } + + /** + * 行驶未作业 点火、速度大于0、且未作业 + * + * @param gps + * @return + */ + private boolean isDrivingNotWork(TbGisGps gps) { + // 根据规则判断是否为“行驶未作业” + return gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) > 0 && (gps.getIsWork() == 0 || gps.getIsWork() == -1); + } + + + /** + * 停靠作业 点火 速度小于等于0 且在作业 或者 熄火 且在作业 + * + * @param gps + * @return + */ + private boolean isStoppedWork(TbGisGps gps) { + return (gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) <= 0 && (gps.getIsWork() == 1)) || (gps.getAcc() == 0 && (gps.getIsWork() == 1)); + } + + /** + * 停靠未作业 点火 速度小于等于0 且未作业 或者 熄火 且未作业 + * + * @param gps + * @return + */ + private boolean isStoppedNotWork(TbGisGps gps) { + return (gps.getAcc()%2 == 1 && gps.getSpeed().compareTo(BigDecimal.ZERO) <= 0 && (gps.getIsWork() == 0 || gps.getIsWork() == -1)) || (gps.getAcc() == 0 && (gps.getIsWork() == 0 || gps.getIsWork() == -1)); + } + + private static long calculateTimeDifferenceInMinutes(Date startTime, Date endTime) { + long timeDifference = endTime.getTime() - startTime.getTime(); + return timeDifference / (1000 * 60); + } + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsStatisticsServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsStatisticsServiceImpl.java new file mode 100644 index 0000000..6ad7182 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisGpsStatisticsServiceImpl.java @@ -0,0 +1,194 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.*; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.gis.entity.TbGisGpsStatistics; +import com.gci.boot.modules.gis.mapper.TbGisGpsStatisticsMapper; +import com.gci.boot.modules.gis.service.ITbGisGpsStatisticsService; +import com.gci.boot.modules.projects.service.IProjectsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 车辆gps相关数据统计 服务实现类 + *

+ * + * @author 2464 + * @since 2023-10-31 + */ +@Service +public class TbGisGpsStatisticsServiceImpl extends ServiceImpl implements ITbGisGpsStatisticsService { + + @Autowired + private ITbVehicleService vehicleService; + + @Autowired + private IProjectsService projectsService; + @Autowired + private TbGisGpsStatisticsMapper gisGpsStatisticsMapper; + + @Override + public void init(String time) { + DateTime dateTime = new DateTime(time); + DateTime beginOfMonth = DateUtil.beginOfMonth(dateTime); + DateTime endOfMonth = DateUtil.endOfMonth(dateTime); + DateTime toDay = new DateTime(); + if (endOfMonth.after(toDay)) { + endOfMonth = DateUtil.endOfDay(DateUtil.offset(toDay,DateField.DAY_OF_MONTH,-1)); + } + + List list = vehicleService.list(); + List gisGpsStatisticsList = gisGpsStatisticsMapper.initStatisticsCount(beginOfMonth,endOfMonth); + for (TbVehicle tbVehicle : list) { + List collect = gisGpsStatisticsList.stream().filter(g -> g.getPlateNumber().equals(tbVehicle.getPlateNumber())).collect(Collectors.toList()); + if (ObjectUtil.isEmpty(collect)) { + DateRange range = DateUtil.range(beginOfMonth, endOfMonth, DateField.DAY_OF_MONTH); + while (range.hasNext()) { + DateTime next = range.next(); + TbGisGpsStatistics tbGisGpsStatistics = collect.parallelStream().filter(g -> g.getStatisTime().equals(next.toString("yyyy-MM-dd"))).findAny().orElse(new TbGisGpsStatistics()); + if (BeanUtil.isEmpty(tbGisGpsStatistics)) { + if (StrUtil.isNotBlank(tbVehicle.getProjectId())) { + tbGisGpsStatistics.setProjectId(tbVehicle.getProjectId()); + } + tbGisGpsStatistics.setSupportEic(StrUtil.isBlank(tbVehicle.getVinCode()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportJt(StrUtil.isBlank(tbVehicle.getLocationTerminalId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportSafety(StrUtil.isBlank(tbVehicle.getActiveSafetyDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportVideo(StrUtil.isBlank(tbVehicle.getVideoDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportTerminal(CommonConstant.NO); + tbGisGpsStatistics.setVehicleType(tbVehicle.getVehicleType()); + tbGisGpsStatistics.setDealer(tbVehicle.getDealer()); + tbGisGpsStatistics.setPlateNumber(tbVehicle.getPlateNumber()); + tbGisGpsStatistics.setStatisTime(next.toString("yyyy-MM-dd")); + tbGisGpsStatistics.setJtCount(0L); + tbGisGpsStatistics.setJtValidCount(0L); + tbGisGpsStatistics.setJtNotValidCount(0L); + tbGisGpsStatistics.setEicCount(0L); + tbGisGpsStatistics.setEicValidCount(0L); + tbGisGpsStatistics.setEicNotValidCount(0L); + tbGisGpsStatistics.setWorkCount(0L); + tbGisGpsStatistics.setWorkNotValidCount(0L); + tbGisGpsStatistics.setWorkValidCount(0L); + gisGpsStatisticsList.add(tbGisGpsStatistics); + } else { + if (StrUtil.isNotBlank(tbVehicle.getProjectId())) { + tbGisGpsStatistics.setProjectId(tbVehicle.getProjectId()); + } + tbGisGpsStatistics.setSupportEic(StrUtil.isBlank(tbVehicle.getVinCode()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportJt(StrUtil.isBlank(tbVehicle.getLocationTerminalId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportSafety(StrUtil.isBlank(tbVehicle.getActiveSafetyDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportVideo(StrUtil.isBlank(tbVehicle.getVideoDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setVehicleType(tbVehicle.getVehicleType()); + tbGisGpsStatistics.setDealer(tbVehicle.getDealer()); + } + } + } else { + DateRange range = DateUtil.range(beginOfMonth, endOfMonth, DateField.DAY_OF_MONTH); + while (range.hasNext()) { + DateTime next = range.next(); + TbGisGpsStatistics tbGisGpsStatistics = collect.parallelStream().filter(g -> g.getStatisTime().equals(next.toString("yyyy-MM-dd"))).findAny().orElse(new TbGisGpsStatistics()); + if (BeanUtil.isEmpty(tbGisGpsStatistics)) { + if (StrUtil.isNotBlank(tbVehicle.getProjectId())) { + tbGisGpsStatistics.setProjectId(tbVehicle.getProjectId()); + } + tbGisGpsStatistics.setSupportEic(StrUtil.isBlank(tbVehicle.getVinCode()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportJt(StrUtil.isBlank(tbVehicle.getLocationTerminalId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportSafety(StrUtil.isBlank(tbVehicle.getActiveSafetyDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportVideo(StrUtil.isBlank(tbVehicle.getVideoDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportTerminal(CommonConstant.NO); + tbGisGpsStatistics.setVehicleType(tbVehicle.getVehicleType()); + tbGisGpsStatistics.setDealer(tbVehicle.getDealer()); + tbGisGpsStatistics.setPlateNumber(tbVehicle.getPlateNumber()); + tbGisGpsStatistics.setStatisTime(next.toString("yyyy-MM-dd")); + tbGisGpsStatistics.setJtCount(0L); + tbGisGpsStatistics.setJtValidCount(0L); + tbGisGpsStatistics.setJtNotValidCount(0L); + tbGisGpsStatistics.setEicCount(0L); + tbGisGpsStatistics.setEicValidCount(0L); + tbGisGpsStatistics.setEicNotValidCount(0L); + tbGisGpsStatistics.setWorkCount(0L); + tbGisGpsStatistics.setWorkNotValidCount(0L); + tbGisGpsStatistics.setWorkValidCount(0L); + gisGpsStatisticsList.add(tbGisGpsStatistics); + } else { + if (StrUtil.isNotBlank(tbVehicle.getProjectId())) { + tbGisGpsStatistics.setProjectId(tbVehicle.getProjectId()); + } + tbGisGpsStatistics.setSupportEic(StrUtil.isBlank(tbVehicle.getVinCode()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportJt(StrUtil.isBlank(tbVehicle.getLocationTerminalId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportSafety(StrUtil.isBlank(tbVehicle.getActiveSafetyDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportVideo(StrUtil.isBlank(tbVehicle.getVideoDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setVehicleType(tbVehicle.getVehicleType()); + tbGisGpsStatistics.setDealer(tbVehicle.getDealer()); + } + } + } + } + remove(new QueryWrapper().between("statis_time",beginOfMonth.toString("yyyy-MM-dd"),endOfMonth.toString("yyyy-MM-dd"))); + saveBatch(gisGpsStatisticsList); + + } + + @Override + public void gen() { + DateTime dateTime = new DateTime(); + String time = dateTime.offset(DateField.DAY_OF_YEAR, -1).toString(DatePattern.NORM_DATE_PATTERN); + insertData(time); + } + + + private void insertData(String time) { + List list = vehicleService.list(); + List gisGpsStatisticsList = gisGpsStatisticsMapper.StatisticsCount(time); + for (TbVehicle tbVehicle : list) { + TbGisGpsStatistics tbGisGpsStatistics = gisGpsStatisticsList.parallelStream().filter(g -> g.getPlateNumber().equals(tbVehicle.getPlateNumber())).findAny().orElse(new TbGisGpsStatistics()); + if (BeanUtil.isEmpty(tbGisGpsStatistics)) { + if (StrUtil.isNotBlank(tbVehicle.getProjectId())) { + tbGisGpsStatistics.setProjectId(tbVehicle.getProjectId()); + } + tbGisGpsStatistics.setSupportEic(StrUtil.isBlank(tbVehicle.getVinCode()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportJt(StrUtil.isBlank(tbVehicle.getLocationTerminalId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportSafety(StrUtil.isBlank(tbVehicle.getActiveSafetyDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportVideo(StrUtil.isBlank(tbVehicle.getVideoDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportTerminal(CommonConstant.NO); + tbGisGpsStatistics.setVehicleType(tbVehicle.getVehicleType()); + tbGisGpsStatistics.setDealer(tbVehicle.getDealer()); + tbGisGpsStatistics.setPlateNumber(tbVehicle.getPlateNumber()); + tbGisGpsStatistics.setStatisTime(time); + tbGisGpsStatistics.setJtCount(0L); + tbGisGpsStatistics.setJtValidCount(0L); + tbGisGpsStatistics.setJtNotValidCount(0L); + tbGisGpsStatistics.setEicCount(0L); + tbGisGpsStatistics.setEicValidCount(0L); + tbGisGpsStatistics.setEicNotValidCount(0L); + tbGisGpsStatistics.setWorkCount(0L); + tbGisGpsStatistics.setWorkNotValidCount(0L); + tbGisGpsStatistics.setWorkValidCount(0L); + gisGpsStatisticsList.add(tbGisGpsStatistics); + } else { + if (StrUtil.isNotBlank(tbVehicle.getProjectId())) { + tbGisGpsStatistics.setProjectId(tbVehicle.getProjectId()); + } + tbGisGpsStatistics.setSupportEic(StrUtil.isBlank(tbVehicle.getVinCode()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportJt(StrUtil.isBlank(tbVehicle.getLocationTerminalId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportSafety(StrUtil.isBlank(tbVehicle.getActiveSafetyDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setSupportVideo(StrUtil.isBlank(tbVehicle.getVideoDeviceId()) ? CommonConstant.NO : CommonConstant.YES); + tbGisGpsStatistics.setVehicleType(tbVehicle.getVehicleType()); + tbGisGpsStatistics.setDealer(tbVehicle.getDealer()); + } + } + remove(new QueryWrapper().apply("statis_time = {0}", time)); + saveBatch(gisGpsStatisticsList); + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisRunningbusServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisRunningbusServiceImpl.java new file mode 100644 index 0000000..f521acd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisRunningbusServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.gis.service.impl; + +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆实时信息表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class TbGisRunningbusServiceImpl extends ServiceImpl implements ITbGisRunningbusService { + +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingAlarmServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingAlarmServiceImpl.java new file mode 100644 index 0000000..44aef98 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingAlarmServiceImpl.java @@ -0,0 +1,59 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.date.BetweenFormatter; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.FormatUtil; +import com.gci.boot.modules.gis.entity.TbGisActiveSafetyAlarm; +import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm; +import com.gci.boot.modules.gis.mapper.TbGisSpeedingAlarmMapper; +import com.gci.boot.modules.gis.service.ITbGisSpeedingAlarmService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.statis.vo.AlarmTrendVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 超速记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class TbGisSpeedingAlarmServiceImpl extends ServiceImpl implements ITbGisSpeedingAlarmService { + + @Autowired + private TbGisSpeedingAlarmMapper tbGisSpeedingAlarmMapper; + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + Page list = tbGisSpeedingAlarmMapper.pageBuild(page, lambdaQueryWrapper); + for (TbGisSpeedingAlarm record : list.getRecords()) { + String duration = FormatUtil.formattedTimeDifference(record.getStartTime(), record.getEndTime()); + record.setDuration(duration); + } + return list; + } + + @Override + public List findListByTime(Date startTime, Date endTime) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.between(TbGisSpeedingAlarm::getStartTime, startTime, endTime); + List list = tbGisSpeedingAlarmMapper.selectList(queryWrapper); + return list; + } + + @Override + public List findTrendListByTime(Date startTime, Date endTime) { + return this.tbGisSpeedingAlarmMapper.findTrendListByTime(DateUtils.formatTime(startTime), DateUtils.formatTime(endTime)); + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingThresholdServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingThresholdServiceImpl.java new file mode 100644 index 0000000..c82ae95 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisSpeedingThresholdServiceImpl.java @@ -0,0 +1,194 @@ +package com.gci.boot.modules.gis.service.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.gis.entity.TbGisSpeedingThreshold; +import com.gci.boot.modules.gis.mapper.TbGisSpeedingThresholdMapper; +import com.gci.boot.modules.gis.service.ITbGisSpeedingThresholdService; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; + +/** + *

+ * 超速阈值设置 服务实现类 + *

+ * + * @author 2464 + * @since 2023-12-25 + */ +@Service +public class TbGisSpeedingThresholdServiceImpl extends ServiceImpl + implements ITbGisSpeedingThresholdService { + + @Autowired + private IProjectsService projectsService; + + @Autowired + private ISysDictService sysDictService; + + @Override + public void saveItem(TbGisSpeedingThreshold tbGisSpeedingThreshold) { + // 为0时时全局通用数据 + if ("0".equals(tbGisSpeedingThreshold.getThresholdType())) { + tbGisSpeedingThreshold.setProjectId(null); + tbGisSpeedingThreshold.setVehicleType(null); + throw new GciBootException("全局通用暂不支持新增"); + } else { + check(tbGisSpeedingThreshold); + } + save(tbGisSpeedingThreshold); + rel(); + } + + /** + * 校验数据 + * + * @param tbGisSpeedingThreshold + */ + private void check(TbGisSpeedingThreshold tbGisSpeedingThreshold) { + if (StrUtil.isBlank(tbGisSpeedingThreshold.getProjectId())) { + throw new GciBootException("项目不能为空!"); + } + if ("1".equals(tbGisSpeedingThreshold.getThresholdType())) { + tbGisSpeedingThreshold.setVehicleType(null); + } else if ("2".equals(tbGisSpeedingThreshold.getThresholdType())) { + if (StrUtil.isBlank(tbGisSpeedingThreshold.getVehicleType())) { + throw new GciBootException("车辆种类通用时车辆种类不能为空!"); + } + } else { + throw new GciBootException("非法字典值!"); + } + } + + @Override + public void updateItem(TbGisSpeedingThreshold tbGisSpeedingThreshold) { + if (tbGisSpeedingThreshold.getId().equals(CommonConstant.DEFAULT_THRESHOLD)) { + throw new GciBootException("全局通用暂不支持编辑"); + } + // 为0时时全局通用数据 + if ("0".equals(tbGisSpeedingThreshold.getThresholdType())) { + tbGisSpeedingThreshold.setProjectId(null); + tbGisSpeedingThreshold.setVehicleType(null); + throw new GciBootException("全局通用暂不支持编辑"); + } else { + check(tbGisSpeedingThreshold); + } + if (tbGisSpeedingThreshold.getIsValid() == 1) { + int count = + count(new LambdaUpdateWrapper() + .eq(TbGisSpeedingThreshold::getThresholdType, tbGisSpeedingThreshold.getThresholdType()) + .eq(TbGisSpeedingThreshold::getProjectId, tbGisSpeedingThreshold.getProjectId()) + .eq(StrUtil.isNotBlank(tbGisSpeedingThreshold.getVehicleType()), + TbGisSpeedingThreshold::getVehicleType, tbGisSpeedingThreshold.getVehicleType()) + .eq(TbGisSpeedingThreshold::getIsValid, 1)); + if (count > 0) { + throw new GciBootException("编辑失败!同一个类型内只能有一条启用数据!"); + } + } + updateById(tbGisSpeedingThreshold); + rel(); + } + + @Override + public void cancel(String id) { + if (id.equals(CommonConstant.DEFAULT_THRESHOLD)) { + throw new GciBootException("默认全局通用不支持禁用!"); + } + TbGisSpeedingThreshold byId = getById(id); + if (BeanUtil.isEmpty(id)) { + throw new GciBootException("id错误!"); + } else { + byId.setIsValid(0); + updateById(byId); + rel(); + } + } + + @Override + public void unCancel(String id) { + TbGisSpeedingThreshold byId = getById(id); + if (BeanUtil.isEmpty(id)) { + throw new GciBootException("id错误!"); + } else { + int count = count(new LambdaUpdateWrapper() + .eq(TbGisSpeedingThreshold::getThresholdType, byId.getThresholdType()) + .eq(TbGisSpeedingThreshold::getProjectId, byId.getProjectId()) + .eq(StrUtil.isNotBlank(byId.getVehicleType()), TbGisSpeedingThreshold::getVehicleType, + byId.getVehicleType()) + .eq(TbGisSpeedingThreshold::getIsValid, 1)); + if (count > 0) { + throw new GciBootException("启用失败!同一个类型内只能有一条启用数据!"); + } + byId.setIsValid(1); + updateById(byId); + rel(); + } + } + + @Override + public void removeItem(String id) { + if (id.equals(CommonConstant.DEFAULT_THRESHOLD)) { + throw new GciBootException("默认全局通用不支持删除!"); + } + removeById(id); + rel(); + } + + @Override + public void rel() { + List projectsList = projectsService.list(); + List dictModelList = sysDictService.queryDictItemsByCode("vehicle_type"); + + Map stringStringHashMap = new HashMap<>(); + + List gisSpeedingThresholdList = list(new LambdaQueryWrapper() + .eq(TbGisSpeedingThreshold::getIsValid, 1).orderByDesc(TbGisSpeedingThreshold::getThresholdType)); + for (Projects projects : projectsList) { + for (DictModel dictModel : dictModelList) { + TbGisSpeedingThreshold tbGisSpeedingThreshold1 = gisSpeedingThresholdList.stream() + .filter(t -> "2".equals(t.getThresholdType()) && projects.getId().equals(t.getProjectId()) + && dictModel.getValue().equals(t.getVehicleType())) + .findFirst().orElse(null); + if (tbGisSpeedingThreshold1 != null) { + stringStringHashMap.put(CommonConstant.THRESHOLD + projects.getId() + ":" + dictModel.getValue(), + JsonUtil.object2JsonAll(tbGisSpeedingThreshold1)); + } else { + TbGisSpeedingThreshold tbGisSpeedingThreshold2 = gisSpeedingThresholdList.stream() + .filter(t -> "1".equals(t.getThresholdType()) && projects.getId().equals(t.getProjectId())) + .findFirst().orElse(null); + if (tbGisSpeedingThreshold2 != null) { + stringStringHashMap.put( + CommonConstant.THRESHOLD + projects.getId() + ":" + dictModel.getValue(), + JsonUtil.object2JsonAll(tbGisSpeedingThreshold2)); + } else { + TbGisSpeedingThreshold tbGisSpeedingThreshold = gisSpeedingThresholdList.stream() + .filter(t -> t.getId().equals(CommonConstant.DEFAULT_THRESHOLD)).findFirst().orElse(null); + if (tbGisSpeedingThreshold != null) { + stringStringHashMap.put( + CommonConstant.THRESHOLD + projects.getId() + ":" + dictModel.getValue(), + JsonUtil.object2JsonAll(tbGisSpeedingThreshold)); + } + } + } + } + } + RedisUtil.multiSet(stringStringHashMap); + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisStoppingAlarmServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisStoppingAlarmServiceImpl.java new file mode 100644 index 0000000..f63ee8d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisStoppingAlarmServiceImpl.java @@ -0,0 +1,38 @@ +package com.gci.boot.modules.gis.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.FormatUtil; +import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm; +import com.gci.boot.modules.gis.entity.TbGisStoppingAlarm; +import com.gci.boot.modules.gis.mapper.TbGisStoppingAlarmMapper; +import com.gci.boot.modules.gis.service.ITbGisStoppingAlarmService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + *

+ * 停车超时记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-01 + */ +@Service +public class TbGisStoppingAlarmServiceImpl extends ServiceImpl implements ITbGisStoppingAlarmService { + + @Autowired + private TbGisStoppingAlarmMapper gisStoppingAlarmMapper; + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + Page list = gisStoppingAlarmMapper.pageBuild(page, lambdaQueryWrapper); + for (TbGisStoppingAlarm record : list.getRecords()) { + String duration = FormatUtil.formattedTimeDifference(record.getStartTime(), record.getEndTime()); + record.setDuration(duration); + } + return list; + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisVehicleFaultAlarmServiceImpl.java b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisVehicleFaultAlarmServiceImpl.java new file mode 100644 index 0000000..8449a00 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/service/impl/TbGisVehicleFaultAlarmServiceImpl.java @@ -0,0 +1,157 @@ +package com.gci.boot.modules.gis.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.FormatUtil; +import com.gci.boot.common.util.RedisKey; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.enums.AlarmCountType; +import com.gci.boot.enums.AlarmType; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.gis.dto.VehicleFaultDto; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.entity.TbGisVehicleFaultAlarm; +import com.gci.boot.modules.gis.mapper.TbGisVehicleFaultAlarmMapper; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.gis.service.ITbGisVehicleFaultAlarmService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.gis.vo.VehicleFaultVo; +import com.gci.boot.modules.statis.vo.AlarmTrendVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 车辆车机故障异常记录表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-09 + */ +@Service +public class TbGisVehicleFaultAlarmServiceImpl extends ServiceImpl implements ITbGisVehicleFaultAlarmService { + + @Resource + private TbGisVehicleFaultAlarmMapper gisVehicleFaultAlarmMapper; + @Autowired + private ITbGisRunningbusService gisRunningbusService; + + @Override + public List countFault(String projectId) { + List vehicleFaultDtos = new ArrayList<>(); + AlarmCountType[] values = AlarmCountType.values(); + for (AlarmCountType value : values) { + VehicleFaultDto vehicleFaultDto = new VehicleFaultDto(); + vehicleFaultDto.setName(value.getName()); + vehicleFaultDto.setCountList(value.getAlarmTypeList().stream().map(AlarmType::getDescription).collect(Collectors.toList())); + vehicleFaultDtos.add(vehicleFaultDto); + } + List vehicleFaultVo = gisVehicleFaultAlarmMapper.countFault(projectId, vehicleFaultDtos); + if (vehicleFaultVo.size() < vehicleFaultDtos.size()) { + for (VehicleFaultDto vehicleFaultDto : vehicleFaultDtos) { + VehicleFaultVo vo = vehicleFaultVo.stream().filter(v -> v.getName().equals(vehicleFaultDto.getName())).findFirst().orElse(new VehicleFaultVo()); + if (BeanUtil.isEmpty(vo)) { + vo.setCount(0); + vo.setName(vehicleFaultDto.getName()); + } + vehicleFaultVo.add(vo); + } + } + return vehicleFaultVo; + } + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + Page list = gisVehicleFaultAlarmMapper.pageBuild(page, lambdaQueryWrapper); + for (TbGisVehicleFaultAlarm record : list.getRecords()) { + String duration = FormatUtil.formattedTimeDifference(record.getAlarmStartTime(), record.getAlarmEndTime()); + record.setDuration(duration); + } + return list; + } + + @Override + public List findListByTime(Date startTime, Date endTime) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.between(TbGisVehicleFaultAlarm::getAlarmStartTime, startTime, endTime); + List list = this.gisVehicleFaultAlarmMapper.selectList(queryWrapper); + return list; + } + + @Override + public List findTrendListByTime(Date startTime, Date endTime) { + return this.gisVehicleFaultAlarmMapper.findTrendListByTime(DateUtils.formatTime(startTime), DateUtils.formatTime(endTime)); + } + + @Override + public void close(String ids, String remark) { + List split = StrUtil.split(ids, StrUtil.COMMA); + List list = list(new LambdaQueryWrapper().in(TbGisVehicleFaultAlarm::getId, split)); + if (list.size() < split.size()) { + throw new GciBootException("id错误!"); + } + TbGisVehicleFaultAlarm find = list.stream().filter(i -> i.getIsClosed() == 1).findAny().orElse(null); + if (find != null) { + throw new GciBootException("数据中有已关闭告警!请刷新后重新勾选!"); + } + DateTime dateTime = new DateTime(); + JSONObject jsonObject = new JSONObject(); + jsonObject.set("status", true); + jsonObject.set("time", dateTime.toString()); + jsonObject.set("endTime", dateTime.toString()); + HashMap needSet = new HashMap<>(list.size()); + for (TbGisVehicleFaultAlarm faultAlarm : list) { + needSet.put(RedisKey.VEHICLE_IS_FAULT_ALARM + faultAlarm.getPlateNumber() + ":" + faultAlarm.getFaultType(),jsonObject.toString()); + faultAlarm.setIsClosed(1); + faultAlarm.setCloseType("2"); + faultAlarm.setAlarmEndTime(dateTime); + faultAlarm.setCloseTime(dateTime); + faultAlarm.setRemark(remark); + gisRunningbusService.update(new LambdaUpdateWrapper().eq(TbGisRunningbus::getPlateNumber,faultAlarm.getPlateNumber()) + .set(TbGisRunningbus::getFaultAlarm,checkFaultAlarm(faultAlarm.getPlateNumber()))); + } + RedisUtil.multiSet(needSet); + updateBatchById(list); + + } + + private Integer checkFaultAlarm(String plateNumber) { + int integer = 0; + AlarmType[] values = AlarmType.values(); + List collect = new ArrayList(); + for (AlarmType value : values) { + collect.add(RedisKey.VEHICLE_IS_FAULT_ALARM + plateNumber + ":" + value.getProp()); + } + List objects = RedisUtil.multiGet(collect); + if (ObjectUtil.isNotEmpty(objects)) { + for (Object object : objects) { + JSONObject jsonObject = new JSONObject(StrUtil.removeAll(StrUtil.strip(Convert.toStr(object), "\""),"\\")); + if (ObjectUtil.isNotEmpty(jsonObject)) { + Boolean status = jsonObject.getBool("status"); + if (status) { + integer = 1; + return integer; + } + } + } + } + return integer; + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/EverydayGisVo.java b/src/main/java/com/gci/boot/modules/gis/vo/EverydayGisVo.java new file mode 100644 index 0000000..6be05e6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/EverydayGisVo.java @@ -0,0 +1,140 @@ +package com.gci.boot.modules.gis.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.common.dict.annotation.Dict; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author 24642 + */ + +@Data +public class EverydayGisVo { + + private Integer index; + + /** + * 项目id + */ + @JsonPropertyDescription("项目id") + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @Excel(name = "所属项目",dict = "tb_projects,project_name,id") + private String projectId; + + /** + * 车牌号 + */ + @JsonPropertyDescription("车牌号") + @Excel(name = "车牌号") + private String plateNumber; + + /** + * 车辆种类 + */ + @JsonPropertyDescription("车辆种类") + @Dict(dicCode = "vehicle_type") + @Excel(name = "车辆种类",dict = "vehicle_type") + private String vehicleType; + + /** + * 车辆品牌 + */ + @JsonPropertyDescription("车辆品牌") + @Dict(dicCode = "vehicle_brand") + @Excel(name = "车辆品牌",dict = "vehicle_brand") + private String vehicleBrand; + + /** + * 车辆型号 + */ + @JsonPropertyDescription("车辆型号") + private String vehicleModel; + + /** + * 统计时间 + */ + @JsonPropertyDescription("统计时间") + private String statisTime; + + /** + * 行驶里程 km + */ + @JsonPropertyDescription("行驶里程 km") + private BigDecimal totalMile; + + /** + * 作业里程 km + */ + @JsonPropertyDescription("作业里程 km") + private BigDecimal workMile; + + /** + * 行驶时长 h + */ + @JsonPropertyDescription("行驶时长 h") + private BigDecimal totalTime; + + /** + * 作业时长 h + */ + @JsonPropertyDescription("作业时长 h") + private BigDecimal workTime; + + /** + * 行驶作业时长 h + */ + @JsonPropertyDescription("行驶作业时长 h") + private BigDecimal travelWorkTime; + + /** + * 停靠作业时长 h + */ + @JsonPropertyDescription("停靠作业时长 h") + private BigDecimal stopWorkTime; + + /** + * 平均行驶速度 km/h + */ + @JsonPropertyDescription("平均行驶速度 km/h") + private BigDecimal avgSpeed = BigDecimal.ZERO; + + /** + * 平均作业速度 km/h + */ + @JsonPropertyDescription("平均作业速度 km/h") + private BigDecimal avgWorkSpeed = BigDecimal.ZERO; + + /** + * 作业开始时间 + */ + @JsonPropertyDescription("作业开始时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date workStartTime; + + /** + * 作业结束时间 + */ + @JsonPropertyDescription("作业结束时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date workEndTime; + + /** + * 在线时长 h + */ + @JsonPropertyDescription("在线时长 h") + private BigDecimal onlineTime; + + /** + * 通电停靠时长 h + */ + @JsonPropertyDescription("通电停靠时长 h") + private BigDecimal onlineStopTime; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/EverydayMileCountVo.java b/src/main/java/com/gci/boot/modules/gis/vo/EverydayMileCountVo.java new file mode 100644 index 0000000..3088c11 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/EverydayMileCountVo.java @@ -0,0 +1,23 @@ +package com.gci.boot.modules.gis.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author 24642 + */ +@Data +public class EverydayMileCountVo { + /** + * 行驶里程 km + */ + @ApiModelProperty("行驶里程 km") + private BigDecimal totalMile = BigDecimal.ZERO; + /** + * 作业里程 km + */ + @ApiModelProperty("作业里程 km") + private BigDecimal workMile = BigDecimal.ZERO; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/FenceSpeedBeanVO.java b/src/main/java/com/gci/boot/modules/gis/vo/FenceSpeedBeanVO.java new file mode 100644 index 0000000..dd6c72b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/FenceSpeedBeanVO.java @@ -0,0 +1,29 @@ +package com.gci.boot.modules.gis.vo; + +import cn.hutool.json.JSONObject; +import lombok.Data; + +import java.util.Date; + +@Data +public class FenceSpeedBeanVO { + + /** + * 告警类型 1-围栏 2-超速 + */ + public Integer type; + /** + * 告警标志 1-开始 2-结束 + */ + public Integer flag; + + /** + * 采集时间 + */ + public Date time; + + /** + * 实体对象,根据告警类型不同而不同 + */ + private JSONObject data; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/GisHistoryVo.java b/src/main/java/com/gci/boot/modules/gis/vo/GisHistoryVo.java new file mode 100644 index 0000000..630a703 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/GisHistoryVo.java @@ -0,0 +1,27 @@ +package com.gci.boot.modules.gis.vo; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; +import java.util.List; + +/** + * @author 24642 + */ +@NoArgsConstructor +@Data +public class GisHistoryVo { + /** + * 日期 + */ + private String day; + /** + * 时间记录 + */ + private Date dayTime; + /** + * 时间段分组 + */ + private List timeSlot; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/GisProjectTreeVo.java b/src/main/java/com/gci/boot/modules/gis/vo/GisProjectTreeVo.java new file mode 100644 index 0000000..43d8fc8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/GisProjectTreeVo.java @@ -0,0 +1,29 @@ +package com.gci.boot.modules.gis.vo; + +import com.gci.boot.modules.basedata.entity.TbVehicle; +import lombok.Data; + +import java.util.List; + +/** + * @author 24642 + */ +@Data +public class GisProjectTreeVo { + /** + * 项目ID + */ + private String projectId; + /** + * 项目名称 + */ + private String projectName; + /** + * 车辆列表 + */ + private List vehicleList; + /** + * 已关联车辆 + */ + private List hadBind; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/GisRedisVehicleVo.java b/src/main/java/com/gci/boot/modules/gis/vo/GisRedisVehicleVo.java new file mode 100644 index 0000000..4f674f9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/GisRedisVehicleVo.java @@ -0,0 +1,89 @@ +package com.gci.boot.modules.gis.vo; + +import com.gci.boot.common.util.LatLonPoint; +import lombok.Data; + +import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.LocalTime; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +/** + * @author 24642 + */ +@Data +public class GisRedisVehicleVo { + /** + * 围栏id + */ + private String fenceId; + /** + * 围栏名称 + */ + private String fenceName; + /** + * 车牌号 查询的时候使用的 + */ + private String plateNumber; + /** + * 开始时间 + */ + private String startTime; + /** + * 结束时间 + */ + private String endTime; + /** + * 围栏类型 1-停场 2-行驶 + */ + private Integer fenceType; + /** + * 是否跨天 + */ + private Integer isOvernight; + /** + * 车辆驶出围栏多少分钟后开始告警,整数 + */ + private Integer alertDelayMinutes; + /** + * 围栏json + */ + private String geoJson; + /** + * 围栏坐标list + */ + private List coordinateList; + + /** + * 判断当前gps时间是否在围栏限制的生效时间范围内 + * @param gpsTime + * @return + */ + public boolean isWithinFenceTime(Date gpsTime){ + try { + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); + String formatGpsTime = sdf.format(gpsTime); + LocalTime current = LocalTime.parse(formatGpsTime); + LocalTime start = LocalTime.parse(startTime); + LocalTime end = LocalTime.parse(endTime); + + if (Objects.nonNull(isOvernight) && isOvernight == 1) { + // 如果跨夜,将结束时间加一天 + end = end.plus(Duration.ofHours(24)); + } + if (start.isBefore(end)) { + // 同一天内的时间段 + return !current.isBefore(start) && !current.isAfter(end); + } else { + // 跨天的时间段,例如 22:00 到 06:00 + return !current.isBefore(start) || !current.isAfter(end); + } + } catch (Exception e) { + e.printStackTrace(); + // 解析时间出错,返回false + return false; + } + } +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/GisVehicleVo.java b/src/main/java/com/gci/boot/modules/gis/vo/GisVehicleVo.java new file mode 100644 index 0000000..87eacf3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/GisVehicleVo.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.gis.vo; + +import lombok.Data; + +import java.util.List; + +/** + * @author 24642 + */ +@Data +public class GisVehicleVo { + /** + * 方案id + */ + private String planId; + /** + * 车辆列表 + */ + private List vehicleList; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/PointListDTO.java b/src/main/java/com/gci/boot/modules/gis/vo/PointListDTO.java new file mode 100644 index 0000000..a336bb1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/PointListDTO.java @@ -0,0 +1,55 @@ +package com.gci.boot.modules.gis.vo; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 经纬度点集合及其他信息Item + */ +@NoArgsConstructor +@Data +public class PointListDTO { + /** + * location + */ + private List location; + /** + * 电量 + */ + private Integer stateOfCharge; + /** + * 实时速度 + */ + private BigDecimal speed; + /** + * 总里程 + */ + private BigDecimal totalMileage; + /** + * 总电压 + */ + private BigDecimal totalVoltage; + /** + * 上报时间 + */ + private String gpsTime; + /** + * 0-熄火1-点火 + */ + private Integer acc; + /** + * 1-工作2-断开 + */ + private Integer dcStatus; + /** + * 1-纯电2-混动3-燃油-99-无效、-100-异常 + */ + private Integer operatingMode; + /** + * 作业状态 + */ + private Integer isWork; +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/gis/vo/StatisGisVo.java b/src/main/java/com/gci/boot/modules/gis/vo/StatisGisVo.java new file mode 100644 index 0000000..bee935d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/StatisGisVo.java @@ -0,0 +1,144 @@ +package com.gci.boot.modules.gis.vo; + +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author 24642 + */ +@Data +public class StatisGisVo { + + + private Integer index; + + /** + * 项目id + */ + @JsonPropertyDescription("项目id") + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectId; + + /** + * 车牌号 + */ + @JsonPropertyDescription("车牌号") + private String plateNumber; + + /** + * 车辆种类 + */ + @JsonPropertyDescription("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + /** + * 车辆品牌 + */ + @JsonPropertyDescription("车辆品牌") + @Dict(dicCode = "vehicle_brand") + private String vehicleBrand; + + /** + * 车辆型号 + */ + @JsonPropertyDescription("车辆型号") + private String vehicleModel; + + /** + * 统计时间 + */ + @JsonPropertyDescription("统计时间") + private String statisTime; + + /** + * 行驶里程 km + */ + @JsonPropertyDescription("行驶里程 km") + private BigDecimal totalMile; + + /** + * 作业里程 km + */ + @JsonPropertyDescription("作业里程 km") + private BigDecimal workMile; + + /** + * 行驶时长 h + */ + @JsonPropertyDescription("行驶时长 h") + private BigDecimal totalTime; + + /** + * 作业时长 h + */ + @JsonPropertyDescription("作业时长 h") + private BigDecimal workTime; + + /** + * 行驶作业时长 h + */ + @JsonPropertyDescription("行驶作业时长 h") + private BigDecimal travelWorkTime; + + /** + * 停靠作业时长 h + */ + @JsonPropertyDescription("停靠作业时长 h") + private BigDecimal stopWorkTime; + + /** + * 平均行驶速度 km/h + */ + @JsonPropertyDescription("平均行驶速度 km/h") + private BigDecimal avgSpeed = BigDecimal.ZERO; + + /** + * 平均作业速度 km/h + */ + @JsonPropertyDescription("平均作业速度 km/h") + private BigDecimal avgWorkSpeed = BigDecimal.ZERO; + + /** + * 在线时长 h + */ + @JsonPropertyDescription("在线时长 h") + private BigDecimal onlineTime; + + /** + * 通电停靠时长 h + */ + @JsonPropertyDescription("通电停靠时长 h") + private BigDecimal onlineStopTime; + + /** + * 应出勤天数 + */ + @JsonPropertyDescription("应出勤天数") + private Integer requiredAttendanceDays; + /** + * 实际出勤天数 + */ + @JsonPropertyDescription("实际出勤天数") + private Integer actualAttendanceDays; + /** + * 未出勤天数 + */ + @JsonPropertyDescription("未出勤天数") + private Integer notAttendanceDays; + /** + * 作业线路效率 % + */ + @JsonPropertyDescription("作业线路效率 %") + private BigDecimal mileEfficiency = new BigDecimal("0.00"); + /** + * 日均有效使用率 % + */ + @JsonPropertyDescription("日均有效使用率 %") + private BigDecimal timeEfficiency = new BigDecimal("0.00"); +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/TimeSlotDTO.java b/src/main/java/com/gci/boot/modules/gis/vo/TimeSlotDTO.java new file mode 100644 index 0000000..b1e553b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/TimeSlotDTO.java @@ -0,0 +1,100 @@ +package com.gci.boot.modules.gis.vo; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 时间段分组Item + */ +@NoArgsConstructor +@Data +public class TimeSlotDTO { + /** + * 记录开始时间 + */ + private Date slotTime; + /** + * 结束时间 + */ + private Date endTime; + /** + * power--充电driving--行驶working--作业中 + */ + private String type; + /** + * timeRange + */ + private String timeRange; + /** + * timeCount + */ + private String timeCount; + /** + * 充电量 + */ + private BigDecimal chargedEnergy; + /** + * 充电比 + */ + private BigDecimal chargedEfficiency; + /** + * 平均速度 + */ + private Double averageSpeed; + /** + * 行驶里程 + */ + private BigDecimal mileage; + /** + * 平均耗电量 + */ + private BigDecimal powerConsumption; + /** + * 是否跨天1-是0-否 + */ + private Integer isOvernight; + + /** + * 1-行驶未作业 2-行驶作业 3-停靠作业 4-停靠未作业 + */ + private Integer recordType; + + /** + * 开始里程 + */ + private BigDecimal startMile; + /** + * 结束里程 + */ + private BigDecimal endMile; + /** + * 开始电量 + */ + private Integer startGisGpsStateOfCharge; + /** + * 结束电量 + */ + private Integer endGisGpsStateOfCharge; + + private BigDecimal lon; + + private BigDecimal lat; + /** + * 是否合并记录 + */ + private Boolean logMerge; + /** + * 经纬度点集合及其他信息 + */ + private List pointList; + + /** + * 工作状态点集合 + */ + private List workLine; + +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/gis/vo/VehicleFaultVo.java b/src/main/java/com/gci/boot/modules/gis/vo/VehicleFaultVo.java new file mode 100644 index 0000000..b3883a4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/VehicleFaultVo.java @@ -0,0 +1,9 @@ +package com.gci.boot.modules.gis.vo; + +import lombok.Data; + +@Data +public class VehicleFaultVo { + private String name; + private Integer count; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/VehicleWorkVO.java b/src/main/java/com/gci/boot/modules/gis/vo/VehicleWorkVO.java new file mode 100644 index 0000000..c36dc51 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/VehicleWorkVO.java @@ -0,0 +1,22 @@ +package com.gci.boot.modules.gis.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +/** + * @author lyz + * @date 2023/10/24 14:03 + */ +@Data +public class VehicleWorkVO { + + private String numberPlate; + + private String driverMile = "-"; + + private String driverHour = "-"; + + private String workMile = "-"; + + private String workHour = "-"; +} diff --git a/src/main/java/com/gci/boot/modules/gis/vo/WorkLineVo.java b/src/main/java/com/gci/boot/modules/gis/vo/WorkLineVo.java new file mode 100644 index 0000000..7c9eca7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/gis/vo/WorkLineVo.java @@ -0,0 +1,10 @@ +package com.gci.boot.modules.gis.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class WorkLineVo { + private List workPointList; +} diff --git a/src/main/java/com/gci/boot/modules/monitor/controller/MonitorController.java b/src/main/java/com/gci/boot/modules/monitor/controller/MonitorController.java new file mode 100644 index 0000000..2a56b02 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/controller/MonitorController.java @@ -0,0 +1,118 @@ +package com.gci.boot.modules.monitor.controller; + +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.gis.vo.GisRedisVehicleVo; +import com.gci.boot.modules.monitor.service.IMonitorService; +import com.gci.boot.modules.monitor.vo.AlarmCountVO; +import com.gci.boot.modules.monitor.vo.OverallMonitorVO; +import com.gci.boot.modules.monitor.vo.RunningbusVO; +import com.gci.boot.modules.monitor.vo.VehicleTreeVO; +import com.gci.boot.modules.video.vo.VideoDeviceVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@Api(tags="全局监控") +@Slf4j +@RestController +@RequestMapping("/monitor") +public class MonitorController { + + @Autowired + private IMonitorService monitorService; + + /** + * 全部列表查询 + * @param statusType + * @return + */ + @AddSysLog(value = "全局监控-全部列表查询") + @DataPermission(item="tgr.projectId", sqlIds = {"com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper.queryOverallVehicle"}) + @GetMapping(value = "/list") + public Result queryList(String statusType, String plateNumber, String projectId, String vehicleType) { + List list = monitorService.getOverallVehicle(statusType,plateNumber,projectId,vehicleType); + return Result.ok(list); + } + + /** + * 获取项目车辆树形数据 + * @param plateNumber + * @return + */ + @AddSysLog(value = "全局监控-获取项目车辆树形数据") + @DataPermission(item="a.projectId", sqlIds = {"com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper.queryProjrctVehicle"}) + @GetMapping(value = "/getVehicleTree") + public Result getVehicleTree(String plateNumber) { + //获取所有车辆对应项目,为空的归到其它。 --》项目名称->车牌 + List list = monitorService.getVehicleTree(plateNumber); + return Result.ok(list); + } + + /** + * 获取车辆详情 + * @param plateNumber + * @return + */ + @AddSysLog(value = "全局监控-获取车辆详情") + @GetMapping(value = "/getVehicleInfo") + public Result getVehicleInfo(String plateNumber) { + OverallMonitorVO vo = monitorService.getVehicleInfo(plateNumber); + return Result.ok(vo); + } + + /** + * 获取车辆数量 + * @return + */ + @AddSysLog(value = "全局监控-获取车辆数量") + @DataPermission(item="tb_gis_runningbus.projectId", sqlIds = {"com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper.selectList"}) + @GetMapping(value = "/getVehicleCount") + public Result getVehicleCount() { + List list = monitorService.getVehicleCount(); + return Result.ok(list); + } + + /** + * 根据车牌获取车辆视频通道信息 + * @return + */ + @AddSysLog(value = "全局监控-根据车牌获取车辆视频通道信息") + @GetMapping(value = "/getVehicleVideoChannel") + public Result getVehicleVideoChannel(String plateNumber) { + try{ + VideoDeviceVO vo = monitorService.getVehicleVideoChannel(plateNumber); + return Result.ok(vo); + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } + + /** + * 实时监控--获取车辆详情 + * @return + */ + @AddSysLog(value = "实时监控-获取车辆详情") + @GetMapping(value = "/getRunningbusInfo") + public Result getRunningbusInfo(String plateNumber) { + RunningbusVO vo = monitorService.getRunningbusInfo(plateNumber); + return Result.ok(vo); + } + + /** + * 实时监控--实时获取车辆关联围栏 + * @return + */ + @AddSysLog(value = "实时监控-实时获取车辆关联围栏") + @GetMapping(value = "/getVehicleFenceInfo") + public Result getVehicleFenceInfo(String plateNumber) { + List list = monitorService.getVehicleFenceInfo(plateNumber); + return Result.ok(list); + } +} diff --git a/src/main/java/com/gci/boot/modules/monitor/enums/DirectionEnum.java b/src/main/java/com/gci/boot/modules/monitor/enums/DirectionEnum.java new file mode 100644 index 0000000..c434876 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/enums/DirectionEnum.java @@ -0,0 +1,52 @@ +package com.gci.boot.modules.monitor.enums; + +import cn.hutool.core.util.StrUtil; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Objects; + +public enum DirectionEnum { + + E(45, 135, "东"), + S(135, 225, "南"), + W(225, 315, "西"), + N_1(315, 360, "北"), + N_2(0, 45, "北"); + + @Getter + private Integer min; + @Getter + private Integer max; + @Getter + private String label; + + DirectionEnum(Integer min, Integer max, String label) { + this.min = min; + this.max = max; + this.label = label; + } + + + public static String get(String str) { + int val = 0; + if(StrUtil.isNotBlank(str)){ + try{ + val = Integer.valueOf(str); + }catch (Exception e){ + e.printStackTrace(); + } + } + int finalVal = val; + DirectionEnum directionEnum = Arrays.stream(values()) + .filter(r -> finalVal > r.min && finalVal <= r.max) + .findFirst() + .orElse(null); + + if(Objects.nonNull(directionEnum)){ + return directionEnum.label; + } else{ + return ""; + } + } +} diff --git a/src/main/java/com/gci/boot/modules/monitor/enums/VehicleStatusEnum.java b/src/main/java/com/gci/boot/modules/monitor/enums/VehicleStatusEnum.java new file mode 100644 index 0000000..278eaa4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/enums/VehicleStatusEnum.java @@ -0,0 +1,68 @@ +package com.gci.boot.modules.monitor.enums; + +import lombok.Getter; + +public enum VehicleStatusEnum { + + // "" 1 2 3 4 5 6 + // 状态: 全部车辆 在线 离线 故障告警 围栏告警 超速告警 主动安全告警 + + /** + * 全部车辆 + */ + ALL("全部车辆",""), + /** + * 在线 + */ + IS_ONLINE("在线","1"), + /** + * 离线 + */ + NO_ONLINE("离线","2"), + /** + * 故障告警 + */ + FAULT("故障告警","3"), + /** + * 围栏告警 + */ + FENCE("围栏告警","4"), + /** + * 超速告警 + */ + SPEED("超速告警","5"), + /** + * 主动安全告警 + */ + SAFETY("主动安全告警","6"), + /** + * 作业中 + */ + WORK("作业中","7") + ; + /** + * 维修状态 + */ + @Getter + private String type; + + @Getter + private String statusType; + + + + VehicleStatusEnum(String type, String statusType) { + this.type = type; + this.statusType = statusType; + } + + public static VehicleStatusEnum getEnum(String type){ + for (VehicleStatusEnum statusEnum : VehicleStatusEnum.values()) { + if (statusEnum.getType().equals(type)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/monitor/service/IMonitorService.java b/src/main/java/com/gci/boot/modules/monitor/service/IMonitorService.java new file mode 100644 index 0000000..874fcdd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/service/IMonitorService.java @@ -0,0 +1,63 @@ +package com.gci.boot.modules.monitor.service; + +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.vo.GisRedisVehicleVo; +import com.gci.boot.modules.monitor.vo.AlarmCountVO; +import com.gci.boot.modules.monitor.vo.OverallMonitorVO; +import com.gci.boot.modules.monitor.vo.RunningbusVO; +import com.gci.boot.modules.monitor.vo.VehicleTreeVO; +import com.gci.boot.modules.video.vo.VideoDeviceVO; + +import java.util.List; + +public interface IMonitorService { + + /** + * 获取全局监控车辆数据 + * @param statusType + * @return + */ + List getOverallVehicle(String statusType,String plateNumber,String projectId, String vehicleType); + + /** + * 获取所有车辆对应项目,为空的归到其它 + * @param plateNumber + * @return + */ + List getVehicleTree(String plateNumber); + + /** + * 获取各状态车辆数量 + * @return + */ + List getVehicleCount(); + + + /** + * 全局监控--获取车辆详情 + * @param plateNumber + * @return + */ + OverallMonitorVO getVehicleInfo(String plateNumber); + + /** + * 实时监控--根据车牌获取车辆视频通道信息 + * @param plateNumber + * @return + */ + VideoDeviceVO getVehicleVideoChannel(String plateNumber); + + /** + * 实时监控--获取车辆详情 + * @param plateNumber + * @return + */ + RunningbusVO getRunningbusInfo(String plateNumber); + + /** + * 实时监控--实时获取车辆关联围栏 + * @param plateNumber + * @return + */ + List getVehicleFenceInfo(String plateNumber); +} diff --git a/src/main/java/com/gci/boot/modules/monitor/service/impl/MonitorServiceImpl.java b/src/main/java/com/gci/boot/modules/monitor/service/impl/MonitorServiceImpl.java new file mode 100644 index 0000000..2bde737 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/service/impl/MonitorServiceImpl.java @@ -0,0 +1,202 @@ +package com.gci.boot.modules.monitor.service.impl; + +import cn.hutool.Hutool; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.gci.boot.common.util.FormatUtil; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.gis.vo.GisRedisVehicleVo; +import com.gci.boot.modules.monitor.enums.VehicleStatusEnum; +import com.gci.boot.modules.monitor.service.IMonitorService; +import com.gci.boot.modules.monitor.vo.RunningbusVO; +import com.gci.boot.modules.video.service.IVideoService; +import com.gci.boot.modules.video.vo.VideoDeviceVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.monitor.enums.DirectionEnum; +import com.gci.boot.modules.monitor.vo.AlarmCountVO; +import com.gci.boot.modules.monitor.vo.OverallMonitorVO; +import com.gci.boot.modules.monitor.vo.VehicleTreeVO; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class MonitorServiceImpl implements IMonitorService { + + @Autowired + private ITbGisRunningbusService runningbusService; + @Autowired + private TbGisRunningbusMapper runningbusMapper; + @Autowired + private IVideoService videoService; + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private ITbVehicleService vehicleService; + + /** + * 获取全局监控车辆数据 + * @param statusType + * @return + */ + @Override + public List getOverallVehicle(String statusType, String plateNumber, String projectId, String vehicleType){ + //status -1在线,2-离线,3-故障告警,4-围栏告警,5-超速告警,6-主动安全告警 + List list = runningbusMapper.queryOverallVehicle(statusType,plateNumber,projectId,vehicleType); + return list; + } + + /** + * 获取所有车辆对应项目,为空的归到其它 + * @param plateNumber + * @return + */ + @Override + public List getVehicleTree(String plateNumber){ + List treeVO = runningbusMapper.queryProjrctVehicle(plateNumber); + return treeVO; + } + + /** + * 获取各状态车辆数量 + * @return + */ + @Override + public List getVehicleCount(){ + LambdaQueryWrapper busQuery = new LambdaQueryWrapper<>(); + List busList = runningbusMapper.selectList(busQuery); + List list = new ArrayList<>(); + AlarmCountVO vo = new AlarmCountVO(VehicleStatusEnum.ALL.getType(),VehicleStatusEnum.ALL.getStatusType(),busList.stream().count()); + AlarmCountVO vo1 = new AlarmCountVO(VehicleStatusEnum.IS_ONLINE.getType(), VehicleStatusEnum.IS_ONLINE.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getIsOnline()) && 1 == item.getIsOnline()).count()); + AlarmCountVO vo2 = new AlarmCountVO(VehicleStatusEnum.NO_ONLINE.getType(), VehicleStatusEnum.NO_ONLINE.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getIsOnline()) && 0 == item.getIsOnline()).count()); + AlarmCountVO vo3 = new AlarmCountVO(VehicleStatusEnum.FAULT.getType(), VehicleStatusEnum.FAULT.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getFaultAlarm()) && 1 == item.getFaultAlarm()).count()); + AlarmCountVO vo4 = new AlarmCountVO(VehicleStatusEnum.FENCE.getType(), VehicleStatusEnum.FENCE.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getFenceAlarm()) && 1 == item.getFenceAlarm()).count()); + AlarmCountVO vo5 = new AlarmCountVO(VehicleStatusEnum.SPEED.getType(), VehicleStatusEnum.SPEED.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getSpeedingAlarm()) && 1 == item.getSpeedingAlarm()).count()); + AlarmCountVO vo6 = new AlarmCountVO(VehicleStatusEnum.SAFETY.getType(), VehicleStatusEnum.SAFETY.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getSafetyAlarm()) && 1 == item.getSafetyAlarm()).count()); + AlarmCountVO vo7 = new AlarmCountVO(VehicleStatusEnum.WORK.getType(), VehicleStatusEnum.WORK.getStatusType(), + busList.stream().filter(item->Objects.nonNull(item.getIsWork()) && 1 == item.getIsWork()).count()); + list.add(vo); + list.add(vo1); + list.add(vo2); + list.add(vo3); + list.add(vo4); + list.add(vo5); + list.add(vo6); + list.add(vo7); + return list; + } + + /** + * 获取车辆详情 + * @param plateNumber + * @return + */ + @Override + public OverallMonitorVO getVehicleInfo(String plateNumber){ + OverallMonitorVO vo = runningbusMapper.queryVehicleInfo(plateNumber); + if(StrUtil.isNotBlank(vo.getDir())){ + vo.setDirection(DirectionEnum.get(vo.getDir())); + } + return vo; + } + + @Override + public VideoDeviceVO getVehicleVideoChannel(String plateNumber) { + VideoDeviceVO vo = videoService.getVideoDevice(plateNumber); + return vo; + } + + @Override + public RunningbusVO getRunningbusInfo(String plateNumber) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbGisRunningbus::getPlateNumber,plateNumber).last(" limit 1 "); + TbGisRunningbus tbGisRunningbus = runningbusMapper.selectOne(queryWrapper); + if(Objects.nonNull(tbGisRunningbus)){ + RunningbusVO vo = new RunningbusVO(); + // + LambdaQueryWrapper vehicleLambdaQueryWrapper = new LambdaQueryWrapper<>(); + vehicleLambdaQueryWrapper.eq(TbVehicle::getPlateNumber,plateNumber).last(" limit 1 "); + TbVehicle tbVehicle = vehicleService.getOne(vehicleLambdaQueryWrapper); + if(Objects.nonNull(tbVehicle)){ + vo.setVehicleBrand(tbVehicle.getVehicleBrand()); + vo.setVehicleModel(tbVehicle.getVehicleModel()); + vo.setVehicleType(tbVehicle.getVehicleType()); + } + + BeanUtil.copyProperties(tbGisRunningbus,vo); + if(StrUtil.isNotBlank(tbGisRunningbus.getVehicleJson())){ + vo.setVehicleJSONObject(JSONUtil.parseObj(tbGisRunningbus.getVehicleJson())); + } + if(StrUtil.isNotBlank(tbGisRunningbus.getAlarmDataJson())){ + vo.setAlarmDataJSONObject(JSONUtil.parseObj(tbGisRunningbus.getAlarmDataJson())); + } + if(StrUtil.isNotBlank(tbGisRunningbus.getElectricMotorJson())){ + String handleElectricMotorJson = FormatUtil.replaceStatusValues("status",tbGisRunningbus.getElectricMotorJson()); + vo.setElectricMotorJSONArray(JSONUtil.parseArray(handleElectricMotorJson)); + //转速取最大值 + double controllerTemperature = 0.0; + double temperature = 0.0; + for (int i = 0; i < vo.getElectricMotorJSONArray().size(); i++) { + if((Integer)vo.getElectricMotorJSONArray().getJSONObject(i).get("rpm") > vo.getMaxRpm()){ + vo.setMaxRpm((Integer)vo.getElectricMotorJSONArray().getJSONObject(i).get("rpm")); + } + if(i==0){ + controllerTemperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("controllerTemperature").toString()); + temperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("temperature").toString()); + vo.setMaxControllerTemperature(String.valueOf(controllerTemperature)); + vo.setMaxTemperature(String.valueOf(temperature)); + } + if(Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("controllerTemperature").toString()) > controllerTemperature){ + controllerTemperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("controllerTemperature").toString()); + vo.setMaxControllerTemperature(String.valueOf(controllerTemperature)); + } + if(Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("temperature").toString()) > temperature){ + temperature = Double.valueOf(vo.getElectricMotorJSONArray().getJSONObject(i).get("temperature").toString()); + vo.setMaxTemperature(String.valueOf(temperature)); + } + } + } + return vo; + } + return null; + } + + @Override + public List getVehicleFenceInfo(String plateNumber) { + String key = CacheConstant.VEHICLE_FENCE_KEY + plateNumber; + Object obj = RedisUtil.get(key); + if(Objects.nonNull(obj)){ + List gisRedisVehicleVos = JSONUtil.toList(JSONUtil.toJsonPrettyStr(obj),GisRedisVehicleVo.class); + gisRedisVehicleVos = gisRedisVehicleVos.stream().filter(b->{ return b.isWithinFenceTime(new Date()); }).collect(Collectors.toList()); + return gisRedisVehicleVos; + } + + return null; + } + + + +} diff --git a/src/main/java/com/gci/boot/modules/monitor/vo/AlarmCountVO.java b/src/main/java/com/gci/boot/modules/monitor/vo/AlarmCountVO.java new file mode 100644 index 0000000..e837a6f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/vo/AlarmCountVO.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.monitor.vo; + +import lombok.Data; + +@Data +public class AlarmCountVO { + + private String type; + + private String statusType; + + private Long count; + + public AlarmCountVO(String type, String statusType, Long count) { + this.type = type; + this.statusType = statusType; + this.count = count; + } +} diff --git a/src/main/java/com/gci/boot/modules/monitor/vo/OverallMonitorVO.java b/src/main/java/com/gci/boot/modules/monitor/vo/OverallMonitorVO.java new file mode 100644 index 0000000..e079c41 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/vo/OverallMonitorVO.java @@ -0,0 +1,97 @@ +package com.gci.boot.modules.monitor.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +public class OverallMonitorVO { + + private String id; + + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ApiModelProperty("所属项目") + private String projectId; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("gps采集时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date gpsTime; + + @Dict(dicCode = "online_status") + @ApiModelProperty("设备是否在线 0-离线 1-在线") + private Integer isOnline; + + @Dict(dicCode = "acc_status") + @ApiModelProperty("acc状态 0-熄火 1-点火") + private Integer acc; + + @Dict(dicCode = "charge_status") + @ApiModelProperty("充电状态 1-停车充电、2-行驶充电、3-未充电 4-充电完成、-99-无效、-100-异常") + private Integer chargeStatus; + + @ApiModelProperty("剩余电量比例 %") + private Integer stateOfCharge; + + @ApiModelProperty("速度 单位km/h") + private String speed; + + @ApiModelProperty("累计里程 单位km") + private BigDecimal totalMileage; + + @ApiModelProperty("纬度") + private BigDecimal lat; + + @ApiModelProperty("经度") + private BigDecimal lon; + + @ApiModelProperty("高德纬度") + private BigDecimal gdLat; + + @ApiModelProperty("高德经度") + private BigDecimal gdLon; + + @ApiModelProperty("故障报警 0-正常 1-异常") + private Integer faultAlarm; + + @ApiModelProperty("围栏告警 0-正常 1-异常") + private Integer fenceAlarm; + + @ApiModelProperty("超速告警 0-正常 1-异常") + private Integer speedingAlarm; + + @ApiModelProperty("主动安全告警-0-正常 1-异常") + private Integer safetyAlarm; + + @ApiModelProperty("方向角") + private String dir; + /** + * 告警状态,四个告警有一告警就为1,都不告警为0 + */ + private Integer alarmStatus; + + + @Dict(dicCode = "vehicle_brand") + @ApiModelProperty("车辆品牌") + private String vehicleBrand; + @ApiModelProperty("车辆型号") + private String vehicleModel; + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + @ApiModelProperty("方向") + private String direction; + /** + * 是否作业 0-否 1-是 + */ + @Dict(dicCode = "yes_no") + private Integer isWork; +} diff --git a/src/main/java/com/gci/boot/modules/monitor/vo/RunningbusVO.java b/src/main/java/com/gci/boot/modules/monitor/vo/RunningbusVO.java new file mode 100644 index 0000000..18480c0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/vo/RunningbusVO.java @@ -0,0 +1,157 @@ +package com.gci.boot.modules.monitor.vo; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.math.BigDecimal; +import java.util.Date; + +@Data +public class RunningbusVO { + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("定位终端标识") + private String gpsNo; + + @ApiModelProperty("主动安全设备标识") + private String adasNo; + + @ApiModelProperty("车辆状态 1-启动 2-熄火 3-其它 -99-无效 -100:异常") + private Integer status; + + @ApiModelProperty("vin码") + private String vinCode; + + @ApiModelProperty("gps采集时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date gpsTime; + + @ApiModelProperty("纬度") + private BigDecimal lat; + + @ApiModelProperty("经度") + private BigDecimal lon; + + @ApiModelProperty("高德纬度") + private BigDecimal gdLat; + + private BigDecimal gdLon; + + @ApiModelProperty("速度 单位km/h") + private Double speed; + + @ApiModelProperty("方向角") + private String dir; + + @ApiModelProperty("高程") + private Integer altitude; + + @ApiModelProperty("acc状态 0-熄火 1-点火") + private Integer acc; + + @ApiModelProperty("设备是否在线 0-离线 1-在线") + private Integer isOnline; + + @ApiModelProperty("故障报警 0-正常 1-异常") + private Integer faultAlarm; + + @ApiModelProperty("围栏告警 0-正常 1-异常") + private Integer fenceAlarm; + + @ApiModelProperty("超速告警 0-正常 1-异常") + private Integer speedingAlarm; + + @ApiModelProperty("主动安全告警-0-正常 1-异常") + private Integer safetyAlarm; + + @Dict(dicCode = "charge_status") + @ApiModelProperty("充电状态 1-停车充电、2-行驶充电、3-未充电 4-充电完成、-99-无效、-100-异常") + private Integer chargeStatus; + + @ApiModelProperty("运行模式 1-纯电 2-混动 3-燃油 -99-无效、-100-异常") + private Integer operatingMode; + + @ApiModelProperty("作业状态 1-作业中") + private Integer isWork; + + @ApiModelProperty("累计里程 单位km") + private BigDecimal totalMileage; + + @ApiModelProperty("总电压 单位V") + private BigDecimal totalVoltage; + + @ApiModelProperty("总电流 单位A") + private BigDecimal totalCurrent; + + @ApiModelProperty("剩余电量比例 %") + private Integer stateOfCharge; + + @ApiModelProperty("1-工作 2-断开") + private Integer dcStatus; + + @ApiModelProperty("挡位") + private String gearPosition; + + @ApiModelProperty("主动安全故障标识") + private String warnNo; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ApiModelProperty("所属项目id") + private String projectId; + + @ApiModelProperty("转速") + private Integer maxRpm = 0 ; + + @ApiModelProperty("控制器温度") + private String maxControllerTemperature ; + + @ApiModelProperty("温度") + private String maxTemperature ; + + @ApiModelProperty("整车数据") + @JsonInclude(JsonInclude.Include.ALWAYS) + private JSONObject vehicleJSONObject = new JSONObject(); + + @ApiModelProperty("报警数据") + @JsonInclude(JsonInclude.Include.ALWAYS) + private JSONObject alarmDataJSONObject= new JSONObject(); + + @ApiModelProperty("驱动机数据") + @JsonInclude(JsonInclude.Include.ALWAYS) + private JSONArray electricMotorJSONArray = new JSONArray(); +} diff --git a/src/main/java/com/gci/boot/modules/monitor/vo/VehicleTreeVO.java b/src/main/java/com/gci/boot/modules/monitor/vo/VehicleTreeVO.java new file mode 100644 index 0000000..4995126 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/monitor/vo/VehicleTreeVO.java @@ -0,0 +1,15 @@ +package com.gci.boot.modules.monitor.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class VehicleTreeVO { + + private String projectId; + + private String projectName; + + private List children; +} diff --git a/src/main/java/com/gci/boot/modules/msg/enums/RepairSenderEnum.java b/src/main/java/com/gci/boot/modules/msg/enums/RepairSenderEnum.java new file mode 100644 index 0000000..3d0d682 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/enums/RepairSenderEnum.java @@ -0,0 +1,64 @@ +package com.gci.boot.modules.msg.enums; + +import lombok.Getter; + +public enum RepairSenderEnum { + /** + * 发送用户类型 + * 1-项目成员中部门为运营维保部且角色包含运维部领导 + * 2-项目成员中部门为运营维保部 + * 3-账号部门为维修、保养单指派的维修厂 + * 4-账号部门包括所属项目在项目档案中的客户 + */ + + /** + * 待派单 + */ + WAIT_SEND(2,"2"), + /** + * 待报价 + */ + WAIT_OFFER(3,"3"), + + /** + * 待审核 + */ + WAIT_CHECK_OFFER(4,"2"), + + /** + * 待审批 + */ + WAIT_LEADER_CHECK_OFFER(5,"1"), + + /** + * 维修中 + */ + REPAIRING(6,"3"), + + /** + * 待确认 + */ + WAIT_CONFIRM_RESULT(7,"2") + ; + + + @Getter + private Integer flowStatus; + @Getter + private String sendType; + + + RepairSenderEnum(Integer flowStatus, String sendType){ + this.flowStatus = flowStatus; + this.sendType = sendType; + } + + public static RepairSenderEnum getEnumByFlowStatus(Integer flowStatus){ + for (RepairSenderEnum typeEnum : RepairSenderEnum.values()) { + if (typeEnum.getFlowStatus() == flowStatus) { + return typeEnum; + } + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/modules/msg/enums/SenderTypeEnum.java b/src/main/java/com/gci/boot/modules/msg/enums/SenderTypeEnum.java new file mode 100644 index 0000000..5df5fc0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/enums/SenderTypeEnum.java @@ -0,0 +1,35 @@ +package com.gci.boot.modules.msg.enums; + +import lombok.Getter; + +public enum SenderTypeEnum { + // 1 2 3 4 5 6 7 8 + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + + YYWB_LEADER("1","com.gci.cdnev.smallprogram.modules.msg.service.MsgUserService","getYYWBLeaderUserIds"), + YYWB("2","com.gci.cdnev.smallprogram.modules.msg.service.MsgUserService","getYYWBUserIds"), + REPAIR_SHOP("3","com.gci.cdnev.smallprogram.modules.msg.service.MsgUserService","getRepairShopUserIds"), + CUSTOMER("4","com.gci.cdnev.smallprogram.modules.msg.service.MsgUserService","getCustomerUserIds"); + + @Getter + private String sendType; + @Getter + private String className; + @Getter + private String methodName; + + SenderTypeEnum(String sendType, String className, String methodName){ + this.sendType = sendType; + this.className = className; + this.methodName = methodName; + } + + public static SenderTypeEnum getEnumByType(String type){ + for (SenderTypeEnum typeEnum : SenderTypeEnum.values()) { + if (typeEnum.getSendType().equals(type)) { + return typeEnum; + } + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/modules/msg/enums/UpkeepBillSenderEnum.java b/src/main/java/com/gci/boot/modules/msg/enums/UpkeepBillSenderEnum.java new file mode 100644 index 0000000..8d3dd0f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/enums/UpkeepBillSenderEnum.java @@ -0,0 +1,59 @@ +package com.gci.boot.modules.msg.enums; + +import lombok.Getter; + +public enum UpkeepBillSenderEnum { + /** + * 发送用户类型 + * 1-项目成员中部门为运营维保部且角色包含运维部领导 + * 2-项目成员中部门为运营维保部 + * 3-账号部门为维修、保养单指派的维修厂 + * 4-账号部门包括所属项目在项目档案中的客户 + */ + + /** + * 待派单 + */ + WAIT_SEND(2,"2"), + /** + * 待报价 + */ + WAIT_OFFER(3,"3"), + + /** + * 待审核 + */ + WAIT_CHECK_OFFER(4,"2"), + + /** + * 保养中 + */ + REPAIRING(6,"3"), + + /** + * 待确认 + */ + WAIT_CONFIRM_RESULT(7,"2") + ; + + + @Getter + private Integer flowStatus; + @Getter + private String sendType; + + + UpkeepBillSenderEnum(Integer flowStatus, String sendType){ + this.flowStatus = flowStatus; + this.sendType = sendType; + } + + public static UpkeepBillSenderEnum getEnumByFlowStatus(Integer flowStatus){ + for (UpkeepBillSenderEnum typeEnum : UpkeepBillSenderEnum.values()) { + if (typeEnum.getFlowStatus() == flowStatus) { + return typeEnum; + } + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/modules/msg/enums/WorkOrderType.java b/src/main/java/com/gci/boot/modules/msg/enums/WorkOrderType.java new file mode 100644 index 0000000..f8fe67c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/enums/WorkOrderType.java @@ -0,0 +1,44 @@ +package com.gci.boot.modules.msg.enums; + +import lombok.Getter; + +public enum WorkOrderType { + + REPAIR("维修","1","/vehicles/VehiclesMaintain"), + UPKEEP_BILL("保养台账","2","/vehicles/UpkeepBill"), + UPKEEP_PLAN("保养计划","3","/vehicles/UpkeepPlan"), + VIOLATION("违章","4","/vehicles/Violation"), + ACCIDENT("事故","5","/vehicles/accident"), + INSPECTION("年检","6","/vehicles/inspection"), + INSURANCE("保险","7","/vehicle/insurance"), + NOT_FIND("没找到对应菜单的","0","xxx") + ; + + /** + * 工单类型不能超过5个字 + */ + @Getter + private String type; + + @Getter + private String typeNum; + + @Getter + private String menuUrl; + + + WorkOrderType(String type, String typeNum, String menuUrl) { + this.type = type; + this.typeNum = typeNum; + this.menuUrl = menuUrl; + } + + public static WorkOrderType getEnumByType(String type){ + for (WorkOrderType typeEnum : WorkOrderType.values()) { + if (typeEnum.getType().equals(type)) { + return typeEnum; + } + } + return NOT_FIND; + } +} diff --git a/src/main/java/com/gci/boot/modules/msg/service/MsgPushService.java b/src/main/java/com/gci/boot/modules/msg/service/MsgPushService.java new file mode 100644 index 0000000..0ff32ac --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/service/MsgPushService.java @@ -0,0 +1,11 @@ +package com.gci.boot.modules.msg.service; + +import com.gci.boot.modules.msg.vo.MsgRedisVO; + +public interface MsgPushService { + + /** + * 事件状态变化调用接口推送消息--先往redis队列存 + */ + void pushMsgToRedis(MsgRedisVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/msg/service/impl/MsgPushServiceImpl.java b/src/main/java/com/gci/boot/modules/msg/service/impl/MsgPushServiceImpl.java new file mode 100644 index 0000000..50282e0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/service/impl/MsgPushServiceImpl.java @@ -0,0 +1,30 @@ +package com.gci.boot.modules.msg.service.impl; + +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Objects; + +@Service +@Slf4j +public class MsgPushServiceImpl implements MsgPushService { + + @Resource + private RedisTemplate redisTemplate; + + @Override + public void pushMsgToRedis(MsgRedisVO vo) { + //还没长期模板、暂先屏蔽消息推reids +// if(Objects.nonNull(vo)){ +// String string = JsonUtil.object2Json(vo); +// redisTemplate.opsForList().leftPush(CacheConstant.WX_MSG_PUSH, string); +// } + } + +} diff --git a/src/main/java/com/gci/boot/modules/msg/vo/MsgRedisVO.java b/src/main/java/com/gci/boot/modules/msg/vo/MsgRedisVO.java new file mode 100644 index 0000000..4b612aa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/msg/vo/MsgRedisVO.java @@ -0,0 +1,49 @@ +package com.gci.boot.modules.msg.vo; + +import lombok.Data; + +@Data +public class MsgRedisVO { + /** + * 发送用户类型 + * 1-项目成员中部门为运营维保部且角色包含运维部领导 + * 2-项目成员中部门为运营维保部 + * 3-账号部门为维修、保养单指派的维修厂 + * 4-账号部门包括所属项目在项目档案中的客户 + */ + private String senderType; + /** + * 对应业务工单id + */ + private String orderId; + /** + * 项目id + */ + private String projectId; + /** + * 工单类型 + */ + private String short_thing4; + /** + * 工单状态 + */ + private String phrase1; + /** + * 更新时间 + */ + private String time2; + /** + * 温馨提示 + */ + private String thing3; + + public MsgRedisVO(String senderType, String orderId, String projectId, String short_thing4, String phrase1, String time2, String thing3) { + this.senderType = senderType; + this.orderId = orderId; + this.projectId = projectId; + this.short_thing4 = short_thing4; + this.phrase1 = phrase1; + this.time2 = time2; + this.thing3 = thing3; + } +} diff --git a/src/main/java/com/gci/boot/modules/projects/controller/ProjectsController.java b/src/main/java/com/gci/boot/modules/projects/controller/ProjectsController.java new file mode 100644 index 0000000..9e30621 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/controller/ProjectsController.java @@ -0,0 +1,298 @@ +package com.gci.boot.modules.projects.controller; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.driver.vo.DriverUserVo; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.mapper.ProjectUserRelMapper; +import com.gci.boot.modules.projects.mapper.ProjectsMapper; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.LoginUser; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; + +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 项目基础信息表 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +@Slf4j +@RestController +@RequestMapping("/projects/projects") +public class ProjectsController { + + @Autowired + private IProjectsService projectsService; + @Autowired + private ISysUserService sysUserService; + @Autowired + private ProjectUserRelMapper projectUserRelMapper; + @Autowired + private ProjectsMapper projectsMapper; + + + @AddSysLog(value = "项目档案-列表查询") + @GetMapping("/list") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getAllProjects"}) + public Result list(Projects item) { + List list = projectsMapper.getAllProjects(); + return Result.ok(list); + } + + @AddSysLog(value = "项目档案-分页查询") + @GetMapping("/page") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getPage"}) + public Result page(Projects item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(Projects.class, item); + queryWrapper.eq(Projects::getDelFlag,0); + queryWrapper.orderByDesc(Projects::getCreateTime); + Page page = new Page(pageNo, pageSize); +// IPage pageList = projectsService.page(page,queryWrapper); + //配合注释做数据权限 + IPage pageList = projectsService.getPage(page,queryWrapper); + for(Projects pro:pageList.getRecords()) { + projectsService.initBusId(pro); + projectsService.initUserId(pro); + pro.setVehicleNum(projectsService.getVehicleTypeNumStr(pro.getBusIds())); + SysUser sysUser = sysUserService.getByUsername(pro.getCreateBy()); + if(ObjectUtil.isNotNull(sysUser)){ + pro.setCreateUserId(sysUser.getId()); + } + } + return Result.ok(pageList); + } + + @AddSysLog(value = "项目档案-新增") + @PostMapping("/add") + public Result add(@RequestBody Projects item){ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(StrUtil.isBlank(item.getUserIds())){ + return Result.error(101,"项目成员必须包含当前创建人!"); + }else{ + if(!item.getUserIds().contains(sysUser.getId())){ + return Result.error(101,"项目成员必须包含当前创建人!"); + } + + } + projectsService.saveItem(item,sysUser.getUsername()); + return Result.ok(); + } + + @AddSysLog(value = "项目档案-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody Projects item){ + Projects projects = projectsService.getById(item.getId()); + SysUser sysUser = sysUserService.getByUsername(projects.getCreateBy()); + if(StrUtil.isBlank(item.getUserIds())){ + return Result.error(101,"项目成员必须包含当前创建人!"); + }else{ + if(Objects.nonNull(sysUser) && !item.getUserIds().contains(sysUser.getId())){ + return Result.error(101,"项目成员必须包含当前创建人!"); + } + + } + log.info("---项目基础信息edit-----"+JsonUtil.object2Json(item)); + projectsService.saveItem(item,sysUser.getUsername()); + return Result.ok(); + } + + @AddSysLog(value = "项目档案-删除") + @DeleteMapping("/delete") + public Result delete(Projects item){ + if (item.getId().equals(CommonConstant.INNER_PROJECT)) { + throw new GciBootException("默认项目无法删除!"); + } + projectsService.removeById(item.getId()); + return Result.ok(); + } + + /** + * 启用禁用 + * @param item + * @return + */ + @PostMapping("/updateStatus") + public Result updateStatus(@RequestBody Projects item){ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + projectsService.updateStatus(item, sysUser.getUsername()); + return Result.ok(); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "项目档案-导出") + @GetMapping("/simple/export") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getPage"}) + public Result export(Projects item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "项目基础信息.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + + Result> result = (Result>)page(item,1,20000); + List list = result.getResult().getRecords(); + + EasyExcel.write(output, Projects.class).sheet("sheet1").doWrite(list); + //EasyExcel.write(output, Projects.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "项目档案-分页导出") + @GetMapping("/multi/export") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getPage"}) + public Result multiExport(Projects item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "项目基础信息.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, Projects.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages simpleImport(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(Projects.class).sheet().doReadSync(); + log.info("数据量:{}",list.size()); + projectsService.saveBatch(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + return Result.ok(); + } + + @AddSysLog(value = "项目档案-获取项目成员") + @GetMapping("/getUserByProjectId") + public Result getUserByProjectId(String projectId, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + List list = new ArrayList<>(); + if(StrUtil.isBlank(projectId)){ + return Result.error(101,"项目id不能为空!"); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("project_id", projectId); + List projectUserRelList = projectUserRelMapper.selectList(queryWrapper); + if(CollectionUtil.isNotEmpty(projectUserRelList)){ + List userIds = projectUserRelList.stream().map(ProjectUserRel::getUserId).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(userIds)){ +// LambdaQueryWrapper userQueryWrapper = new LambdaQueryWrapper<>(); +// userQueryWrapper.in(SysUser::getId,userIds); +// list = sysUserService.list(userQueryWrapper); + SysUser user = new SysUser(); + LambdaQueryWrapper userQueryWrapper = QueryGenerator.initQueryWrapper(SysUser.class, user); + userQueryWrapper.in(SysUser::getId,userIds); + Page page = new Page(pageNo, pageSize); + IPage pageList = sysUserService.page(page,userQueryWrapper); + + // 处理等保解密数据 + Iterator userIterator = pageList.getRecords().iterator(); + while (userIterator.hasNext()) { + SysUser sysUser = userIterator.next(); + sysUser.setPhone(sysUserService.processPhone(sysUser)); + } + return Result.ok(pageList); + } + } + + return Result.ok(null); + } +} diff --git a/src/main/java/com/gci/boot/modules/projects/controller/TbContractController.java b/src/main/java/com/gci/boot/modules/projects/controller/TbContractController.java new file mode 100644 index 0000000..321e794 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/controller/TbContractController.java @@ -0,0 +1,242 @@ +package com.gci.boot.modules.projects.controller; + + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; +import java.util.Objects; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.modules.projects.entity.TbContract; +import com.gci.boot.modules.projects.entity.TbContractVehicle; +import com.gci.boot.modules.projects.service.ITbContractService; +import com.gci.boot.modules.projects.service.ITbContractVehicleService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckService; +import com.gci.boot.modules.system.vo.LoginUser; + +import cn.hutool.core.util.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 合同档案 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-01 + */ +@Slf4j +@RestController +@RequestMapping("/projects/contract") +public class TbContractController { + + @Autowired + private ITbContractService tbContractService; + @Autowired + private MinioUtils minioUtils; + @Autowired + private ITbContractVehicleService contractVehicleService; + + @AddSysLog(value = "合同档案-列表查询") + @GetMapping("/list") + public Result list(TbContract item) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbContract.class, item); + queryWrapper.orderByDesc(TbContract::getCreateTime); + List list = tbContractService.list(queryWrapper); + for(TbContract pro:list) { + //获取车辆明细 + tbContractService.initVehicleCheckDetail(pro); + //补充车型明细 + List vehicleDetails = contractVehicleService.getByContractId(pro.getId()); + pro.setVehicleDetails(vehicleDetails); + //租赁合同 + if("1".equals(pro.getContractType())&&vehicleDetails!=null) { + int vehicleCount = 0; + for (TbContractVehicle vd : vehicleDetails) { + vehicleCount += vd.getQuantity(); + } + pro.setVehicleCount(vehicleCount); + } + if("1".equals(pro.getContractType())&&pro.getVehicleList()!=null) { + pro.setVehicleCount(pro.getVehicleList().size()); + } + } + return Result.ok(list); + } + + @AddSysLog(value = "合同档案-分页查询") + @GetMapping("/page") + public Result page(TbContract item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbContract.class, item); + queryWrapper.orderByDesc(TbContract::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = tbContractService.page(page,queryWrapper); + for(TbContract pro:pageList.getRecords()) { + //获取车辆明细 + tbContractService.initVehicleCheckDetail(pro); + //补充车型明细 + List vehicleDetails = contractVehicleService.getByContractId(pro.getId()); + pro.setVehicleDetails(vehicleDetails); + //租赁合同 + if("1".equals(pro.getContractType())&&vehicleDetails!=null) { + int vehicleCount = 0; + for (TbContractVehicle vd : vehicleDetails) { + vehicleCount += vd.getQuantity(); + } + pro.setVehicleCount(vehicleCount); + } + //初始化车辆价格、保险 + tbContractService.initItem(pro); + } + return Result.ok(pageList); + } + + @AddSysLog(value = "合同档案-新增") + @PostMapping("/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbContract item){ + tbContractService.saveItem(item); + return Result.ok(); + } + + @AddSysLog(value = "合同档案-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbContract item){ + tbContractService.updateItem(item); + return Result.ok(); + } + + @AddSysLog(value = "合同档案-删除") + @DeleteMapping("/delete") + public Result delete(TbContract item){ + tbContractService.removeById(item.getId()); + //同步删除车辆细项 + LambdaQueryWrapper delWrapper = new LambdaQueryWrapper<>(); + delWrapper.eq(TbContractVehicle::getContractId,item.getId()); + contractVehicleService.remove(delWrapper); + return Result.ok(); + } + + /** + * 文件上传 + */ + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.getCommonFileTypes())); + } + + /** + * 根据合同类型获取签约方列表 + * @param contractType + * @return + */ + @GetMapping("/getSigningList") + public Result getSigningList(String contractType) { + String sysOrgCode = null; + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser!=null) { + sysOrgCode = sysUser.getOrgCode(); + } + List list = tbContractService.getSigningList(contractType, sysOrgCode); + return Result.ok(list); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "合同档案-导出") + @GetMapping("/simple/export") + public Result export(TbContract item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "合同档案.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result result = list(item); + List list = (List)result.getResult(); + EasyExcel.write(output, TbContract.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "合同档案-分页导出") + @GetMapping("/multi/export") + public Result multiExport(TbContract item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "合同档案.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, TbContract.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages + * 车辆验收管理 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Slf4j +@RestController +@RequestMapping("/projects/vehicleCheck") +public class TbVehicleCheckController { + + @Autowired + private ITbVehicleCheckService tbVehicleCheckService; + @Autowired + private ITbVehicleCheckProjectService tbVehicleCheckProjectService; + @Autowired + private ITbVehicleCheckDetailService tbVehicleCheckDetailService; + @Autowired + private MinioUtils minioUtils; + @Autowired + private IProjectsService projectsService; + + @AddSysLog(value = "车辆验收管理-列表查询") + @GetMapping("/list") + //采购交车没有项目id + //@DataPermission(item="tb_vehicle_check.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.TbVehicleCheckMapper.selectList"}) + public Result list(TbVehicleCheck item) { + if(!StringUtils.hasLength(item.getCheckType())) { + item.setCheckType("1"); + } + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbVehicleCheck.class, item); + if(StringUtils.hasLength(item.getPlateNumber())||StringUtils.hasLength(item.getFrameNumber())) { + String where = ""; + if(StringUtils.hasLength(item.getPlateNumber())) { + where += " and cd.plate_number like '%"+item.getPlateNumber()+"%'"; + } + if(StringUtils.hasLength(item.getFrameNumber())) { + where += " and cd.frame_number like '%"+item.getFrameNumber()+"%'"; + } + String sql = "select 1 from tb_vehicle_check_detail cd where tb_vehicle_check.id = cd.check_id "+where; + queryWrapper.exists(sql); + } + if("1".equals(item.getCheckType())) { + queryWrapper.orderByAsc(TbVehicleCheck::getStatus); + }else { + //采购交车没有项目id + List listProjectIds = projectsService.queryProjectListOfUser(); + queryWrapper.in(CollectionUtils.isNotEmpty(listProjectIds),TbVehicleCheck::getProjectId, listProjectIds); + queryWrapper.orderByAsc(TbVehicleCheck::getReceiveStatus); + } + queryWrapper.orderByDesc(TbVehicleCheck::getCreateTime); + List list = tbVehicleCheckService.list(queryWrapper); + tbVehicleCheckService.initItem(list); + for(TbVehicleCheck template:list) { + tbVehicleCheckDetailService.getVehiclesByCheckId(template); + tbVehicleCheckProjectService.getProjectsByCheckId(template); + template.setVehicleCount(template.getVehicleList().size()); + } + return Result.ok(list); + } + + @AddSysLog(value = "车辆验收管理-分页查询") + @GetMapping("/page") + //采购交车没有项目id + //@DataPermission(item="tb_vehicle_check.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.TbVehicleCheckMapper.selectPage"}) + public Result page(TbVehicleCheck item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + if(!StringUtils.hasLength(item.getCheckType())) { + item.setCheckType("1"); + } + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbVehicleCheck.class, item); + if(StringUtils.hasLength(item.getPlateNumber())||StringUtils.hasLength(item.getFrameNumber())) { + String where = ""; + if(StringUtils.hasLength(item.getPlateNumber())) { + where += " and cd.plate_number like '%"+item.getPlateNumber()+"%'"; + } + if(StringUtils.hasLength(item.getFrameNumber())) { + where += " and cd.frame_number like '%"+item.getFrameNumber()+"%'"; + } + String sql = "select 1 from tb_vehicle_check_detail cd where tb_vehicle_check.id = cd.check_id "+where; + queryWrapper.exists(sql); + } + if("1".equals(item.getCheckType())) { + queryWrapper.orderByAsc(TbVehicleCheck::getStatus); + }else { + //采购交车没有项目id + List listProjectIds = projectsService.queryProjectListOfUser(); + queryWrapper.in(CollectionUtils.isNotEmpty(listProjectIds),TbVehicleCheck::getProjectId, listProjectIds); + queryWrapper.orderByAsc(TbVehicleCheck::getReceiveStatus); + } + queryWrapper.orderByDesc(TbVehicleCheck::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = tbVehicleCheckService.page(page,queryWrapper); + tbVehicleCheckService.initItem(pageList.getRecords()); + for(TbVehicleCheck template:pageList.getRecords()) { + //获取租赁收车 + tbVehicleCheckService.getChildren(template); + tbVehicleCheckDetailService.getVehiclesByCheckId(template); + tbVehicleCheckProjectService.getProjectsByCheckId(template); + template.setVehicleCount(template.getVehicleList().size()); + } + return Result.ok(pageList); + } + + @AddSysLog(value = "车辆验收管理-新增") + @PostMapping("/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbVehicleCheck item){ + if(!StringUtils.hasLength(item.getCheckType())) { + return Result.error("验收类型不能为空"); + } + String error = tbVehicleCheckService.saveItem(item); + return Result.ok("操作成功。"+error); + } + + @AddSysLog(value = "车辆验收管理-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbVehicleCheck item){ + String error = tbVehicleCheckService.saveItem(item); + return Result.ok("操作成功。"+error); + } + + @AddSysLog(value = "车辆验收管理-删除") + @DeleteMapping("/delete") + public Result delete(TbVehicleCheck item){ + tbVehicleCheckService.removeById(item.getId()); + return Result.ok(); + } + + /** + * 文件上传 + */ + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.getCommonFileTypes())); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "车辆验收管理-导出") + @GetMapping("/simple/export") + @DataPermission(item="tb_vehicle_check.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.TbVehicleCheckMapper.selectList"}) + public Result export(TbVehicleCheck item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "车辆验收管理.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result result = list(item); + List list = (List)result.getResult(); + if("2".equals(item.getCheckType())) { + List list2 = new ArrayList<>(); + for(TbVehicleCheck src:list) { + TbVehicleCheckVo vo = new TbVehicleCheckVo(); + BeanUtilsCopy.copyBeanProp(vo, src); + list2.add(vo); + } + EasyExcel.write(output, TbVehicleCheckVo.class).sheet("sheet1").doWrite(list2); + }else { + EasyExcel.write(output, TbVehicleCheck.class).sheet("sheet1").doWrite(list); + } + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "车辆验收管理-分页导出") + @GetMapping("/multi/export") + @DataPermission(item="tb_vehicle_check.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.TbVehicleCheckMapper.selectPage"}) + public Result multiExport(TbVehicleCheck item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "车辆验收管理.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, TbVehicleCheck.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages + * 车辆验收车辆详情 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Slf4j +@RestController +@RequestMapping("/projects/vehicleCheckDetail") +public class TbVehicleCheckDetailController { + + @Autowired + private ITbVehicleCheckDetailService tbVehicleCheckProjectService; + + @AddSysLog(value = "车辆验收车辆详情-列表查询") + @GetMapping("/list") + public Result list(TbVehicleCheckDetail item) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbVehicleCheckDetail.class, item); + /*LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser!=null) { + queryWrapper.likeRight(StringUtils.hasLength(sysUser.getOrgCode()),TbVehicleCheckDetail::getSysOrgCode, sysUser.getOrgCode()); + }*/ + //queryWrapper.eq(TbVehicleCheckDetail::getCancelFlag, CommonConstant.STATUS_1); + queryWrapper.orderByDesc(TbVehicleCheckDetail::getCreateTime); + List list = tbVehicleCheckProjectService.list(queryWrapper); + return Result.ok(list); + } + + @AddSysLog(value = "车辆验收车辆详情-分页列表查询") + @GetMapping("/page") + public Result page(TbVehicleCheckDetail item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbVehicleCheckDetail.class, item); + /*LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser!=null) { + queryWrapper.likeRight(StringUtils.hasLength(sysUser.getOrgCode()),TbVehicleCheckDetail::getSysOrgCode, sysUser.getOrgCode()); + }*/ + queryWrapper.orderByDesc(TbVehicleCheckDetail::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = tbVehicleCheckProjectService.page(page,queryWrapper); + return Result.ok(pageList); + } + + @AddSysLog(value = "车辆验收车辆详情-添加") + @PostMapping("/add") + public Result add(@RequestBody TbVehicleCheckDetail item){ + tbVehicleCheckProjectService.save(item); + return Result.ok(); + } + + @AddSysLog(value = "车辆验收车辆详情-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody TbVehicleCheckDetail item){ + tbVehicleCheckProjectService.updateById(item); + return Result.ok(); + } + + @AddSysLog(value = "车辆验收车辆详情-删除") + @DeleteMapping("/delete") + public Result delete(TbVehicleCheckDetail item){ + tbVehicleCheckProjectService.removeById(item.getId()); + return Result.ok(); + } + + /** + * 多次读入 + * @param request + * @return + */ + @AddSysLog(value = "车辆验收车辆详情-导入") + @PostMapping("/simple/import") + public Result simpleImport(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(TbVehicleCheckDetail.class).sheet().doReadSync(); + for (TbVehicleCheckDetail tbVehicleCheckDetail : list) { + if (NumberUtil.isNumber(tbVehicleCheckDetail.getCurbWeightString())) { + tbVehicleCheckDetail.setCurbWeight(NumberUtil.toBigDecimal(tbVehicleCheckDetail.getCurbWeightString())); + } else { + tbVehicleCheckDetail.setCurbWeight(null); + } + } + return Result.ok(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + return Result.ok(); + } + +} diff --git a/src/main/java/com/gci/boot/modules/projects/controller/TbVehicleCheckProjectController.java b/src/main/java/com/gci/boot/modules/projects/controller/TbVehicleCheckProjectController.java new file mode 100644 index 0000000..bcd5aac --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/controller/TbVehicleCheckProjectController.java @@ -0,0 +1,94 @@ +package com.gci.boot.modules.projects.controller; + + +import java.util.List; + +import com.gci.boot.common.log.annotation.AddSysLog; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.projects.entity.TbVehicleCheckProject; +import com.gci.boot.modules.projects.service.ITbVehicleCheckProjectService; +import com.gci.boot.modules.system.vo.LoginUser; + +/** + *

+ * 车辆验收项目 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@RestController +@RequestMapping("/projects/vehicleCheckProject") +public class TbVehicleCheckProjectController { + + @Autowired + private ITbVehicleCheckProjectService tbVehicleCheckProjectService; + + @AddSysLog(value = "车辆验收项目-列表查询") + @GetMapping("/list") + public Result list(TbVehicleCheckProject item) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbVehicleCheckProject.class, item); + /*LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser!=null) { + queryWrapper.likeRight(StringUtils.hasLength(sysUser.getOrgCode()),TbVehicleCheckProject::getSysOrgCode, sysUser.getOrgCode()); + }*/ + //queryWrapper.eq(TbVehicleCheckProject::getCancelFlag, CommonConstant.STATUS_1); + queryWrapper.orderByDesc(TbVehicleCheckProject::getCreateTime); + List list = tbVehicleCheckProjectService.list(queryWrapper); + return Result.ok(list); + } + + @AddSysLog(value = "车辆验收项目-分页列表查询") + @GetMapping("/page") + public Result page(TbVehicleCheckProject item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbVehicleCheckProject.class, item); + /*LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser!=null) { + queryWrapper.likeRight(StringUtils.hasLength(sysUser.getOrgCode()),TbVehicleCheckProject::getSysOrgCode, sysUser.getOrgCode()); + }*/ + queryWrapper.orderByDesc(TbVehicleCheckProject::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = tbVehicleCheckProjectService.page(page,queryWrapper); + return Result.ok(pageList); + } + + @AddSysLog(value = "车辆验收项目-添加") + @PostMapping("/add") + public Result add(@RequestBody TbVehicleCheckProject item){ + tbVehicleCheckProjectService.save(item); + return Result.ok(); + } + + @AddSysLog(value = "车辆验收项目-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody TbVehicleCheckProject item){ + tbVehicleCheckProjectService.updateById(item); + return Result.ok(); + } + + @AddSysLog(value = "车辆验收项目-删除") + @DeleteMapping("/delete") + public Result delete(TbVehicleCheckProject item){ + tbVehicleCheckProjectService.removeById(item.getId()); + return Result.ok(); + } + +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/ProjectUserRel.java b/src/main/java/com/gci/boot/modules/projects/entity/ProjectUserRel.java new file mode 100644 index 0000000..5d5cc67 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/ProjectUserRel.java @@ -0,0 +1,73 @@ +package com.gci.boot.modules.projects.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 项目基础信息表 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +@Getter +@Setter +@TableName("tb_project_user_rel") +@ApiModel(value = "ProjectUserRel对象", description = "项目和用户关联表") +@ColumnWidth(20) +public class ProjectUserRel implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + + @ExcelProperty(value = "项目id", index = 0) + @ApiModelProperty("项目id") + private String projectId; + + @ExcelProperty(value = "用户id", index = 1) + @ApiModelProperty("用户id") + private String userId; + + @ExcelIgnore + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @ExcelIgnore + @ApiModelProperty("创建人") + private String createBy; + + @ExcelIgnore + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + @ExcelIgnore + @ApiModelProperty("更新人") + private String updateBy; + +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/ProjectVehicleBindLog.java b/src/main/java/com/gci/boot/modules/projects/entity/ProjectVehicleBindLog.java new file mode 100644 index 0000000..77efcfc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/ProjectVehicleBindLog.java @@ -0,0 +1,76 @@ +package com.gci.boot.modules.projects.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 项目基础信息表 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +@Getter +@Setter +@TableName("tb_project_vehicle_bind_log") +@ApiModel(value = "项目绑定车辆日志对象", description = "项目绑定车辆日志对象表") +public class ProjectVehicleBindLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + /** + * 项目id + */ + private String projectId; + + /** + * 项目名称 + */ + private String projectName; + + /** + * 车牌号 + */ + private String plateNumber; + + /** + * 绑定类型 1-绑定 2-解绑 + */ + private Integer bindType; + + /** + * 操作来源 1-车辆操作 2-项目结束 3-项目操作 + */ + private Integer bindSource; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @ApiModelProperty("创建人") + private String createBy; + +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/Projects.java b/src/main/java/com/gci/boot/modules/projects/entity/Projects.java new file mode 100644 index 0000000..b928dd5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/Projects.java @@ -0,0 +1,150 @@ +package com.gci.boot.modules.projects.entity; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 项目基础信息表 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +@Getter +@Setter +@TableName("tb_projects") +@ApiModel(value = "Projects对象", description = "项目基础信息表") +@ColumnWidth(20) +public class Projects implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属客户") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_customer_archives", dicText = "name", dicCode = "id") + private String customerId; + + @ExcelProperty(value = "项目名称", index = 0) + @ApiModelProperty("项目名称,必填且唯一") + @SelectQuery(Type = SelectQuery.SelectType.LIKE) + private String projectName; + + @ExcelProperty(value = "项目负责人", index = 1) + @ApiModelProperty("负责人的姓名") + @SelectQuery(Type = SelectQuery.SelectType.LIKE) + private String projectManager; + + @ExcelIgnore + @ApiModelProperty("对方单位的名称") + private String counterparty; + + @ExcelIgnore + @ApiModelProperty("联系人的姓名") + private String contactPerson; + + @ExcelProperty(value = "电话号码", index = 2) + @ApiModelProperty("联系人的电话号码") + @SelectQuery(Type = SelectQuery.SelectType.LIKE) + private String contactPhone; + + @ExcelProperty(value = "开始日期", index = 3) + @ApiModelProperty("项目开始日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + private Date startDate; + + @ExcelProperty(value = "结束日期", index = 4) + @ApiModelProperty("项目结束日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + private Date endDate; + + @ExcelIgnore + @ApiModelProperty("所属机构编码") + private String sysOrgCode; + + @ExcelIgnore + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @ExcelIgnore + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty(value = "更新时间",index = 8) + private Date updateTime; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "username") + @ExcelProperty(value = "更新人",converter = DictConverter.class,index = 7) + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("废弃状态 0-正常 1-废弃") + private Integer cancelFlag; + + @ApiModelProperty("历史车辆") + @ExcelIgnore + private String hisVehicleId; + + @ExcelProperty(value = "状态", converter = DictConverter.class, index = 5) + @ApiModelProperty("状态(1 进行中,0 结束)") + @Dict(dicCode = "project_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String status; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + @ExcelProperty(value = "车牌号", converter = DictConverter.class, index = 11) + @TableField(exist = false) + @Dict(dictTable = "tb_vehicle", dicText = "plate_number", dicCode = "id") + public String busIds; + + @ExcelProperty(value = "项目成员", converter = DictConverter.class, index = 12) + @TableField(exist = false) + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + public String userIds; + + @ExcelIgnore + @TableField(exist = false) + @ApiModelProperty("车辆数") + public String vehicleNum; + + @ExcelIgnore + @TableField(exist = false) + @ApiModelProperty("创建人id") + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + public String createUserId; +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/TbContract.java b/src/main/java/com/gci/boot/modules/projects/entity/TbContract.java new file mode 100644 index 0000000..08e4c27 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/TbContract.java @@ -0,0 +1,196 @@ +package com.gci.boot.modules.projects.entity; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentLoopMerge; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +/** + *

+ * 合同档案 + *

+ * + * @author xushuhan + * @since 2023-09-01 + */ +@Getter +@Setter +@TableName("tb_contract") +@ApiModel(value = "TbContract对象", description = "合同档案") +@TableRepeat(aClass = TbContract.class,groups = {SaveValidated.class,UpdateValidated.class}) +/*@ContentRowHeight(10) +@HeadRowHeight(20)*/ +@ColumnWidth(20) +public class TbContract implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属项目") + @ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectId; + + @ApiModelProperty("合同名称") + @SelectQuery + @ExcelProperty(value = "合同名称", index = 2) + private String name; + + @ApiModelProperty("合同编号") + @SelectQuery + @FieldRepeat(message = "合同编号不能重复!") + @ExcelProperty(value = "合同编号", index = 3) + private String contractNo; + + @ApiModelProperty("合同类型(客户租赁合同、保险合同、维修合同、车辆采购合同、定制件采购合同、耗材采购合同、资产评估合同、法人尽调合同)") + @ExcelProperty(value = "合同类型", converter = DictConverter.class, index = 1) + @Dict(dicCode = "contract_type") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String contractType; + + @ApiModelProperty("签约方(客户档案(客户租赁合同)、维修厂档案(维修合同)、车辆供应商档案(车辆采购合同)、保险档案(保险合同),其填文本)") + @ExcelIgnore + private String signingId; + + @ApiModelProperty("签约时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + //@DateTimeFormat("yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "签约时间", index = 6,format="yyyy-MM-dd") + private Date signingTime; + + @ApiModelProperty("合同总价(含税)") + @ExcelIgnore + private Double totalPrice; + + @ApiModelProperty("合同总价(不含税)") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private Double totalPriceNoTax; + + @ApiModelProperty("增值税率") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private Double addedTaxRate; + + @ApiModelProperty("增值税") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private Double addedTax; + + @ApiModelProperty("生效时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @ExcelProperty(value = "生效时间", index = 7) + private Date startTime; + + @ApiModelProperty("终止时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @ExcelProperty(value = "失效时间", index = 8) + private Date endTime; + + @ApiModelProperty("备注") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String remark; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "username") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty(value = "更新时间") + private Date updateTime; + + @ApiModelProperty("合同文件") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String fileUrl; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + @ExcelIgnore + @Length(max = 256,groups = {SaveValidated.class,UpdateValidated.class},message = "货物名称长度不能超过256") + @ApiModelProperty("货物名称") + private String goodsName; + + //车辆数 + @ExcelIgnore + private Integer vehicleCount; + + @SelectQuery + @ExcelProperty(value = "签约方", index = 4) + private String signingName; + + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "状态", converter = DictConverter.class, index = 5) + @Dict(dicCode = "contrack_status") + private String status; + + @ExcelIgnore + @TableField(exist = false) + @ApiModelProperty("车型明细") + private List vehicleDetails; + + @ExcelIgnore + @ApiModelProperty("车辆明细") + @TableField(exist = false) + List vehicleList; + +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/TbContractVehicle.java b/src/main/java/com/gci/boot/modules/projects/entity/TbContractVehicle.java new file mode 100644 index 0000000..5ee9cf7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/TbContractVehicle.java @@ -0,0 +1,101 @@ +package com.gci.boot.modules.projects.entity; + + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +import org.hibernate.validator.constraints.Length; + +@TableName("tb_contract_vehicle") +@ApiModel(value = "TbContractVehicle对象", description = "合同车辆细项表") +@TableRepeat(aClass = TbContractVehicle.class,groups = {SaveValidated.class, UpdateValidated.class}) +@Data +public class TbContractVehicle implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + @ApiModelProperty("合同id") + private String contractId; + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + @NotBlank(message = "车辆品牌不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @NotBlank(message = "车辆型号不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @NotBlank(message = "车辆种类不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleType; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private Integer quantity; + + @ApiModelProperty("单价(万元含税)") + @NotNull(message = "单价不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private Double totalPrice; + + @ApiModelProperty("整备质量") + @Digits(integer = 6 , fraction = 2,message = "整备质量整数不能超过6位,小数不能超过2位",groups = {SaveValidated.class,UpdateValidated.class}) + private BigDecimal curbWeight; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheck.java b/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheck.java new file mode 100644 index 0000000..7b7084c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheck.java @@ -0,0 +1,257 @@ +package com.gci.boot.modules.projects.entity; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.simpleframework.xml.core.Validate; + +/** + *

+ * 车辆验收 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Getter +@Setter +@TableName("tb_vehicle_check") +@ApiModel(value = "TbVehicleCheck对象", description = "车辆验收") +@ColumnWidth(20) +public class TbVehicleCheck implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属项目") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectId; + + @ApiModelProperty("所属合同") + @ExcelProperty(value = "所属合同", converter = DictConverter.class, index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_contract", dicText = "name", dicCode = "id") + private String contractId; + + @ApiModelProperty("车辆种类") + @ExcelProperty(value = "车辆种类", converter = DictConverter.class, index = 3) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("模板") + @ExcelProperty(value = "模板名称", converter = DictConverter.class, index = 1) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_vehicle_check_template", dicText = "name", dicCode = "id") + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String templateId; + + @ApiModelProperty("交车人") + @ExcelProperty(value = "交车人", index = 7) + private String sentVehicleUser; + + @ApiModelProperty("验收人id") + @ExcelProperty(value = "验收人", converter = DictConverter.class, index = 8) + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + private String checkUserId; + + @ApiModelProperty("验收人") + @ExcelIgnore + private String checkUserName; + + @ApiModelProperty("接收人id") + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + @ExcelIgnore + //@ExcelProperty(value = "接收人", converter = DictConverter.class, index = 9) + private String acceptUserId; + + @ApiModelProperty("接收人") + @ExcelIgnore + private String acceptUserName; + + @ApiModelProperty("验收时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "验收日期", index = 6) + private Date checkTime; + + @ApiModelProperty("初登日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private Date registrationTime; + + @ApiModelProperty("验收地址") + @ExcelIgnore + private String checkAddress; + + @ApiModelProperty("验收结果(0不合格,1合格)") + @Dict(dicCode = "check_status") + @ExcelProperty(value = "验收结果", converter = DictConverter.class, index = 5) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String checkStatus; + + @ApiModelProperty("验收结论") + @ExcelIgnore + private String remark; + + @ApiModelProperty("验收单") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String ckeckUrl; + + @ApiModelProperty("保函") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String ensureUrl; + + @ApiModelProperty("其他") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String otherUrl; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ApiModelProperty("删除标志") + @ExcelIgnore + private Integer delFlag; + + @ApiModelProperty("验收类型") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelIgnore + @Dict(dicCode = "check_type") + private String checkType; + + @ApiModelProperty("交车人id") + //@ExcelProperty(value = "交车人", converter = DictConverter.class, index = 6) + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + @ExcelIgnore + private String sentVehicleUserId; + + @ApiModelProperty("来源(1后台,2小程序)") + @ExcelIgnore + private String sourceType; + + @ApiModelProperty("租赁交车id") + @ExcelIgnore + private String parentId; + + @ApiModelProperty("状态(0待提交,1已提交)") + @ExcelIgnore + @Dict(dicCode = "edit_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String status; + + @ApiModelProperty("收车状态(0未交车,0.5未收车,1已收车)") + @ExcelIgnore + @Dict(dicCode = "receive_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String receiveStatus; + + //验收项目 + @TableField(exist = false) + @ExcelIgnore + private String projectNames; + + //车辆信息 + //车牌号列表 + @TableField(exist = false) + @ExcelProperty(value = "车辆信息", index = 2) + private String plateNumbers; + + @TableField(exist = false) + @ExcelIgnore + @Validate + private List vehicleList; + + @TableField(exist = false) + @ExcelIgnore + private List projectList; + + //租赁收车 + @TableField(exist = false) + @ExcelIgnore + private TbVehicleCheck children; + + //未处理违章数 + @TableField(exist = false) + @ExcelIgnore + private Integer violationCount = 0; + + //未处理事故数 + @TableField(exist = false) + @ExcelIgnore + private Integer accidentInfoCount = 0; + + @TableField(exist = false) + @ExcelIgnore + private String frameNumber; + + @TableField(exist = false) + @ExcelIgnore + private String plateNumber; + + //车架号列表 + @TableField(exist = false) + @ExcelIgnore + private String frameNumbers; + + //车辆数 + @TableField(exist = false) + @ExcelProperty(value = "车辆数量", index = 4) + private Integer vehicleCount = 0; +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckDetail.java b/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckDetail.java new file mode 100644 index 0000000..b38f9ed --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckDetail.java @@ -0,0 +1,140 @@ +package com.gci.boot.modules.projects.entity; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import com.alibaba.excel.annotation.format.DateTimeFormat; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.basedata.entity.TbVehicle; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 车辆验收车辆详情 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Getter +@Setter +@TableName("tb_vehicle_check_detail") +@ApiModel(value = "TbVehicleCheckDetail对象", description = "车辆验收车辆详情") +public class TbVehicleCheckDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("验收id") + private String checkId; + + @ApiModelProperty("车辆id") + private String vehicleId; + + //弃用 + @Deprecated + @ApiModelProperty("车辆型号") + private String vehicleNo; + + @ApiModelProperty("车架号") + @ExcelProperty(value = "车架号") + private String frameNumber; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + /*@ApiModelProperty("删除标志") + @ExcelIgnore + private Integer delFlag;*/ + + /*@TableField(exist = false) + @ExcelIgnore + private TbVehicle vehicle;*/ + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + @ExcelProperty(value = "车辆品牌", converter = DictConverter.class) + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @ExcelProperty(value = "车辆型号") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类", converter = DictConverter.class) + private String vehicleType; + + @ExcelProperty(value = "车牌号") + private String plateNumber; + + + @Digits(integer = 6 , fraction = 2,message = "整备质量整数不能超过6位,小数不能超过2位",groups = {SaveValidated.class,UpdateValidated.class}) + private BigDecimal curbWeight; + + @ExcelProperty(value = "整备质量(kg)") + @TableField(exist = false) + private String curbWeightString; + + @TableField(exist = false) + @ExcelIgnore + private Double price; + + @ApiModelProperty("保险单号") + @TableField(exist = false) + @ExcelIgnore + private String insuranceNo; + + @ApiModelProperty("保险公司名称") + @TableField(exist = false) + @ExcelIgnore + private String insuranceName; + +} diff --git a/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckProject.java b/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckProject.java new file mode 100644 index 0000000..78cb2fd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/entity/TbVehicleCheckProject.java @@ -0,0 +1,89 @@ +package com.gci.boot.modules.projects.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.io.Serializable; +import java.util.Date; + +import com.alibaba.excel.annotation.format.DateTimeFormat; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 车辆验收项目 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Getter +@Setter +@TableName("tb_vehicle_check_project") +@ApiModel(value = "TbVehicleCheckProject对象", description = "车辆验收项目") +public class TbVehicleCheckProject implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("验收项目") + private String name; + + @ApiModelProperty("验收内容") + private String content; + + @ApiModelProperty("排序") + private Integer sort; + + @ApiModelProperty("验收id") + private String checkId; + + @ApiModelProperty("验收结果") + private String checkStatus; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("模板项目id") + private String templateProjectId; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + /*@ApiModelProperty("删除标志") + @ExcelIgnore + private Integer delFlag;*/ + + +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/ProjectUserRelMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/ProjectUserRelMapper.java new file mode 100644 index 0000000..ffefac2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/ProjectUserRelMapper.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.projects.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.entity.Projects; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 项目基础信息表 Mapper 接口 + *

+ * + * @author wangqihang + * @since 2023-10-23 + */ +public interface ProjectUserRelMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/ProjectVehicleBindLogMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/ProjectVehicleBindLogMapper.java new file mode 100644 index 0000000..0c54b73 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/ProjectVehicleBindLogMapper.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.projects.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.projects.entity.ProjectVehicleBindLog; +import com.gci.boot.modules.projects.entity.Projects; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 项目基础信息表 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +public interface ProjectVehicleBindLogMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/ProjectsMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/ProjectsMapper.java new file mode 100644 index 0000000..225caf4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/ProjectsMapper.java @@ -0,0 +1,44 @@ +package com.gci.boot.modules.projects.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gci.boot.modules.driver.vo.DriverUserVo; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.vo.VehicleTypeVO; +import com.gci.boot.modules.system.entity.SysDepart; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 项目基础信息表 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +public interface ProjectsMapper extends BaseMapper { + List getProjectsByDepartCodes(@Param("list")List list); + + /** + * 查车辆类型数量 + */ + List queryVehicleTypeNum(@Param("vehicleIds")List vehicleIds); + + /** + * 查全部项目,用于数据权限 + */ + List getAllProjects(); + + /** + * 分页查--区分数据权限 + */ + IPage getPage(IPage page, @Param("ew")Wrapper wrapper); + + /** + * 获取所有项目,加一层用于数据权限注解,创建时间升序 + */ + List getAllProjectsAuth(); +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/TbContractMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/TbContractMapper.java new file mode 100644 index 0000000..c7d113c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/TbContractMapper.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.projects.mapper; + +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.projects.entity.TbContract; + +/** + *

+ * 合同档案 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-09-01 + */ +public interface TbContractMapper extends BaseMapper { + + List getProjectContract(); + +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/TbContractVehicleMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/TbContractVehicleMapper.java new file mode 100644 index 0000000..9313faa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/TbContractVehicleMapper.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.projects.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.projects.entity.TbContractVehicle; + +public interface TbContractVehicleMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckDetailMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckDetailMapper.java new file mode 100644 index 0000000..932ffcb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckDetailMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.projects.mapper; + +import com.gci.boot.modules.projects.entity.TbVehicleCheckDetail; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆验收车辆详情 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +public interface TbVehicleCheckDetailMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckMapper.java new file mode 100644 index 0000000..40aedbe --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.projects.mapper; + +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆验收 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +public interface TbVehicleCheckMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckProjectMapper.java b/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckProjectMapper.java new file mode 100644 index 0000000..5df74d6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/TbVehicleCheckProjectMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.projects.mapper; + +import com.gci.boot.modules.projects.entity.TbVehicleCheckProject; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 车辆验收项目 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +public interface TbVehicleCheckProjectMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectUserRelMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectUserRelMapper.xml new file mode 100644 index 0000000..d38f8fe --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectUserRelMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectVehicleBindLogMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectVehicleBindLogMapper.xml new file mode 100644 index 0000000..52650dc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectVehicleBindLogMapper.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectsMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectsMapper.xml new file mode 100644 index 0000000..54ad7b4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/ProjectsMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractMapper.xml new file mode 100644 index 0000000..e4f2696 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractMapper.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractVehicleMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractVehicleMapper.xml new file mode 100644 index 0000000..c7b933d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbContractVehicleMapper.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckDetailMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckDetailMapper.xml new file mode 100644 index 0000000..0dce918 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckDetailMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckMapper.xml new file mode 100644 index 0000000..b5dc1dc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckProjectMapper.xml b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckProjectMapper.xml new file mode 100644 index 0000000..cb7ba1d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/mapper/xml/TbVehicleCheckProjectMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/projects/service/IProjectUserRelService.java b/src/main/java/com/gci/boot/modules/projects/service/IProjectUserRelService.java new file mode 100644 index 0000000..7043027 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/IProjectUserRelService.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.projects.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.entity.Projects; + +import java.util.List; + +/** + *

+ * 项目基础信息表 服务类 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +public interface IProjectUserRelService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/IProjectVehicleBindLogService.java b/src/main/java/com/gci/boot/modules/projects/service/IProjectVehicleBindLogService.java new file mode 100644 index 0000000..8db275c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/IProjectVehicleBindLogService.java @@ -0,0 +1,35 @@ +package com.gci.boot.modules.projects.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.projects.entity.ProjectVehicleBindLog; + +import java.util.List; + +/** + * @author lyz + * @date 2023/10/8 14:14 + */ +public interface IProjectVehicleBindLogService extends IService { + + /** + *添加绑定日志 + * @param projectId 项目id + * @param projectName 项目名称 + * @param plateNumber 车牌号 + * @param bindType 绑定类型 1-绑定 2-解绑 + * @param bindSource 操作来源 1-车辆操作 2-项目结束 3-项目操作 + * @param createBy 创建人 + */ + void addLog(String projectId,String projectName,String plateNumber,Integer bindType,Integer bindSource,String createBy); + + /** + *添加绑定日志 + * @param projectId + * @param projectName + * @param plateNumbers + * @param bindType + * @param bindSource + * @param createBy + */ + void addBatchLog(String projectId, String projectName, List plateNumbers, Integer bindType, Integer bindSource, String createBy); +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/IProjectsService.java b/src/main/java/com/gci/boot/modules/projects/service/IProjectsService.java new file mode 100644 index 0000000..21cdcf1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/IProjectsService.java @@ -0,0 +1,66 @@ +package com.gci.boot.modules.projects.service; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.driver.vo.DriverUserVo; +import com.gci.boot.modules.projects.entity.Projects; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 项目基础信息表 服务类 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +public interface IProjectsService extends IService { + + void saveItem(Projects item,String createBy); + + void initBusId(Projects item); + + void initUserId(Projects item); + + void updateStatus(Projects item,String createBy); + + List queryProjectListOfUser(); + + List listAll(); + + /** + * 识别当前用户的身份(所属的机构类别 1普通部门,2维修厂,3客户公司(租赁方),0根节点) + * @return + */ + Integer judgeDepartCategory(); + + + String getVehicleTypeNumStr(String vehicleIdsStr ); + + /** + * 分页查--区分数据权限 + */ + IPage getPage(IPage page, Wrapper wrapper); + + /** + * 获取所有项目,加一层用于数据权限注解,创建时间升序 + */ + List getAllProjectsAuth(); + + /** + * 获取用户所有权限项目id,超级管理员PM0000返回全部数据 + */ + List queryAllProjectListOfUser(); + /** + * 获取用户所有权限的车牌号,超级管理员PM0000返回全部数据 + */ + List queryAllPlateNumberListOfUser(); + + /** + * 获取用户所有权限的车牌号,超级管理员PM0000返回全部数据 + */ + List queryAllVehicleListOfUser(); +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/ITbContractService.java b/src/main/java/com/gci/boot/modules/projects/service/ITbContractService.java new file mode 100644 index 0000000..13e776b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/ITbContractService.java @@ -0,0 +1,37 @@ +package com.gci.boot.modules.projects.service; + +import com.gci.boot.modules.projects.entity.TbContract; + +import java.util.List; +import java.util.Map; + +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 合同档案 服务类 + *

+ * + * @author xushuhan + * @since 2023-09-01 + */ +public interface ITbContractService extends IService { + + + List getSigningList(String contractType, String sysOrgCode); + + void checkItem(TbContract item); + + void initVehicleCheckDetail(TbContract contract); + + void initItem(TbContract item); + + void saveItem(TbContract item); + + void updateItem(TbContract item); + + void updateStatus(String id); + + Map getCarPrice(String contractId); + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/ITbContractVehicleService.java b/src/main/java/com/gci/boot/modules/projects/service/ITbContractVehicleService.java new file mode 100644 index 0000000..6807950 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/ITbContractVehicleService.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.projects.service; + +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.projects.entity.TbContractVehicle; + +public interface ITbContractVehicleService extends IService { + + List getByContractId(String contractId); + + void saveItem(List list); + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckDetailService.java b/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckDetailService.java new file mode 100644 index 0000000..62568ee --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckDetailService.java @@ -0,0 +1,31 @@ +package com.gci.boot.modules.projects.service; + +import com.gci.boot.modules.projects.entity.TbContract; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.projects.entity.TbVehicleCheckDetail; + +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆验收车辆详情 服务类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +public interface ITbVehicleCheckDetailService extends IService { + + void getVehiclesByCheckId(TbVehicleCheck check); + + void saveItem(TbVehicleCheck check); + + void checkVehicle(TbVehicleCheck check); + + List getVehiclesByCheckIds(List ids); + + void initVehicleCheckDetail(TbContract contract); + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckProjectService.java b/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckProjectService.java new file mode 100644 index 0000000..b0f619a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckProjectService.java @@ -0,0 +1,21 @@ +package com.gci.boot.modules.projects.service; + +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.projects.entity.TbVehicleCheckProject; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 车辆验收项目 服务类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +public interface ITbVehicleCheckProjectService extends IService { + + void saveItem(TbVehicleCheck check); + + void getProjectsByCheckId(TbVehicleCheck check); + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckService.java b/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckService.java new file mode 100644 index 0000000..ce9b798 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/ITbVehicleCheckService.java @@ -0,0 +1,25 @@ +package com.gci.boot.modules.projects.service; + +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; + +/** + *

+ * 车辆验收 服务类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +public interface ITbVehicleCheckService extends IService { + + String saveItem(TbVehicleCheck item); + + void getChildren(TbVehicleCheck parent); + + void initItem(List list); + + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectUserRelServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectUserRelServiceImpl.java new file mode 100644 index 0000000..fda8657 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectUserRelServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.projects.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.mapper.ProjectUserRelMapper; +import com.gci.boot.modules.projects.service.IProjectUserRelService; +import org.springframework.stereotype.Service; + +/** + *

+ * 车辆验收 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Service +public class ProjectUserRelServiceImpl extends ServiceImpl implements IProjectUserRelService { + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectVehicleBindLogServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectVehicleBindLogServiceImpl.java new file mode 100644 index 0000000..628038e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectVehicleBindLogServiceImpl.java @@ -0,0 +1,54 @@ +package com.gci.boot.modules.projects.service.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.projects.entity.ProjectVehicleBindLog; +import com.gci.boot.modules.projects.mapper.ProjectVehicleBindLogMapper; +import com.gci.boot.modules.projects.service.IProjectVehicleBindLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +/** + * @author lyz + * @date 2023/10/8 14:15 + */ +@Service +public class ProjectVehicleBindLogServiceImpl extends ServiceImpl implements IProjectVehicleBindLogService { + @Autowired + private ProjectVehicleBindLogMapper projectVehicleBindLogMapper; + @Override + public void addLog(String projectId, String projectName, String plateNumber, Integer bindType, Integer bindSource, String createBy) { + ProjectVehicleBindLog log = bindLog(projectId,projectName,plateNumber,bindType,bindSource,createBy); + this.projectVehicleBindLogMapper.insert(log); + } + + @Override + public void addBatchLog(String projectId, String projectName, List plateNumbers, Integer bindType, Integer bindSource, String createBy) { + List logs = new ArrayList<>(plateNumbers.size()); + plateNumbers.stream().forEach(plateNumber->{ + ProjectVehicleBindLog log = bindLog(projectId,projectName,plateNumber,bindType,bindSource,createBy); + logs.add(log); + }); + this.saveBatch(logs); + } + + private ProjectVehicleBindLog bindLog(String projectId, String projectName, String plateNumber, Integer bindType, Integer bindSource, String createBy){ + ProjectVehicleBindLog log = new ProjectVehicleBindLog(); + log.setProjectId(projectId); + log.setProjectName(projectName); + log.setPlateNumber(plateNumber); + log.setBindType(bindType); + log.setBindSource(bindSource); + log.setCreateTime(new Date()); + log.setCreateBy(createBy); + return log; + } +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectsServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectsServiceImpl.java new file mode 100644 index 0000000..a5c7eed --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/ProjectsServiceImpl.java @@ -0,0 +1,508 @@ +package com.gci.boot.modules.projects.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.mapper.TbVehicleMapper; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.driver.entity.TbDriver; +import com.gci.boot.modules.driver.service.ITbDriverService; +import com.gci.boot.modules.driver.vo.DriverUserVo; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.mapper.ProjectUserRelMapper; +import com.gci.boot.modules.projects.mapper.ProjectsMapper; +import com.gci.boot.modules.projects.service.IProjectUserRelService; +import com.gci.boot.modules.projects.service.IProjectVehicleBindLogService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.projects.vo.VehicleTypeVO; +import com.gci.boot.modules.system.entity.SysDepart; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.service.ISysDepartService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.vo.LoginUser; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +/** + *

+ * 项目基础信息表 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-08-25 + */ +@Service +public class ProjectsServiceImpl extends ServiceImpl implements IProjectsService { + + public final String PROJECT_ID = "project_id"; + @Autowired + private ITbVehicleService iTbVehicleService; + + @Autowired + private IProjectVehicleBindLogService projectVehicleBindLogService; + + @Autowired + private TbVehicleMapper tbVehicleMapper; + + @Autowired + private ProjectsMapper projectsMapper; + + @Autowired + private ISysDepartService sysDepartService; + + @Autowired + private ISysRoleService sysRoleService; + + @Autowired + private ITbDriverService tbDriverService; + + @Autowired + private ProjectUserRelMapper projectUserRelMapper; + + @Autowired + private IProjectUserRelService projectUserRelService; + @Autowired + private ITbGisRunningbusService gisRunningbusService; + + @Override + @Transactional + public void saveItem(Projects item,String createBy) { + if (CommonConstant.INNER_PROJECT.equals(item.getId())) { + item.setCustomerId(null); + } + checkItem(item); + String busIds = item.getBusIds(); + String oldBusIds = ""; + boolean needLog = false,edit = false; + // 说明是更新,否则为新增 + if (StringUtils.isNotEmpty(item.getId())) { + edit = true; + List oldIds = getVehicleIdsByProjectId(item.getId()); + oldBusIds = oldIds.isEmpty() ? "" : String.join(",", oldIds); + } else { + if (StringUtils.isNotEmpty(busIds)) { + needLog = true; + } + } + item.setHisVehicleId(busIds); + if (StringUtils.isNotEmpty(item.getId())) { + updateById(item); + }else{ + save(item); + } + // 清除项目 ID + tbVehicleMapper.clearProductId(item.getId()); + if (StringUtils.isNotEmpty(busIds)) { + List busIdList = Arrays.asList(busIds.split(",")); + updateVehicleProjectId(busIdList, item.getId()); + } + if (needLog) { + List plateNumbers = getPlateNumbersByVehicleIds(Arrays.asList(busIds.split(","))); + projectVehicleBindLogService.addBatchLog(item.getId(), item.getProjectName(), plateNumbers, 1, 3, createBy); + } + if (edit && !oldBusIds.equals(busIds)) { + List oldBusIdList = new ArrayList<>(); + List editBusIdList = new ArrayList<>(); + try { + oldBusIdList = Arrays.asList(oldBusIds.split(",")); + } catch (Exception e) { + } + try { + editBusIdList = Arrays.asList(busIds.split(",")); + } catch (Exception e) { + } + // 解绑的 + List unbindVehicleIds = new ArrayList<>(oldBusIdList); + unbindVehicleIds.removeAll(editBusIdList); + + if (!unbindVehicleIds.isEmpty()) { + List unbindPlateNumbers = getPlateNumbersByVehicleIds(unbindVehicleIds); + projectVehicleBindLogService.addBatchLog(item.getId(), item.getProjectName(), unbindPlateNumbers, 2, 3, createBy); + } + // 新绑定的 + List bindVehicleIds = new ArrayList<>(editBusIdList); + bindVehicleIds.removeAll(oldBusIdList); + + if (!bindVehicleIds.isEmpty()) { + List bindPlateNumbers = getPlateNumbersByVehicleIds(bindVehicleIds); + projectVehicleBindLogService.addBatchLog(item.getId(), item.getProjectName(), bindPlateNumbers, 1, 3, createBy); + } + + } + //保存项目和成员关系 + if(StringUtils.isNotEmpty(item.getId())){ + QueryWrapper delQueryWrapper = new QueryWrapper<>(); + delQueryWrapper.eq("project_id", item.getId()); + projectUserRelMapper.delete(delQueryWrapper); + } + + if(StringUtils.isNotEmpty(item.getUserIds())){ + String[] arrUserId = item.getUserIds().split(","); + if(ArrayUtils.isNotEmpty(arrUserId)){ + List listProjUserRel = new ArrayList<>(); + for(String userId: arrUserId){ + ProjectUserRel projectUser = new ProjectUserRel(); + projectUser.setProjectId(item.getId()); + projectUser.setUserId(userId); + listProjUserRel.add(projectUser); + } + projectUserRelService.saveBatch(listProjUserRel); + } + } + } + + public void checkItem(Projects item) { + if(item.getStartDate().after(item.getEndDate())) { + throw new GciBootException("开始日期不能大于结束日期"); + } + String name = item.getProjectName().trim(); + if(StringUtils.isEmpty(name)) { + throw new GciBootException("项目名称不能为空"); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.ne(StringUtils.isNotEmpty(item.getId()),"id", item.getId()); + queryWrapper.eq("project_name", name); + int count = count(queryWrapper); + if(count>0) { + throw new GciBootException("项目名称不能重复"); + } + } + + @Override + public void initBusId(Projects item) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("project_id", item.getId()); + List list = tbVehicleMapper.selectList(queryWrapper); + String busIds = null; + for (TbVehicle tbVehicle : list) { + if(busIds==null) { + busIds = tbVehicle.getId(); + }else { + busIds += ","+tbVehicle.getId(); + } + } + item.setBusIds(busIds); + } + + @Override + public void initUserId(Projects item) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("project_id", item.getId()); + List list = projectUserRelMapper.selectList(queryWrapper); + String userIds = null; + for (ProjectUserRel projectUserRel : list) { + if(userIds==null) { + userIds = projectUserRel.getUserId(); + }else { + userIds += ","+projectUserRel.getUserId(); + } + } + item.setUserIds(userIds); + } + + @Override + @Transactional + public void updateStatus(Projects item,String createBy) { + if(CommonConstant.STATUS_1.equals(item.getStatus())) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("project_id", item.getId()); + List list = tbVehicleMapper.selectList(queryWrapper); + String busIds = list.stream().map(a->{return a.getId();}).collect(Collectors.joining(",")); + List plateNumbers = list.stream().map(a->{return a.getPlateNumber();}).collect(Collectors.toList()); + item.setBusIds(busIds); + if(StringUtils.isNotEmpty(item.getBusIds())) { + item.setHisVehicleId(item.getBusIds()); + } + item.setStatus(CommonConstant.STATUS_0); + updateById(item); + tbVehicleMapper.clearProductId(item.getId()); + if(!plateNumbers.isEmpty()){ + projectVehicleBindLogService.addBatchLog(item.getId(),item.getProjectName(),plateNumbers,2,3,createBy); + } + }else if(CommonConstant.STATUS_0.equals(item.getStatus())) { + item.setStatus(CommonConstant.STATUS_1); + updateById(item); + } + } + + @Override + public List queryProjectListOfUser() { + final List result = new ArrayList<>(); + // 获取登录用户信息 + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser==null || org.apache.commons.lang3.StringUtils.isEmpty(sysUser.getId())){ + throw new RuntimeException("用户未登录"); + } + List departList = sysDepartService.getDepartByUserId(sysUser.getId()); + //flag标识是否是客户公司身份 1_普通部门,2_维修厂,3_客户公司 + int departCategory = 0; + boolean flag = false; + List listDepart = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(departList)){ + for(SysDepart depart: departList){ + if(depart.getOrgCategory()==1){ + departCategory = 1; + break; + }else if(depart.getOrgCategory()==2){ + if(departCategory == 0){ + departCategory = 2; + } + return result; + }else if(depart.getOrgCategory()==3){ + departCategory = 3; + listDepart.add(depart.getOrgCode()); + } + } + } + //按照部门类型依次处理:1、内部员工,2、客户人员(司机、客户管理员),3、其他人员 + if(departCategory == 1){ + List listProjectUserRel = projectUserRelMapper.selectList(new QueryWrapper().eq("user_id", sysUser.getId())); + listProjectUserRel.stream().forEach(rel -> { + result.add(rel.getProjectId()); + }); + }else if(departCategory == 3){ + TbDriver tbDiver = tbDriverService.getOne(new QueryWrapper().eq("user_id", sysUser.getId())); + if(tbDiver != null && tbDiver.getId() != null && org.apache.commons.lang3.StringUtils.isNotEmpty(tbDiver.getProjectId())){ + //处理司机的情况 + String[] projectIdStr = tbDiver.getProjectId().split(","); + if(ArrayUtils.isNotEmpty(projectIdStr)){ + for(String projectIdDriver: projectIdStr){ + result.add(projectIdDriver); + } + } + }else{ + //处理客户其他人员的情况 + List projectsByDepartCodes = projectsMapper.getProjectsByDepartCodes(listDepart); + projectsByDepartCodes.stream().forEach(proj -> { + result.add(proj.getId()); + }); + } + } + return result; + } + + @Override + public List listAll() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("cancel_flag",0); + return this.projectsMapper.selectList(queryWrapper); + } + + /** + * 处理逻辑:有效看是否有普通部门,作为内部员工处理,其次判断客户公司和维修厂 + * @return + */ + @Override + public Integer judgeDepartCategory() { + // 获取登录用户信息 + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser==null || org.apache.commons.lang3.StringUtils.isEmpty(sysUser.getId())){ + throw new RuntimeException("用户未登录"); + } + List departList = sysDepartService.getDepartByUserId(sysUser.getId()); + //判断用户身份: 1_普通部门,2_维修厂,3_司机,4_客户公司其他人员,5_超级管理员,0、其他身份 + int departCategory = 0; + //获取角色,判断是否包含超级管理员 + List listRole = sysRoleService.getRoleByUserId(sysUser.getId()); + if(CollectionUtils.isEmpty(listRole)){ + //角色配置为空 + throw new RuntimeException("角色配置为空"); + } + StringBuilder sbRole = new StringBuilder(); + listRole.forEach(lRole -> { + sbRole.append(","+lRole.getRoleCode()); + }); + String strRole = sbRole.toString(); + if(strRole.contains("PM0000")){ + return 5; + } + + List listDepart = new ArrayList<>(); + if(CollectionUtils.isNotEmpty(departList)){ + for(SysDepart depart: departList){ + if(depart.getOrgCategory()==1){ + departCategory = 1; + break; + }else if(depart.getOrgCategory()==2){ + if(departCategory == 0){ + departCategory = 2; + } + }else if(depart.getOrgCategory()==3){ + TbDriver tbDiver = tbDriverService.getOne(new QueryWrapper().eq("user_id", sysUser.getId())); + if(tbDiver != null && tbDiver.getId() != null){ + //处理司机的情况 + departCategory = 3; + }else{ + //公司的其他人员 + if(departCategory == 0 || departCategory == 2){ + departCategory = 4; + } + } + } + } + } + return departCategory; + } + + @Override + public String getVehicleTypeNumStr(String vehicleIdsStr) { + if(StrUtil.isBlank(vehicleIdsStr)){ + return null; + } + List vehicleIds = Arrays.asList(vehicleIdsStr.split(",")); + List list = projectsMapper.queryVehicleTypeNum(vehicleIds); + if(CollectionUtils.isNotEmpty(list)){ + String str = ""; + for (VehicleTypeVO vehicleTypeVO : list){ + str += vehicleTypeVO.getItemText() + ":" + vehicleTypeVO.getCount() + "辆"; + if(list.indexOf(vehicleTypeVO)!= list.size()-1){ + str += ","; + }else{ + str += "。"; + } + } + return str; + } + return null; + } + + @Override + public IPage getPage(IPage page, Wrapper wrapper) { + IPage pageList = projectsMapper.getPage(page, wrapper); + return pageList; + } + + @Override + public List getAllProjectsAuth() { + List list = projectsMapper.getAllProjectsAuth(); + return list; + } + + @Override + public List queryAllProjectListOfUser() { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser==null || StringUtils.isEmpty(sysUser.getId())){ + return null; + } + //获取角色:为判断超级管理员准备 + List listRole = sysRoleService.getRoleByUserId(sysUser.getId()); + if(CollectionUtils.isEmpty(listRole)){ + return null; + } + StringBuilder sbRole = new StringBuilder(); + listRole.forEach(lRole -> { + sbRole.append(","+lRole.getRoleCode()); + }); + String strRole = sbRole.toString(); + if(strRole.contains("PM0000")){ + List allList = this.getAllProjectsAuth(); + if(CollectionUtils.isNotEmpty(allList)){ + return allList.stream().map(Projects::getId).collect(Collectors.toList()); + }else{ + return null; + } + } + return this.queryProjectListOfUser(); + } + + @Override + public List queryAllVehicleListOfUser() { + //获取项目id + List projectIds = this.queryAllProjectListOfUser(); + if(Objects.isNull(projectIds)){ + projectIds = new ArrayList<>(); + projectIds.add("No Permission"); + } + //获取车牌信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicle::getCancelFlag,0) + .in(TbVehicle::getProjectId,projectIds); + List vehicles = tbVehicleMapper.selectList(queryWrapper); + return vehicles; + } + + @Override + public List queryAllPlateNumberListOfUser() { + //获取项目id + List projectIds = this.queryAllProjectListOfUser(); + if(CollectionUtils.isEmpty(projectIds)){ + projectIds = new ArrayList<>(); + projectIds.add("No Permission"); + } + //获取车牌信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicle::getCancelFlag,0) + .in(TbVehicle::getProjectId,projectIds); + List vehicles = tbVehicleMapper.selectList(queryWrapper); + if(CollectionUtils.isNotEmpty(vehicles)){ + return vehicles.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList()); + }else{ + return new ArrayList<>(); + } + } + + /** + * 获取车辆车牌号方法 + * @param vehicleIds + * @return + */ + private List getPlateNumbersByVehicleIds(List vehicleIds) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("id", vehicleIds); + List vehicles = tbVehicleMapper.selectList(queryWrapper); + return vehicles.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList()); + } + + private List getVehicleIdsByProjectId(String projectId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(PROJECT_ID, projectId); + List list = tbVehicleMapper.selectList(queryWrapper); + return list.stream().map(TbVehicle::getId).collect(Collectors.toList()); + } + + + /** + * 更新方法 + * @param vehicleIds + * @param projectId + */ + private void updateVehicleProjectId(List vehicleIds, String projectId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("id", vehicleIds); + queryWrapper.and(w -> w.eq(PROJECT_ID, CommonConstant.INNER_PROJECT).or().isNull(PROJECT_ID)); + TbVehicle bus = new TbVehicle(); + bus.setProjectId(projectId); + tbVehicleMapper.update(bus, queryWrapper); + //更新runningBus项目id + CompletableFuture.runAsync(() -> { + List plateNumbers = this.getPlateNumbersByVehicleIds(vehicleIds); + if(CollectionUtils.isNotEmpty(plateNumbers)){ + gisRunningbusService.update(new LambdaUpdateWrapper().in(TbGisRunningbus::getPlateNumber,plateNumbers) + .set(TbGisRunningbus::getProjectId,projectId)); + } + }); + } + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/TbContractServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/TbContractServiceImpl.java new file mode 100644 index 0000000..5ca415f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/TbContractServiceImpl.java @@ -0,0 +1,344 @@ +package com.gci.boot.modules.projects.service.impl; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.Lock; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbCustomerArchives; +import com.gci.boot.modules.basedata.entity.TbInsuranceCompanyArchives; +import com.gci.boot.modules.basedata.entity.TbRepairShopArchives; +import com.gci.boot.modules.basedata.entity.TbVehicleSupplierArchives; +import com.gci.boot.modules.basedata.service.ITbCustomerArchivesService; +import com.gci.boot.modules.basedata.service.ITbInsuranceCompanyArchivesService; +import com.gci.boot.modules.basedata.service.ITbRepairShopArchivesService; +import com.gci.boot.modules.basedata.service.ITbVehicleSupplierArchivesService; +import com.gci.boot.modules.projects.entity.TbContract; +import com.gci.boot.modules.projects.entity.TbContractVehicle; +import com.gci.boot.modules.projects.entity.TbVehicleCheckDetail; +import com.gci.boot.modules.projects.mapper.TbContractMapper; +import com.gci.boot.modules.projects.service.ITbContractService; +import com.gci.boot.modules.projects.service.ITbContractVehicleService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckDetailService; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.service.ITbInsuranceService; + +import cn.hutool.core.util.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 合同档案 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-01 + */ +@Slf4j +@Service +public class TbContractServiceImpl extends ServiceImpl implements ITbContractService { + + @Autowired + private ITbCustomerArchivesService tbCustomerArchivesService; + @Autowired + private ITbInsuranceCompanyArchivesService tbInsuranceCompanyArchivesService; + @Autowired + private ITbRepairShopArchivesService tbRepairShopArchivesService; + @Autowired + private ITbVehicleSupplierArchivesService tbVehicleSupplierArchivesService; + + @Autowired + private ITbContractVehicleService contractVehicleService; + @Autowired + private ITbVehicleCheckDetailService vehicleCheckDetailService; + @Autowired + private ITbInsuranceService insuranceService; + + @Autowired + private ITbInsuranceCompanyArchivesService insuranceCompanyArchivesService; + + @Autowired + private Lock lock; + + DecimalFormat df2 = new DecimalFormat("#.00"); + + @Transactional + @Override + public void saveItem(TbContract item) { + if("1".equals(item.getContractType())||"4".equals(item.getContractType())) { + item.setStatus("0"); + } + checkItem(item); + save(item); + //处理车辆细项 + if(Objects.nonNull(item.getVehicleDetails()) && item.getVehicleDetails().size()>0){ + item.getVehicleDetails().stream().forEach(s->s.setContractId(item.getId())); + contractVehicleService.saveItem(item.getVehicleDetails()); + } + } + + @Transactional + @Override + public void updateItem(TbContract item) { + checkItem(item); + updateById(item); + //处理车辆细项--先删后存 + LambdaQueryWrapper delWrapper = new LambdaQueryWrapper<>(); + delWrapper.eq(TbContractVehicle::getContractId,item.getId()); + contractVehicleService.remove(delWrapper); + if(Objects.nonNull(item.getVehicleDetails()) && item.getVehicleDetails().size()>0){ + item.getVehicleDetails().stream().forEach(s->s.setContractId(item.getId())); + contractVehicleService.saveItem(item.getVehicleDetails()); + } + } + + //根据合同类型获取签约方列表 + @Override + public List getSigningList(String contractType,String sysOrgCode) { + List dataList = new ArrayList<>(); + if("1".equals(contractType)) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + //queryWrapper.likeRight(StringUtils.hasLength(sysOrgCode),"sys_org_code", sysOrgCode); + List list = tbCustomerArchivesService.list(queryWrapper); + for(TbCustomerArchives item:list) { + TbContract con = new TbContract(); + con.setContractType(contractType); + con.setId(item.getId()); + con.setName(item.getName()); + dataList.add(con); + } + }else if("2".equals(contractType)) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + //queryWrapper.likeRight(StringUtils.hasLength(sysOrgCode),"sys_org_code", sysOrgCode); + List list = tbInsuranceCompanyArchivesService.list(queryWrapper); + for(TbInsuranceCompanyArchives item:list) { + TbContract con = new TbContract(); + con.setContractType(contractType); + con.setId(item.getId()); + con.setName(item.getName()); + dataList.add(con); + } + }else if("3".equals(contractType)) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + //queryWrapper.likeRight(StringUtils.hasLength(sysOrgCode),"sys_org_code", sysOrgCode); + List list = tbRepairShopArchivesService.list(queryWrapper); + for(TbRepairShopArchives item:list) { + TbContract con = new TbContract(); + con.setContractType(contractType); + con.setId(item.getId()); + con.setName(item.getName()); + dataList.add(con); + } + }else if("4".equals(contractType)) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + //queryWrapper.likeRight(StringUtils.hasLength(sysOrgCode),"sys_org_code", sysOrgCode); + List list = tbVehicleSupplierArchivesService.list(queryWrapper); + for(TbVehicleSupplierArchives item:list) { + TbContract con = new TbContract(); + con.setContractType(contractType); + con.setId(item.getId()); + con.setName(item.getName()); + dataList.add(con); + } + }else { + return null; + } + return dataList; + } + + public void checkItem(TbContract item) { + if(ObjectUtil.isAllNotEmpty(item.getStartTime(),item.getEndTime())){ + if(item.getStartTime().after(item.getEndTime())) { + throw new GciBootException("生效时间不能大于失效时间"); + } + } + if(StringUtils.hasLength(item.getFileUrl())) { + if(item.getFileUrl().split(",").length>10) { + throw new GciBootException("上传合同档案不能超过10个!"); + } + }else { + //throw new GciBootException("请上传合同档案!"); + } + if("1".equals(item.getContractType())) { + if(!StringUtils.hasLength(item.getProjectId())) { + throw new GciBootException("请选择项目"); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbContract::getProjectId, item.getProjectId()); + queryWrapper.ne(StringUtils.hasLength(item.getId()),TbContract::getId, item.getId()); + int count = count(queryWrapper); + if(count>0) { + throw new GciBootException("该项目的租户合同已存在"); + } + } + } + + //TODO 交接单状态判断(已提交),合同id + @Override + public void updateStatus(String id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(StringUtils.hasLength(id),TbContract::getId,id); + queryWrapper.eq(TbContract::getStatus, "0"); + List list = list(queryWrapper); + for(TbContract item:list) { + //获取车辆明细 + vehicleCheckDetailService.initVehicleCheckDetail(item); + int tatol = 0; + Map map = new HashMap<>(); + for(TbVehicleCheckDetail d:item.getVehicleList()) { + if(StringUtils.hasLength(d.getPlateNumber())) { + int count = map.getOrDefault(d.getVehicleModel(), 0); + map.put(d.getVehicleModel(), count+1); + tatol++; + } + } + //1客户租赁合同、4车辆采购合同 + if("4".equals(item.getContractType())) { + //交接单车辆大于采购合同车辆数 + if(tatol>=item.getVehicleCount()&&item.getVehicleCount()!=0) { + item.setStatus("1"); + updateById(item); + } + }else if("1".equals(item.getContractType())) { + boolean pass = true; + //交接单车辆大于租赁合同车型明细车辆数 + List vehicleList = contractVehicleService.getByContractId(item.getId()); + if(vehicleList.size()==0) { + pass = false; + } + for (TbContractVehicle type : vehicleList) { + if(!map.containsKey(type.getVehicleModel())) { + pass = false; + break; + } + int count = map.get(type.getVehicleModel()); + if(count 0){ + updateStatus(null); + } + }catch (Exception ex){ + log.error("合同状态更新出错, {}", ex); + }finally { + //释放锁 + if(n > 0){ + lock.delLock(key, value); + } + } + } + + //4采购合同、1租赁合同获取交接车车辆详情数据 + @Override + public void initVehicleCheckDetail(TbContract item) { + vehicleCheckDetailService.initVehicleCheckDetail(item); + } + + //初始化车辆价格、保险 + @Override + public void initItem(TbContract item) { + if(item.getVehicleList()==null||item.getVehicleList().size()<1) { + return; + } + //1客户租赁合同、4车辆采购合同 + if("4".equals(item.getContractType())) { + /*Double price = 0d; + if(item.getVehicleCount()>0) { + price = new Double(df2.format(item.getTotalPrice()/item.getVehicleCount()/10000)); + }*/ + Map pmap = new HashMap<>(); + if(item.getVehicleDetails()!=null) { + for(TbContractVehicle d:item.getVehicleDetails()) { + pmap.put(d.getVehicleModel(), d.getTotalPrice()); + } + } + for(TbVehicleCheckDetail d:item.getVehicleList()) { + if(pmap.containsKey(d.getVehicleModel())) { + d.setPrice(pmap.get(d.getVehicleModel())); + }else { + d.setPrice(0d); + } + } + }else if("1".equals(item.getContractType())) { + Map violationMap = item.getVehicleDetails().stream().collect(Collectors.toMap(TbContractVehicle::getVehicleModel,Function.identity())); + + List vids = item.getVehicleList().stream().map(t->t.getVehicleId()).collect(Collectors.toList()); + Map insuranceMap = insuranceService.getLastInsurance(vids); + + List coms = insuranceCompanyArchivesService.list(); + Map comsMap = coms.stream().collect(Collectors.toMap(TbInsuranceCompanyArchives::getId,Function.identity())); + + for(TbVehicleCheckDetail d:item.getVehicleList()) { + Double price = 0d; + if(violationMap.containsKey(d.getVehicleModel())) { + price = new Double(violationMap.get(d.getVehicleModel()).getTotalPrice()); + } + d.setPrice(price); + if(insuranceMap.containsKey(d.getVehicleId())) { + String insuranceNo = ""; + TbInsurance in = insuranceMap.get(d.getVehicleId()); + if(in==null) { + continue; + } + if("1".equals(in.getHasCommercialInsurance())) { + insuranceNo = in.getCommercialInsuranceNo(); + }else { + insuranceNo = in.getCompulsoryInsuranceNo(); + } + d.setInsuranceNo(insuranceNo); + if(comsMap.containsKey(in.getCompulsoryCompanyId())) { + d.setInsuranceName(comsMap.get(in.getCompulsoryCompanyId()).getName()); + } + } + } + + + } + } + + @Override + public Map getCarPrice(String contractId) { + List list = contractVehicleService.getByContractId(contractId); + Map pmap = new HashMap<>(); + for(TbContractVehicle d:list) { + pmap.put(d.getVehicleModel(), d.getTotalPrice()); + } + return pmap; + } + + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/TbContractVehicleServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/TbContractVehicleServiceImpl.java new file mode 100644 index 0000000..8402788 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/TbContractVehicleServiceImpl.java @@ -0,0 +1,49 @@ +package com.gci.boot.modules.projects.service.impl; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.ValidateUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.projects.entity.TbContractVehicle; +import com.gci.boot.modules.projects.mapper.TbContractVehicleMapper; +import com.gci.boot.modules.projects.service.ITbContractVehicleService; + +import cn.hutool.core.util.StrUtil; + + +@Service +public class TbContractVehicleServiceImpl extends ServiceImpl implements ITbContractVehicleService { + + @Override + public List getByContractId(String contractId) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(TbContractVehicle::getContractId,contractId); + return list(query); + } + + @Override + public void saveItem(List list) { + int count = 1; + Set vehicleModel = new HashSet<>(); + for (TbContractVehicle tbContractVehicle : list) { + String valid = ValidateUtil.valid(tbContractVehicle, SaveValidated.class); + if (StrUtil.isNotBlank(valid)) { + throw new GciBootException("车型明细:第"+count+"行:"+valid); + } + vehicleModel.add(tbContractVehicle.getVehicleModel()); + count++; + } + if(vehicleModel.size() + * 车辆验收车辆详情 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Service +public class TbVehicleCheckDetailServiceImpl extends ServiceImpl implements ITbVehicleCheckDetailService { + + @Autowired + private ITbVehicleService tbVehicleService; + + @Override + public void getVehiclesByCheckId(TbVehicleCheck check) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicleCheckDetail::getCheckId, check.getId()); + queryWrapper.orderByAsc(TbVehicleCheckDetail::getCreateTime); + List list = list(queryWrapper); + check.setVehicleList(list); + + Set con = new LinkedHashSet<>(); + Set fras = new LinkedHashSet<>(); + for (TbVehicleCheckDetail pro : list) { + if(StringUtils.hasLength(pro.getPlateNumber())) { + con.add(pro.getPlateNumber()); + } + if(StringUtils.hasLength(pro.getFrameNumber())) { + fras.add(pro.getFrameNumber()); + } + } + String projectNames = String.join(",", con); + String frameNumbers = String.join(",", fras); + check.setPlateNumbers(projectNames); + check.setFrameNumbers(frameNumbers); + + } + + @Override + public void saveItem(TbVehicleCheck check) { + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("check_id", check.getId()); + remove(queryWrapper); + + Set ids = check.getVehicleList().stream().map(t->t.getVehicleId()).collect(Collectors.toSet()); + Map map = new HashMap<>(); + if(ids.size()>0) { + List busList = tbVehicleService.listByIds(ids); + map = busList.stream().collect(Collectors.toMap(TbVehicle::getId,Function.identity())); + } + List updateCar = new ArrayList<>(); + List projects = new ArrayList<>(); + for(TbVehicleCheckDetail project:check.getVehicleList()) { + if(map.containsKey(project.getVehicleId())) { + TbVehicle car = map.get(project.getVehicleId()); + if(CommonConstant.INNER_PROJECT.equals(car.getProjectId())&&StringUtils.hasLength(check.getProjectId())) { + car.setProjectId(check.getProjectId()); + updateCar.add(car); + } + BeanUtilsCopy.copyBeanPropFilterId(project, car); + } + project.setCheckId(check.getId()); + projects.add(project); + } + saveBatch(projects); + + //租赁交车,更新未分配项目车辆的项目id + if("2".equals(check.getCheckType())&&updateCar.size()>0) { + tbVehicleService.updateBatchById(updateCar); + } + } + + @Override + public void checkVehicle(TbVehicleCheck check) { + if(!"3".equals(check.getCheckType())&&check.getVehicleList()==null&&check.getVehicleList().size()<1) { + throw new GciBootException("车辆信息不能为空"); + } + if("1".equals(check.getCheckType())) { + Set vset = check.getVehicleList().stream().map(t->t.getFrameNumber()).collect(Collectors.toSet()); + if(vset.size()!=check.getVehicleList().size()) { + throw new GciBootException("车架号不能重复"); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.ne("check_id", check.getId()); + queryWrapper.in("frame_number", vset); + //查询其他项目 + String sql = "select 1 from tb_vehicle_check c where tb_vehicle_check_detail.check_id = c.id and c.id !='"+check.getId()+"' and c.project_id='"+check.getProjectId()+"'"; + queryWrapper.exists(sql); + int exist = count(queryWrapper); + if(exist>0) { + throw new GciBootException("车架号不能重复!"); + } + } + if(StringUtils.hasLength(check.getCkeckUrl())) { + if(check.getCkeckUrl().split(",").length>10) { + throw new GciBootException("上传验收单不能超过10个!"); + } + } + if(StringUtils.hasLength(check.getEnsureUrl())) { + if(check.getEnsureUrl().split(",").length>10) { + throw new GciBootException("上传保函不能超过10个!"); + } + } + if(StringUtils.hasLength(check.getOtherUrl())) { + if(check.getOtherUrl().split(",").length>10) { + throw new GciBootException("上传其他文件不能超过10个!"); + } + } + } + + @Override + public List getVehiclesByCheckIds(List ids) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbVehicleCheckDetail::getCheckId, ids); + queryWrapper.orderByDesc(TbVehicleCheckDetail::getCreateTime); + List list = list(queryWrapper); + return list; + } + + public List getVehicleCheckDetails(String checkType,String contractId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + String sql = "select 1 from tb_vehicle_check vc where vc.status='1' and tb_vehicle_check_detail.check_id = vc.id and vc.check_type='" + +checkType+"' and vc.contract_id='"+contractId+"'"; + queryWrapper.exists(sql); + queryWrapper.orderByDesc(TbVehicleCheckDetail::getCreateTime); + List list = list(queryWrapper); + + return list; + } + + //4采购合同、1租赁合同获取交接车车辆详情数据 + @Override + public void initVehicleCheckDetail(TbContract contract) { + String checkType = ""; + if("1".equals(contract.getContractType())) { + checkType = "2"; + }else if("4".equals(contract.getContractType())) { + checkType = "1"; + } + if(!StringUtils.hasLength(checkType)) { + return; + } + List details = getVehicleCheckDetails(checkType, contract.getId()); + contract.setVehicleList(details); + } + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckProjectServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckProjectServiceImpl.java new file mode 100644 index 0000000..43b8f9d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckProjectServiceImpl.java @@ -0,0 +1,81 @@ +package com.gci.boot.modules.projects.service.impl; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.BeanUtilsCopy; +import com.gci.boot.modules.basedata.entity.TbVehicleCheckTemplateProject; +import com.gci.boot.modules.basedata.service.ITbVehicleCheckTemplateProjectService; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.projects.entity.TbVehicleCheckProject; +import com.gci.boot.modules.projects.mapper.TbVehicleCheckProjectMapper; +import com.gci.boot.modules.projects.service.ITbVehicleCheckProjectService; + +/** + *

+ * 车辆验收项目 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Service +public class TbVehicleCheckProjectServiceImpl extends ServiceImpl implements ITbVehicleCheckProjectService { + + @Autowired + private ITbVehicleCheckTemplateProjectService tbVehicleCheckTemplateProjectService; + + @Override + public void getProjectsByCheckId(TbVehicleCheck check) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicleCheckProject::getCheckId, check.getId()); + queryWrapper.orderByAsc(TbVehicleCheckProject::getSort); + List list = list(queryWrapper); + check.setProjectList(list); + Set con = new LinkedHashSet<>(); + for (TbVehicleCheckProject pro : list) { + con.add(pro.getName()); + } + String projectNames = String.join(",", con); + check.setProjectNames(projectNames); + } + + @Override + public void saveItem(TbVehicleCheck check) { + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("check_id", check.getId()); + remove(queryWrapper); + /*if(!StringUtils.hasLength(check.getTemplateId())) { + return; + }*/ + /*List ids = check.getProjectList().stream().map(t->t.getTemplateProjectId()).collect(Collectors.toList()); + Map tempMap = tbVehicleCheckTemplateProjectService.getMapByIds(ids); + */ + List projects = new ArrayList<>(); + int sort = 1; + for(TbVehicleCheckProject project:check.getProjectList()) { + /*if(!StringUtils.hasLength(project.getName())&&tempMap.containsKey(project.getTemplateProjectId())) { + TbVehicleCheckTemplateProject temp = tempMap.get(project.getTemplateProjectId()); + BeanUtilsCopy.copyBeanPropFilterId(project, temp); + }*/ + project.setSort(sort); + project.setCheckId(check.getId()); + projects.add(project); + sort++; + } + saveBatch(projects); + } + +} diff --git a/src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckServiceImpl.java b/src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckServiceImpl.java new file mode 100644 index 0000000..5e36c1b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/service/impl/TbVehicleCheckServiceImpl.java @@ -0,0 +1,299 @@ +package com.gci.boot.modules.projects.service.impl; + +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionRemindService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.BeanUtilsCopy; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.Lock; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.projects.entity.TbContract; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.projects.entity.TbVehicleCheckDetail; +import com.gci.boot.modules.projects.mapper.TbVehicleCheckMapper; +import com.gci.boot.modules.projects.service.IProjectVehicleBindLogService; +import com.gci.boot.modules.projects.service.ITbContractService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckDetailService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckProjectService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckService; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.mapper.TbAccidentProgressMapper; +import com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionInfoService; + +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 车辆验收 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Slf4j +@Service +public class TbVehicleCheckServiceImpl extends ServiceImpl implements ITbVehicleCheckService { + + @Autowired + private ITbVehicleCheckProjectService tbVehicleCheckProjectService; + @Autowired + private ITbVehicleCheckDetailService tbVehicleCheckDetailService; + @Autowired + private ITbContractService tbContractService; + @Autowired + private TbAccidentProgressMapper accidentProgressMapper; + @Autowired + private TbViolationRecordMapper violationRecordMapper; + @Autowired + private ITbVehicleService vehicleService; + + @Autowired + private IProjectVehicleBindLogService projectVehicleBindLogService; + + @Autowired + private ITbAnnualInspectionInfoService annualInspectionInfoService; + + @Autowired + private ITbAnnualInspectionRemindService annualInspectionRemindService; + + @Autowired + private Lock lock; + @Autowired + private ITbGisRunningbusService gisRunningbusService; + + DecimalFormat df2 = new DecimalFormat("#.00"); + + @Transactional + @Override + public String saveItem(TbVehicleCheck item) { + tbVehicleCheckDetailService.checkVehicle(item); + if("3".equals(item.getCheckType())) { + TbVehicleCheck parent = getById(item.getParentId()); + if(!StringUtils.hasLength(item.getParentId())||parent==null) { + throw new GciBootException("租赁交车不能为空!"); + } + item.setProjectId(parent.getProjectId()); + item.setContractId(parent.getContractId()); + item.setVehicleType(parent.getVehicleType()); + item.setTemplateId(parent.getTemplateId()); + item.setRegistrationTime(parent.getRegistrationTime()); + } + if("2".equals(item.getCheckType())&&"1".equals(item.getStatus())) { + item.setReceiveStatus("0.5"); + } + saveOrUpdate(item); + if("1".equals(item.getCheckType())&&"1".equals(item.getStatus())&&item.getVehicleList()!=null&&item.getVehicleList().size()!=0) { + createVehicle(item); + createAnnualInspectionInfo(item); + } + if(!"3".equals(item.getCheckType())) { + tbVehicleCheckDetailService.saveItem(item); + tbVehicleCheckProjectService.saveItem(item); + tbContractService.updateStatus(item.getContractId()); + }else { + String error = updateStatus(item.getParentId()); + return error; + } + return ""; + } + + //获取租赁收车 + @Override + public void getChildren(TbVehicleCheck parent) { + if("2".equals(parent.getCheckType())) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicleCheck::getParentId,parent.getId()); + List list = list(queryWrapper); + if(list.size()>0) { + parent.setChildren(list.get(0)); + } + } + } + + //获取未处理违章数、未处理事故数 + @Override + public void initItem(List list) { + if(list.size()<1) { + return; + } + List accident = accidentProgressMapper.getCheckAccidentInfoCount(); + Map accidentMap = new HashMap<>(); + for (TbVehicleCheck vo : accident) { + accidentMap.put(vo.getId()+vo.getProjectId(), vo); + } + + List violation = violationRecordMapper.getCheckViolationCount(); + Map violationMap = new HashMap<>(); + for (TbVehicleCheck vo : violation) { + violationMap.put(vo.getId()+vo.getProjectId(), vo); + } + + for(TbVehicleCheck item:list) { + String key = item.getId()+item.getProjectId(); + if(accidentMap.containsKey(key)) { + item.setAccidentInfoCount(accidentMap.get(key).getAccidentInfoCount()); + } + if(violationMap.containsKey(key)) { + item.setViolationCount(violationMap.get(key).getViolationCount()); + } + } + } + + //租赁交车状态更新 + public String updateStatus(String id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicleCheck::getReceiveStatus, "0.5"); + queryWrapper.eq(TbVehicleCheck::getStatus, "1"); + queryWrapper.eq(TbVehicleCheck::getCheckType, "2"); + queryWrapper.eq(StringUtils.hasLength(id),TbVehicleCheck::getId, id); + List list = list(queryWrapper); + initItem(list); + String error = ""; + for (TbVehicleCheck item : list) { + getChildren(item); + if(item.getChildren()==null||"0".equals(item.getChildren().getStatus())) { + continue; + } + if(item.getAccidentInfoCount()==0&&item.getViolationCount()==0) { + item.setReceiveStatus("1"); + updateById(item); + }else { + error = "当前车辆有违章或事故未处理,请及时处理!"; + } + } + return error; + } + + + @Scheduled(cron = "0 */10 * * * ?") + public void statusTask() { + log.info("---------租赁交车状态更新----------"); + String key = CommonConstant.CHECK_STATUS_TASK_LOCK; + String value = lock.getUniqueNum(); + int n = 0 ; + try { + n = lock.getLock(key, value); + if(n > 0){ + updateStatus(null); + } + }catch (Exception ex){ + log.error("租赁交车状态更新出错, {}", ex); + }finally { + //释放锁 + if(n > 0){ + lock.delLock(key, value); + } + } + } + + //生成车辆档案 + public List createVehicle(TbVehicleCheck item) { + List vlist = vehicleService.list(); + Set frameNumberSet = vlist.stream().map(t->t.getFrameNumber()).collect(Collectors.toSet()); + Set plateNumberSet = vlist.stream().map(t->t.getPlateNumber()).collect(Collectors.toSet()); + List ves = new ArrayList<>(); + TbContract contract = tbContractService.getById(item.getContractId()); + String name = ""; + if(contract!=null) { + name = contract.getSigningId(); + } + Map pmap = tbContractService.getCarPrice(item.getContractId()); + //TODO 验证车牌,车架等 + for (TbVehicleCheckDetail vd : item.getVehicleList()) { + if(frameNumberSet.contains(vd.getFrameNumber())) { + continue; + } + if(plateNumberSet.contains(vd.getPlateNumber())) { + continue; + } + TbVehicle tbVehicle = new TbVehicle(); + BeanUtilsCopy.copyBeanProp(tbVehicle, vd); + tbVehicle.setProjectId(item.getProjectId()); + if(StrUtil.isBlank(tbVehicle.getProjectId())){ + tbVehicle.setProjectId(CommonConstant.INNER_PROJECT); + }else { + projectVehicleBindLogService.addLog(tbVehicle.getProjectId(), null,tbVehicle.getPlateNumber(),1,1,item.getCreateBy()); + } + tbVehicle.setVinCode(tbVehicle.getFrameNumber()); + tbVehicle.setSourceType("2"); + tbVehicle.setDealer(name); + tbVehicle.setDeliveryTime(new Date()); + if(pmap.containsKey(tbVehicle.getVehicleModel())) { + tbVehicle.setPrice(pmap.get(tbVehicle.getVehicleModel())); + } + vehicleService.save(tbVehicle); + + vd.setVehicleId(tbVehicle.getId()); + ves.add(tbVehicle); + //更新runningBus项目id + CompletableFuture.runAsync(() -> { + gisRunningbusService.update(new LambdaUpdateWrapper().eq(TbGisRunningbus::getPlateNumber,tbVehicle.getPlateNumber()) + .set(TbGisRunningbus::getProjectId,tbVehicle.getProjectId())); + }); + } + return ves; + } + + //生成年检信息 + public void createAnnualInspectionInfo(TbVehicleCheck item) { + if(item.getRegistrationTime()==null) { + return; + } + List vlist = annualInspectionInfoService.list(); + Set plateNumberSet = vlist.stream().map(t->t.getPlateNumber()).collect(Collectors.toSet()); + List alist = new ArrayList<>(); + Date today = item.getRegistrationTime(); + Date nextYear = DateUtils.addYear(today, 1); + for (TbVehicleCheckDetail vd : item.getVehicleList()) { + if(plateNumberSet.contains(vd.getPlateNumber())) { + continue; + } + TbAnnualInspectionInfo info = new TbAnnualInspectionInfo(); + BeanUtilsCopy.copyBeanProp(info, vd); + if(StrUtil.isBlank(info.getProjectId())){ + info.setProjectId(CommonConstant.INNER_PROJECT); + } + info.setHandlingDate(today); + info.setValidityPeriod(nextYear); + info.setProcessedPerson(item.getCreateBy()); + if(!StringUtils.hasLength(info.getProcessedPerson())){ + info.setProcessedPerson(""); + } + info.setMiscellaneousFee(BigDecimal.ZERO); + info.setServiceFee(BigDecimal.ZERO); + info.setTestingFee(BigDecimal.ZERO); + info.setTotalFee(BigDecimal.ZERO); + info.setSourceType("2"); + alist.add(info); + } + annualInspectionInfoService.saveBatch(alist); + annualInspectionRemindService.init(); + } + + +} diff --git a/src/main/java/com/gci/boot/modules/projects/vo/TbVehicleCheckVo.java b/src/main/java/com/gci/boot/modules/projects/vo/TbVehicleCheckVo.java new file mode 100644 index 0000000..5de6d60 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/vo/TbVehicleCheckVo.java @@ -0,0 +1,217 @@ +package com.gci.boot.modules.projects.vo; + +import java.io.Serializable; +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 车辆验收 + *

+ * + * @author xushuhan + * @since 2023-09-11 + */ +@Getter +@Setter +@TableName("tb_vehicle_check") +@ApiModel(value = "TbVehicleCheck对象", description = "车辆验收") +@ColumnWidth(20) +public class TbVehicleCheckVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属项目") + @ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectId; + + @ApiModelProperty("所属合同") + @ExcelProperty(value = "所属合同", converter = DictConverter.class, index = 1) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_contract", dicText = "name", dicCode = "id") + private String contractId; + + @ApiModelProperty("车辆种类") + @ExcelProperty(value = "车辆种类", converter = DictConverter.class, index = 6) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("模板") + @ExcelProperty(value = "模板名称", converter = DictConverter.class, index = 2) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_vehicle_check_template", dicText = "name", dicCode = "id") + private String templateId; + + @ApiModelProperty("交车人") + //@ExcelProperty(value = "交车人", index = 11) + @ExcelIgnore + private String sentVehicleUser; + + @ApiModelProperty("验收人id") + @ExcelIgnore + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + private String checkUserId; + + @ApiModelProperty("验收人") + @ExcelProperty(value = "验收人", index = 12) + private String checkUserName; + + @ApiModelProperty("接收人id") + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + @ExcelIgnore + private String acceptUserId; + + @ApiModelProperty("接收人") + @ExcelIgnore + private String acceptUserName; + + @ApiModelProperty("验收时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat("yyyy-MM-dd HH:mm") + @ExcelProperty(value = "验收日期", index = 10) + private Date checkTime; + + @ApiModelProperty("验收地址") + @ExcelIgnore + private String checkAddress; + + @ApiModelProperty("验收结果") + @Dict(dicCode = "check_status") + @ExcelProperty(value = "验收结果", converter = DictConverter.class, index = 9) + private String checkStatus; + + @ApiModelProperty("验收结论") + @ExcelIgnore + private String remark; + + @ApiModelProperty("验收单") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String ckeckUrl; + + @ApiModelProperty("保函") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String ensureUrl; + + @ApiModelProperty("其他") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String otherUrl; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ApiModelProperty("删除标志") + @ExcelIgnore + private Integer delFlag; + + @ApiModelProperty("验收类型") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelIgnore + private String checkType; + + @ApiModelProperty("交车人id") + @ExcelProperty(value = "交车人", converter = DictConverter.class, index = 11) + @Dict(dictTable = "sys_user", dicText = "realname", dicCode = "id") + private String sentVehicleUserId; + + + @ApiModelProperty("来源(1后台,2小程序)") + @ExcelIgnore + private String sourceType; + + @ApiModelProperty("租赁交车id") + @ExcelIgnore + private String parentId; + + @ApiModelProperty("状态(0待提交,1已提交)") + @ExcelIgnore + @Dict(dicCode = "edit_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String status; + + @ApiModelProperty("收车状态(0未收车,1已收车)") + @Dict(dicCode = "receive_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "状态监控", converter = DictConverter.class, index = 4) + private String receiveStatus; + + //验收项目 + @TableField(exist = false) + @ExcelIgnore + private String projectNames; + + //车辆信息 + @TableField(exist = false) + @ExcelProperty(value = "车辆信息", index = 3) + private String plateNumbers; + + + //未处理违章数 + @TableField(exist = false) + @ExcelProperty(value = "未处理违章数", index = 7) + private Integer violationCount = 0; + + //未处理事故数 + @TableField(exist = false) + @ExcelProperty(value = "未处理事故数", index = 8) + private Integer accidentInfoCount = 0; + + //车辆数 + @TableField(exist = false) + @ExcelProperty(value = "车辆数量", index = 5) + private Integer vehicleCount = 0; +} diff --git a/src/main/java/com/gci/boot/modules/projects/vo/VehicleTypeVO.java b/src/main/java/com/gci/boot/modules/projects/vo/VehicleTypeVO.java new file mode 100644 index 0000000..9c0fefb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/projects/vo/VehicleTypeVO.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.projects.vo; + +import lombok.Data; + +@Data +public class VehicleTypeVO { + + private Integer count; + + private String vehicleType; + + private String itemText; +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/AccidentInfoStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/AccidentInfoStatisController.java new file mode 100644 index 0000000..b2963aa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/AccidentInfoStatisController.java @@ -0,0 +1,103 @@ +package com.gci.boot.modules.statis.controller; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.AccidentInfoStatisService; +import com.gci.boot.modules.statis.service.AnnualInspectionInfoStatisService; +import com.gci.boot.modules.statis.vo.AccidentInfoStatisVo; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +@Api(tags="事故统计") +@Slf4j +@RestController +@RequestMapping("/statis/accidentInfo") +public class AccidentInfoStatisController { + + @Autowired + private AccidentInfoStatisService accidentInfoStatisService; + @Autowired + private ISysDictService sysDictService; + + @AddSysLog(value = "事故统计-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="tai.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper.findStatisAccidentInfoByDayMonthYear"}) + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page<>(pageNo, pageSize); + IPage pageList = accidentInfoStatisService.page(page,vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog(value = "事故统计-导出") + @GetMapping("/export") + @DataPermission(item="tai.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper.findStatisAccidentInfoAll"}) + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "事故统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List> datas = accidentInfoStatisService.getAll(vo); + EasyExcel.write(output) + .head(head()) + .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) + .sheet("事故统计") + .doWrite(datas); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + + private List> head() { + List> headList = new ArrayList<>(); + //固定列 + headList.add(Collections.singletonList("所属项目")); + headList.add(Collections.singletonList("统计期间")); + headList.add(Collections.singletonList("车辆种类")); + headList.add(Collections.singletonList("事故次数")); + //动态列 + List modelList = sysDictService.queryDictItemsByCode("accident_form"); + for (DictModel dictModel : modelList) { + headList.add(Collections.singletonList(dictModel.getText())); + } + return headList; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/AnnualInspectionInfoStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/AnnualInspectionInfoStatisController.java new file mode 100644 index 0000000..37d3994 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/AnnualInspectionInfoStatisController.java @@ -0,0 +1,79 @@ +package com.gci.boot.modules.statis.controller; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.AnnualInspectionInfoStatisService; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; + +@Api(tags="年检统计") +@Slf4j +@RestController +@RequestMapping("/statis/annualInspectionInfo") +public class AnnualInspectionInfoStatisController { + + @Autowired + private AnnualInspectionInfoStatisService annualInspectionInfoStatisService; + + @AddSysLog(value = "年检统计-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.findStatisAnnualInspectionInfoByDayMonthYear"}) + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page<>(pageNo, pageSize); + IPage pageList = annualInspectionInfoStatisService.page(page,vo); + return Result.ok(pageList); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "年检统计-导出") + @GetMapping("/export") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.findStatisAnnualInspectionInfoAll"}) + public Result export(StatisParamVO vo,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "年检统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + List list = annualInspectionInfoStatisService.getAll(vo); + // 根据用户传入字段 假设我们要忽略 date + Set excludeColumnFiledNames = new HashSet(); + excludeColumnFiledNames.add("plateNumber"); + EasyExcel.write(output, AnnualInspectionInfoStatisVo.class).excludeColumnFieldNames(excludeColumnFiledNames).sheet("年检统计").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/BusinessController.java b/src/main/java/com/gci/boot/modules/statis/controller/BusinessController.java new file mode 100644 index 0000000..a77fd0a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/BusinessController.java @@ -0,0 +1,102 @@ +package com.gci.boot.modules.statis.controller; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.statis.service.BusinessService; +import com.gci.boot.modules.statis.vo.BusinessStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * 业务板块成本 + * @author 24642 + */ +@Api(tags="项目成本统计") +@Slf4j +@RestController +@RequestMapping("/statis/business") +public class BusinessController { + + @Autowired + private BusinessService businessService; + @Autowired + private IProjectsService projectsService; + + @AddSysLog(value = "业务板块成本-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getAllProjectsAuth"}) + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page<>(pageNo, pageSize); + IPage pageList = businessService.page(page,vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog(value = "业务板块成本-导出") + @GetMapping("/export") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getAllProjectsAuth"}) + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "业务板块成本.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List> datas = businessService.getAll(vo); + EasyExcel.write(output) + .head(head()) + .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) + .sheet("事故统计") + .doWrite(datas); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + private List> head() { + List> headList = new ArrayList<>(); + //固定列 + headList.add(Collections.singletonList("业务")); + headList.add(Collections.singletonList("统计期间")); + //动态列 + List list = projectsService.list(new LambdaQueryWrapper().orderByAsc(Projects::getCreateTime)); + for (Projects projects : list) { + headList.add(Collections.singletonList(projects.getProjectName())); + } + return headList; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/ProjectStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/ProjectStatisController.java new file mode 100644 index 0000000..a187df1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/ProjectStatisController.java @@ -0,0 +1,73 @@ +package com.gci.boot.modules.statis.controller; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.ProjectStatisService; +import com.gci.boot.modules.statis.vo.ProjectStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; + +@Api(tags="项目成本统计") +@Slf4j +@RestController +@RequestMapping("/statis/project") +public class ProjectStatisController { + + @Autowired + private ProjectStatisService projectStatisService; + + @AddSysLog(value = "项目成本统计-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page<>(pageNo, pageSize); + IPage pageList = projectStatisService.page(page,vo); + return Result.ok(pageList); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "项目成本统计-导出") + @GetMapping("/export") + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "项目成本统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + List list = projectStatisService.getAll(vo); + EasyExcel.write(output, ProjectStatisVo.class).sheet("项目成本统计").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/RepairStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/RepairStatisController.java new file mode 100644 index 0000000..e0c2a9c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/RepairStatisController.java @@ -0,0 +1,133 @@ +package com.gci.boot.modules.statis.controller; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.RepairStatisService; +import com.gci.boot.modules.statis.vo.RepairBoardVO; +import com.gci.boot.modules.statis.vo.RepairStatisVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; + +@Api(tags="维修统计") +@Slf4j +@RestController +@RequestMapping("/statis/repair") +public class RepairStatisController { + + @Autowired + private RepairStatisService repairStatisService; + @Autowired + private ISysDictService sysDictService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "维修统计-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="tri.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper.findStatisRepairByDayMonthYear"}) + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = repairStatisService.getRepairStatisPage(page, vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog(value = "维修统计-导出") + @GetMapping("/export") + @DataPermission(item="tri.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper.findStatisRepairAll"}) + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "维修业务量统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List> datas = repairStatisService.getAllRepairStatis(vo); + EasyExcel.write(output) + .head(head()) + .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) + .sheet("维修业务量统计") + .doWrite(datas); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + + private List> head() { + List> headList = new ArrayList<>(); + //固定列 + headList.add(Collections.singletonList("所属项目")); + headList.add(Collections.singletonList("统计期间")); + headList.add(Collections.singletonList("车辆种类")); + headList.add(Collections.singletonList("维修车次")); + headList.add(Collections.singletonList("维修金额(元)")); + headList.add(Collections.singletonList("平均金额(车/元)")); + //动态列 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for (DictModel dictModel : modelList) { + headList.add(Collections.singletonList(dictModel.getText())); + } + return headList; + } + + /** + * 数据看板----维修情况 + * @param startTime + * @param endTime + * @return + */ + @GetMapping(value = "/getRepairInfo") + public Result getRepairInfo(String startTime, String endTime) { + Date startParam = null; + Date endParam = null; + if(StrUtil.isNotBlank(startTime)){ + startParam = DateUtil.parse(startTime); + } + if(StrUtil.isNotBlank(endTime)){ + endParam = DateUtil.parse(endTime); + } + + List getRepairInfo = repairStatisService.getRepairInfo(startParam,endParam); + return Result.ok(getRepairInfo); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/TbInsuranceStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/TbInsuranceStatisController.java new file mode 100644 index 0000000..e66b4b4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/TbInsuranceStatisController.java @@ -0,0 +1,145 @@ +package com.gci.boot.modules.statis.controller; + + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.modules.statis.service.InsuranceRecordService; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.vo.InsuranceRecordStatisVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.vo.InsuranceStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.service.ITbInsuranceService; + +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 保险报表 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Slf4j +@RestController +@RequestMapping("/statis/insurance") +public class TbInsuranceStatisController { + + @Autowired + private ITbInsuranceService tbInsuranceCheckService; + @Autowired + private InsuranceRecordService insuranceRecordService; + + + @AddSysLog(value = "保险业务量报表-分页查询") + @GetMapping("/list") + @DataPermission(item="ti.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper.findStatisInsuranceByDayMonthYear"}) + public Result list(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + Page page = new Page<>(pageNo, pageSize); + List pageList = tbInsuranceCheckService.page(page, vo); + page.setRecords(pageList); + return Result.ok(page); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "保险业务量报表-导出") + @GetMapping("/simple/export") + @DataPermission(item="ti.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper.findStatisInsuranceByDayMonthYear"}) + public Result export(StatisParamVO item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "保险报表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result> result = (Result>)list(item,1,20000); + List list = result.getResult().getRecords(); + EasyExcel.write(output, InsuranceStatisVo.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "保险统计-保险年度信息-分页列表查询") + @GetMapping(value = "/yearList") + @DataPermission(item="tir.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper.findYearStatisInsuranceRecord"}) + public Result queryPageList(InsuranceRecordStatisVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = insuranceRecordService.getInsuranceRecordStatisPageV2(page, vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog("保险统计-保险年度信息-导出") + @GetMapping("/yearExport") + @DataPermission(item="tir.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper.findYearStatisInsuranceRecord"}) + public Result yearExport(InsuranceRecordStatisVO record, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "保险年度信息报表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Page page = new Page(1, -1); + IPage pageList = insuranceRecordService.getInsuranceRecordStatisPageV2(page, record); + List list = pageList.getRecords(); + EasyExcel.write(output, InsuranceRecordStatisVO.class).sheet("保险年度信息").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/UpkeepStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/UpkeepStatisController.java new file mode 100644 index 0000000..adb160e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/UpkeepStatisController.java @@ -0,0 +1,132 @@ +package com.gci.boot.modules.statis.controller; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.RepairStatisService; +import com.gci.boot.modules.statis.service.UpkeepStatisService; +import com.gci.boot.modules.statis.vo.*; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; + +@Api(tags="保养统计") +@Slf4j +@RestController +@RequestMapping("/statis/upkeep") +public class UpkeepStatisController { + + @Autowired + private UpkeepStatisService upkeepStatisService; + @Autowired + private ISysDictService sysDictService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "保养统计-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="tub.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper.findStatisUpkeepByDayMonthYear"}) + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = upkeepStatisService.getUpkeepStatisPage(page, vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog(value = "保养统计-导出") + @GetMapping("/export") + @DataPermission(item="tub.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper.findStatisUpkeepAll"}) + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "保养业务量统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List> datas = upkeepStatisService.getAllUpkeepStatis(vo); + EasyExcel.write(output) + .head(head()) + .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) + .sheet("保养业务量统计") + .doWrite(datas); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + + private List> head() { + List> headList = new ArrayList<>(); + //固定列 + headList.add(Collections.singletonList("所属项目")); + headList.add(Collections.singletonList("统计期间")); + headList.add(Collections.singletonList("车辆种类")); + headList.add(Collections.singletonList("保养车次")); + headList.add(Collections.singletonList("保养金额(元)")); + headList.add(Collections.singletonList("平均金额(车/元)")); + //动态列 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for (DictModel dictModel : modelList) { + headList.add(Collections.singletonList(dictModel.getText())); + } + return headList; + } + + /** + * 数据看板----保养 + * @param startTime + * @param endTime + * @return + */ + @AddSysLog(value = "数据看板-保养信息") + @GetMapping(value = "/getUpkeepInfo") + public Result getUpkeepInfo(String startTime, String endTime) { + Date startParam = null; + Date endParam = null; + if(StrUtil.isNotBlank(startTime)){ + startParam = DateUtil.parse(startTime); + } + if(StrUtil.isNotBlank(endTime)){ + endParam = DateUtil.parse(endTime); + } + UpkeepBoardVO vo = upkeepStatisService.getUpkeepInfo(startParam,endParam); + return Result.ok(vo); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/VehicleAnalysisController.java b/src/main/java/com/gci/boot/modules/statis/controller/VehicleAnalysisController.java new file mode 100644 index 0000000..58e5b77 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/VehicleAnalysisController.java @@ -0,0 +1,202 @@ +package com.gci.boot.modules.statis.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.driver.entity.TbDriver; +import com.gci.boot.modules.driver.service.ITbDriverService; +import com.gci.boot.modules.statis.service.VehicleStatisService; +import com.gci.boot.modules.statis.vo.DriverAnalysisVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.VehicleAnalysisVO; +import com.gci.boot.modules.statis.vo.VehicleStatisVo; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author lyz + * @date 2023/10/24 9:24 + */ +@Api(tags="分析统计") +@Slf4j +@RestController +@RequestMapping("/analysis") +public class VehicleAnalysisController { + + @Autowired + private ITbVehicleService iTbVehicleService; + + @Autowired + private ITbDriverService iTbDriverService; + + @Autowired + private VehicleStatisService vehicleStatisService; + + @AddSysLog(value = "车辆评价-分页列表查询") + @GetMapping(value = "/vehicle/list") + @DataPermission(item="tb_vehicle.projectId", sqlIds = {"com.gci.boot.modules.basedata.mapper.TbVehicleMapper.selectPage"}) + public Result vehicleList(TbVehicle vehicle, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) throws ParseException { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getProjectId()),TbVehicle::getProjectId,vehicle.getProjectId()); + lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(vehicle.getPlateNumber()),TbVehicle::getPlateNumber, vehicle.getPlateNumber()); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getVehicleBrand()),TbVehicle::getVehicleBrand,vehicle.getVehicleBrand()); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getDealer()),TbVehicle::getDealer,vehicle.getDealer()); + lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(vehicle.getVehicleModel()),TbVehicle::getVehicleModel, vehicle.getVehicleModel()); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getVehicleType()),TbVehicle::getVehicleType, vehicle.getVehicleType()); + lambdaQueryWrapper.eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0); + lambdaQueryWrapper.between(vehicle.getDeliveryTimeStart()!=null, TbVehicle::getDeliveryTime, vehicle.getDeliveryTimeStart(), vehicle.getDeliveryTimeEnd()); + lambdaQueryWrapper.orderByAsc(TbVehicle::getProjectId); + lambdaQueryWrapper.orderByDesc(TbVehicle::getPlateNumber); + IPage pageList = iTbVehicleService.page(page, lambdaQueryWrapper); + + List vehicles = pageList.getRecords(); + List vos = vehicleStatisService.analysisVehicleByListAndTime(vehicles, DateUtils.parseDate("1976-01-01","yyyy-MM-dd"),new Date()); + IPage results = new Page<>(pageNo,pageSize); + results.setCurrent(pageList.getCurrent()); + results.setTotal(pageList.getTotal()); + results.setRecords(vos); + return Result.ok(results); + } + + @AddSysLog(value = "车辆评价-导出") + @GetMapping(value = "/vehicle/export") + @DataPermission(item="tb_vehicle.projectId", sqlIds = {"com.gci.boot.modules.basedata.mapper.TbVehicleMapper.selectList"}) + public Result vehicleExport(TbVehicle vehicle, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req,HttpServletResponse response) throws ParseException { + try (OutputStream output = response.getOutputStream()){ + String fileName = "车辆评价列表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getProjectId()),TbVehicle::getProjectId,vehicle.getProjectId()); + lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(vehicle.getPlateNumber()),TbVehicle::getPlateNumber, vehicle.getPlateNumber()); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getVehicleBrand()),TbVehicle::getVehicleBrand,vehicle.getVehicleBrand()); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getDealer()),TbVehicle::getDealer,vehicle.getDealer()); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(vehicle.getVehicleModel()),TbVehicle::getVehicleModel, vehicle.getVehicleModel()); + lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(vehicle.getVehicleType()),TbVehicle::getVehicleType, vehicle.getVehicleType()); + lambdaQueryWrapper.eq(TbVehicle::getCancelFlag, CommonConstant.DEL_FLAG_0); + lambdaQueryWrapper.between(vehicle.getDeliveryTimeStart()!=null, TbVehicle::getDeliveryTime, vehicle.getDeliveryTimeStart(), vehicle.getDeliveryTimeEnd()); + lambdaQueryWrapper.orderByAsc(TbVehicle::getProjectId); + lambdaQueryWrapper.orderByDesc(TbVehicle::getPlateNumber); + List vehicles = iTbVehicleService.list(lambdaQueryWrapper); + List vos = vehicleStatisService.analysisVehicleByListAndTime(vehicles, DateUtils.parseDate("1976-01-01","yyyy-MM-dd"),new Date()); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + ExcelExportUtil.exportExcel(exportParams,VehicleAnalysisVO.class,vos).write(output); + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + + @AddSysLog(value = "司机画像列表-分页列表查询") + @GetMapping(value = "/driver/list") + @DataPermission(item="tb_driver.projectId", sqlIds = {"com.gci.boot.modules.driver.mapper.TbDriverMapper.selectPage"}) + public Result driverList( @RequestParam(name = "projectId",required = false) String projectId, + @RequestParam(name = "name",required = false) String name, + @RequestParam(name = "startTime",required = true) String startTime, + @RequestParam(name = "endTime",required = true) String endTime, + @RequestParam(name = "entryStatus",required = false) String entryStatus, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page<>(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(projectId),TbDriver::getProjectId,projectId); + lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(name),TbDriver::getName, name); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(entryStatus),TbDriver::getEntryStatus,entryStatus); + lambdaQueryWrapper.eq(TbDriver::getDelFlag, CommonConstant.DEL_FLAG_0); + lambdaQueryWrapper.orderByAsc(TbDriver::getProjectId); + lambdaQueryWrapper.orderByDesc(TbDriver::getName); + IPage pageList = iTbDriverService.page(page, lambdaQueryWrapper); + List drivers = pageList.getRecords(); + List vos = vehicleStatisService.analysisDriverByListAndTime(drivers, startTime,endTime); + IPage results = new Page<>(pageNo,pageSize); + results.setCurrent(pageList.getCurrent()); + results.setTotal(pageList.getTotal()); + results.setRecords(vos); + return Result.ok(results); + } + + + @AddSysLog(value = "司机画像列表-导出") + @GetMapping(value = "/driver/export") + @DataPermission(item="tb_driver.projectId", sqlIds = {"com.gci.boot.modules.driver.mapper.TbDriverMapper.selectList"}) + public Result driverExport(@RequestParam(name = "projectId",required = false) String projectId, + @RequestParam(name = "name",required = false) String name, + @RequestParam(name = "startTime",required = true) String startTime, + @RequestParam(name = "endTime",required = true) String endTime, + @RequestParam(name = "entryStatus",required = false) String entryStatus, + HttpServletRequest req, HttpServletResponse response) { + try (OutputStream output = response.getOutputStream()){ + + String fileName = "司机画像列表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(projectId),TbDriver::getProjectId,projectId); + lambdaQueryWrapper.like(ObjectUtil.isNotEmpty(name),TbDriver::getName, name); + lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(entryStatus),TbDriver::getEntryStatus,entryStatus); + lambdaQueryWrapper.eq(TbDriver::getDelFlag, CommonConstant.DEL_FLAG_0); + lambdaQueryWrapper.orderByAsc(TbDriver::getProjectId); + lambdaQueryWrapper.orderByDesc(TbDriver::getName); + List drivers = iTbDriverService.list(lambdaQueryWrapper); + List vos = vehicleStatisService.analysisDriverByListAndTime(drivers, startTime,endTime); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + Workbook sheets =ExcelExportUtil.exportExcel(exportParams,DriverAnalysisVO.class,vos); + sheets.write(output); + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/VehicleRentalController.java b/src/main/java/com/gci/boot/modules/statis/controller/VehicleRentalController.java new file mode 100644 index 0000000..de9bf80 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/VehicleRentalController.java @@ -0,0 +1,78 @@ +package com.gci.boot.modules.statis.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.VehicleRentalService; +import com.gci.boot.modules.statis.vo.VehicleRentalVo; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +/** + * @author 24642 + */ +@Api(tags="车辆组件收入") +@Slf4j +@RestController +@RequestMapping("/statis/vehicleRental") +public class VehicleRentalController { + @Autowired + private VehicleRentalService vehicleRentalService; + + @GetMapping(value = "/list") + @DataPermission(item="tb_contract.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.TbContractMapper.selectList"}) + public Result queryPageList(VehicleRentalVo query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = vehicleRentalService.pageBuild(page,query); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @GetMapping("/export") + @DataPermission(item="tb_contract.projectId", sqlIds = {"com.gci.boot.modules.projects.mapper.TbContractMapper.selectList"}) + public Result export(VehicleRentalVo query, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "车辆租金收入.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + IPage pageList = vehicleRentalService.pageBuild(page,query); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + Workbook sheets = ExcelExportUtil.exportExcel(exportParams, VehicleRentalVo.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/VehicleStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/VehicleStatisController.java new file mode 100644 index 0000000..bdaf872 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/VehicleStatisController.java @@ -0,0 +1,74 @@ +package com.gci.boot.modules.statis.controller; + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.VehicleStatisService; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.VehicleStatisVo; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; + +@Api(tags="单车成本统计") +@Slf4j +@RestController +@RequestMapping("/statis/vehicle") +public class VehicleStatisController { + + @Autowired + private VehicleStatisService vehicleStatisService; + + @AddSysLog(value = "单车成本统计-列表查询") + @GetMapping(value = "/list") + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page<>(pageNo, pageSize); + IPage pageList = vehicleStatisService.page(page,vo); + return Result.ok(pageList); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "单车成本统计-导出") + @GetMapping("/export") + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "单车成本统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + List list = vehicleStatisService.getAll(vo); + EasyExcel.write(output, VehicleStatisVo.class).sheet("单车成本统计").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/ViolationStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/ViolationStatisController.java new file mode 100644 index 0000000..12638bf --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/ViolationStatisController.java @@ -0,0 +1,113 @@ +package com.gci.boot.modules.statis.controller; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.service.UpkeepStatisService; +import com.gci.boot.modules.statis.service.ViolationStatisService; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.UpkeepStatisVO; +import com.gci.boot.modules.statis.vo.ViolationRecordStatisVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +@Api(tags="违章统计") +@Slf4j +@RestController +@RequestMapping("/statis/violation") +public class ViolationStatisController { + + @Autowired + private ViolationStatisService violationStatisService; + @Autowired + private ISysDictService sysDictService; + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "违章统计-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="s.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.findStatisViolationByDayMonthYear"}) + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = violationStatisService.getViolationStatisPage(page, vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog(value = "违章统计-导出") + @GetMapping("/export") + @DataPermission(item="s.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.findStatisViolationAll"}) + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "违章业务量统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List> datas = violationStatisService.getAllViolationStatis(vo); + EasyExcel.write(output) + .head(head()) + .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) + .sheet("违章业务量统计") + .doWrite(datas); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + + private List> head() { + List> headList = new ArrayList<>(); + //固定列 + headList.add(Collections.singletonList("所属项目")); + headList.add(Collections.singletonList("统计期间")); + headList.add(Collections.singletonList("车辆种类")); + headList.add(Collections.singletonList("违章车次")); + headList.add(Collections.singletonList("违章金额(元)")); + headList.add(Collections.singletonList("平均金额(车/元)")); + //动态列 + List modelList = sysDictService.queryDictItemsByCode("violation_behavior"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for (DictModel dictModel : modelList) { + headList.add(Collections.singletonList(dictModel.getText())); + } + return headList; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/controller/WeighbridgeStatisController.java b/src/main/java/com/gci/boot/modules/statis/controller/WeighbridgeStatisController.java new file mode 100644 index 0000000..ee94e83 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/controller/WeighbridgeStatisController.java @@ -0,0 +1,79 @@ +package com.gci.boot.modules.statis.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.basedata.entity.TbCustomerFollowTemplate; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.WeighbridgeStatisVo; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +@Api(tags="地磅数据统计") +@Slf4j +@RestController +@RequestMapping("/statis/weighbridge") +public class WeighbridgeStatisController { + + + /** + * 单纯写死的数据 + * @param vo + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @GetMapping(value = "/list") + public Result queryPageList(StatisParamVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + page.setRecords(new ArrayList()); + return Result.ok(page); + } + /** + * 导出 + * @return + */ + @GetMapping("/export") + public Result export(StatisParamVO vo, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "地磅数据统计.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List weighbridgeStatisVos = new ArrayList<>(); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + Workbook sheets = ExcelExportUtil.exportExcel(exportParams, WeighbridgeStatisVo.class, weighbridgeStatisVos); + sheets.write(output); + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/AccidentInfoStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/AccidentInfoStatisService.java new file mode 100644 index 0000000..f563151 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/AccidentInfoStatisService.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.AccidentInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; + +import java.util.List; + +public interface AccidentInfoStatisService { + IPage page(Page page, StatisParamVO vo); + + List> getAll(StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/AnnualInspectionInfoStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/AnnualInspectionInfoStatisService.java new file mode 100644 index 0000000..fa09008 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/AnnualInspectionInfoStatisService.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; + +import java.util.List; + +public interface AnnualInspectionInfoStatisService { + IPage page(Page page, StatisParamVO vo); + + List getAll(StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/BusinessService.java b/src/main/java/com/gci/boot/modules/statis/service/BusinessService.java new file mode 100644 index 0000000..4bd57d8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/BusinessService.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.BusinessStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; + +import java.util.List; + +public interface BusinessService { + IPage page(Page page, StatisParamVO vo); + + List> getAll(StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/InsuranceRecordService.java b/src/main/java/com/gci/boot/modules/statis/service/InsuranceRecordService.java new file mode 100644 index 0000000..2c3e037 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/InsuranceRecordService.java @@ -0,0 +1,12 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.vo.InsuranceRecordStatisVO; + +public interface InsuranceRecordService { + + Page getInsuranceRecordStatisPage(Page page, InsuranceRecordStatisVO vo); + + Page getInsuranceRecordStatisPageV2(Page page, InsuranceRecordStatisVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/ProjectStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/ProjectStatisService.java new file mode 100644 index 0000000..6bfc6a4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/ProjectStatisService.java @@ -0,0 +1,15 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.ProjectStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.VehicleStatisVo; + +import java.util.List; + +public interface ProjectStatisService { + IPage page(Page page, StatisParamVO vo); + + List getAll(StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/RepairStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/RepairStatisService.java new file mode 100644 index 0000000..a04ab72 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/RepairStatisService.java @@ -0,0 +1,32 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.RepairBoardVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; + +import java.util.Date; +import java.util.List; + +public interface RepairStatisService { + + /** + * 分页列表查询 + * @param page + * @param vo + * @return + */ + Page getRepairStatisPage(Page page, StatisParamVO vo); + + + /** + * 全部列表查询 + * @param vo + * @return + */ + List> getAllRepairStatis(StatisParamVO vo); + + /** + * 数据看板----维修情况 + */ + List getRepairInfo(Date startTime, Date endTime); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/UpkeepStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/UpkeepStatisService.java new file mode 100644 index 0000000..ecc6c5e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/UpkeepStatisService.java @@ -0,0 +1,33 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.RepairBoardVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.UpkeepBoardVO; + +import java.util.Date; +import java.util.List; + +public interface UpkeepStatisService { + + /** + * 分页列表查询 + * @param page + * @param vo + * @return + */ + Page getUpkeepStatisPage(Page page, StatisParamVO vo); + + + /** + * 全部列表查询 + * @param vo + * @return + */ + List> getAllUpkeepStatis(StatisParamVO vo); + + /** + * 数据看板----保养 + */ + UpkeepBoardVO getUpkeepInfo(Date startTime, Date endTime); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/VehicleRentalService.java b/src/main/java/com/gci/boot/modules/statis/service/VehicleRentalService.java new file mode 100644 index 0000000..ff83cbe --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/VehicleRentalService.java @@ -0,0 +1,9 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.VehicleRentalVo; + +public interface VehicleRentalService { + IPage pageBuild(Page page, VehicleRentalVo query); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/VehicleStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/VehicleStatisService.java new file mode 100644 index 0000000..e18d1eb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/VehicleStatisService.java @@ -0,0 +1,24 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.driver.entity.TbDriver; +import com.gci.boot.modules.statis.vo.DriverAnalysisVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.VehicleAnalysisVO; +import com.gci.boot.modules.statis.vo.VehicleStatisVo; + +import java.text.ParseException; +import java.util.Date; +import java.util.List; + +public interface VehicleStatisService { + IPage page(Page page, StatisParamVO vo); + + List getAll(StatisParamVO vo); + + List analysisVehicleByListAndTime(List vehicles,Date startTime,Date endTime); + + List analysisDriverByListAndTime(List vehicles, String startTime, String endTime); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/ViolationStatisService.java b/src/main/java/com/gci/boot/modules/statis/service/ViolationStatisService.java new file mode 100644 index 0000000..ff68b59 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/ViolationStatisService.java @@ -0,0 +1,25 @@ +package com.gci.boot.modules.statis.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.StatisParamVO; + +import java.util.List; + +public interface ViolationStatisService { + + /** + * 分页列表查询 + * @param page + * @param vo + * @return + */ + Page getViolationStatisPage(Page page, StatisParamVO vo); + + + /** + * 全部列表查询 + * @param vo + * @return + */ + List> getAllViolationStatis(StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/AccidentInfoStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/AccidentInfoStatisServiceImpl.java new file mode 100644 index 0000000..0aabc76 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/AccidentInfoStatisServiceImpl.java @@ -0,0 +1,101 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.service.AccidentInfoStatisService; +import com.gci.boot.modules.statis.vo.AccidentInfoStatisVo; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.ColumnItemVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class AccidentInfoStatisServiceImpl implements AccidentInfoStatisService { + + @Autowired + private TbAccidentInfoMapper accidentInfoMapper; + @Autowired + private ISysDictService sysDictService; + + @Override + public IPage page(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + IPage list = accidentInfoMapper.findStatisAccidentInfoByDayMonthYear(page,vo); + if (!list.getRecords().isEmpty()) { + List accidentForm = sysDictService.queryDictItemsByCode("accident_form"); + for (AccidentInfoStatisVo record : list.getRecords()) { + List columnItemVOS = new ArrayList<>(); + List tbAccidentInfos = accidentInfoMapper.selectBatchIds(StrUtil.split(record.getIds(),",")); + for (DictModel dictModel : accidentForm) { + ColumnItemVO columnItemVO = new ColumnItemVO(); + columnItemVO.setColName(dictModel.getText()); + long count = tbAccidentInfos.stream().filter(item -> dictModel.getValue().equals(item.getAccidentForm())).count(); + columnItemVO.setCount(Convert.toInt(count)); + columnItemVOS.add(columnItemVO); + } + record.setColList(columnItemVOS); + } + } + return list; + } + + @Override + public List> getAll(StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List> datas = new ArrayList<>(); + List list = accidentInfoMapper.findStatisAccidentInfoAll(vo); + + //车辆种类字典 + List vehicleTypeList = sysDictService.queryDictItemsByCode("vehicle_type"); + Map vehicleTypeMap = vehicleTypeList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + List accidentForm = sysDictService.queryDictItemsByCode("accident_form"); + for (AccidentInfoStatisVo record : list) { + List data = new ArrayList<>(); + data.add(record.getProjectName()); + data.add(record.getStatisTime()); + data.add(vehicleTypeMap.getOrDefault(record.getVehicleType(),record.getVehicleType()+"无匹配字典")); + data.add(record.getAccidentTimes()); + + List tbAccidentInfos = accidentInfoMapper.selectBatchIds(StrUtil.split(record.getIds(),",")); + for (DictModel dictModel : accidentForm) { + long count = tbAccidentInfos.stream().filter(item -> dictModel.getValue().equals(item.getAccidentForm())).count(); + data.add(count); + } + datas.add(data); + } + return datas; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/AnnualInspectionInfoStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/AnnualInspectionInfoStatisServiceImpl.java new file mode 100644 index 0000000..a11e7c2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/AnnualInspectionInfoStatisServiceImpl.java @@ -0,0 +1,141 @@ +package com.gci.boot.modules.statis.service.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.projects.entity.ProjectVehicleBindLog; +import com.gci.boot.modules.projects.service.IProjectVehicleBindLogService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.statis.service.AnnualInspectionInfoStatisService; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper; + +import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class AnnualInspectionInfoStatisServiceImpl implements AnnualInspectionInfoStatisService { + @Autowired + private TbAnnualInspectionInfoMapper annualInspectionInfoMapper; + @Autowired + private ISysDictService sysDictService; + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbVehicleService vehicleService; + @Autowired + private IProjectVehicleBindLogService bindLogService; + + @Override + public IPage page(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + IPage pageList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoByDayMonthYear(page,vo); + extracted(vo, pageList.getRecords()); + return pageList; + } + + private void extracted(StatisParamVO vo, List records) { + if (records.isEmpty()) { + return; + } + List list = vehicleService.list(); + Map>> stringMapMap = CollStreamUtil.groupBy2Key(list, TbVehicle::getProjectId, TbVehicle::getVehicleType); + List bindLogList = bindLogService.list(new LambdaQueryWrapper().isNotNull(ProjectVehicleBindLog::getProjectId)); + for (AnnualInspectionInfoStatisVo record : records) { + //年检期间车数 不是年检次数 没有做一年的限制可能会有重复的数据 + int countPeriod = 0; + //项目下种类车数 当前车辆数量 减去统计期间绑定车辆 加上统计期间解绑车辆 + int count = 0; + if (StrUtil.isNotBlank(record.getPlateNumbers())) { + countPeriod = StrUtil.split(record.getPlateNumbers(),StrUtil.COMMA).size(); + } + + List theTypeVehicleList = new ArrayList<>(); + + if (ObjectUtil.isEmpty(stringMapMap.get(record.getProjectId()))) { + count = 0; + } else { + Map> stringListMap = stringMapMap.get(record.getProjectId()); + if (ObjectUtil.isEmpty(stringListMap.get(record.getVehicleType()))) { + count = 0; + } else { + theTypeVehicleList = stringListMap.get(record.getVehicleType()); + count = theTypeVehicleList.size(); + } + } + + List collect = bindLogList.stream().filter(i -> + DateUtil.format(i.getCreateTime(), vo.getStatisTime()).equals(record.getStatisTime()) + && i.getProjectId().equals(record.getProjectId())).collect(Collectors.toList()); + for (ProjectVehicleBindLog projectVehicleBindLog : collect) { + TbVehicle vehicle = theTypeVehicleList.stream().filter(t -> t.getPlateNumber().equals(projectVehicleBindLog.getPlateNumber())).findFirst().orElse(null); + if (vehicle == null) { + continue; + } + if (projectVehicleBindLog.getBindType() == 1) { + count = count - 1; + } else if (projectVehicleBindLog.getBindType() == 2){ + count = count + 1; + } + } + + //车辆总数为0年检车数大于0 完成率为100%,车辆总数为0年检车数为0 完成率为0% + if (count <= 0 && countPeriod >0) { + record.setCompletionRate("100%"); + } else if (count <= 0) { + record.setCompletionRate("0%"); + } else { + double div = NumberUtil.div(countPeriod, count); + if (div > 1) { + div = 1; + } + record.setCompletionRate(NumberUtil.formatPercent(div,2)); + } + } + } + + @Override + public List getAll(StatisParamVO vo) { + if ("1".equals(vo.getStatisType())) { + vo.setStatisTime("YYYY-MM-DD"); + } else if ("2".equals(vo.getStatisType())) { + vo.setStatisTime("YYYY-MM"); + } else if ("3".equals(vo.getStatisType())) { + vo.setStatisTime("YYYY"); + } else { + vo.setStatisTime("YYYY-MM-DD"); + } + + List all = + annualInspectionInfoMapper.findStatisAnnualInspectionInfoAll(vo, new ArrayList<>()); + extracted(vo, all); + return all; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/BusinessServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/BusinessServiceImpl.java new file mode 100644 index 0000000..2eaf4f6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/BusinessServiceImpl.java @@ -0,0 +1,239 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.collection.CollStreamUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Segment; +import cn.hutool.core.util.PageUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.statis.service.BusinessService; +import com.gci.boot.modules.statis.vo.*; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class BusinessServiceImpl implements BusinessService { + + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private TbInsuranceMapper insuranceMapper; + @Autowired + private TbUpkeepBillMapper upkeepBillMapper; + @Autowired + private TbAnnualInspectionInfoMapper annualInspectionInfoMapper; + @Autowired + private IProjectsService projectsService; + @Autowired + private ISysDictService sysDictService; + + @Override + public IPage page(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List repairList = new ArrayList<>(); + List insuranceList = new ArrayList<>(); + List upkeepList = new ArrayList<>(); + List annualInspectionInfoList = new ArrayList<>(); + + String businessType = vo.getBusinessType(); + if (StrUtil.isBlank(businessType)) { + repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo); + insuranceList = insuranceMapper.findStatisInsuranceByProject(vo); + upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo); + annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo); + } else if ("1".equals(businessType)) { + repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo); + } else if ("2".equals(businessType)) { + insuranceList = insuranceMapper.findStatisInsuranceByProject(vo); + } else if ("3".equals(businessType)) { + upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo); + } else if ("4".equals(businessType)) { + annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo); + } + +// List projects = projectsService.list(new LambdaQueryWrapper().orderByAsc(Projects::getCreateTime)); + List projects = projectsService.getAllProjectsAuth(); + ArrayList businessStatisVos = getBusinessStatisVos(projects,repairList, insuranceList, upkeepList, annualInspectionInfoList); + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(businessStatisVos.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(businessStatisVos.size()); + page.setPages(totalPage); + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > businessStatisVos.size()) { + endIndex = businessStatisVos.size(); + } + page.setRecords(businessStatisVos.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } + + @Override + public List> getAll(StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List> datas = new ArrayList<>(); + + List repairList = new ArrayList<>(); + List insuranceList = new ArrayList<>(); + List upkeepList = new ArrayList<>(); + List annualInspectionInfoList = new ArrayList<>(); + + String businessType = vo.getBusinessType(); + if (StrUtil.isBlank(businessType)) { + repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo); + insuranceList = insuranceMapper.findStatisInsuranceByProject(vo); + upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo); + annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo); + } else if ("1".equals(businessType)) { + repairList = repairInfoMapper.findStatisRepairAllGroupByProject(vo); + } else if ("2".equals(businessType)) { + insuranceList = insuranceMapper.findStatisInsuranceByProject(vo); + } else if ("3".equals(businessType)) { + upkeepList = upkeepBillMapper.findStatisUpkeepAllGroupByProject(vo); + } else if ("4".equals(businessType)) { + annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAllGroupByProject(vo); + } + +// List projects = projectsService.list(new LambdaQueryWrapper().orderByAsc(Projects::getCreateTime)); + List projects = projectsService.getAllProjectsAuth(); + ArrayList businessStatisVos = getBusinessStatisVos(projects,repairList, insuranceList, upkeepList, annualInspectionInfoList); + + List dictModels = sysDictService.queryDictItemsByCode("business_type"); + Map collect = dictModels.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + for (BusinessStatisVo businessStatisVo : businessStatisVos) { + List data = new ArrayList<>(); + data.add(collect.getOrDefault(businessStatisVo.getBusinessType(),businessStatisVo.getBusinessType()+"无匹配字典")); + data.add(businessStatisVo.getStatisTime()); + for (ColumnItemVo2 columnItemVo2 : businessStatisVo.getColList()) { + data.add(columnItemVo2.getCount()); + } + datas.add(data); + } + + return datas; + } + + private ArrayList getBusinessStatisVos(List projects, List repairList, List insuranceList, List upkeepList, List annualInspectionInfoList) { + + Map map = new HashMap<>(); + Map> repairListMap = CollStreamUtil.groupByKey(repairList, RepairStatisVO::getStatisTime); + for (Map.Entry> repairListMapEntry : repairListMap.entrySet()) { + String key = repairListMapEntry.getKey(); + List value = repairListMapEntry.getValue(); + BusinessStatisVo businessStatisVo = new BusinessStatisVo(); + //维修 + businessStatisVo.setBusinessType("1"); + businessStatisVo.setStatisTime(repairListMapEntry.getKey()); + ArrayList columnItemVo2s = new ArrayList<>(); + Map collect = value.stream().collect(Collectors.toMap(RepairStatisVO::getProjectId, RepairStatisVO::getRepairAmount)); + for (Projects project : projects) { + ColumnItemVo2 columnItemVo = new ColumnItemVo2(); + columnItemVo.setColName(project.getProjectName()); + columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0)); + columnItemVo2s.add(columnItemVo); + } + businessStatisVo.setColList(columnItemVo2s); + map.put(key + "1",businessStatisVo); + } + + Map> insuranceListMap = CollStreamUtil.groupByKey(insuranceList, InsuranceStatisVo::getStatisTime); + for (Map.Entry> insuranceListEntry : insuranceListMap.entrySet()) { + String key = insuranceListEntry.getKey(); + List value = insuranceListEntry.getValue(); + BusinessStatisVo businessStatisVo = new BusinessStatisVo(); + //保险 + businessStatisVo.setBusinessType("2"); + businessStatisVo.setStatisTime(insuranceListEntry.getKey()); + ArrayList columnItemVo2s = new ArrayList<>(); + Map collect = value.stream().collect(Collectors.toMap(InsuranceStatisVo::getProjectId, InsuranceStatisVo::getTotalPrice)); + for (Projects project : projects) { + ColumnItemVo2 columnItemVo = new ColumnItemVo2(); + columnItemVo.setColName(project.getProjectName()); + columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0)); + columnItemVo2s.add(columnItemVo); + } + businessStatisVo.setColList(columnItemVo2s); + map.put(key + "2",businessStatisVo); + } + Map> upkeepListMap = CollStreamUtil.groupByKey(upkeepList, UpkeepStatisVO::getStatisTime); + for (Map.Entry> upkeepListEntry : upkeepListMap.entrySet()) { + String key = upkeepListEntry.getKey(); + List value = upkeepListEntry.getValue(); + BusinessStatisVo businessStatisVo = new BusinessStatisVo(); + //保养 + businessStatisVo.setBusinessType("3"); + businessStatisVo.setStatisTime(upkeepListEntry.getKey()); + ArrayList columnItemVo2s = new ArrayList<>(); + Map collect = value.stream().collect(Collectors.toMap(UpkeepStatisVO::getProjectId, UpkeepStatisVO::getUpkeepAmount)); + for (Projects project : projects) { + ColumnItemVo2 columnItemVo = new ColumnItemVo2(); + columnItemVo.setColName(project.getProjectName()); + columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0)); + columnItemVo2s.add(columnItemVo); + } + businessStatisVo.setColList(columnItemVo2s); + map.put(key + "3",businessStatisVo); + } + + + Map> annualInspectionInfoListMap = CollStreamUtil.groupByKey(annualInspectionInfoList, AnnualInspectionInfoStatisVo::getStatisTime); + for (Map.Entry> annualInspectionInfoListEntry : annualInspectionInfoListMap.entrySet()) { + String key = annualInspectionInfoListEntry.getKey(); + List value = annualInspectionInfoListEntry.getValue(); + BusinessStatisVo businessStatisVo = new BusinessStatisVo(); + //维修 + businessStatisVo.setBusinessType("4"); + businessStatisVo.setStatisTime(annualInspectionInfoListEntry.getKey()); + ArrayList columnItemVo2s = new ArrayList<>(); + Map collect = value.stream().collect(Collectors.toMap(AnnualInspectionInfoStatisVo::getProjectId, AnnualInspectionInfoStatisVo::getInspectionAmount)); + for (Projects project : projects) { + ColumnItemVo2 columnItemVo = new ColumnItemVo2(); + columnItemVo.setColName(project.getProjectName()); + columnItemVo.setCount(collect.getOrDefault(project.getId(),0.0)); + columnItemVo2s.add(columnItemVo); + } + businessStatisVo.setColList(columnItemVo2s); + map.put(key + "4",businessStatisVo); + } + ArrayList businessStatisVos = new ArrayList<>(map.values()); + if (!businessStatisVos.isEmpty()) { + businessStatisVos.sort(Comparator.comparing(BusinessStatisVo::getStatisTime).thenComparing(BusinessStatisVo::getBusinessType)); + } + return businessStatisVos; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/InsuranceRecordServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/InsuranceRecordServiceImpl.java new file mode 100644 index 0000000..566f138 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/InsuranceRecordServiceImpl.java @@ -0,0 +1,98 @@ +package com.gci.boot.modules.statis.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.service.InsuranceRecordService; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper; +import com.gci.boot.modules.vehicles.vo.InsurancePriceVO; +import com.gci.boot.modules.vehicles.vo.InsuranceRecordStatisVO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.text.DecimalFormat; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class InsuranceRecordServiceImpl implements InsuranceRecordService { + + @Autowired + private TbInsuranceRecordMapper insuranceRecordMapper; + + @Override + public Page getInsuranceRecordStatisPage(Page page, InsuranceRecordStatisVO vo) { + List list = insuranceRecordMapper.findYearStatisInsuranceRecord(page, vo); + //补充 车辆年度保费、保费变化、次年保费预算 + List priceList = insuranceRecordMapper.findStatisInsurancePrice(); + Map priceMap = priceList.stream() + .collect(Collectors.toMap(price -> price.getPlateNumber() + "_" + price.getYearTime(), InsurancePriceVO::getAmount)); + for(InsuranceRecordStatisVO record : list){ + record.setAnnualPremium(priceMap.getOrDefault(record.getPlateNumber()+"_"+record.getStatisTime(),null)); + // 获取前一年 + int previousYear = Integer.parseInt(record.getStatisTime()) - 1; + if(Objects.nonNull(record.getAnnualPremium()) && Objects.nonNull(priceMap.getOrDefault(record.getPlateNumber()+"_"+previousYear,null))){ + double change = record.getAnnualPremium() - priceMap.getOrDefault(record.getPlateNumber()+"_"+previousYear,null); + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + if (change > 0) { + record.setPremiumChange("+" + decimalFormat.format(change)); + } else if (change < 0) { + record.setPremiumChange(decimalFormat.format(change)); + } else { + record.setPremiumChange("0"); + } + + } + // 获取后一年 + int nextYear = Integer.parseInt(record.getStatisTime()) + 1; + record.setNextYearPremium(priceMap.getOrDefault(record.getPlateNumber()+"_"+nextYear,null)); + } + page.setRecords(list); + return page; + } + + @Override + public Page getInsuranceRecordStatisPageV2(Page page, InsuranceRecordStatisVO vo) { + //保险基础数据 + List list = insuranceRecordMapper.findYearStatisInsuranceRecordV2(page, vo); + //出险车次 出险金额(元) 平均出险金额(元/车次) + List recordList = insuranceRecordMapper.findYearStatisInsuranceRecord(new Page(1, -1), new InsuranceRecordStatisVO()); + //补充 车辆年度保费、保费变化、次年保费预算 + List listAll = insuranceRecordMapper.findYearStatisInsuranceRecordV2(new Page(1, -1), new InsuranceRecordStatisVO()); + Map priceMap = listAll.stream() + .collect(Collectors.toMap(price -> price.getPlateNumber() + "_" + price.getStatisTime(), InsuranceRecordStatisVO::getAnnualPremium)); + for(InsuranceRecordStatisVO record : list){ + if(CollectionUtils.isNotEmpty(recordList)){ + InsuranceRecordStatisVO e = recordList.stream().filter(item -> item.getPlateNumber().equals(record.getPlateNumber()) && item.getStatisTime().equals(record.getStatisTime())) + .findFirst().orElse(null); + if(Objects.nonNull(e)){ + record.setInsuranceAmount(e.getInsuranceAmount()); + record.setInsuranceTimes(e.getInsuranceTimes()); + record.setAvgAmount(e.getAvgAmount()); + } + } + // 获取前一年 + int previousYear = Integer.parseInt(record.getStatisTime()) - 1; + if(Objects.nonNull(record.getAnnualPremium()) && Objects.nonNull(priceMap.getOrDefault(record.getPlateNumber()+"_"+previousYear,null))){ + double change = record.getAnnualPremium() - priceMap.getOrDefault(record.getPlateNumber()+"_"+previousYear,null); + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + if (change > 0) { + record.setPremiumChange("+" + decimalFormat.format(change)); + } else if (change < 0) { + record.setPremiumChange(decimalFormat.format(change)); + } else { + record.setPremiumChange("0"); + } + + } + // 获取后一年 + int nextYear = Integer.parseInt(record.getStatisTime()) + 1; + record.setNextYearPremium(priceMap.getOrDefault(record.getPlateNumber()+"_"+nextYear,null)); + } + page.setRecords(list); + return page; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/ProjectStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/ProjectStatisServiceImpl.java new file mode 100644 index 0000000..a7ff2d9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/ProjectStatisServiceImpl.java @@ -0,0 +1,169 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Segment; +import cn.hutool.core.util.PageUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.statis.service.ProjectStatisService; +import com.gci.boot.modules.statis.vo.*; +import com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Service +@Slf4j +public class ProjectStatisServiceImpl implements ProjectStatisService { + + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private TbUpkeepBillMapper upkeepBillMapper; + @Autowired + private TbInsuranceMapper insuranceMapper; + @Autowired + private TbAnnualInspectionInfoMapper annualInspectionInfoMapper; + @Autowired + private IProjectsService projectsService; + + + @Override + public IPage page(Page page, StatisParamVO vo) { + ArrayList projectStatisVos = getProjectStatisVos(vo); + + if (projectStatisVos.size() == 0) { + return page; + } + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(projectStatisVos.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(projectStatisVos.size()); + page.setPages(totalPage); + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > projectStatisVos.size()) { + endIndex = projectStatisVos.size(); + } + page.setRecords(projectStatisVos.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } + + private ArrayList getProjectStatisVos(StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + //用户关联项目 + List listProjectIds = projectsService.queryProjectListOfUser(); + + List repairList = repairInfoMapper.findStatisRepairAll(vo,listProjectIds); + List upkeepList = upkeepBillMapper.findStatisUpkeepAll(vo,listProjectIds); + List insuranceList = insuranceMapper.findStatisInsuranceAll(vo,listProjectIds); + List annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAll(vo,listProjectIds); + + Map map = getStringProjectStatisVoMap(repairList, upkeepList, insuranceList, annualInspectionInfoList); + ArrayList projectStatisVos = new ArrayList<>(map.values()); + if (!projectStatisVos.isEmpty()) { + projectStatisVos.sort(Comparator.comparing(ProjectStatisVo::getStatisTime)); + } + return projectStatisVos; + } + + @Override + public List getAll(StatisParamVO vo) { + ArrayList projectStatisVos = getProjectStatisVos(vo); + return projectStatisVos; + } + + private Map getStringProjectStatisVoMap(List repairList, List upkeepList, List insuranceList, List annualInspectionInfoList) { + //创建一个Map,用于存储项目Id,项目名称和车辆类型为键,ReportListVo为值 + Map map = new HashMap<>(); + for (RepairStatisVO to : repairList) { + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + ProjectStatisVo rl = map.get(key); + rl.setRepairAmount(rl.getRepairAmount()+to.getRepairAmount()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + ProjectStatisVo rl = new ProjectStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setRepairAmount(to.getRepairAmount()); + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (UpkeepStatisVO to : upkeepList) { + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + ProjectStatisVo rl = map.get(key); + rl.setUpkeepAmount(rl.getUpkeepAmount()+ to.getUpkeepAmount()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + ProjectStatisVo rl = new ProjectStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setUpkeepAmount(to.getUpkeepAmount()); + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (InsuranceStatisVo to : insuranceList) { + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + ProjectStatisVo rl = map.get(key); + rl.setInsuranceAmount(rl.getInsuranceAmount()+ to.getTotalPrice()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + ProjectStatisVo rl = new ProjectStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setInsuranceAmount(to.getTotalPrice()); + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (AnnualInspectionInfoStatisVo to : annualInspectionInfoList) { + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getProjectId() + "," + to.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + ProjectStatisVo rl = map.get(key); + rl.setInspectionAmount(rl.getInspectionAmount() + to.getInspectionAmount()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + ProjectStatisVo rl = new ProjectStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setInspectionAmount(to.getInspectionAmount()); + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + return map; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/RepairStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/RepairStatisServiceImpl.java new file mode 100644 index 0000000..eb95bad --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/RepairStatisServiceImpl.java @@ -0,0 +1,193 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.service.RepairStatisService; +import com.gci.boot.modules.statis.vo.ColumnItemVO; +import com.gci.boot.modules.statis.vo.RepairBoardVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.RepairStatisVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.service.ITbRepairInfoService; +import com.gci.boot.modules.vehicles.service.ITbRepairOfferService; +import com.gci.boot.modules.vehicles.vo.RepairDetailVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.security.auth.callback.LanguageCallback; +import java.text.DecimalFormat; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class RepairStatisServiceImpl implements RepairStatisService { + + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private ISysDictService sysDictService; + @Autowired + private ITbRepairInfoService repairInfoService; + @Autowired + private ITbRepairOfferService repairOfferService; + + @Override + public Page getRepairStatisPage(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List list = new ArrayList<>(); + list = repairInfoMapper.findStatisRepairByDayMonthYear(page,vo); + + //补充动态列---报修分类 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for(RepairStatisVO repairStatisVO : list){ + //todo 维修报价的分类 + List repairIds = Arrays.asList(repairStatisVO.getRepairIds().split(",")); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbRepairOffer::getRepairId,repairIds); + List offerList = repairOfferService.list(queryWrapper); + //处理数据维修细项 + List repairDetailList = new ArrayList<>(); + for(TbRepairOffer offer : offerList){ + if(StrUtil.isNotBlank(offer.getRepairDetailJson())){ + repairDetailList.addAll(JSONUtil.toList(offer.getRepairDetailJson(), RepairDetailVO.class)); + } + } + List colList = new ArrayList<>(); + for(DictModel dictModel : modelList){ + ColumnItemVO itemVO = new ColumnItemVO(); + itemVO.setColName(dictModel.getText()); + long count = repairDetailList.stream().filter(item->dictModel.getValue().equals(item.getRepairClass())).count(); + itemVO.setCount((int) count); + colList.add(itemVO); + } + repairStatisVO.setColList(colList); + } + page.setRecords(list); + return page; + } + + @Override + public List> getAllRepairStatis(StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List list = new ArrayList<>(); + list = repairInfoMapper.findStatisRepairAll(vo,new ArrayList<>()); + List> datas = new ArrayList<>(); + //车辆种类字典 + List vehicleTypeList = sysDictService.queryDictItemsByCode("vehicle_type"); + Map vehicleTypeMap = vehicleTypeList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + + //补充动态列---报修分类 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for(RepairStatisVO repairStatisVO : list){ + List data = new ArrayList<>(); + data.add(repairStatisVO.getProjectName()); + data.add(repairStatisVO.getStatisTime()); + data.add(vehicleTypeMap.getOrDefault(repairStatisVO.getVehicleType(),repairStatisVO.getVehicleType() + " 无匹配字典")); + data.add(repairStatisVO.getRepairTimes()); + data.add(repairStatisVO.getRepairAmount()); + data.add(repairStatisVO.getAvgAmount()); + //todo 维修报价的分类 + List repairIds = Arrays.asList(repairStatisVO.getRepairIds().split(",")); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbRepairOffer::getRepairId,repairIds); + List offerList = repairOfferService.list(queryWrapper); + //处理数据维修细项 + List repairDetailList = new ArrayList<>(); + for(TbRepairOffer offer : offerList){ + if(StrUtil.isNotBlank(offer.getRepairDetailJson())){ + repairDetailList.addAll(JSONUtil.toList(offer.getRepairDetailJson(), RepairDetailVO.class)); + } + } + for(DictModel dictModel : modelList){ + long count = repairDetailList.stream().filter(item->dictModel.getValue().equals(item.getRepairClass())).count(); + data.add(count); + } + datas.add(data); + } + return datas; + } + + @Override + public List getRepairInfo(Date startTime, Date endTime) { + List result = new ArrayList<>(); + //如果开始结束时间为空,默认取近半年的 + if (Objects.isNull(startTime) || Objects.isNull(endTime)) { + Calendar calendar = Calendar.getInstance(); + endTime = calendar.getTime(); + calendar.add(Calendar.MONTH, -6); + startTime = calendar.getTime(); + } + //查时间区间内完成维修的工单,已开始时间为查询 + LambdaQueryWrapper repairQuery = new LambdaQueryWrapper<>(); + repairQuery.eq(TbRepairInfo::getFlowStatus,8) + .le(TbRepairInfo::getRepairTime,endTime) + .ge(TbRepairInfo::getRepairTime,startTime); + List repairInfoList = repairInfoService.list(repairQuery); + if(Objects.nonNull(repairInfoList) && repairInfoList.size()>0){ + List repairIds = repairInfoList.stream().map(TbRepairInfo::getId).collect(Collectors.toList()); + LambdaQueryWrapper offerQuery = new LambdaQueryWrapper<>(); + offerQuery.in(TbRepairOffer::getRepairId,repairIds); + List offerList = repairOfferService.list(offerQuery); + //查维修细项 + if(Objects.nonNull(offerList) && offerList.size()>0){ + //报修分类字典 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + List repairDetailList = new ArrayList<>(); + for(TbRepairOffer offer : offerList){ + if(StrUtil.isNotBlank(offer.getRepairDetailJson())){ + repairDetailList.addAll(JSONUtil.toList(offer.getRepairDetailJson(), RepairDetailVO.class)); + } + } + for(DictModel dictModel : modelList){ + long count = repairDetailList.stream().filter(item->dictModel.getValue().equals(item.getRepairClass())).count(); + RepairBoardVO vo = new RepairBoardVO(); + vo.setRepairClass(dictModel.getText()); + vo.setCount((int)count); + result.add(vo); + } + } + } + if(result.size() > 0){ + int sum = result.stream() .mapToInt(RepairBoardVO::getCount).sum(); + if(sum > 0){ + // 保留两位小数的格式 + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + + result.forEach(item->{ + double percent = (double) item.getCount() / sum * 100; + String formattedPercent = decimalFormat.format(percent); + item.setPercent(formattedPercent + "%"); + }); + } + } + return result; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/UpkeepStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/UpkeepStatisServiceImpl.java new file mode 100644 index 0000000..b0dd544 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/UpkeepStatisServiceImpl.java @@ -0,0 +1,172 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.service.RepairStatisService; +import com.gci.boot.modules.statis.service.UpkeepStatisService; +import com.gci.boot.modules.statis.vo.*; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.entity.*; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper; +import com.gci.boot.modules.vehicles.service.*; +import com.gci.boot.modules.vehicles.vo.RepairDetailVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.text.DecimalFormat; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class UpkeepStatisServiceImpl implements UpkeepStatisService { + + @Autowired + private TbUpkeepBillMapper upkeepBillMapper; + @Autowired + private ISysDictService sysDictService; + @Autowired + private ITbUpkeepBillService upkeepBillService; + @Autowired + private ITbUpkeepOfferService upkeepOfferService; + @Autowired + private ITbUpkeepPlanService upkeepPlanService; + + @Override + public Page getUpkeepStatisPage(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List list = new ArrayList<>(); + list = upkeepBillMapper.findStatisUpkeepByDayMonthYear(page,vo); + + //补充动态列---报修分类 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for(UpkeepStatisVO upkeepStatisVO : list){ + //todo 维修报价的分类 + List upkeepBillIds = Arrays.asList(upkeepStatisVO.getUpkeepBillIds().split(",")); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbUpkeepOffer::getUpkeepBillId,upkeepBillIds); + List offerList = upkeepOfferService.list(queryWrapper); + //处理数据维修细项 + List repairDetailList = new ArrayList<>(); + for(TbUpkeepOffer offer : offerList){ + if(StrUtil.isNotBlank(offer.getUpkeepDetailJson())){ + repairDetailList.addAll(JSONUtil.toList(offer.getUpkeepDetailJson(), RepairDetailVO.class)); + } + } + List colList = new ArrayList<>(); + for(DictModel dictModel : modelList){ + ColumnItemVO itemVO = new ColumnItemVO(); + itemVO.setColName(dictModel.getText()); + long count = repairDetailList.stream().filter(item->dictModel.getValue().equals(item.getRepairClass())).count(); + itemVO.setCount((int) count); + colList.add(itemVO); + } + upkeepStatisVO.setColList(colList); + } + page.setRecords(list); + return page; + } + + @Override + public List> getAllUpkeepStatis(StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + List list = new ArrayList<>(); + list = upkeepBillMapper.findStatisUpkeepAll(vo,new ArrayList<>()); + + List> datas = new ArrayList<>(); + //车辆种类字典 + List vehicleTypeList = sysDictService.queryDictItemsByCode("vehicle_type"); + Map vehicleTypeMap = vehicleTypeList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + //补充动态列---报修分类 + List modelList = sysDictService.queryDictItemsByCode("repair_class"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for(UpkeepStatisVO upkeepStatisVO : list){ + List data = new ArrayList<>(); + data.add(upkeepStatisVO.getProjectName()); + data.add(upkeepStatisVO.getStatisTime()); + data.add(vehicleTypeMap.getOrDefault(upkeepStatisVO.getVehicleType(),upkeepStatisVO.getVehicleType() + " 无匹配字典")); + data.add(upkeepStatisVO.getUpkeepTimes()); + data.add(upkeepStatisVO.getUpkeepAmount()); + data.add(upkeepStatisVO.getAvgAmount()); + //todo 维修报价的分类 + List upkeepBillIds = Arrays.asList(upkeepStatisVO.getUpkeepBillIds().split(",")); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbUpkeepOffer::getUpkeepBillId,upkeepBillIds); + List offerList = upkeepOfferService.list(queryWrapper); + //处理数据维修细项 + List repairDetailList = new ArrayList<>(); + for(TbUpkeepOffer offer : offerList){ + if(StrUtil.isNotBlank(offer.getUpkeepDetailJson())){ + repairDetailList.addAll(JSONUtil.toList(offer.getUpkeepDetailJson(), RepairDetailVO.class)); + } + } + for(DictModel dictModel : modelList){ + long count = repairDetailList.stream().filter(item->dictModel.getValue().equals(item.getRepairClass())).count(); + data.add(count); + } + datas.add(data); + } + return datas; + } + + @Override + public UpkeepBoardVO getUpkeepInfo(Date startTime, Date endTime) { + UpkeepBoardVO vo = new UpkeepBoardVO(); + //如果开始结束时间为空,默认取近半年的 + if (Objects.isNull(startTime) || Objects.isNull(endTime)) { + Calendar calendar = Calendar.getInstance(); + endTime = calendar.getTime(); + calendar.add(Calendar.MONTH, -6); + startTime = calendar.getTime(); + } + LambdaQueryWrapper planQuery = new LambdaQueryWrapper<>(); + planQuery.ne(TbUpkeepPlan::getAuditStatus,"4") + .le(TbUpkeepPlan::getPredictTime,endTime) + .ge(TbUpkeepPlan::getPredictTime,startTime); + int planCount = upkeepPlanService.count(planQuery); + vo.setPlanCount(planCount); + + LambdaQueryWrapper billQuery = new LambdaQueryWrapper<>(); + billQuery.ne(TbUpkeepBill::getFlowStatus,9) + .le(TbUpkeepBill::getPredictTime,endTime) + .ge(TbUpkeepBill::getPredictTime,startTime); + List billList = upkeepBillService.list(billQuery); + if(Objects.nonNull(billList) && billList.size()>0){ + int done = (int)billList.stream().filter(item->item.getFlowStatus() == 8).count(); + int undone = billList.size() - done; + + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + double percent = (double) done / billList.size() * 100; + String formattedPercent = decimalFormat.format(percent); + + vo.setOrderCount(billList.size()); + vo.setDoneOrderCount(done); + vo.setUndoneOrderCount(undone); + vo.setPercent(formattedPercent + "%"); + } + return vo; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/VehicleRentalServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/VehicleRentalServiceImpl.java new file mode 100644 index 0000000..829ed9f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/VehicleRentalServiceImpl.java @@ -0,0 +1,286 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Segment; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.PageUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.projects.entity.TbContract; +import com.gci.boot.modules.projects.entity.TbContractVehicle; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.projects.entity.TbVehicleCheckDetail; +import com.gci.boot.modules.projects.service.ITbContractService; +import com.gci.boot.modules.projects.service.ITbContractVehicleService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckDetailService; +import com.gci.boot.modules.projects.service.ITbVehicleCheckService; +import com.gci.boot.modules.statis.service.VehicleRentalService; +import com.gci.boot.modules.statis.vo.VehicleRentalVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class VehicleRentalServiceImpl implements VehicleRentalService { + + @Autowired + private ITbContractService contractService; + + @Autowired + private ITbVehicleCheckService vehicleCheckService; + + @Autowired + private ITbVehicleCheckDetailService detailService; + + @Autowired + private ITbContractVehicleService contractVehicleService; + + @Override + public IPage pageBuild(Page page, VehicleRentalVo query) { + List recordList = getVehicleRentalList(query); + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(recordList.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(recordList.size()); + page.setPages(totalPage); + if (page.getSize() == -1) { + page.setRecords(recordList); + return page; + } + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > recordList.size()) { + endIndex = recordList.size(); + } + page.setRecords(recordList.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } + + private List getVehicleRentalList(VehicleRentalVo query) { + List rentalVos = new ArrayList<>(); + BigDecimal wan = new BigDecimal(10000); + //查询租赁合同 + List contractList = contractService.list(new LambdaQueryWrapper() + .eq(TbContract::getContractType, '1') + .like(StrUtil.isNotBlank(query.getContractName()),TbContract::getName,query.getContractName()) + ); + if (contractList.isEmpty()) { + return rentalVos; + } + Map contractIdNameMap = contractList.stream().collect(Collectors.toMap(TbContract::getId, TbContract::getName)); + //根据合同查询对应的车型明细 + List contractVehicleList = contractVehicleService.list(new LambdaQueryWrapper().in(TbContractVehicle::getContractId, contractIdNameMap.keySet())); + Map> contractVehicleContractIdGroup = contractVehicleList.stream().collect(Collectors.groupingBy(TbContractVehicle::getContractId)); + + //根据合同查询已提交的交车单 + List vehicleCheckList = vehicleCheckService.list(new LambdaQueryWrapper() + .eq(TbVehicleCheck::getStatus, '1') + .eq(TbVehicleCheck::getCheckType, '2') + .in(TbVehicleCheck::getContractId,contractIdNameMap.keySet()) + .and(i->i.eq(TbVehicleCheck::getReceiveStatus,"0.5").or().eq(TbVehicleCheck::getReceiveStatus,'1'))); + if (vehicleCheckList.isEmpty()) { + return rentalVos; + } + Map> vehicleCheckContractIdGroup = vehicleCheckList.stream().collect(Collectors.groupingBy(TbVehicleCheck::getContractId)); + + //根据交车单查询收车单 + List afterVehicleCheckList = vehicleCheckService.list(new LambdaQueryWrapper() + .in(TbVehicleCheck::getParentId, vehicleCheckList.stream().map(TbVehicleCheck::getId).collect(Collectors.toList()))); + + List checkIds = vehicleCheckList.stream().map(TbVehicleCheck::getId).collect(Collectors.toList()); + if (!afterVehicleCheckList.isEmpty()) { + checkIds.addAll(afterVehicleCheckList.stream().map(TbVehicleCheck::getId).collect(Collectors.toList())); + } + Map> afterVehicleCheckParentGroup = afterVehicleCheckList.stream().collect(Collectors.groupingBy(TbVehicleCheck::getParentId)); + //根据交接车单查询对应车辆 + List checkDetailList = detailService.list(new LambdaQueryWrapper() + .in(TbVehicleCheckDetail::getCheckId, checkIds) + //车型 + .like(StrUtil.isNotBlank(query.getVehicleModel()), TbVehicleCheckDetail::getVehicleModel, query.getVehicleModel()) + .eq(StrUtil.isNotBlank(query.getVehicleType()), TbVehicleCheckDetail::getVehicleType, query.getVehicleType()) + //车架号 + .like(StrUtil.isNotBlank(query.getFrameNumber()), TbVehicleCheckDetail::getFrameNumber, query.getFrameNumber()) + .like(StrUtil.isNotBlank(query.getPlateNumber()), TbVehicleCheckDetail::getPlateNumber, query.getPlateNumber()) + ); + if (checkDetailList.isEmpty()) { + return rentalVos; + } + Map> checkDetailCheckIdGroup = checkDetailList.stream().collect(Collectors.groupingBy(TbVehicleCheckDetail::getCheckId)); + for (TbContract tbContract : contractList) { + //根据合同找交车单 + List tbVehicleChecks = vehicleCheckContractIdGroup.get(tbContract.getId()); + if (ObjectUtil.isNotEmpty(tbVehicleChecks)) { + for (TbVehicleCheck tbVehicleCheck : tbVehicleChecks) { + //根据交车单找收车单 + List afterVehicleChecks = afterVehicleCheckParentGroup.get(tbVehicleCheck.getId()); + if (ObjectUtil.isEmpty(afterVehicleChecks)) { + //交车单没有对应的收车单时 + List tbVehicleCheckDetails = checkDetailCheckIdGroup.get(tbVehicleCheck.getId()); + if (ObjectUtil.isNotEmpty(tbVehicleCheckDetails)) { + for (TbVehicleCheckDetail tbVehicleCheckDetail : tbVehicleCheckDetails) { + VehicleRentalVo vehicleRentalVo = new VehicleRentalVo(); + vehicleRentalVo.setVehicleType(tbVehicleCheckDetail.getVehicleType()); + vehicleRentalVo.setPlateNumber(tbVehicleCheckDetail.getPlateNumber()); + vehicleRentalVo.setFrameNumber(tbVehicleCheckDetail.getFrameNumber()); + vehicleRentalVo.setVehicleModel(tbVehicleCheckDetail.getVehicleModel()); + vehicleRentalVo.setContractName(tbContract.getName()); + //格式化时间 + vehicleRentalVo.setContractStartDate(DateUtil.beginOfDay(tbContract.getStartTime())); + vehicleRentalVo.setContractEndDate(DateUtil.beginOfDay(tbContract.getEndTime())); + //根据合同查找车型 明细 + List inContractVehicle = contractVehicleContractIdGroup.get(tbContract.getId()); + if (ObjectUtil.isEmpty(inContractVehicle)) { + vehicleRentalVo.setRentalUnitPrice(BigDecimal.ZERO); + } else { + TbContractVehicle tbContractVehicle = inContractVehicle.stream().filter(i -> i.getVehicleModel().equals(tbVehicleCheckDetail.getVehicleModel())).findFirst().orElse(null); + if (tbContractVehicle == null) { + vehicleRentalVo.setRentalUnitPrice(BigDecimal.ZERO); + } else { + vehicleRentalVo.setRentalUnitPrice(NumberUtil.mul(tbContractVehicle.getTotalPrice(), wan)); + } + } + //格式化时间 + vehicleRentalVo.setRentalDeliveryDate(DateUtil.beginOfDay(tbVehicleCheck.getCheckTime())); + //没有收车时间 +// vehicleRentalVo.setRentalDeliveryDate(); + + boolean target = false; + VehicleRentalVo cer = vehicleRentalVo; + boolean first = true; + DateTime timeTi = DateUtil.beginOfDay(tbContract.getStartTime()); + while (!target) { + //按月偏移 + timeTi.offset(DateField.MONTH,1); + if (first) { + cer.setPaymentDate(timeTi.toJdkDate()); + first = false; + if (!DateUtil.beginOfDay(cer.getContractStartDate()).equals(DateUtil.beginOfDay(cer.getRentalDeliveryDate()))) { + long day = DateUtil.betweenDay(cer.getRentalDeliveryDate(), timeTi, true); + cer.setAmountCollected(NumberUtil.div(NumberUtil.mul(cer.getRentalUnitPrice(),day),30).setScale(2, RoundingMode.HALF_UP)); + } else { + if (timeTi.after(cer.getContractEndDate())) { + long day = DateUtil.betweenDay(DateUtil.offsetMonth(timeTi, -1), cer.getContractEndDate(), true) + 1; + cer.setAmountCollected(NumberUtil.div(NumberUtil.mul(cer.getRentalUnitPrice(),day),30).setScale(2, RoundingMode.HALF_UP)); + target = true; + } else { + cer.setAmountCollected(cer.getRentalUnitPrice()); + } + } + } else { + VehicleRentalVo the = new VehicleRentalVo(); + BeanUtil.copyProperties(cer,the); + cer = the; + cer.setPaymentDate(timeTi.toJdkDate()); + if (timeTi.after(cer.getContractEndDate())) { + long day = DateUtil.betweenDay(DateUtil.offsetMonth(timeTi, -1), cer.getContractEndDate(), true) + 1; + cer.setAmountCollected(NumberUtil.div(NumberUtil.mul(cer.getRentalUnitPrice(),day),30).setScale(2, RoundingMode.HALF_UP)); + target = true; + } else { + cer.setAmountCollected(cer.getRentalUnitPrice()); + } + } + rentalVos.add(cer); + } + + } + } + } else { + //交车单有对应的收车单时 + List tbVehicleCheckDetails = checkDetailCheckIdGroup.get(tbVehicleCheck.getId()); + if (ObjectUtil.isNotEmpty(tbVehicleCheckDetails)) { + for (TbVehicleCheckDetail tbVehicleCheckDetail : tbVehicleCheckDetails) { + VehicleRentalVo vehicleRentalVo = new VehicleRentalVo(); + vehicleRentalVo.setVehicleType(tbVehicleCheckDetail.getVehicleType()); + vehicleRentalVo.setPlateNumber(tbVehicleCheckDetail.getPlateNumber()); + vehicleRentalVo.setFrameNumber(tbVehicleCheckDetail.getFrameNumber()); + vehicleRentalVo.setVehicleModel(tbVehicleCheckDetail.getVehicleModel()); + vehicleRentalVo.setContractName(tbContract.getName()); + //格式化时间 + vehicleRentalVo.setContractStartDate(DateUtil.beginOfDay(tbContract.getStartTime())); + vehicleRentalVo.setContractEndDate(DateUtil.beginOfDay(tbContract.getEndTime())); + //根据合同查找车型 明细 + List inContractVehicle = contractVehicleContractIdGroup.get(tbContract.getId()); + if (ObjectUtil.isEmpty(inContractVehicle)) { + vehicleRentalVo.setRentalUnitPrice(BigDecimal.ZERO); + } else { + TbContractVehicle tbContractVehicle = inContractVehicle.stream().filter(i -> i.getVehicleModel().equals(tbVehicleCheckDetail.getVehicleModel())).findFirst().orElse(null); + if (tbContractVehicle == null) { + vehicleRentalVo.setRentalUnitPrice(BigDecimal.ZERO); + } else { + vehicleRentalVo.setRentalUnitPrice(NumberUtil.mul(tbContractVehicle.getTotalPrice(), wan)); + } + } + //格式化时间 + vehicleRentalVo.setRentalDeliveryDate(DateUtil.beginOfDay(tbVehicleCheck.getCheckTime())); + //收车时间 + vehicleRentalVo.setRentalPickupDate(DateUtil.beginOfDay(afterVehicleChecks.get(0).getCheckTime())); + + boolean target = false; + VehicleRentalVo cer = vehicleRentalVo; + boolean first = true; + DateTime timeTi = DateUtil.beginOfDay(tbContract.getStartTime()); + while (!target) { + //按月偏移 + timeTi.offset(DateField.MONTH,1); + if (first) { + cer.setPaymentDate(timeTi.toJdkDate()); + first = false; + if (!DateUtil.beginOfDay(cer.getContractStartDate()).equals(DateUtil.beginOfDay(cer.getRentalDeliveryDate()))) { + long day = DateUtil.betweenDay(cer.getRentalDeliveryDate(), timeTi, true); + cer.setAmountCollected(NumberUtil.div(NumberUtil.mul(cer.getRentalUnitPrice(),day),30).setScale(2, RoundingMode.HALF_UP)); + } else { + if (timeTi.after(cer.getContractEndDate())) { + long day = DateUtil.betweenDay(DateUtil.offsetMonth(timeTi, -1), cer.getContractEndDate(), true) + 1; + cer.setAmountCollected(NumberUtil.div(NumberUtil.mul(cer.getRentalUnitPrice(),day),30).setScale(2, RoundingMode.HALF_UP)); + target = true; + } else { + cer.setAmountCollected(cer.getRentalUnitPrice()); + } + } + } else { + VehicleRentalVo the = new VehicleRentalVo(); + BeanUtil.copyProperties(cer,the); + cer = the; + cer.setPaymentDate(timeTi.toJdkDate()); + if (timeTi.after(cer.getRentalPickupDate())) { + long day = DateUtil.betweenDay(DateUtil.offsetMonth(timeTi, -1), cer.getRentalPickupDate(), true) + 1; + cer.setAmountCollected(NumberUtil.div(NumberUtil.mul(cer.getRentalUnitPrice(),day),30).setScale(2, RoundingMode.HALF_UP)); + target = true; + } else { + cer.setAmountCollected(cer.getRentalUnitPrice()); + } + } + rentalVos.add(cer); + } + + } + } + } + } + } + } + if (ObjectUtil.isAllNotEmpty(query.getPaymentDateStart(),query.getPaymentDateEnd())) { + rentalVos = rentalVos.stream().filter(r->DateUtil.isOverlap(query.getPaymentDateStart(),query.getPaymentDateEnd(),r.getPaymentDate(),r.getPaymentDate())).collect(Collectors.toList()); + } + rentalVos.sort(Comparator.comparing(VehicleRentalVo::getPlateNumber).thenComparing(VehicleRentalVo::getContractName).thenComparing(VehicleRentalVo::getPaymentDate)); + return rentalVos; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/VehicleStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/VehicleStatisServiceImpl.java new file mode 100644 index 0000000..ba617f0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/VehicleStatisServiceImpl.java @@ -0,0 +1,648 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Segment; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.PageUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.driver.entity.TbDriver; +import com.gci.boot.modules.driver.mapper.TbDriverSignInMapper; +import com.gci.boot.modules.driver.vo.DriverWorkVO; +import com.gci.boot.modules.gis.entity.TbGisActiveSafetyAlarm; +import com.gci.boot.modules.gis.entity.TbGisFenceAlarm; +import com.gci.boot.modules.gis.entity.TbGisGps; +import com.gci.boot.modules.gis.entity.TbGisSpeedingAlarm; +import com.gci.boot.modules.gis.service.*; +import com.gci.boot.modules.gis.vo.VehicleWorkVO; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.statis.service.VehicleStatisService; +import com.gci.boot.modules.statis.vo.*; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.mapper.*; +import com.gci.boot.modules.vehicles.service.ITbAccidentInfoService; +import com.gci.boot.modules.vehicles.service.ITbViolationRecordService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.text.ParseException; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Service +@Slf4j +public class VehicleStatisServiceImpl implements VehicleStatisService { + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private TbUpkeepBillMapper upkeepBillMapper; + @Autowired + private TbInsuranceMapper insuranceMapper; + @Autowired + private TbAnnualInspectionInfoMapper annualInspectionInfoMapper; + + @Autowired + private IGisGpsAnalysisService iGisGpsAnalysisService; + + @Autowired + private ITbAccidentInfoService iTbAccidentInfoService; + + @Autowired + private ITbViolationRecordService iTbViolationRecordService; + @Autowired + private ITbGisSpeedingAlarmService iTbGisSpeedingAlarmService; + @Autowired + private ITbGisFenceAlarmService iTbGisFenceAlarmService; + @Autowired + private ITbGisActiveSafetyAlarmService iTbGisActiveSafetyAlarmService; + @Autowired + private ITbGisGpsService iTbGisGpsService; + @Autowired + private TbViolationRecordMapper violationRecordMapper; + @Autowired + private ITbVehicleService vehicleService; + + @Autowired + private TbDriverSignInMapper driverSignInMapper; + @Autowired + private IProjectsService projectsService; + + @Override + public IPage page(Page page, StatisParamVO vo) { + List vehicleStatisVos = getVehicleStatisVos(vo); + if (vehicleStatisVos.size() == 0) { + return page; + } + PageUtil.setOneAsFirstPageNo(); + int totalPage = PageUtil.totalPage(vehicleStatisVos.size(), Convert.toInt(page.getSize())); + if (page.getCurrent() > totalPage) { + page.setCurrent(totalPage); + } + page.setTotal(vehicleStatisVos.size()); + page.setPages(totalPage); + Segment integerSegment = PageUtil.toSegment(Convert.toInt(page.getCurrent()), Convert.toInt(page.getSize())); + Integer endIndex = integerSegment.getEndIndex(); + if (endIndex > vehicleStatisVos.size()) { + endIndex = vehicleStatisVos.size(); + } + page.setRecords(vehicleStatisVos.subList(integerSegment.getStartIndex(), endIndex)); + return page; + } + + private Map getVehicleTraffic(StatisParamVO vo) { + List repairList = repairInfoMapper.findStatisRepairAndPlateNumberAll(vo,new ArrayList<>()); + List upkeepList = upkeepBillMapper.findStatisUpkeepAndPlateNumberAll(vo,new ArrayList<>()); + List insuranceList = insuranceMapper.findStatisInsuranceAndPlateNumberAll(vo,new ArrayList<>()); + List annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAndPlateNumberAll(vo,new ArrayList<>()); + + Map vehicleStatisMap = new HashMap<>(); + + for (RepairStatisVO to : repairList) { + String key = to.getPlateNumber(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (vehicleStatisMap.containsKey(key)) { + VehicleStatisVo rl = vehicleStatisMap.get(key); + rl.setRepairAmount(rl.getRepairAmount() + to.getRepairAmount()); + rl.setRepairNum(rl.getRepairNum() + to.getRepairTimes()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setRepairNum(to.getRepairTimes().longValue()); + rl.setRepairAmount(to.getRepairAmount()); + rl.setPlateNumber(to.getPlateNumber()); + //将新的ReportListVo对象放入Map中 + vehicleStatisMap.put(key, rl); + } + } + for (UpkeepStatisVO to : upkeepList) { + String key = to.getPlateNumber(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (vehicleStatisMap.containsKey(key)) { + VehicleStatisVo rl = vehicleStatisMap.get(key); + rl.setUpkeepAmount(rl.getUpkeepAmount() + to.getUpkeepAmount()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setPlateNumber(to.getPlateNumber()); + rl.setUpkeepAmount(to.getUpkeepAmount()); + //将新的ReportListVo对象放入Map中 + vehicleStatisMap.put(key, rl); + } + } + for (InsuranceStatisVo to : insuranceList) { + String key = to.getPlateNumber(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (vehicleStatisMap.containsKey(key)) { + VehicleStatisVo rl = vehicleStatisMap.get(key); + rl.setInsuranceAmount(rl.getInsuranceAmount() + to.getTotalPrice()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setPlateNumber(to.getPlateNumber()); + rl.setInsuranceAmount(to.getTotalPrice()); + //将新的ReportListVo对象放入Map中 + vehicleStatisMap.put(key, rl); + } + } + for (AnnualInspectionInfoStatisVo to : annualInspectionInfoList) { + String key = to.getPlateNumber(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (vehicleStatisMap.containsKey(key)) { + VehicleStatisVo rl = vehicleStatisMap.get(key); + rl.setInspectionAmount(rl.getInspectionAmount() + to.getInspectionAmount()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setPlateNumber(to.getPlateNumber()); + rl.setInspectionAmount(to.getInspectionAmount()); + //将新的ReportListVo对象放入Map中 + vehicleStatisMap.put(key, rl); + } + } + return vehicleStatisMap; + } + + private List getVehicleStatisVos(StatisParamVO vo) { + + vo.setStatisTime("YYYY"); + + //用户关联项目 + List listProjectIds = projectsService.queryAllProjectListOfUser(); + + //车辆基础信息 + List list = vehicleService.list(new LambdaQueryWrapper() + .like(StrUtil.isNotBlank(vo.getPlateNumber()),TbVehicle::getPlateNumber,vo.getPlateNumber()) + .like(StrUtil.isNotBlank(vo.getFrameNumber()),TbVehicle::getFrameNumber,vo.getFrameNumber())); + + List repairList = repairInfoMapper.findStatisRepairAndPlateNumberAllHis(vo,listProjectIds); + List upkeepList = upkeepBillMapper.findStatisUpkeepAndPlateNumberAllHis(vo,listProjectIds); + List insuranceList = insuranceMapper.findStatisInsuranceAndPlateNumberAllHis(vo,listProjectIds); + List annualInspectionInfoList = annualInspectionInfoMapper.findStatisAnnualInspectionInfoAndPlateNumberAllHis(vo,listProjectIds); + List violationList = violationRecordMapper.findStatisViolationAndPlateNumberAllHis(vo, listProjectIds); + + Map map = getStringVehicleStatisVoMap(vo,list,repairList, upkeepList, insuranceList, annualInspectionInfoList,violationList); + ArrayList vehicleStatisVos = new ArrayList<>(map.values()); + if (!vehicleStatisVos.isEmpty()) { + vehicleStatisVos.sort(Comparator.comparing(VehicleStatisVo::getStatisTime)); + } + return vehicleStatisVos; + } + + @Override + public List getAll(StatisParamVO vo) { + return getVehicleStatisVos(vo); + } + + @Override + public List analysisVehicleByListAndTime(List vehicles, Date startTime, Date endTime) { + List plates = vehicles.stream().map(v -> v.getPlateNumber()).collect(Collectors.toList()); + List workVOList = iGisGpsAnalysisService.findAnalysisByTimeAndVehicle(plates, startTime, endTime); + + Map groupBy = workVOList.stream().collect(Collectors.toMap(VehicleWorkVO::getNumberPlate, vehicleWorkVO -> vehicleWorkVO)); + StatisParamVO queryVO = new StatisParamVO(); + queryVO.setPlates(plates); + queryVO.setStatisTime("yyyy-MM-dd"); + queryVO.setStartTime(DateUtils.formatTime(startTime)); + queryVO.setEndTime(DateUtils.formatTime(endTime)); + + Map groupByTraffic = getVehicleTraffic(queryVO); + + List analysisVOS = vehicles.stream().map(a -> { + VehicleAnalysisVO vo = new VehicleAnalysisVO(); + VehicleWorkVO work = groupBy.getOrDefault(a.getPlateNumber(), new VehicleWorkVO()); + VehicleStatisVo traffic = groupByTraffic.getOrDefault(a.getPlateNumber(), new VehicleStatisVo()); + BeanUtils.copyProperties(a, vo); + vo.setCost(a.getPrice().toString()); + vo.setAge(String.valueOf(DateUtil.betweenYear(vo.getDeliveryTime(), new Date(), false))); + vo.setResidualValue("0"); + vo.setRentalIncome("0"); + + vo.setDriverMile(work.getDriverMile()); + vo.setDriverHour(work.getDriverHour()); + vo.setWorkMile(work.getWorkMile()); + vo.setWorkHour(work.getWorkHour()); + + vo.setRepairNum(traffic.getRepairNum().toString()); + vo.setRepairFee(traffic.getRepairAmount().toString()); + vo.setInsuranceFee(traffic.getInsuranceAmount().toString()); + vo.setAnnualFee(traffic.getInspectionAmount().toString()); + vo.setUpkeepFee(traffic.getUpkeepAmount().toString()); + + return vo; + }).collect(Collectors.toList()); + return analysisVOS; + } + + @Override + public List analysisDriverByListAndTime(List drivers, String startTime, String endTime) { + //得到要查询的司机id信息 + List driverIds = drivers.stream().map(v -> v.getId()).collect(Collectors.toList()); + if(driverIds.isEmpty()){ + return new ArrayList<>(); + } + List driverWorkVOS = new ArrayList<>(); + //得到统计时段 司机上下班的信息 + try { + driverWorkVOS = driverSignInMapper.findWorkByList(driverIds, DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm:ss"), DateUtils.parseDate(endTime, "yyyy-MM-dd HH:mm:ss")); + } catch (ParseException e) { + e.printStackTrace(); + return new ArrayList<>(); + } + //根据司机进行司机作业信息分组 + Map> groupByDriver = driverWorkVOS.stream().collect(Collectors.groupingBy(DriverWorkVO::getDriverId)); + List analysisVOS = drivers.parallelStream().map(a -> { + DriverAnalysisVO vo = new DriverAnalysisVO(); + BeanUtils.copyProperties(a, vo); + List workList = groupByDriver.getOrDefault(a.getId(),new ArrayList<>()); + //去重统计时段里司机驾驶的车辆种类 + String vehicleType = workList.stream().map(w -> w.getVehicleType()).distinct().collect(Collectors.joining(",")); + vo.setVehicleType(vehicleType); + + //去重统计时段里司机的车辆信息 + List plateNumberByDriver = workList.stream().map(w -> w.getPlateNumber()).distinct().collect(Collectors.toList()); + + //根据司机的车辆及工作时段统计各类数据。 + String accidentNum = getAccidentNum(plateNumberByDriver, workList); + + String violationNum = getViolationNum(plateNumberByDriver, workList); + + String speedNum = getSpeedNum(plateNumberByDriver, workList); + + String fenceNum = getFenceNum(plateNumberByDriver, workList); + + String safetyNum = getSafetyNum(plateNumberByDriver, workList); + String driverMile = getDriverMileNum(plateNumberByDriver, workList); + + vo.setAccidentNum(accidentNum); + vo.setViolationNum(violationNum); + vo.setSpeedNum(speedNum); + vo.setFenceNum(fenceNum); + vo.setSafetyNum(safetyNum); + vo.setDriverMile(driverMile); + return vo; + }).collect(Collectors.toList()); + return analysisVOS; + } + + + private String getAccidentNum(List plateNumbers, List workList) { + if (plateNumbers.isEmpty()) { + return ""; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbAccidentInfo::getPlateNumber, plateNumbers); + queryWrapper.and(wrapper -> { + workList.forEach(work -> { + wrapper.or(inner -> { + inner.between(TbAccidentInfo::getAccidentTime, work.getWorkStartTime(), work.getWorkEndTIme()); + }); + }); + }); + int count = iTbAccidentInfoService.count(queryWrapper); + return String.valueOf(count); + } + + private String getViolationNum(List plateNumbers, List workList) { + if (plateNumbers.isEmpty()) { + return ""; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbViolationRecord::getPlateNumber, plateNumbers); + queryWrapper.and(wrapper -> { + workList.forEach(work -> { + wrapper.or(inner -> { + inner.between(TbViolationRecord::getViolationTime, work.getWorkStartTime(), work.getWorkEndTIme()); + }); + }); + }); + int count = iTbViolationRecordService.count(queryWrapper); + return String.valueOf(count); + } + + private String getSpeedNum(List plateNumbers, List workList) { + if (plateNumbers.isEmpty()) { + return ""; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbGisSpeedingAlarm::getPlateNumber, plateNumbers); + queryWrapper.and(wrapper -> { + workList.forEach(work -> { + wrapper.or(inner -> { + inner.between(TbGisSpeedingAlarm::getStartTime, work.getWorkStartTime(), work.getWorkEndTIme()); + }); + }); + }); + int count = iTbGisSpeedingAlarmService.count(queryWrapper); + return String.valueOf(count); + } + + private String getFenceNum(List plateNumbers, List workList) { + if (plateNumbers.isEmpty()) { + return ""; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbGisFenceAlarm::getPlateNumber, plateNumbers); + queryWrapper.and(wrapper -> { + workList.forEach(work -> { + wrapper.or(inner -> { + inner.between(TbGisFenceAlarm::getStartTime, work.getWorkStartTime(), work.getWorkEndTIme()); + }); + }); + }); + int count = iTbGisFenceAlarmService.count(queryWrapper); + return String.valueOf(count); + } + + private String getSafetyNum(List plateNumbers, List workList) { + if (plateNumbers.isEmpty()) { + return ""; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbGisActiveSafetyAlarm::getPlateNumber, plateNumbers); + queryWrapper.and(wrapper -> { + workList.forEach(work -> { + wrapper.or(inner -> { + inner.between(TbGisActiveSafetyAlarm::getAlertStartTime, work.getWorkStartTime(), work.getWorkEndTIme()); + }); + }); + }); + int count = iTbGisActiveSafetyAlarmService.count(queryWrapper); + return String.valueOf(count); + } + + private String getDriverMileNum(List plateNumbers, List workList) { + if (plateNumbers.isEmpty()) { + return ""; + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbGisGps::getPlateNumber, plateNumbers); + queryWrapper.eq(TbGisGps::getRecordSource, 2); + queryWrapper.eq(TbGisGps::getIsValid, 1); + queryWrapper.and(wrapper -> { + workList.forEach(work -> { + wrapper.or(inner -> { + inner.between(TbGisGps::getGpsTime, work.getWorkStartTime(), work.getWorkEndTIme()); + }); + }); + }); + queryWrapper.orderByAsc(TbGisGps::getGpsTime); + List list = iTbGisGpsService.list(queryWrapper); + //删除掉脏数据 + list.removeIf(l -> ObjectUtil.isEmpty(l.getTotalMileage())); + if (list.isEmpty()) { + return ""; + } + Map> groupedByPlateNumber = list.stream() + .collect(Collectors.groupingBy(TbGisGps::getPlateNumber)); + double totalDifference = groupedByPlateNumber.values().stream() + .mapToDouble(group -> group.get(group.size() - 1).getTotalMileage().subtract(group.get(0).getTotalMileage()).doubleValue()) + .sum(); + return new BigDecimal(totalDifference).setScale(2,BigDecimal.ROUND_HALF_UP).toString(); + } + + private Map getStringVehicleStatisVoMap(StatisParamVO vo, List list, List repairList, List upkeepList, List insuranceList, List annualInspectionInfoList, List violationList) { + Map> collect = list.stream().collect(Collectors.groupingBy(TbVehicle::getPlateNumber)); + Set strings = collect.keySet(); + + //创建一个Map,用于存储项目Id,项目名称和车辆类型为键,ReportListVo为值 + Map map = new HashMap<>(); + for (RepairStatisVO to : repairList) { + if (!strings.contains(to.getPlateNumber())) { + continue; + } + TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0); + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + VehicleStatisVo rl = map.get(key); + rl.setRepairAmount(rl.getRepairAmount() + to.getRepairAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setPlateNumber(to.getPlateNumber()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setRepairAmount(to.getRepairAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (UpkeepStatisVO to : upkeepList) { + if (!strings.contains(to.getPlateNumber())) { + continue; + } + TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0); + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + VehicleStatisVo rl = map.get(key); + rl.setUpkeepAmount(rl.getUpkeepAmount() + to.getUpkeepAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setPlateNumber(to.getPlateNumber()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setUpkeepAmount(to.getUpkeepAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (InsuranceStatisVo to : insuranceList) { + if (!strings.contains(to.getPlateNumber())) { + continue; + } + TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0); + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + VehicleStatisVo rl = map.get(key); + rl.setInsuranceAmount(rl.getInsuranceAmount() + to.getTotalPrice()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setPlateNumber(to.getPlateNumber()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setInsuranceAmount(to.getTotalPrice()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (AnnualInspectionInfoStatisVo to : annualInspectionInfoList) { + if (!strings.contains(to.getPlateNumber())) { + continue; + } + TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0); + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + VehicleStatisVo rl = map.get(key); + rl.setInspectionAmount(rl.getInspectionAmount() + to.getInspectionAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setPlateNumber(to.getPlateNumber()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setInspectionAmount(to.getInspectionAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (ViolationRecordStatisVO to : violationList) { + if (!strings.contains(to.getPlateNumber())) { + continue; + } + TbVehicle vehicle = collect.get(to.getPlateNumber()).get(0); + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getPlateNumber() + "," + vehicle.getVehicleType() + "," + to.getStatisTime(); + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + VehicleStatisVo rl = map.get(key); + rl.setViolationAmount(rl.getViolationAmount() + to.getViolationAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setPlateNumber(to.getPlateNumber()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(to.getStatisTime()); + rl.setViolationAmount(to.getViolationAmount()); + rl.setVehicleType(vehicle.getVehicleType()); + rl.setVehicleBrand(vehicle.getVehicleBrand()); + rl.setVehicleModel(vehicle.getVehicleModel()); + rl.setFrameNumber(vehicle.getFrameNumber()); + if (to.getStatisTime().equals(String.valueOf(DateUtil.year(vehicle.getDeliveryTime())))) { + rl.setPrice(vehicle.getPrice()); + } + + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + for (TbVehicle to : list) { + int year = DateUtil.year(to.getDeliveryTime()); + if (StrUtil.isNotBlank(vo.getStartTime())) { + if (DateUtil.parse(vo.getStartTime()).year() != year) { + continue; + } + } + //生成一个键,由项目Id,项目名称和车辆类型组成,用逗号分隔 + String key = to.getPlateNumber() + "," + to.getVehicleType() + "," + year; + //如果Map中已经存在该键,说明已经有一个ReportListVo对象,那么只需要更新其维修统计字段 + if (map.containsKey(key)) { + VehicleStatisVo rl = map.get(key); + rl.setVehicleBrand(to.getVehicleBrand()); + rl.setVehicleModel(to.getVehicleModel()); + rl.setFrameNumber(to.getFrameNumber()); + rl.setVehicleType(to.getVehicleType()); + } else { + //否则,创建一个新的ReportListVo对象,并设置其项目Id,项目名称,车辆类型和维修统计字段 + VehicleStatisVo rl = new VehicleStatisVo(); + rl.setProjectId(to.getProjectId()); + rl.setPlateNumber(to.getPlateNumber()); + rl.setVehicleType(to.getVehicleType()); + rl.setStatisTime(String.valueOf(year)); + rl.setVehicleBrand(to.getVehicleBrand()); + rl.setVehicleModel(to.getVehicleModel()); + rl.setFrameNumber(to.getFrameNumber()); + rl.setPrice(to.getPrice()); + //将新的ReportListVo对象放入Map中 + map.put(key, rl); + } + } + return map; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/service/impl/ViolationStatisServiceImpl.java b/src/main/java/com/gci/boot/modules/statis/service/impl/ViolationStatisServiceImpl.java new file mode 100644 index 0000000..8a07cf2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/service/impl/ViolationStatisServiceImpl.java @@ -0,0 +1,111 @@ +package com.gci.boot.modules.statis.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.service.UpkeepStatisService; +import com.gci.boot.modules.statis.service.ViolationStatisService; +import com.gci.boot.modules.statis.vo.ColumnItemVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.UpkeepStatisVO; +import com.gci.boot.modules.statis.vo.ViolationRecordStatisVO; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.entity.TbUpkeepOffer; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper; +import com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper; +import com.gci.boot.modules.vehicles.service.ITbUpkeepBillService; +import com.gci.boot.modules.vehicles.service.ITbUpkeepOfferService; +import com.gci.boot.modules.vehicles.vo.RepairDetailVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class ViolationStatisServiceImpl implements ViolationStatisService { + + @Autowired + private TbViolationRecordMapper violationRecordMapper; + @Autowired + private ISysDictService sysDictService; + + @Override + public Page getViolationStatisPage(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List list = new ArrayList<>(); + list = violationRecordMapper.findStatisViolationByDayMonthYear(page,vo); + + //补充动态列---违章分类 + List modelList = sysDictService.queryDictItemsByCode("violation_behavior"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for(ViolationRecordStatisVO violationRecordStatisVO : list){ + List violationActs = Arrays.asList(violationRecordStatisVO.getViolationActIds().split(",")); + List colList = new ArrayList<>(); + for(DictModel dictModel : modelList){ + ColumnItemVO itemVO = new ColumnItemVO(); + itemVO.setColName(dictModel.getText()); + long count = violationActs.stream().filter(item->dictModel.getValue().equals(item)).count(); + itemVO.setCount((int) count); + colList.add(itemVO); + } + violationRecordStatisVO.setColList(colList); + } + page.setRecords(list); + return page; + } + + @Override + public List> getAllViolationStatis(StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + + List list = new ArrayList<>(); + list = violationRecordMapper.findStatisViolationAll(vo); + + List> datas = new ArrayList<>(); + //车辆种类字典 + List vehicleTypeList = sysDictService.queryDictItemsByCode("vehicle_type"); + Map vehicleTypeMap = vehicleTypeList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + //补充动态列---报修分类 + List modelList = sysDictService.queryDictItemsByCode("violation_behavior"); + modelList.sort(Comparator.comparing(DictModel::getValue)); + for(ViolationRecordStatisVO violationRecordStatisVO : list){ + List data = new ArrayList<>(); + data.add(violationRecordStatisVO.getProjectName()); + data.add(violationRecordStatisVO.getStatisTime()); + data.add(vehicleTypeMap.getOrDefault(violationRecordStatisVO.getVehicleType(),violationRecordStatisVO.getVehicleType() + " 无匹配字典")); + data.add(violationRecordStatisVO.getViolationTimes()); + data.add(violationRecordStatisVO.getViolationAmount()); + data.add(violationRecordStatisVO.getAvgAmount()); + //补充动态列---违章分类 + List violationActs = Arrays.asList(violationRecordStatisVO.getViolationActIds().split(",")); + for(DictModel dictModel : modelList){ + long count = violationActs.stream().filter(item->dictModel.getValue().equals(item)).count(); + data.add(count); + } + datas.add(data); + } + return datas; + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/AccidentInfoStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/AccidentInfoStatisVo.java new file mode 100644 index 0000000..3ddb69a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/AccidentInfoStatisVo.java @@ -0,0 +1,37 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class AccidentInfoStatisVo { + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + private String projectName; + + @ApiModelProperty("统计期间") + private String statisTime; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("事故次数") + private Integer accidentTimes; + + @ApiModelProperty("id") + private String ids; + + @ApiModelProperty("动态列") + private List colList; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/AlarmTrendVO.java b/src/main/java/com/gci/boot/modules/statis/vo/AlarmTrendVO.java new file mode 100644 index 0000000..1de279d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/AlarmTrendVO.java @@ -0,0 +1,18 @@ +package com.gci.boot.modules.statis.vo; + +import com.gci.boot.common.util.FormatUtil; +import lombok.Data; + +/** + * @author lyz + * @date 2023/9/23 19:35 + */ +@Data +public class AlarmTrendVO { + private String month; + private Long count; + + public String getMonth() { + return FormatUtil.convertToMonthDescription(this.month); + } +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/AnnualInspectionInfoStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/AnnualInspectionInfoStatisVo.java new file mode 100644 index 0000000..3554edb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/AnnualInspectionInfoStatisVo.java @@ -0,0 +1,52 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + + +@Data +public class AnnualInspectionInfoStatisVo { + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆类型",converter = DictConverter.class) + private String vehicleType; + + @ApiModelProperty("统计期间") + @ExcelProperty("统计期间") + private String statisTime; + + @ApiModelProperty("车牌号") + @ExcelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("年检次数") + @ExcelProperty("年检次数") + private Integer inspectionTimes; + + @ApiModelProperty("完成率") + @ExcelProperty("完成率") + private String completionRate; + + @ApiModelProperty("年检金额") + @ExcelProperty("年检金额(元)") + private Double inspectionAmount; + + @ApiModelProperty("平均金额") + @ExcelProperty("平均金额(元)") + private Double avgAmount; + + @ApiModelProperty("车牌号") + @ExcelIgnore + private String plateNumbers; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/BusinessStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/BusinessStatisVo.java new file mode 100644 index 0000000..cfc5a1c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/BusinessStatisVo.java @@ -0,0 +1,18 @@ +package com.gci.boot.modules.statis.vo; + +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class BusinessStatisVo { + @Dict(dicCode = "business_type") + private String businessType; + + @ApiModelProperty("统计期间") + private String statisTime; + + private List colList; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVO.java b/src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVO.java new file mode 100644 index 0000000..39cb4a6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVO.java @@ -0,0 +1,11 @@ +package com.gci.boot.modules.statis.vo; + +import lombok.Data; + +@Data +public class ColumnItemVO { + + private String colName; + + private Integer count; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVo2.java b/src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVo2.java new file mode 100644 index 0000000..8cd1207 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/ColumnItemVo2.java @@ -0,0 +1,11 @@ +package com.gci.boot.modules.statis.vo; + +import lombok.Data; + +@Data +public class ColumnItemVo2 { + + private String colName; + + private Double count; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/DriverAnalysisVO.java b/src/main/java/com/gci/boot/modules/statis/vo/DriverAnalysisVO.java new file mode 100644 index 0000000..064c446 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/DriverAnalysisVO.java @@ -0,0 +1,65 @@ +package com.gci.boot.modules.statis.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import lombok.Data; + +/** + * @author lyz + * @date 2023/10/23 19:46 + */ +@Data +public class DriverAnalysisVO { + + @ExcelProperty(value = "所属项目",converter = DictConverter.class) + @Excel(name = "所属项目",width = 30,dict = "tb_projects,project_name,id") + @Dict(dictTable = "tb_projects",dicCode = "id",dicText = "project_name") + private String projectId; + + @Excel(width = 15,name = "司机姓名") + private String name ; + + @Excel(width = 15,name = "年龄") + private String age ; + + @Excel(width = 15,name = "性别",dict = "sex") + @Dict(dicCode = "sex") + private String sex ; + + @Excel(width = 15,name = "在职状态",dict = "entry_status") + @Dict(dicCode = "entry_status") + private String entryStatus; + + @Excel(width = 15,name = "安全得分") + private String secureScore; + + @Excel(width = 15,name = "安全里程(km)") + private String secureMile; + + @Excel(width = 15,name = "驾驶车型",dict = "vehicle_type") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @Excel(width = 15,name = "事故次数") + private String accidentNum; + + @Excel(width = 15,name = "违章次数") + private String violationNum; + + @Excel(width = 15,name = "超速次数") + private String speedNum; + + + @Excel(width = 15,name = "围栏告警次数") + private String fenceNum; + + @Excel(width = 15,name = "主动安全告警次数") + private String safetyNum; + + @Excel(width = 15,name = "驾驶里程(km)") + private String driverMile; + + +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/InsuranceStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/InsuranceStatisVo.java new file mode 100644 index 0000000..88e1a71 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/InsuranceStatisVo.java @@ -0,0 +1,68 @@ +package com.gci.boot.modules.statis.vo; + +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.constant.CommonConstant; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * + */ +@Data +@ColumnWidth(20) +public class InsuranceStatisVo { + + @ExcelIgnore + private String projectId; + + @ExcelProperty(value = "所属项目", index = 0) + private String projectName; + + @ExcelProperty(value = "统计期间", index = 1) + private String statisTime; + + @ExcelProperty(value = "车辆型号", index = 2) + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("车牌号") + @ExcelIgnore + private String plateNumber; + + @ExcelProperty(value = "保险车次", index = 3) + private Integer vehicleCount = 0; + + @ExcelProperty(value = "保险金额(元)", index = 4) + private Double totalPrice = 0d; + + @ExcelProperty(value = "平均金额(元/车)", index = 5) + private Double avgPrice = 0d; + + public Double getAvgPrice() { + return CommonConstant.formatDouble((this.totalPrice/this.vehicleCount)); + } + + //统计类型 1按日,2按月,3按年 + @ExcelIgnore + private String type; + + @ApiModelProperty("日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @ExcelIgnore + private Date createDateStart; + + @ApiModelProperty("日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @ExcelIgnore + private Date createDateEnd; + +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/ProjectStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/ProjectStatisVo.java new file mode 100644 index 0000000..920addd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/ProjectStatisVo.java @@ -0,0 +1,42 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ProjectStatisVo { + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类",converter = DictConverter.class) + private String vehicleType; + + @ApiModelProperty("统计期间") + @ExcelProperty(value = "统计期间") + private String statisTime; + + @ApiModelProperty("维修金额") + @ExcelProperty(value = "维修金额") + private Double repairAmount = 0.0; + + @ApiModelProperty("保险金额") + @ExcelProperty(value = "保险金额") + private Double insuranceAmount = 0.0; + + @ApiModelProperty("保养金额") + @ExcelProperty(value = "保养金额") + private Double upkeepAmount = 0.0; + + @ApiModelProperty("年检金额") + @ExcelProperty(value = "年检金额") + private Double inspectionAmount = 0.0; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/RepairBoardVO.java b/src/main/java/com/gci/boot/modules/statis/vo/RepairBoardVO.java new file mode 100644 index 0000000..d20278e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/RepairBoardVO.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.statis.vo; + +import lombok.Data; + +/** + * 车务-维修-数据看板 + */ +@Data +public class RepairBoardVO { + + private String repairClass; + + private Integer count; + + private String percent; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/RepairStatisVO.java b/src/main/java/com/gci/boot/modules/statis/vo/RepairStatisVO.java new file mode 100644 index 0000000..5d42ea0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/RepairStatisVO.java @@ -0,0 +1,53 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +@Data +public class RepairStatisVO { + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + private String projectName; + + @ApiModelProperty("统计时间") + private String statisTime; + + @ApiModelProperty("维修车次") + private Integer repairTimes; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("维修金额") + private Double repairAmount; + + @ApiModelProperty("平均金额") + private Double avgAmount; + + @ApiModelProperty("维修信息表id") + private String repairIds; + + private List colList; + +} + diff --git a/src/main/java/com/gci/boot/modules/statis/vo/SafetyDataVO.java b/src/main/java/com/gci/boot/modules/statis/vo/SafetyDataVO.java new file mode 100644 index 0000000..696eff9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/SafetyDataVO.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.statis.vo; + +import lombok.Data; + +/** + * @author lyz + * @date 2023/9/23 19:07 + */ +@Data +public class SafetyDataVO { + private String name; + private Long count; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/StatisParamVO.java b/src/main/java/com/gci/boot/modules/statis/vo/StatisParamVO.java new file mode 100644 index 0000000..484e67f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/StatisParamVO.java @@ -0,0 +1,55 @@ +package com.gci.boot.modules.statis.vo; + +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.List; + + +@Data +public class StatisParamVO { + /** + * 统计期间 + */ + private String statisTime; + /** + * 项目Id + */ + private String projectId; + /** + * 统计期间类型 + */ + private String statisType; + /** + * 车辆类型 + */ + private String vehicleType; + + /** + * 车牌 + */ + private String plateNumber; + + /** + * 车牌集合 + */ + List plates; + /** + * 开始时间 + */ + private String startTime; + /** + * 结束时间 + */ + private String endTime; + /** + * 统计类型 1-维修 2-保险 3-保养 4-年检 + */ + private String businessType; + /** + * 车架号 + */ + private String frameNumber; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/UpkeepBoardVO.java b/src/main/java/com/gci/boot/modules/statis/vo/UpkeepBoardVO.java new file mode 100644 index 0000000..bf4a669 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/UpkeepBoardVO.java @@ -0,0 +1,17 @@ +package com.gci.boot.modules.statis.vo; + +import lombok.Data; + +@Data +public class UpkeepBoardVO { + + private Integer planCount; + + private Integer orderCount; + + private Integer doneOrderCount; + + private Integer undoneOrderCount; + + private String percent; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/UpkeepStatisVO.java b/src/main/java/com/gci/boot/modules/statis/vo/UpkeepStatisVO.java new file mode 100644 index 0000000..a4199a4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/UpkeepStatisVO.java @@ -0,0 +1,48 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class UpkeepStatisVO { + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + private String projectName; + + @ApiModelProperty("统计时间") + private String statisTime; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("保养车次") + private Integer upkeepTimes; + + @ApiModelProperty("保养金额") + private Double upkeepAmount; + + @ApiModelProperty("平均金额") + private Double avgAmount; + + @ApiModelProperty("保养台账表id") + private String upkeepBillIds; + + private List colList; + +} + diff --git a/src/main/java/com/gci/boot/modules/statis/vo/VehicleAnalysisVO.java b/src/main/java/com/gci/boot/modules/statis/vo/VehicleAnalysisVO.java new file mode 100644 index 0000000..e545ddc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/VehicleAnalysisVO.java @@ -0,0 +1,91 @@ +package com.gci.boot.modules.statis.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * @author lyz + * @date 2023/10/23 19:46 + */ +@Data +public class VehicleAnalysisVO { + + @ExcelProperty(value = "所属项目",converter = DictConverter.class) + @Excel(name = "所属项目",width = 30,dict = "tb_projects,project_name,id") + @Dict(dictTable = "tb_projects",dicCode = "id",dicText = "project_name") + private String projectId; + + @Excel(name = "车牌号",width = 15) + private String plateNumber; + + @Excel(name = "车架号",width = 20) + private String frameNumber; + + @Excel(name = "所属车商",width = 20,dict = "tb_vehicle_supplier_archives,shortened,id") + @Dict(dictTable = "tb_vehicle_supplier_archives",dicCode = "id",dicText = "shortened") + private String dealer; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy年MM月dd日") + @Excel(name = "交付时间",width = 20,format = "yyyy-MM-dd HH:mm:ss") + private Date deliveryTime; + + @Excel(name = "品牌",width = 15,dict = "vehicle_brand") + @Dict(dicCode = "vehicle_brand") + private String vehicleBrand; + + @Excel(name = "型号",width = 15) + private String vehicleModel; + + @Excel(name = "车辆种类",width = 20,dict = "vehicle_type") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @Excel(width = 15,name = "车辆成本(万元)") + private String cost; + + @Excel(width = 15,name = "使用年限(年)") + private String age; + + @Excel(width = 15,name = "行驶里程(km)") + private String driverMile; + + @Excel(width = 15,name = "行驶时长(h)") + private String driverHour; + + @Excel(width = 15,name = "作业里程(km)") + private String workMile; + + @Excel(width = 15,name = "作业时长(h)") + private String workHour; + + @Excel(width = 15,name = "租金收入(万元)") + private String rentalIncome; + + @Excel(width = 15,name = "剩余价值(万元)") + private String residualValue; + + @Excel(width = 15,name = "维修次数") + private String repairNum; + + @Excel(width = 15,name = "维修费用(元)") + private String repairFee; + + @Excel(width = 15,name = "保险费用(元)") + private String insuranceFee; + + @Excel(width = 15,name = "年检费用(元)") + private String annualFee; + + @Excel(width = 15,name = "保养费用(元)") + private String upkeepFee; + +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/VehicleRentalVo.java b/src/main/java/com/gci/boot/modules/statis/vo/VehicleRentalVo.java new file mode 100644 index 0000000..017887d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/VehicleRentalVo.java @@ -0,0 +1,91 @@ +package com.gci.boot.modules.statis.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.common.dict.annotation.Dict; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 车辆租金收益vo + * @author 24642 + */ +@Getter +@Setter +@ToString +public class VehicleRentalVo { + @Excel(name = "车辆种类",dict = "vehicle_type",width = 9) + @JsonPropertyDescription("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @Excel(name = "车牌号") + @JsonPropertyDescription("车牌号") + private String plateNumber; + + @JsonPropertyDescription("车架号") + @Excel(name = "车架号") + private String frameNumber; + + @JsonPropertyDescription("车辆型号") +// @Excel(name = "车辆型号") + private String vehicleModel; + + @Excel(name = "合同名称") + @JsonPropertyDescription("合同名称") + private String contractName; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("合同生效日期") + @Excel(name = "合同生效日期",width = 11,format = "yyyy-MM-dd") + private Date contractStartDate; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("合同终止日期") + @Excel(name = "合同终止日期",width = 11,format = "yyyy-MM-dd") + private Date contractEndDate; + + @Excel(name = "租赁单价(元/月/台)",numFormat = "#.##") + private BigDecimal rentalUnitPrice; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("租赁交车日期") + @Excel(name = "租赁交车日期",width = 11,format = "yyyy-MM-dd") + private Date rentalDeliveryDate; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("租赁收车日期") + @Excel(name = "租赁收车日期",width = 11,format = "yyyy-MM-dd") + private Date rentalPickupDate; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("收款日期") + @Excel(name = "收款日期",width = 11,format = "yyyy-MM-dd") + private Date paymentDate; + + @JsonPropertyDescription("收款金额") + @Excel(name = "收款金额",numFormat = "#.##") + private BigDecimal amountCollected; + + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("查询收款日期开始") + private Date paymentDateStart; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @JsonPropertyDescription("查询收款日期结束") + private Date paymentDateEnd; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/VehicleStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/VehicleStatisVo.java new file mode 100644 index 0000000..d946075 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/VehicleStatisVo.java @@ -0,0 +1,85 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author 24642 + */ +@Data +public class VehicleStatisVo { + @JsonPropertyDescription("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") +// @ExcelProperty(value = "所属项目",converter = DictConverter.class) +// @ColumnWidth(value = 30) + @ExcelIgnore + private String projectId; + + @JsonPropertyDescription("车牌号") + @ExcelProperty(value = "车牌号",order = 4) + private String plateNumber; + + @JsonPropertyDescription("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类",converter = DictConverter.class,order = 1) + private String vehicleType; + + @JsonPropertyDescription("品牌") + @Dict(dicCode = "vehicle_brand") + @ExcelProperty(value = "品牌",converter = DictConverter.class,order = 2) + private String vehicleBrand; + + @JsonPropertyDescription("型号") + @ExcelProperty(value = "型号",order = 3) + private String vehicleModel; + + @JsonPropertyDescription("车架号") + @ExcelProperty(value = "车架号",order = 5) + private String frameNumber; + + @JsonPropertyDescription("运行年限") + @ExcelProperty(value = "运行年限",order = 6) + private String statisTime; + + @JsonPropertyDescription("维修次数") + @ExcelIgnore + private Long repairNum = 0L; + + @JsonPropertyDescription("采购费用") + @ExcelProperty(value = "采购费用(万元)",order = 7) + private Double price = 0.0; + + @JsonPropertyDescription("改装费用") + @ExcelProperty(value = "改装费用(元)",order = 8) + private Double modificationCosts = 0.0; + + @JsonPropertyDescription("维修金额") + @ExcelProperty(value = "维修费用(元)",order = 9) + private Double repairAmount = 0.0; + + @JsonPropertyDescription("保养金额") + @ExcelProperty(value = "保养费用(元)",order = 10) + private Double upkeepAmount = 0.0; + + @JsonPropertyDescription("保险金额") + @ExcelProperty(value = "保险费用(元)",order = 11) + private Double insuranceAmount = 0.0; + + @JsonPropertyDescription("年检金额") + @ExcelProperty(value = "年检费用(元)",order = 12) + private Double inspectionAmount = 0.0; + + @JsonPropertyDescription("违章金额") + @ExcelProperty(value = "违章费用(元)",order = 13) + private Double violationAmount = 0.0; + + @JsonPropertyDescription("能耗金额") + @ExcelProperty(value = "能耗费用(元)",order = 14) + private Double energyAmount = 0.0; +} diff --git a/src/main/java/com/gci/boot/modules/statis/vo/ViolationRecordStatisVO.java b/src/main/java/com/gci/boot/modules/statis/vo/ViolationRecordStatisVO.java new file mode 100644 index 0000000..deca30b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/ViolationRecordStatisVO.java @@ -0,0 +1,48 @@ +package com.gci.boot.modules.statis.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class ViolationRecordStatisVO { + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + private String projectName; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("统计时间") + private String statisTime; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("违章车次") + private Integer violationTimes; + + @ApiModelProperty("违章金额") + private Double violationAmount = 0.0; + + @ApiModelProperty("平均金额") + private Double avgAmount = 0.0; + + @ApiModelProperty("违章行为字典值s") + private String violationActIds; + + private List colList; + +} + diff --git a/src/main/java/com/gci/boot/modules/statis/vo/WeighbridgeStatisVo.java b/src/main/java/com/gci/boot/modules/statis/vo/WeighbridgeStatisVo.java new file mode 100644 index 0000000..364ca90 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/statis/vo/WeighbridgeStatisVo.java @@ -0,0 +1,64 @@ +package com.gci.boot.modules.statis.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +/** + * 地磅数据 + * @author 24642 + */ +@Getter +@Setter +public class WeighbridgeStatisVo { + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @Excel(name = "所属项目",dict = "tb_projects,project_name,id",width = 9) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @JsonPropertyDescription("所属项目") + private String projectId; + + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Excel(name = "车辆种类",dict = "vehicle_type") + @JsonPropertyDescription("车辆种类") + private String vehicleType; + + @Dict(dicCode = "vehicle_brand") + @Excel(name = "品牌",dict = "vehicle_brand") + @JsonPropertyDescription("品牌") + private String vehicleBrand; + + @Excel(name = "型号") + @JsonPropertyDescription("型号") + private String vehicleModel; + + @SelectQuery() + @Excel(name = "车牌号") + @JsonPropertyDescription("车牌号") + private String plateNumber; + + @SelectQuery() + @Excel(name = "车架号") + @JsonPropertyDescription("车架号") + private String frameNumber; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @Excel(name = "进出场时间",format = "yyyy-MM-dd HH:mm:ss") + @JsonPropertyDescription("进出场时间") + private Date time; + + @Excel(name = "重量(kg)") + @JsonPropertyDescription("重量(kg)") + private Double weight; + + @Excel(name = "转运压缩站名称") + @JsonPropertyDescription("转运压缩站名称") + private String stationName; +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/LoginController.java b/src/main/java/com/gci/boot/modules/system/controller/LoginController.java new file mode 100644 index 0000000..e92a59c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/LoginController.java @@ -0,0 +1,270 @@ +package com.gci.boot.modules.system.controller; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.json.JSONUtil; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.CacheUtil; +import com.gci.boot.common.util.LimitCheckUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.common.util.MD5Util; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.system.entity.LoginTimesValidate; +import com.gci.boot.modules.system.service.LoginTimesValidateService; +import com.gci.boot.modules.system.vo.ApiTokenModel; +import com.gci.boot.modules.system.vo.LimitRequest; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.properties.GciSecurityProperties; +import com.gci.boot.modules.system.util.PasswordUtil; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.modules.system.util.AesEncryptUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.vo.SysLoginModel; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.shiro.authc.JwtToken; +import com.gci.boot.modules.system.shiro.vo.DefContants; +import com.gci.boot.modules.system.util.JwtUtil; +import com.gci.boot.modules.system.util.RandImageUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/sys") +@Api(tags = "用户登录") +@EnableConfigurationProperties(GciSecurityProperties.class) +@Slf4j +public class LoginController { + + @Autowired + private ISysUserService sysUserService; + + @Autowired + private LoginTimesValidateService loginTimesValidateService; + + @Autowired + private GciSecurityProperties gciSecurityProperties; + + private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890"; + + @PostMapping("/getApiToken") + public Result getApiToken(@RequestBody ApiTokenModel apiTokenModel, HttpServletRequest request) { + try { + //检查 + String captcha = apiTokenModel.getAppKey(); + if (captcha == null) { + return Result.error("密钥无效!"); + } + //1. 校验用户是否有效 + SysUser user = sysUserService.getByUsername(apiTokenModel.getAppId()); + if(user == null || CommonConstant.USER_FREEZE.toString().equals(user.getStatus())){ + //return Result.error("用户不存在!"); + return Result.error("分配账号或密码错误!"); + } + String username = user.getUsername(); + //2. 校验用户名或密码是否正确 + LimitCheckUtil.check(request, username,null); + String userPassword = apiTokenModel.getAppKey(); + String sysPassword = user.getPassword(); + if(!userPassword.equals(sysPassword)){ + return Result.error("分配账号或密钥错误!"); + } + //3.生成token,存redis + Subject currentUser = SecurityUtils.getSubject(); + String token = JwtUtil.sign(username, user.getPassword()); + //每天限制指定次数 + LimitCheckUtil.putNeedCheck(username,token); + // 设置token缓存有效时间 + RedisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token, gciSecurityProperties.getShiro().getExpireTime()/1000); + currentUser.login(new JwtToken(token)); + Map resultMap = new HashMap<>(); + resultMap.put("token", token); + return Result.ok(resultMap); + }catch (GciBootException gciBootException){ + log.error("",gciBootException); + return Result.error(gciBootException.getMessage()); + }catch (Exception e) { + log.error("", e); + return Result.error("获取密钥失败!"); + } + } + + + @AddSysLog(value = "用户登录", logType = 1) + @PostMapping("/login") + public Result login(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request) { + try { + //检查验证码 + String captcha = sysLoginModel.getCaptcha(); + if (captcha == null) { + return Result.error("验证码无效!"); + } + String lowerCaseCaptcha = captcha.toLowerCase(); + String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + sysLoginModel.getCheckKey(), "utf-8"); + Object checkCode = RedisUtil.get(realKey); + RedisUtil.del(realKey); + if (checkCode == null || !checkCode.equals(lowerCaseCaptcha)) { + return Result.error("验证码错误!"); + } + //1. 校验用户是否有效 + SysUser user = sysUserService.getByUsername(sysLoginModel.getUsername()); + if(user == null || CommonConstant.USER_FREEZE.toString().equals(user.getStatus())){ + //return Result.error("用户不存在!"); + return Result.error("账号或密码错误!"); + } + //2. 校验用户名或密码是否正确 + String password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim(); + String userpassword = PasswordUtil.encrypt(sysLoginModel.getUsername(), password, user.getSalt()); + String syspassword = user.getPassword(); + + LoginTimesValidate validate = loginTimesValidateService.getManageTimes(sysLoginModel.getUsername()); + if (validate.nonTimes()) { + return Result.error("连续输入错误密码次数超限,请稍后重试"); + } + + if(!userpassword.equals(syspassword)){ + loginTimesValidateService.saveManageTimes(validate); + return Result.error("账号或密码错误!"); + } + //3.生成token,存redis + Subject currentUser = SecurityUtils.getSubject(); + + String token = JwtUtil.sign(user.getUsername(), user.getPassword()); + + String pcToken = String.valueOf(RedisUtil.get(CommonConstant.PREFIX_PC_USER + user.getUsername())); + if(ObjectUtil.isNotEmpty(pcToken)){ + RedisUtil.del(CommonConstant.PREFIX_USER_TOKEN + pcToken); + } + // 设置token缓存有效时间 + RedisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token, gciSecurityProperties.getShiro().getExpireTime()/1000); + RedisUtil.set(CommonConstant.PREFIX_PC_USER+user.getUsername(),token); + + currentUser.login(new JwtToken(token)); + + Map resultMap = new HashMap<>(); + user.setPhone(sysUserService.processPhone(user)); + user.setPassword(null); + user.setSalt(null); + user.setEncryptPhone(null); + user.setSecretPhone(null); + + resultMap.put("userInfo", user); + resultMap.put("token", token); + return Result.ok(resultMap); + } catch (Exception e) { + log.error("", e); + return Result.error("登录失败!"); + } + } + + /** + * 后台生成图形验证码 :有效 + * + * @param key + */ + @ApiOperation("获取验证码") + @GetMapping("/randomImage/{key}") + public Result randomImage(@PathVariable String key) { + Result res = new Result(); + try { + String code = RandomUtil.randomString(BASE_CHECK_CODES, 4); + String lowerCaseCode = code.toLowerCase(); + String realKey = MD5Util.MD5Encode(lowerCaseCode + key, "utf-8"); + RedisUtil.set(realKey, lowerCaseCode, 60); + String base64 = RandImageUtil.generate(code); + res.setSuccess(true); + res.setResult(base64); + } catch (Exception e) { + res.error500("获取验证码出错" + e.getMessage()); + e.printStackTrace(); + } + return res; + } + /** + * 退出登录 + * + * @param request + * @return + */ + @AddSysLog(value = "退出登录", logType = 1) + @RequestMapping("/logout") + public Result logout(HttpServletRequest request) { + //用户退出逻辑 + String token = request.getHeader(DefContants.X_ACCESS_TOKEN); + if (StringUtils.isBlank(token)) { + return Result.error("退出登录失败!"); + } + String username = JwtUtil.getUsername(token); + SysUser sysUser = sysUserService.getByUsername(username); + if (sysUser != null) { + log.info(" 用户名: " + sysUser.getRealname() + ",退出成功! "); + //清空用户登录Token缓存 + RedisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token); + //调用shiro的logout + SecurityUtils.getSubject().logout(); + //清空用户的缓存信息(包括部门信息),例如sys:cache:user:: + CacheUtil.evit(CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()); + //清空用户登录Shiro权限缓存 + CacheUtil.evit(CacheConstant.SYS_AUTHORIZATION_CACHE, sysUser.getUsername()); + return Result.ok("退出登录成功!"); + } else { + return Result.error("Token无效!"); + } + } + + /** + * 获取加密字符串 + * + * @return + */ + @GetMapping("/getEncryptedString") + public Result> getEncryptedString() { + Result> result = new Result>(); + Map map = new HashMap(); + map.put("key", AesEncryptUtil.key); + map.put("iv", AesEncryptUtil.iv); + result.setResult(map); + return result; + } + + + /** + * 登陆成功选择用户当前部门 + * + * @param user + * @return + */ + @ApiOperation("切换部门接口") + @PutMapping("/selectDepart") + public Result selectDepart(@RequestBody SysUser user) { + String username = user.getUsername(); + LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if (StringUtils.isBlank(username)) { + username = loginUser.getUsername(); + } + String orgCode = user.getOrgCode(); + loginUser.setOrgCode(user.getOrgCode()); + sysUserService.lambdaUpdate().eq(SysUser::getUsername, username) + .set(SysUser::getOrgCode, orgCode) + .update(); + SysUser sysUser = sysUserService.getByUsername(username); + CacheUtil.evit(CacheConstant.SYS_USERS_CACHE, username); + Map map = new HashMap<>(); + map.put("userInfo", sysUser); + return Result.ok(map); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysDepartController.java b/src/main/java/com/gci/boot/modules/system/controller/SysDepartController.java new file mode 100644 index 0000000..c4c0300 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysDepartController.java @@ -0,0 +1,292 @@ +package com.gci.boot.modules.system.controller; + + +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.system.entity.SysDepart; +import com.gci.boot.modules.system.service.ISysDepartService; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.system.vo.SysDepartTreeModel; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.*; + +/** + *

+ * 组织机构表 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-08-31 + */ +@RestController +@RequestMapping("/sys/depart") +@Slf4j +public class SysDepartController { + + @Autowired + private ISysDepartService sysDepartService; + + + /** + * 查询数据 查出所有部门,并以树结构数据格式响应给前端 + * + * @return + */ + @AddSysLog("查询部门") + @GetMapping("/queryTreeList") + public Result> queryTreeList(String name, SysDepart sysDepart) { + try { + if(StringUtils.isNotBlank(name)){ + sysDepart.setDepartName(name); + } + + return Result.ok(queryDepartTree(sysDepart)); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return Result.error("获取部门失败!"); + } + + + private List queryDepartTree(SysDepart sysDepart){ + List res = new ArrayList<>(); + Map allMap = new HashMap<>(); + Map> childrenMap = new HashMap<>(); + QueryWrapper queryWrapper = QueryWrapperUtil.builder().table(SysDepart.class) + .like(SysDepart::getDepartName) + .orderByAsc(SysDepart::getDepartOrder) + .buildFromObject(sysDepart); + + sysDepartService.list(queryWrapper).forEach(i -> { + SysDepartTreeModel t = new SysDepartTreeModel(); + BeanUtils.copyProperties(i, t); + allMap.put(t.getId(), t); + if (StringUtils.isBlank(i.getParentId())) { + res.add(t); + } else { + List children = childrenMap.get(t.getParentId()); + if (children == null) { + children = new ArrayList<>(); + childrenMap.put(t.getParentId(), children); + } + children.add(t); + } + }); + childrenMap.forEach((k, v) -> { + SysDepartTreeModel t = allMap.get(k); + if (t != null) { + t.setChildren(v); + }else{ + res.addAll(v); + } + }); + return res; + } + @AddSysLog("查询部门") + @GetMapping("/querySubTree") + public Result> querySubTree(SysDepart sysDepart) { + try { + if(StringUtils.isBlank(sysDepart.getOrgCode())){ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(sysUser != null){ + sysDepart.setOrgCode(sysUser.getOrgCode()); + } + } + SysDepart one = sysDepartService.lambdaQuery().eq(SysDepart::getOrgCode, sysDepart.getOrgCode()).one(); + if(one.getOrgCategory() != null && (one.getOrgCategory() == 2 || one.getOrgCategory() == 3)){ + Map allMap = new HashMap<>(); + List res = new ArrayList<>(); + List idList = new ArrayList<>(); + SysDepartTreeModel t = new SysDepartTreeModel(); + BeanUtils.copyProperties(one, t); + allMap.put(t.getId(), t); + res.add(t); + idList.add(one.getId()); + + while(idList.size()>0){ + List list = sysDepartService.lambdaQuery() + .in(SysDepart::getParentId, idList) + .orderByAsc(SysDepart::getDepartOrder) + .list(); + idList.clear(); + list.forEach(i->{ + SysDepartTreeModel tr = new SysDepartTreeModel(); + BeanUtils.copyProperties(i, tr); + allMap.put(tr.getId(), tr); + SysDepartTreeModel parent = allMap.get(tr.getParentId()); + if(parent != null){ + if(parent.getChildren() == null){ + parent.setChildren(new ArrayList<>()); + } + parent.getChildren().add(tr); + } + idList.add(i.getId()); + }); + } + return Result.ok(res); + } + + + return Result.ok(queryDepartTree(new SysDepart())); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return Result.error("获取部门失败!"); + } + + /** + * 添加部门 + * + * @param sysDepart + * @return + */ + @AddSysLog("添加部门") + @PostMapping("/add") + public Result add(@RequestBody SysDepart sysDepart) { + ParamsCheckUtil.paramsAssert() + .notBlank(sysDepart.getOrgCode(), "【机构编码】不能为空!") + .notBlank(sysDepart.getDepartName(), "【机构名称】不能为空!") + .notNull(sysDepart.getOrgCategory(), "【机构类型】不能为空!") + .isTrue(sysDepartService.lambdaQuery().eq(SysDepart::getOrgCode, sysDepart.getOrgCode()).count() == 0, "【机构编码】已存在!"); + if(StringUtils.isBlank(sysDepart.getParentId())){ + ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().and(w->w.isNull(SysDepart::getParentId).or().eq(SysDepart::getParentId, "")).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称!"); + }else{ + ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().eq(SysDepart::getParentId, sysDepart.getParentId()).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称!"); + } + sysDepartService.save(sysDepart); + return Result.ok("添加成功!"); + } + + /** + * 编辑数据 编辑部门的部分数据,并保存到数据库 + * + * @param sysDepart + * @return + */ + @AddSysLog("编辑部门") + @PutMapping("/edit") + public Result edit(@RequestBody SysDepart sysDepart) { + SysDepart sysDepartEntity = sysDepartService.getById(sysDepart.getId()); + if (sysDepartEntity == null) { + return Result.error("未找到对应部门!"); + } + ParamsCheckUtil.paramsAssert() + .notBlank(sysDepart.getOrgCode(), "【机构编码】不能为空!") + .notBlank(sysDepart.getDepartName(), "【机构名称】不能为空!") + .notNull(sysDepart.getOrgCategory(), "【机构类型】不能为空!") + .isTrue(sysDepartService.lambdaQuery() + .ne(SysDepart::getId, sysDepart.getId()) + .eq(SysDepart::getOrgCode, sysDepart.getOrgCode()).count() == 0, "【机构编码】已存在!"); + if(StringUtils.isBlank(sysDepartEntity.getParentId())){ + ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().and(w->w.isNull(SysDepart::getParentId).or().eq(SysDepart::getParentId, "")).ne(SysDepart::getId, sysDepart.getId()).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称!"); + }else{ + ParamsCheckUtil.assertTrue(sysDepartService.lambdaQuery().ne(SysDepart::getId, sysDepart.getId()).eq(SysDepart::getParentId, sysDepartEntity.getParentId()).eq(SysDepart::getDepartName, sysDepart.getDepartName()).count() == 0, "同级机构存在相同名称!"); + } + sysDepartService.updateById(sysDepart); + return Result.ok("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AddSysLog("删除部门") + @DeleteMapping("/delete") + public Result delete(String id) { + SysDepart sysDepart = sysDepartService.getById(id); + if (sysDepart == null) { + return Result.error("未找到对应实体"); + } + Integer count = sysDepartService.lambdaQuery().eq(SysDepart::getParentId, id).count(); + if(count > 0){ + return Result.error("存在下级部门,无法删除!"); + } + sysDepartService.removeById(id); + return Result.ok("删除成功!"); + } + + + /** + * 批量删除 根据前端请求的多个ID,对数据库执行删除相关部门数据的操作 + * + * @param ids + * @return + */ + @AddSysLog("批量删除部门") + @DeleteMapping("/deleteBatch") + public Result deleteBatch(String ids) { + if (ids == null || "".equals(ids.trim())) { + return Result.error("参数不识别!"); + } + this.sysDepartService.deleteBatchWithChildren(Arrays.asList(ids.split(","))); + return Result.ok("删除成功!"); + } + + @PostMapping("/importExcel") + public Result simpleImport(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(SysDepart.class).sheet().doReadSync(); + log.info("数据量:{}",list.size()); + for(SysDepart d : list){ + List one = sysDepartService.lambdaQuery().eq(SysDepart::getDepartName, d.getDepartName()).list(); + if(one.size()>0){ + d.setId(one.get(0).getId()); + } + } + sysDepartService.saveOrUpdateBatch(list); + }catch (IOException e){ + return Result.error("导入错误!"); + } + } + return Result.ok(); + } + + @GetMapping("/exportExcel") + public Result export(String name, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "部门信息.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + List list = sysDepartService.lambdaQuery() + .like(StringUtils.isNotBlank(name), SysDepart::getDepartName, name) + .orderByAsc(SysDepart::getDepartOrder) + .list(); + EasyExcel.write(output, SysDepart.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysDictController.java b/src/main/java/com/gci/boot/modules/system/controller/SysDictController.java new file mode 100644 index 0000000..625f717 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysDictController.java @@ -0,0 +1,221 @@ +package com.gci.boot.modules.system.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.common.util.SqlInjectionCheckUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.entity.SysDict; +import com.gci.boot.modules.system.entity.SysDictItem; +import com.gci.boot.modules.system.service.ISysDictItemService; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +/** + *

+ * 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +@RestController +@RequestMapping("/sys/dict") +@Slf4j +public class SysDictController { + @Autowired + private ISysDictService sysDictService; + @Autowired + private ISysDictItemService sysDictItemService; + + @AddSysLog("查询字典列表") + @GetMapping("/list") + public Result> queryPageList(SysDict sysDict, String column, String order, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + if(StringUtils.isBlank(column)){ + column = "create_time"; + order = "desc"; + } + QueryWrapper queryWrapper = QueryWrapperUtil.builder() + .table(SysDict.class) + .like(SysDict::getDictName) + .like(SysDict::getDictCode) + .like(SysDict::getDescription) + .orderColums(column) + .orders(order) + .buildFromObject(sysDict); + Page page = new Page(pageNo, pageSize); + IPage pageList = sysDictService.page(page, queryWrapper); + log.debug("查询当前页:" + pageList.getCurrent()); + log.debug("查询当前页数量:" + pageList.getSize()); + log.debug("查询结果数量:" + pageList.getRecords().size()); + log.debug("数据总数:" + pageList.getTotal()); + return Result.ok(pageList); + } + + + /** + * @param sysDict + * @return + * @功能:新增 + */ + @AddSysLog("添加字典") + @PostMapping("/add") + public Result add(@RequestBody SysDict sysDict) { + ParamsCheckUtil.paramsAssert() + .notBlank(sysDict.getDictCode(), "【字典编码】不能为空!") + .notBlank(sysDict.getDictName(), "【字典名称】不能为空!") + .notNull(sysDict.getType(), "【数据类型】不能为空!") + .isTrue(sysDictService.lambdaQuery().eq(SysDict::getDictCode, sysDict.getDictCode()).count() == 0, "【字典编码】已存在!") + .isTrue(sysDictService.lambdaQuery().eq(SysDict::getDictName, sysDict.getDictName()).count() == 0, "【字典名称】已存在!") + ; + sysDictService.save(sysDict); + return Result.ok("保存成功!"); + } + + /** + * @param sysDict + * @return + * @功能:编辑 + */ + @AddSysLog("编辑字典") + @PutMapping("/edit") + @CacheEvict(value = CacheConstant.SYS_DICT_CACHE, key = "#sysDict.id") + public Result edit(@RequestBody SysDict sysDict) { + ParamsCheckUtil.ParamsAssert paramsAssert = ParamsCheckUtil.paramsAssert() + .notBlank(sysDict.getId(), "【字典ID】不能为空!"); + SysDict dict = sysDictService.getById(sysDict.getId()); + if (dict == null) { + return Result.error("未找到对应实体"); + } + paramsAssert.notBlank(sysDict.getDictCode(), "【字典编码】不能为空!") + .notBlank(sysDict.getDictName(), "【字典名称】不能为空!") + .notNull(sysDict.getType(), "【数据类型】不能为空!") + .isTrue(sysDictService.lambdaQuery().ne(SysDict::getId, sysDict.getId()).eq(SysDict::getDictCode, sysDict.getDictCode()).count() == 0, "【字典编码】已存在!") + .isTrue(sysDictService.lambdaQuery().ne(SysDict::getId, sysDict.getId()).eq(SysDict::getDictName, sysDict.getDictName()).count() == 0, "【字典名称】已存在!") + ; + sysDictService.updateById(sysDict); + return Result.ok("编辑成功"); + } + + /** + * @param id + * @return + * @功能:删除 + */ + @AddSysLog("删除字典") + @DeleteMapping("/delete") + @CacheEvict(value = CacheConstant.SYS_DICT_CACHE, key = "#id") + public Result delete(String id) { + sysDictService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * @param ids + * @return + * @功能:批量删除 + */ + @AddSysLog("批量删除字典") + @DeleteMapping("/deleteBatch") + @CacheEvict(value = CacheConstant.SYS_DICT_CACHE, allEntries = true) + public Result deleteBatch(String ids) { + if (StringUtils.isBlank(ids)) { + return Result.error("参数不识别!"); + } + sysDictService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("删除成功!"); + } + + + /** + * 前端加载所有数据字典 + * + * @return + */ + @GetMapping("/queryAllDictItems") + public Result loadAllDict() { + Map dictCodeMap = new HashMap<>(); + Map> res = new LinkedHashMap<>(); + sysDictService.lambdaQuery().list().forEach(dict -> { + dictCodeMap.put(dict.getId(), dict.getDictCode()); + res.put(dict.getDictCode(), new ArrayList<>()); + }); + sysDictItemService.lambdaQuery() + .eq(SysDictItem::getStatus, 1) + .orderByAsc(SysDictItem::getSortOrder) + .list() + .forEach(item -> { + DictModel dictModel = new DictModel(); + dictModel.setText(item.getItemText()); + dictModel.setValue(item.getItemValue()); + List dictModels = res.get(dictCodeMap.get(item.getDictId())); + if (dictModels != null) { + dictModels.add(dictModel); + } + }); + + log.debug("-------登录加载系统字典-----"); + log.debug("{}", res); + return Result.ok(res); + } + + /** + * 获取字典数据 + * + * @param dictCode 字典code + * @param dictCode 表名,文本字段,code字段 | 举例:sys_user,realname,id + * @return + */ + @GetMapping("/getDictItems/{dictCode}") + public Result getDictItems(@PathVariable String dictCode) { + log.info(" dictCode : " + dictCode); + List ls; + try { + if (dictCode.indexOf(",") != -1) { + //关联表字典(举例:sys_user,realname,id) + String[] params = dictCode.split(","); + + if (params.length < 3) { + return Result.error("字典Code格式不正确!"); + } + //SQL注入校验(只限制非法串改数据库) + if (SqlInjectionCheckUtil.containsSqlInjection(params[0], params[1], params[2])) { + return Result.error("查询失败!参数存在SQL注入风险"); + } + if (params.length == 4) { + //条件允许单引号‘ + if (SqlInjectionCheckUtil.containsSqlInjection(params[3].replace("'", ""))) { + return Result.error("查询失败!参数存在SQL注入风险"); + } + ls = sysDictService.queryTableDictItemsByCodeAndFilter(params[0], params[1], params[2], params[3]); + } else if (params.length == 3) { + ls = sysDictService.queryTableDictItemsByCode(params[0], params[1], params[2]); + } else { + return Result.error("字典Code格式不正确!"); + } + } else { + //字典表 + ls = sysDictService.queryDictItemsByCode(dictCode); + } + } catch (Exception e) { + log.error("", e); + return Result.error("字典Code格式不正确!"); + } + + return Result.ok(ls); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysDictItemController.java b/src/main/java/com/gci/boot/modules/system/controller/SysDictItemController.java new file mode 100644 index 0000000..12e57ab --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysDictItemController.java @@ -0,0 +1,147 @@ +package com.gci.boot.modules.system.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.system.entity.SysDictItem; +import com.gci.boot.modules.system.service.ISysDictItemService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; + +/** + *

+ * 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +@RestController +@RequestMapping("/sys/dictItem") +@Slf4j +public class SysDictItemController { + @Autowired + private ISysDictItemService sysDictItemService; + + /** + * @功能:查询字典数据 + * @param sysDictItem + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("查询字典项") + @GetMapping("/list") + public Result> queryPageList(SysDictItem sysDictItem, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) { + QueryWrapper queryWrapper = QueryWrapperUtil.builder() + .table(SysDictItem.class) + .like(SysDictItem::getItemText) + .like(SysDictItem::getItemValue) + .orderByAsc(SysDictItem::getSortOrder) + .buildFromObject(sysDictItem); + Page page = new Page<>(pageNo, pageSize); + IPage pageList = sysDictItemService.page(page, queryWrapper); + return Result.ok(pageList); + } + + /** + * @功能:新增 + * @return + */ + @AddSysLog("添加字典项") + @PostMapping("/add") + public Result add(@RequestBody SysDictItem sysDictItem) { + ParamsCheckUtil.paramsAssert() + .notBlank(sysDictItem.getDictId(), "【字典ID】不能为空!") + .notBlank(sysDictItem.getItemText(), "【名称】不能为空!") + .notBlank(sysDictItem.getItemValue(), "【数据值】不能为空!") + .notNull(sysDictItem.getStatus(), "【是否启用】不能为空!") + .isTrue(sysDictItemService.lambdaQuery() + .eq(SysDictItem::getDictId, sysDictItem.getDictId()) + .eq(SysDictItem::getItemText, sysDictItem.getItemText()).count()==0, "【名称】已存在!") + .isTrue(sysDictItemService.lambdaQuery() + .eq(SysDictItem::getDictId, sysDictItem.getDictId()) + .eq(SysDictItem::getItemValue, sysDictItem.getItemValue()).count()==0, "【数据值】已存在!") + ; + sysDictItemService.save(sysDictItem); + return Result.ok("添加成功!"); + } + + /** + * @功能:编辑 + * @param sysDictItem + * @return + */ + @AddSysLog("编辑字典项") + @PutMapping("/edit") + @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + public Result edit(@RequestBody SysDictItem sysDictItem) { + SysDictItem sysdict = sysDictItemService.getById(sysDictItem.getId()); + if(sysdict==null) { + return Result.error("字典项不存在!"); + } + ParamsCheckUtil.paramsAssert() + .notBlank(sysDictItem.getDictId(), "【字典ID】不能为空!") + .notBlank(sysDictItem.getItemText(), "【名称】不能为空!") + .notBlank(sysDictItem.getItemValue(), "【数据值】不能为空!") + .notNull(sysDictItem.getStatus(), "【是否启用】不能为空!") + .isTrue(sysDictItemService.lambdaQuery() + .eq(SysDictItem::getDictId, sysDictItem.getDictId()) + .ne(SysDictItem::getId, sysDictItem.getId()) + .eq(SysDictItem::getItemText, sysDictItem.getItemText()).count()==0, "【名称】已存在!") + .isTrue(sysDictItemService.lambdaQuery() + .eq(SysDictItem::getDictId, sysDictItem.getDictId()) + .ne(SysDictItem::getId, sysDictItem.getId()) + .eq(SysDictItem::getItemValue, sysDictItem.getItemValue()).count()==0, "【数据值】已存在!") + ; + sysDictItemService.updateById(sysDictItem); + return Result.ok("编辑成功"); + } + + /** + * @功能:删除字典数据 + * @param id + * @return + */ + @AddSysLog("删除字典项") + @DeleteMapping("/delete") + @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + public Result delete(String id) { + SysDictItem joinSystem = sysDictItemService.getById(id); + if(joinSystem==null) { + return Result.error("未找到对应字典项"); + } + sysDictItemService.removeById(id); + return Result.ok("删除成功"); + } + + /** + * @功能:批量删除字典数据 + * @param ids + * @return + */ + @AddSysLog("批量删除字典项") + @DeleteMapping("/deleteBatch") + @CacheEvict(value=CacheConstant.SYS_DICT_CACHE, allEntries=true) + public Result deleteBatch(String ids) { + if(ids==null || "".equals(ids.trim())) { + return Result.error("参数不识别!"); + } + this.sysDictItemService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("删除成功!"); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysLogController.java b/src/main/java/com/gci/boot/modules/system/controller/SysLogController.java new file mode 100644 index 0000000..b19b2ac --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysLogController.java @@ -0,0 +1,101 @@ +package com.gci.boot.modules.system.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.system.entity.SysLog; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.service.ISysLogService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpRequest; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; + +/** + *

+ * 系统日志表 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-09-08 + */ +@RestController +@RequestMapping("/sys/log") +public class SysLogController { + + @Autowired + private ISysLogService sysLogService; + + /** + * @param syslog + * @param pageNo + * @param pageSize + * @return + * @功能:查询日志记录 + */ + @GetMapping("/list") + public Result> queryPageList(SysLog syslog, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + String keyWord = req.getParameter("keyWord"); + if (StringUtils.isNotBlank(keyWord)) { + syslog.setLogContent(keyWord); + } + QueryWrapper queryWrapper = QueryWrapperUtil.builder() + .table(SysLog.class) + .like(SysLog::getLogContent) + .orderColums(req.getParameter("column")) + .orders(req.getParameter("order")) + .buildFromObject(syslog); + String createTimeBegin = req.getParameter("createTime_begin"); + String createTimeEnd = req.getParameter("createTime_end"); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + try { + if (StringUtils.isNotBlank(createTimeBegin)) { + queryWrapper.ge("create_time", dateFormat.parse(createTimeBegin + " 00:00:00")); + } + if (StringUtils.isNotBlank(createTimeEnd)) { + queryWrapper.le("create_time", dateFormat.parse(createTimeEnd + " 23:59:59")); + } + } catch (ParseException e) { + throw new GciBootException("日期出错!"); + } + //创建时间/创建人的赋值 + IPage pageList = sysLogService.page(new Page<>(pageNo, pageSize), queryWrapper); + + return Result.ok(pageList); + } + + /** + * @param id + * @return + * @功能:删除单个日志记录 + */ + @DeleteMapping("/delete") + public Result delete(String id) { + sysLogService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * @param ids + * @return + * @功能:批量,全部清空日志记录 + */ + @DeleteMapping("/deleteBatch") + public Result deleteBatch(String ids) { + this.sysLogService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("删除成功!"); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysPermissionController.java b/src/main/java/com/gci/boot/modules/system/controller/SysPermissionController.java new file mode 100644 index 0000000..63d3963 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysPermissionController.java @@ -0,0 +1,429 @@ +package com.gci.boot.modules.system.controller; + + +import cn.hutool.json.JSONArray; +import com.alibaba.excel.util.StringUtils; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.common.util.MD5Util; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.system.entity.SysPermission; +import com.gci.boot.modules.system.entity.SysRolePermission; +import com.gci.boot.modules.system.vo.SysPermissionTree; +import com.gci.boot.modules.system.vo.TreeModel; +import com.gci.boot.modules.system.service.ISysPermissionService; +import com.gci.boot.modules.system.service.ISysRolePermissionService; +import com.gci.boot.modules.system.shiro.vo.DefContants; +import com.gci.boot.modules.system.util.JwtUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 菜单权限表 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@RestController +@RequestMapping("/sys/permission") +@Slf4j +public class SysPermissionController { + @Autowired + private ISysPermissionService sysPermissionService; + @Autowired + private ISysRolePermissionService sysRolePermissionService; + + /** + * 系统菜单列表(一级菜单) + * + * @return + */ + @AddSysLog("查询一级菜单") + @GetMapping("/getSystemMenuList") + public Result> getSystemMenuList(SysPermission permission) { + try { + permission.setMenuType(CommonConstant.MENU_TYPE_MAIN); + QueryWrapper query = QueryWrapperUtil.builder() + .table(SysPermission.class) + .like(SysPermission::getName) + .orderByAsc(SysPermission::getSortNo) + .buildFromObject(permission); + List list = sysPermissionService.list(query); + List sysPermissionTreeList = new ArrayList(); + for(SysPermission sysPermission : list){ + SysPermissionTree sysPermissionTree = new SysPermissionTree(sysPermission); + sysPermissionTreeList.add(sysPermissionTree); + } + return Result.ok(sysPermissionTreeList); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.error("获取菜单失败!"); + } + } + + /** + * 查询子菜单 + * @param parentId + * @return + */ + @AddSysLog("查询子菜单") + @GetMapping( "/getSystemSubmenu") + public Result> getSystemSubmenu(@RequestParam("parentId") String parentId){ + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(SysPermission::getParentId,parentId); + query.orderByAsc(SysPermission::getSortNo); + List list = sysPermissionService.list(query); + List sysPermissionTreeList = new ArrayList(); + for(SysPermission sysPermission : list){ + SysPermissionTree sysPermissionTree = new SysPermissionTree(sysPermission); + sysPermissionTreeList.add(sysPermissionTree); + } + return Result.ok(sysPermissionTreeList); + } + + /** + * 获取全部的权限树 + * + * @return + */ + @AddSysLog("查询菜单树") + @GetMapping("/queryTreeList") + public Result> queryTreeList() { + // 全部权限ids + List ids = new ArrayList<>(); + LambdaQueryWrapper query = new LambdaQueryWrapper(); + query.orderByAsc(SysPermission::getSortNo); + List list = sysPermissionService.list(query); + for (SysPermission sysPer : list) { + ids.add(sysPer.getId()); + } + List treeList = new ArrayList<>(); + getTreeModelList(treeList, list, null); + + Map resMap = new HashMap(); + resMap.put("treeList", treeList); // 全部树节点数据 + resMap.put("ids", ids);// 全部树ids + return Result.ok(resMap); + } + + /** + * 查询用户拥有的菜单权限和按钮权限(根据TOKEN) + * + * @return + */ + @GetMapping("/getUserPermissionByToken") + public Result getUserPermissionByToken(String token, HttpServletRequest request) { + if(StringUtils.isBlank(token)){ + token = request.getHeader(DefContants.X_ACCESS_TOKEN); + } + if (StringUtils.isBlank(token)) { + return Result.error("TOKEN不允许为空!"); + } + log.info(" ------ 通过令牌获取用户拥有的访问菜单 ---- TOKEN ------ " + token); + String username = JwtUtil.getUsername(token); + List metaList = sysPermissionService.queryByUser(username); + //添加首页路由 + if (!metaList.stream().map(SysPermission::getName).anyMatch(name -> "首页".equals(name))) { + List menus = sysPermissionService.lambdaQuery().eq(SysPermission::getName, "首页").list(); + if(menus.size() > 0) { + metaList.add(0, menus.get(0)); + } + } + Map map = new LinkedHashMap<>(); + List> menuArray = new ArrayList(); + this.getPermissionArray(menuArray, metaList, null); + List> authArray = new ArrayList(); + this.getAuthArray(authArray, metaList); + //查询所有的权限 + LambdaQueryWrapper query = new LambdaQueryWrapper(); + List allAuthList = sysPermissionService.lambdaQuery() + .eq(SysPermission::getMenuType, CommonConstant.MENU_TYPE_BUTTON) + .list(); + List> allauthArray = new ArrayList(); + this.getAllAuthArray(allauthArray, allAuthList); + //路由菜单 + map.put("menu", menuArray); + //按钮权限(用户拥有的权限集合) + map.put("auth", authArray); + //全部权限配置集合(按钮权限,访问权限) + map.put("allAuth", allauthArray); + + return Result.ok(map); + } + + /** + * 添加菜单 + * @param permission + * @return + */ + @AddSysLog("添加菜单") + @PostMapping("/add") + public Result add(@RequestBody SysPermission permission) { + ParamsCheckUtil.paramsAssert().notBlank(permission.getName(), "【菜单名称】不能为空!"); + sysPermissionService.addPermission(permission); + return Result.ok("添加成功!"); + } + + /** + * 编辑菜单 + * @param permission + * @return + */ + @AddSysLog("编辑菜单") + @PutMapping("/edit") + public Result edit(@RequestBody SysPermission permission) { + ParamsCheckUtil.paramsAssert().notBlank(permission.getName(), "【菜单名称】不能为空!"); + sysPermissionService.editPermission(permission); + return Result.ok("修改成功!"); + } + + /** + * 删除菜单 + * @param id + * @return + */ + @AddSysLog("删除菜单") + @DeleteMapping("/delete") + public Result delete(String id) { + sysPermissionService.deletePermission(id); + return Result.ok("删除成功!"); + } + + /** + * 获取菜单数组 + * + * @param array + * @param metaList + * @param parentMap + */ + private void getPermissionArray(List> array, List metaList, Map parentMap) { + for (SysPermission permission : metaList) { + if (permission.getMenuType() == null) { + continue; + } + String tempPid = permission.getParentId(); + Map map = getPermissionMap(permission); + if (map == null) { + continue; + } + if (parentMap == null && StringUtils.isBlank(tempPid)) { + array.add(map); + if (permission.getIsLeaf() == null || permission.getIsLeaf() != 1) { + getPermissionArray(array, metaList, map); + } + } else if (parentMap != null && StringUtils.isNotBlank(tempPid) && tempPid.equals(parentMap.get("id"))) { + // 类型( 0:一级菜单 1:子菜单 2:按钮 ) + if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_BUTTON)) { + Map metaJson = (Map) parentMap.get("meta"); + if (metaJson.containsKey("permissionList")) { + ((List>) metaJson.get("permissionList")).add(map); + } else { + JSONArray permissionList = new JSONArray(); + permissionList.add(map); + metaJson.put("permissionList", permissionList); + } + // 类型( 0:一级菜单 1:子菜单 2:按钮 ) + } else if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_SUB) || permission.getMenuType().equals(CommonConstant.MENU_TYPE_MAIN)) { + if (parentMap.containsKey("children")) { + ((List>) parentMap.get("children")).add(map); + } else { + List> children = new ArrayList<>(); + children.add(map); + parentMap.put("children", children); + } + + if (permission.getIsLeaf() == null || permission.getIsLeaf() != 1) { + getPermissionArray(array, metaList, map); + } + } + } + + } + } + + /** + * 获取权限数组 + * @param array + * @param allList + */ + private void getAllAuthArray(List> array,List allList) { + Map map; + for (SysPermission permission : allList) { + map = new LinkedHashMap<>(); + map.put("action", permission.getPerms()); + map.put("status", permission.getStatus()); + map.put("type", permission.getPermsType()); + map.put("describe", permission.getName()); + array.add(map); + } + } + + /** + * 获取权限数组 + * @param array + * @param metaList + */ + private void getAuthArray(List> array,List metaList) { + for (SysPermission permission : metaList) { + if(permission.getMenuType()==null) { + continue; + } + Map map = null; + if(permission.getMenuType().equals(CommonConstant.MENU_TYPE_BUTTON) &&CommonConstant.STATUS_1.equals(permission.getStatus())) { + map = new LinkedHashMap<>(); + map.put("action", permission.getPerms()); + map.put("type", permission.getPermsType()); + map.put("describe", permission.getName()); + array.add(map); + } + } + } + + /** + * 根据菜单配置生成路由json + * + * @param permission + * @return + */ + private Map getPermissionMap(SysPermission permission) { + Map map = new LinkedHashMap<>(); + // 类型(0:一级菜单 1:子菜单 2:按钮) + if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_BUTTON)) { + return null; + } else if (permission.getMenuType().equals(CommonConstant.MENU_TYPE_MAIN) || permission.getMenuType().equals(CommonConstant.MENU_TYPE_SUB)) { + map.put("id", permission.getId()); + if (isWWWHttpUrl(permission.getUrl())) { + map.put("path", MD5Util.MD5Encode(permission.getUrl(), "utf-8")); + } else { + map.put("path", permission.getUrl()); + } + + // 重要规则:路由name (通过URL生成路由name,路由name供前端开发,页面跳转使用) + if (StringUtils.isNotBlank(permission.getComponentName())) { + map.put("name", permission.getComponentName()); + } else { + map.put("name", urlToRouteName(permission.getUrl())); + } + + map.put("component", permission.getComponent()); + Map meta = new LinkedHashMap<>(); + + meta.put("title", permission.getName()); + if (StringUtils.isBlank(permission.getParentId())) { + // 一级菜单跳转地址 + map.put("redirect", permission.getRedirect()); + if (StringUtils.isNotBlank(permission.getIcon())) { + meta.put("icon", permission.getIcon()); + } + } else { + if (StringUtils.isNotBlank(permission.getIcon())) { + meta.put("icon", permission.getIcon()); + } + } + if (isWWWHttpUrl(permission.getUrl())) { + meta.put("url", permission.getUrl()); + } + map.put("meta", meta); + map.put("hidden", permission.getHidden()); + map.put("internalOrExternal", permission.getInternalOrExternal()); + } + + return map; + } + + /** + * 判断是否外网URL 例如: http://localhost:8080/jeecg-boot/swagger-ui.html#/ 支持特殊格式: {{ + * window._CONFIG['domianURL'] }}/druid/ {{ JS代码片段 }},前台解析会自动执行JS代码片段 + * + * @return + */ + private boolean isWWWHttpUrl(String url) { + if (url != null && (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("{{"))) { + return true; + } + return false; + } + + /** + * 通过URL生成路由name(去掉URL前缀斜杠,替换内容中的斜杠‘/’为-) 举例: URL = /isystem/role RouteName = + * isystem-role + * + * @return + */ + private String urlToRouteName(String url) { + if (StringUtils.isNotBlank(url)) { + if (url.startsWith("/")) { + url = url.substring(1); + } + url = url.replace("/", "-"); + + // 特殊标记 + url = url.replace(":", "@"); + return url; + } else { + return null; + } + } + + + private void getTreeModelList(List treeList, List metaList, TreeModel temp) { + for (SysPermission permission : metaList) { + String tempPid = permission.getParentId(); + TreeModel tree = new TreeModel(permission); + if (temp == null && StringUtils.isBlank(tempPid)) { + treeList.add(tree); + if (!tree.getIsLeaf()) { + getTreeModelList(treeList, metaList, tree); + } + } else if (temp != null && tempPid != null && tempPid.equals(temp.getKey())) { + temp.getChildren().add(tree); + if (!tree.getIsLeaf()) { + getTreeModelList(treeList, metaList, tree); + } + } + } + } + + /** + * 保存角色授权 + * + * @return + */ + @AddSysLog("保存角色授权") + @PostMapping("/saveRolePermission") + public Result saveRolePermission(@RequestBody Map params) { + try { + String roleId = params.get("roleId"); + String permissionIds = params.get("permissionIds"); + String lastPermissionIds = params.get("lastpermissionIds"); + this.sysRolePermissionService.saveRolePermission(roleId, permissionIds, lastPermissionIds); + return Result.ok("保存成功!"); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.error("授权失败!"); + } + } + + /** + * 查询角色权限 + * + * @return + */ + @AddSysLog("查询角色权限") + @GetMapping( "/queryRolePermission") + public Result> queryRolePermission(String roleId) { + List list = sysRolePermissionService.lambdaQuery().eq(SysRolePermission::getRoleId, roleId).list(); + return Result.ok(list.stream().map(SysRolePermission -> String.valueOf(SysRolePermission.getPermissionId())).collect(Collectors.toList())); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysRoleController.java b/src/main/java/com/gci/boot/modules/system/controller/SysRoleController.java new file mode 100644 index 0000000..fb54f8e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysRoleController.java @@ -0,0 +1,299 @@ +package com.gci.boot.modules.system.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.entity.SysPermission; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.entity.SysUserRole; +import com.gci.boot.modules.system.service.ISysPermissionService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.service.ISysUserRoleService; +import com.gci.boot.modules.system.vo.TreeModel; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +/** + *

+ * 角色表 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@RestController +@RequestMapping("/sys/role") +@Slf4j +public class SysRoleController { + public static List roleCodeList = new ArrayList<>(); + static{ + roleCodeList.add(CommonConstant.Custom_admin); + roleCodeList.add(CommonConstant.Repair_admin); + roleCodeList.add(CommonConstant.Maintenance_leader); + roleCodeList.add(CommonConstant.Maintenance_admin); + roleCodeList.add(CommonConstant.Driver); + roleCodeList.add(CommonConstant.Legal_admin); + roleCodeList.add(CommonConstant.Market_admin); + } + @Autowired + private ISysRoleService sysRoleService; + @Autowired + private ISysPermissionService sysPermissionService; + @Autowired + private ISysUserRoleService sysUserRoleService; + + /** + * 分页列表查询 + * + * @param role + * @param pageNo + * @param pageSize + * @return + */ + @AddSysLog("查询角色列表") + @GetMapping("/list") + public Result> queryPageList(SysRole role, String column, String order, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + Result> result = new Result<>(); + if(StringUtils.isBlank(column)){ + column = "create_time"; + order = "desc"; + } + QueryWrapper queryWrapper = QueryWrapperUtil.builder() + .table(SysRole.class) + .like(SysRole::getRoleCode) + .like(SysRole::getRoleName) + .orderColums(column) + .orders(order) + .buildFromObject(role); + Page page = new Page<>(pageNo, pageSize); + IPage pageList = sysRoleService.page(page, queryWrapper); + result.setSuccess(true); + result.setResult(pageList); + return result; + } + + /** + * 添加角色 + * + * @param role + * @return + */ + @AddSysLog("添加角色") + @PostMapping("/add") + public Result add(@RequestBody SysRole role) { + ParamsCheckUtil.paramsAssert() + .notBlank(role.getRoleName(), "【角色名称】不能为空!") + .notBlank(role.getRoleCode(), "【角色编码】不能为空!") + .isTrue(sysRoleService.lambdaQuery().eq(SysRole::getRoleCode, role.getRoleCode()).count()==0, "【角色编码】已存在!") + .isTrue(sysRoleService.lambdaQuery().eq(SysRole::getRoleName, role.getRoleName()).count()==0, "【角色名称】已存在!") + ; + try { + role.setCreateTime(new Date()); + sysRoleService.save(role); + return Result.ok("添加成功!"); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.ok("操作失败!"); + } + } + + /** + * 编辑 + * + * @param role + * @return + */ + @AddSysLog("编辑角色") + @PutMapping("/edit") + public Result edit(@RequestBody SysRole role) { + ParamsCheckUtil.paramsAssert() + .notBlank(role.getId(), "【角色ID】不能为空!") + .notBlank(role.getRoleName(), "【角色名称】不能为空!") + .notBlank(role.getRoleCode(), "【角色编码】不能为空!") + .isTrue(sysRoleService.lambdaQuery().ne(SysRole::getId, role.getId()).eq(SysRole::getRoleCode, role.getRoleCode()).count()==0, "【角色编码】已存在!") + .isTrue(sysRoleService.lambdaQuery().ne(SysRole::getId, role.getId()).eq(SysRole::getRoleName, role.getRoleName()).count()==0, "【角色名称】已存在!") + ; + SysRole sysrole = sysRoleService.getById(role.getId()); + if(roleCodeList.contains(sysrole.getRoleCode())){ + return Result.error("内置角色,不允许编辑!"); + } + if (sysrole == null) { + return Result.error("角色不存在!"); + } else { + sysRoleService.updateById(role); + return Result.ok("修改成功!"); + } + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AddSysLog("删除角色") + @DeleteMapping("/delete") + public Result delete(String id) { + ParamsCheckUtil.paramsAssert() + .notBlank(id, "角色ID不能为空!") + .isTrue(sysUserRoleService.lambdaQuery().eq(SysUserRole::getRoleId, id).count()==0, "角色已被使用,无法删除!") + ; + SysRole sysrole = sysRoleService.getById(id); + if(roleCodeList.contains(sysrole.getRoleCode())){ + return Result.error("内置角色,不允许删除!"); + } + sysRoleService.deleteRole(id); + return Result.ok("删除角色成功"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AddSysLog("批量删除角色") + @DeleteMapping("/deleteBatch") + public Result deleteBatch(String ids) { + Result result = new Result(); + if (StringUtils.isBlank(ids)) { + result.error500("未选中角色!"); + } else { + ParamsCheckUtil.paramsAssert() + .isTrue(sysUserRoleService.lambdaQuery().in(SysUserRole::getRoleId, Arrays.asList(ids.split(","))).count()==0, "角色已被使用,无法删除!") + ; + sysRoleService.deleteBatchRole(ids.split(",")); + result.success("删除角色成功!"); + } + return result; + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AddSysLog("通过id查询角色") + @GetMapping(value = "/queryById") + public Result queryById(String id) { + Result result = new Result(); + SysRole sysrole = sysRoleService.getById(id); + if (sysrole == null) { + result.error500("未找到对应实体"); + } else { + result.setResult(sysrole); + result.setSuccess(true); + } + return result; + } + + @AddSysLog("查询所有角色") + @GetMapping("/queryall") + public Result> queryall() { + List list = sysRoleService.list(); + if (list == null || list.size() <= 0) { + return Result.error("未找到角色信息"); + } else { + return Result.ok(list); + } + } + + /** + * 校验角色编码唯一 + */ + @GetMapping("/checkRoleCode") + public Result checkUsername(String id, String roleCode) { + Result result = new Result<>(); + result.setResult(true);//如果此参数为false则程序发生异常 + log.info("--验证角色编码是否唯一---id:" + id + "--roleCode:" + roleCode); + try { + SysRole role = null; + if (StringUtils.isNotBlank(id)) { + role = sysRoleService.getById(id); + } + SysRole newRole = sysRoleService.getOne(new QueryWrapper().lambda().eq(SysRole::getRoleCode, roleCode)); + if (newRole != null) { + //如果根据传入的roleCode查询到信息了,那么就需要做校验了。 + if (role == null) { + //role为空=>新增模式=>只要roleCode存在则返回false + result.setSuccess(false); + result.setMessage("角色编码已存在"); + return result; + } else if (!id.equals(newRole.getId())) { + //否则=>编辑模式=>判断两者ID是否一致- + result.setSuccess(false); + result.setMessage("角色编码已存在"); + return result; + } + } + } catch (Exception e) { + result.setSuccess(false); + result.setResult(false); + result.setMessage(e.getMessage()); + return result; + } + result.setSuccess(true); + return result; + } + + /** + * 用户角色授权功能,查询菜单权限树 + * + * @return + */ + @AddSysLog("查询角色树") + @GetMapping("/queryTreeList") + public Result> queryTreeList() { + //全部权限ids + List ids = new ArrayList<>(); + try { + LambdaQueryWrapper query = new LambdaQueryWrapper(); + query.orderByAsc(SysPermission::getSortNo); + List list = sysPermissionService.list(query); + for (SysPermission sysPer : list) { + ids.add(sysPer.getId()); + } + List treeList = new ArrayList<>(); + getTreeModelList(treeList, list, null); + Map resMap = new HashMap<>(); + resMap.put("treeList", treeList); //全部树节点数据 + resMap.put("ids", ids);//全部树ids + return Result.ok(resMap); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.error(e.getMessage()); + } + } + + private void getTreeModelList(List treeList, List metaList, TreeModel temp) { + for (SysPermission permission : metaList) { + String tempPid = permission.getParentId(); + TreeModel tree = new TreeModel(permission.getId(), tempPid, permission.getName(), permission.getRuleFlag(), permission.getIsLeaf()); + if (temp == null && StringUtils.isBlank(tempPid)) { + treeList.add(tree); + if (!tree.getIsLeaf()) { + getTreeModelList(treeList, metaList, tree); + } + } else if (temp != null && tempPid != null && tempPid.equals(temp.getKey())) { + temp.getChildren().add(tree); + if (!tree.getIsLeaf()) { + getTreeModelList(treeList, metaList, tree); + } + } + } + } +} diff --git a/src/main/java/com/gci/boot/modules/system/controller/SysUserController.java b/src/main/java/com/gci/boot/modules/system/controller/SysUserController.java new file mode 100644 index 0000000..4b581ec --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/controller/SysUserController.java @@ -0,0 +1,419 @@ +package com.gci.boot.modules.system.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.common.util.QueryWrapperUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.service.IProjectUserRelService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.entity.*; +import com.gci.boot.modules.system.service.ISysDepartService; +import com.gci.boot.modules.system.service.ISysUserDepartService; +import com.gci.boot.modules.system.service.ISysUserRoleService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.util.AesEncryptUtil; +import com.gci.boot.modules.system.util.PasswordUtil; +import com.gci.boot.modules.system.util.QsEncodeUtil; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.properties.GciSecurityProperties; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 用户表 前端控制器 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@EnableConfigurationProperties(GciSecurityProperties.class) +@RestController +@RequestMapping("/sys/user") +@Slf4j +public class SysUserController { + @Autowired + private ISysUserService sysUserService; + @Autowired + private ISysUserRoleService sysUserRoleService; + @Autowired + private ISysUserDepartService sysUserDepartService; + @Autowired + private GciSecurityProperties gciSecurityProperties; + @Autowired + private ISysDepartService sysDepartService; + @Autowired + private IProjectsService projectsService; + @Autowired + private IProjectUserRelService projectUserRelService; + + /** + * 获取用户列表数据 + * + * @param user + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("查询用户列表") + @GetMapping("/list") + public Result> queryPageList(SysUser user, String column, String order, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + Result> result = new Result<>(); + if(StringUtils.isBlank(column)){ + column = "create_time"; + order = "desc"; + } + QueryWrapper queryWrapper = QueryWrapperUtil.builder() + .table(SysUser.class) + .like(SysUser::getUsername) + .like(SysUser::getRealname) + .like(SysUser::getPhone) + .like(SysUser::getEmail) + .like(SysUser::getTelephone) + .orderColums(column) + .orders(order) + .buildFromObject(user); + + Page page = new Page<>(pageNo, pageSize); + IPage pageList = sysUserService.page(page, queryWrapper); + + // 处理等保解密数据 + Iterator userIterator = pageList.getRecords().iterator(); + while (userIterator.hasNext()) { + SysUser sysUser = userIterator.next(); + sysUser.setPhone(sysUserService.processPhone(sysUser)); + } + + result.setSuccess(true); + result.setResult(pageList); + log.info(pageList.toString()); + return result; + } + + + /** + * 查询用户信息 单独列表使用 需要联表查询 + * @param user + * @param column + * @param order + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("查询用户列表") + @GetMapping("/listV2") + public Result queryPageListV2(SysUser user, String column, String order, String roleName, String departName, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + if(StringUtils.isBlank(column)){ + column = "create_time"; + order = "desc"; + } + Page page = new Page<>(pageNo, pageSize); + IPage iPage = sysUserService.queryPageListV2(user,roleName,departName,column,order,page); + return Result.ok(iPage); + } + + + @AddSysLog("添加用户") + @PostMapping("/add") + public Result add(@RequestBody Map map) { + String roles = (String) map.get("selectedroles"); + String departs = (String) map.get("selecteddeparts"); + + SysUser user = JsonUtil.map2Object(map, SysUser.class); + ParamsCheckUtil.paramsAssert().notBlank(user.getUsername(), "【用户名】不能为空!") + .notBlank(user.getPassword(), "【密码】不能为空!") + .isTrue(sysUserService.lambdaQuery().eq(SysUser::getUsername, user.getUsername()).count() == 0, String.format("用户名【%s】已存在!", user.getUsername())) + .isTrue(PasswordUtil.checkPassword(user.getPassword()), "密码必须由8-12位数字、大小写字母和特殊符号组成") + ; + + user.setCreateTime(new Date());//设置创建时间 + String salt = PasswordUtil.generateSalt(8); + user.setSalt(salt); + String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt); + user.setPassword(passwordEncode); + user.setStatus(1); + if (StringUtils.isNotBlank(user.getPhone())) { + // 是否开启密码加密存储,如按等保要求,密码需要加密存储 + if (gciSecurityProperties.isEnablePhoneEncrypt()) { + String secret = PasswordUtil.generateSalt(8); + try { + user.setEncryptPhone(QsEncodeUtil.aesEncrypt(user.getPhone(), secret)); + } catch (Exception e) { + return Result.error("【电话号码】加密失败!"); + } + user.setSecretPhone(secret); + user.setPhone(""); + } else { + user.setEncryptPhone(""); + user.setSecretPhone(""); + } + } + List rolesList = Optional.ofNullable(roles).filter(StringUtils::isNotBlank).map(r -> r.split(",")).map(Arrays::asList).orElse(new ArrayList<>()); + List departsList = Optional.ofNullable(departs).filter(StringUtils::isNotBlank).map(r -> r.split(",")).map(Arrays::asList).orElse(new ArrayList<>()); + String projs = (String) map.get("projectIds"); + List projsList = Optional.ofNullable(projs).map(r -> r.split(",")).map(Arrays::asList) + .map(list -> list.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList())) + .orElse(new ArrayList<>()); + sysUserService.addInnerUser(user, rolesList, departsList,projsList); + return Result.ok("添加成功!"); + } + + @AddSysLog("编辑用户") + @PutMapping("/edit") + public Result edit(@RequestBody Map map) { + SysUser sysUser = sysUserService.getById((String) map.get("id")); + if (sysUser == null) { + return Result.error("未找到对应实体"); + } else { + SysUser user = JsonUtil.map2Object(map, SysUser.class); + //不可修改密码 + user.setPassword(sysUser.getPassword()); + + ParamsCheckUtil.ParamsAssert paramAssert = ParamsCheckUtil.paramsAssert().notBlank(user.getUsername(), "【用户名】不能为空!") + .isTrue(user.getUsername().equals(sysUser.getUsername()) || sysUserService.lambdaQuery().eq(SysUser::getUsername, user.getUsername()).count() == 0, String.format("用户名【%s】已存在!", user.getUsername())); + + if (StringUtils.isNotBlank(user.getPhone())) { + // 是否开启密码加密存储,如按等保要求,密码需要加密存储 + if (gciSecurityProperties.isEnablePhoneEncrypt()) { + String secret = PasswordUtil.generateSalt(8); + try { + user.setEncryptPhone(QsEncodeUtil.aesEncrypt(user.getPhone(), secret)); + } catch (Exception e) { + return Result.error("【电话号码】加密失败!"); + } + user.setPhone(""); + } else { + user.setEncryptPhone(""); + user.setSecretPhone(""); + } + } + String roles = (String) map.get("selectedroles"); + List rolesList = Optional.ofNullable(roles).map(r -> r.split(",")).map(Arrays::asList) + .map(list -> list.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList())) + .orElse(new ArrayList<>()); + String departs = (String) map.get("selecteddeparts"); + List departsList = Optional.ofNullable(departs).map(r -> r.split(",")).map(Arrays::asList) + .map(list -> list.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList())) + .orElse(new ArrayList<>()); + String projs = (String) map.get("projectIds"); + List projsList = Optional.ofNullable(projs).map(r -> r.split(",")).map(Arrays::asList) + .map(list -> list.stream().filter(StringUtils::isNotBlank).collect(Collectors.toList())) + .orElse(new ArrayList<>()); + //编辑内部用户(包括关联项目),兼容其他类型的用户修改 + sysUserService.editInnerUser(user, rolesList, departsList,projsList); + return Result.ok("修改成功!"); + } + } + + + /** + * 冻结&解冻用户 + * + * @param map + * @return + */ + @AddSysLog("冻结/解冻用户") + @PostMapping("/frozenBatch") + public Result frozenBatch(@RequestBody Map map) { + String status = map.get("status"); + List userIdList = Optional.ofNullable(map.get("ids")).map(r -> r.split(",")).map(Arrays::asList).orElse(new ArrayList<>()); + sysUserService.lambdaUpdate().in(SysUser::getId, userIdList).set(SysUser::getStatus, Integer.parseInt(status)).update(); + return Result.ok("操作成功!"); + } + + @ApiOperation("获取个人信息接口") + @GetMapping("/queryById") + public Result queryById(String id) { + SysUser sysUser = sysUserService.getById(id); + if (sysUser == null) { + return Result.error("未找到对应实体"); + } + return Result.ok(sysUser); + } + + /** + * 批量删除用户 + */ + @AddSysLog("删除用户") + @DeleteMapping("/deleteBatch") + public Result deleteBatch(String ids) { + this.sysUserService.deleteBatch(Arrays.asList(ids.split(","))); + return Result.ok("删除用户成功"); + } + + @GetMapping("/getUserInfoByToken") + public Result getUserInfoByToken() { + LoginUser user = (LoginUser)SecurityUtils.getSubject().getPrincipal(); + Set userRolesSet = sysUserService.getUserRolesSet(user.getUsername()); + if(userRolesSet.size()>0){ + user.setRoles(userRolesSet.stream().collect(Collectors.joining(","))); + } + return Result.ok(user); + } + + /** + * 用户重置自己的密码 + */ + @AddSysLog("个人重置密码") + @PutMapping("/updatePassword") + public Result changPassword(@RequestBody Map params) { + String username = params.get("username"); + String oldPassword = params.get("oldPassword"); + String password = params.get("password"); + String confirmPassword = params.get("confirmPassword"); + SysUser user = this.sysUserService.getByUsername(username); + if (user == null) { + return Result.error("用户不存在!"); + } + sysUserService.resetPassword(username, oldPassword, password, confirmPassword); + return Result.ok("密码重置成功!"); + } + + /** + * 修改密码接口 + */ + @AddSysLog("用户管理-修改密码") + @PutMapping("/changePassword") + public Result changePassword(@RequestBody SysUser sysUser) { + SysUser u = sysUserService.getByUsername(sysUser.getUsername()); + if (u == null) { + return Result.error("用户不存在!"); + } + try { + sysUser.setPassword(AesEncryptUtil.desEncrypt(sysUser.getPassword().replaceAll("%2B", "\\+")).trim()); + } catch (Exception e) { + e.printStackTrace(); + log.error("修改密码解密失败",e); + throw new GciBootException("修改密码失败!"); + } + String salt = PasswordUtil.generateSalt(8); + if(!PasswordUtil.checkPassword(sysUser.getPassword())){ + return Result.error("密码必须由8-12位数字、大小写字母和特殊符号组成!"); + } + String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), sysUser.getPassword(), salt); + sysUserService.lambdaUpdate() + .eq(SysUser::getId, u.getId()) + .set(SysUser::getPasswordUpdateTime, new Date()) + .set(SysUser::getPassword, passwordEncode) + .set(SysUser::getSalt, salt) + .update(); + return Result.ok("修改密码成功!"); + } + + @GetMapping("/queryUserRole") + public Result> queryUserRole(String userid) { + List list = new ArrayList<>(); + List userRole = sysUserRoleService.lambdaQuery().eq(SysUserRole::getUserId, userid).list(); + for (SysUserRole sysUserRole : userRole) { + list.add(sysUserRole.getRoleId()); + } + return Result.ok(list); + } + + @GetMapping("/queryUserDepart") + public Result> queryUserDepart(String userId) { + List list = new ArrayList<>(); + List userDeparts = sysUserDepartService.lambdaQuery().eq(SysUserDepart::getUserId, userId).list(); + for (SysUserDepart sysUserDepart : userDeparts) { + list.add(sysUserDepart.getDepId()); + } + return Result.ok(list); + } + + @GetMapping("/queryUserProject") + public Result queryUserProject(String userId){ + InnerUserProject userProject = new InnerUserProject(); + //查询是否是内部用户 + List listDepart = sysDepartService.getDepartByUserId(userId); + userProject.setOrgCategory(0); + for(SysDepart dep: listDepart){ + if(dep.getOrgCategory() == 1){ + userProject.setOrgCategory(1); + break; + }else{ + if(dep.getOrgCategory() == 3 || dep.getOrgCategory() == 2){ + userProject.setOrgCategory(dep.getOrgCategory()); + } + } + } + if(userProject.getOrgCategory()==1){ + QueryWrapper queryWrapperProj = new QueryWrapper<>(); + queryWrapperProj.eq("user_id",userId); + //查询内部用户归属的项目 + List listProjOfUser = projectUserRelService.list(queryWrapperProj); + String projIds = null; + for (ProjectUserRel projectUserRel : listProjOfUser) { + if(projIds==null) { + projIds = projectUserRel.getProjectId(); + }else { + projIds += ","+projectUserRel.getProjectId(); + } + } + userProject.setProjectIds(projIds); + } + return Result.ok(userProject); + } + + @GetMapping("/getByRoleCode") + public Result getByRoleCode(String roleCode) { + return Result.ok(sysUserService.getByRoleCode(roleCode)); + } + + + @ApiOperation("解绑微信用户") + @AddSysLog(value = "用户管理-解绑微信用户") + @GetMapping("/unbindUser") + public Result unbindUser(String id) { + SysUser sysUser = sysUserService.getById(id); + if (sysUser == null) { + return Result.error("未找到对应用户"); + } + sysUser.setOpenid(null); + sysUserService.updateById(sysUser); + return Result.ok("解绑成功!"); + } + + @AddSysLog("查询内部用户列表") + @GetMapping("/innerUserList") + public Result> queryInnerUserPageList(SysUser user, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + Result> result = new Result<>(); + + //查询内部机构树 + Page page = new Page<>(pageNo, pageSize); + IPage pageList = sysUserService.queryInnerUserList(page, user); + + // 处理等保解密数据 + Iterator userIterator = pageList.getRecords().iterator(); + while (userIterator.hasNext()) { + SysUser sysUser = userIterator.next(); + sysUser.setPhone(sysUserService.processPhone(sysUser)); + } + + result.setSuccess(true); + result.setResult(pageList); + log.info(pageList.toString()); + return result; + } + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/InnerUserProject.java b/src/main/java/com/gci/boot/modules/system/entity/InnerUserProject.java new file mode 100644 index 0000000..bc04499 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/InnerUserProject.java @@ -0,0 +1,36 @@ +package com.gci.boot.modules.system.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.gci.boot.common.dict.annotation.Dict; +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@Data +public class InnerUserProject implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id 1普通部门,2维修厂,3客户公司(租赁方),0根节点 + */ + private Integer orgCategory; + + /** + * 用户id,用逗号隔开 + */ + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectIds; + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/LoginTimesValidate.java b/src/main/java/com/gci/boot/modules/system/entity/LoginTimesValidate.java new file mode 100644 index 0000000..f0eccf3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/LoginTimesValidate.java @@ -0,0 +1,64 @@ +package com.gci.boot.modules.system.entity; + +/** + * @Author: lyz + * @Description: TODO:登录次数验证 + * @version: v1.0 + * @Modified by: + **/ +public class LoginTimesValidate +{ + private String loginUser; + + private Integer times ; + + private Integer second = 10*60; + + private final static int MAX_LIMIT = 5; + + public boolean nonTimes(){ + return times>=MAX_LIMIT; + } + + public LoginTimesValidate(){ + + } + + public LoginTimesValidate(String loginUser, Integer second){ + this.loginUser = loginUser; + this.second = second; + } + + public LoginTimesValidate(String loginUser){ + this.loginUser = loginUser; + this.times = 0; + } + + public synchronized void addTimes(){ + this.times+=1; + } + + public String getLoginUser() { + return loginUser; + } + + public void setLoginUser(String loginUser) { + this.loginUser = loginUser; + } + + public Integer getTimes() { + return times; + } + + public void setTimes(Integer times) { + this.times = times; + } + + public Integer getSecond() { + return second; + } + + public void setSecond(Integer second) { + this.second = second; + } +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysDepart.java b/src/main/java/com/gci/boot/modules/system/entity/SysDepart.java new file mode 100644 index 0000000..9e7efd9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysDepart.java @@ -0,0 +1,107 @@ +package com.gci.boot.modules.system.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.annotation.ExcelEnum; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.dict.excel.EnumConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 组织机构表 + *

+ * + * @author chenzhiwei + * @since 2023-09-01 + */ +@Data +@TableName("sys_depart") +@ApiModel(value = "SysDepart对象", description = "组织机构表") +public class SysDepart implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("父机构ID") + @Dict(dictTable = "sys_depart", dicCode = "id", dicText = "depart_name") + @ExcelProperty(value = "父机构", converter = DictConverter.class) + private String parentId; + + @ExcelProperty("机构名称") + @ApiModelProperty("机构/部门名称") + private String departName; + + @ExcelProperty("排序") + @ApiModelProperty("排序") + private Integer departOrder; + + @ExcelProperty("描述") + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("机构类别 1普通部门,2维修厂,3客户公司(租赁方),0根节点") + @ExcelEnum("1_普通部门,2_维修厂,3_客户公司,0_根节点") + @ExcelProperty(value = "机构类别", converter = EnumConverter.class) + private Integer orgCategory; + + @ExcelProperty("机构编码") + @ApiModelProperty("机构编码") + private String orgCode; + + @ExcelProperty("联系电话") + @ApiModelProperty("联系电话") + private String mobile; + + @ExcelProperty("传真") + @ApiModelProperty("传真") + private String fax; + + @ExcelProperty("地址") + @ApiModelProperty("地址") + private String address; + + @ExcelProperty("备注") + @ApiModelProperty("备注") + private String memo; + + @ApiModelProperty("状态(1启用,0不启用)") + @ExcelEnum("1_启用,0_不启用") + @ExcelProperty(value = "状态", converter = EnumConverter.class) + private Integer status; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("创建日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ApiModelProperty("更新日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysDict.java b/src/main/java/com/gci/boot/modules/system/entity/SysDict.java new file mode 100644 index 0000000..448afd7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysDict.java @@ -0,0 +1,67 @@ +package com.gci.boot.modules.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import com.alibaba.excel.annotation.ExcelProperty; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +@Data +@TableName("sys_dict") +@ApiModel(value = "SysDict对象", description = "") +public class SysDict implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("字典名称") + private String dictName; + + @ApiModelProperty("字典编码") + private String dictCode; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + @ApiModelProperty("字典类型0为string,1为number") + private Integer type; + + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysDictItem.java b/src/main/java/com/gci/boot/modules/system/entity/SysDictItem.java new file mode 100644 index 0000000..46ff503 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysDictItem.java @@ -0,0 +1,65 @@ +package com.gci.boot.modules.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import com.alibaba.excel.annotation.ExcelProperty; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +@Data +@TableName("sys_dict_item") +@ApiModel(value = "SysDictItem对象", description = "") +public class SysDictItem implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("字典id") + private String dictId; + + @ApiModelProperty("字典项文本") + private String itemText; + + @ApiModelProperty("字典项值") + private String itemValue; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("排序") + private Integer sortOrder; + + @ApiModelProperty("状态(1启用 0不启用)") + private Integer status; + + private String createBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date createTime; + + private String updateBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysLog.java b/src/main/java/com/gci/boot/modules/system/entity/SysLog.java new file mode 100644 index 0000000..38bdd6d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysLog.java @@ -0,0 +1,89 @@ +package com.gci.boot.modules.system.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 系统日志表 + *

+ * + * @author chenzhiwei + * @since 2023-09-08 + */ +@Data +@TableName("sys_log") +@ApiModel(value = "SysLog对象", description = "系统日志表") +public class SysLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("日志类型(1登录日志,2操作日志)") + private Integer logType; + + @ApiModelProperty("日志内容") + private String logContent; + + @ApiModelProperty("操作类型") + private Integer operateType; + + @ApiModelProperty("操作用户账号") + private String userid; + + @ApiModelProperty("操作用户名称") + private String username; + + @ApiModelProperty("IP") + private String ip; + + @ApiModelProperty("请求java方法") + private String method; + + @ApiModelProperty("请求路径") + private String requestUrl; + + @ApiModelProperty("请求参数") + private String requestParam; + + @ApiModelProperty("请求类型") + private String requestType; + + @ApiModelProperty("耗时") + private Long costTime; + + @ApiModelProperty("创建人") + private String createBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("日志来源") + private String logSource; +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysPermission.java b/src/main/java/com/gci/boot/modules/system/entity/SysPermission.java new file mode 100644 index 0000000..f33d755 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysPermission.java @@ -0,0 +1,106 @@ +package com.gci.boot.modules.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import com.alibaba.excel.annotation.ExcelProperty; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 菜单权限表 + *

+ * + * @author chenzhiwei + * @since 2023-08-22 + */ +@Data +@TableName("sys_permission") +@ApiModel(value = "SysPermission对象", description = "菜单权限表") +public class SysPermission implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("父id") + private String parentId; + + @ApiModelProperty("菜单标题") + private String name; + + @ApiModelProperty("路径") + private String url; + + @ApiModelProperty("组件") + private String component; + + @ApiModelProperty("组件名字") + private String componentName; + + @ApiModelProperty("一级菜单跳转地址") + private String redirect; + + @ApiModelProperty("菜单类型(0:一级菜单; 1:子菜单:2:按钮权限)") + private Integer menuType; + + @ApiModelProperty("菜单权限编码") + private String perms; + + @ApiModelProperty("权限策略1显示2禁用") + private String permsType; + + @ApiModelProperty("菜单排序") + private Double sortNo; + + @ApiModelProperty("菜单图标") + private String icon; + + @ApiModelProperty("是否叶子节点: 1:是 0:不是") + private Integer isLeaf; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("按钮权限状态(0无效1有效)") + private String status; + + @ApiModelProperty("是否添加数据权限1是0否") + private Integer ruleFlag; + + @ApiModelProperty("创建人") + private String createBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("是否隐藏路由: 0否,1是") + private Integer hidden; + + @ApiModelProperty("外链菜单打开方式 0/内部打开 1/外部打开") + private Integer internalOrExternal; + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysRole.java b/src/main/java/com/gci/boot/modules/system/entity/SysRole.java new file mode 100644 index 0000000..1242c43 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysRole.java @@ -0,0 +1,67 @@ +package com.gci.boot.modules.system.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 角色表 + *

+ * + * @author chenzhiwei + * @since 2023-08-22 + */ +@Getter +@Setter +@TableName("sys_role") +@ApiModel(value = "SysRole对象", description = "角色表") +public class SysRole implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("角色名称") + private String roleName; + + @ApiModelProperty("角色编码") + private String roleCode; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("创建人") + private String createBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("更新时间") + private Date updateTime; + + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysRolePermission.java b/src/main/java/com/gci/boot/modules/system/entity/SysRolePermission.java new file mode 100644 index 0000000..05178aa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysRolePermission.java @@ -0,0 +1,38 @@ +package com.gci.boot.modules.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 角色权限表 + *

+ * + * @author chenzhiwei + * @since 2023-08-22 + */ +@Data +@TableName("sys_role_permission") +@ApiModel(value = "SysRolePermission对象", description = "角色权限表") +public class SysRolePermission implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("角色id") + private String roleId; + + @ApiModelProperty("权限id") + private String permissionId; + + private String dataRuleIds; + + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysUser.java b/src/main/java/com/gci/boot/modules/system/entity/SysUser.java new file mode 100644 index 0000000..b45daf3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysUser.java @@ -0,0 +1,158 @@ +package com.gci.boot.modules.system.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.annotation.ExcelEnum; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.dict.excel.EnumConverter; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 用户表 + *

+ * + * @author chenzhiwei + * @since 2023-08-22 + */ +@Getter +@Setter +@TableName("sys_user") +@ApiModel(value = "SysUser对象", description = "用户表") +public class SysUser implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("登录账号") + @ExcelProperty("登录账号") + private String username; + + @ApiModelProperty("真实姓名") + @ExcelProperty("真实姓名") + private String realname; + + @ApiModelProperty("密码") + @ExcelIgnore + private String password; + + @ApiModelProperty("md5密码盐") + @ExcelIgnore + private String salt; + + @ApiModelProperty("头像") + @ExcelIgnore + private String avatar; + + @ApiModelProperty("生日") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @ExcelProperty("生日") + private Date birthday; + + @ApiModelProperty("性别(0-默认未知,1-男,2-女)") + @ExcelEnum("0_未知,1_男,2_女") + @ExcelProperty(value = "性别", converter = EnumConverter.class) + private Integer sex; + + @ApiModelProperty("电子邮件") + @ExcelProperty("电子邮件") + private String email; + + @ApiModelProperty("电话") + @ExcelProperty("电话") + private String phone; + + @ApiModelProperty("状态(1-正常,2-冻结)") + @ExcelEnum("1_正常,2_冻结") + @ExcelProperty(value = "状态", converter = EnumConverter.class) + private Integer status; + + @ApiModelProperty("工号,唯一键") + @ExcelProperty("工号") + private String workNo; + + @ApiModelProperty("职务,关联职务表") + @ExcelProperty("职务") + private String post; + + @ApiModelProperty("座机号") + @ExcelProperty("座机号") + private String telephone; + + @ApiModelProperty("创建人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ExcelProperty(value = "创建人", converter = DictConverter.class) + private String createBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("创建时间") + @ExcelProperty("创建时间") + private Date createTime; + + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ApiModelProperty("更新人") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("更新时间") + @ExcelProperty("更新时间") + private Date updateTime; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty("密码修改时间") + @ExcelIgnore + private Date passwordUpdateTime; + + @ApiModelProperty("加密手机") + @ExcelIgnore + private String encryptPhone; + + @ApiModelProperty("密保手机") + @ExcelIgnore + private String secretPhone; + + + @ApiModelProperty("部门编号") + @Dict(dictTable = "sys_depart", dicCode = "org_code", dicText = "depart_name") + private String orgCode; + + @ApiModelProperty("微信openid") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String openid; + + @ApiModelProperty("用户机构") + @TableField(exist = false) + @ExcelIgnore + @Dict(dictTable = "sys_depart",dicCode = "id",dicText = "depart_name") + private String depIds; + + @ApiModelProperty("用户角色") + @TableField(exist = false) + @ExcelIgnore + @Dict(dictTable = "sys_role",dicCode = "id",dicText = "role_name") + private String roleIds; +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysUserDepart.java b/src/main/java/com/gci/boot/modules/system/entity/SysUserDepart.java new file mode 100644 index 0000000..4912a56 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysUserDepart.java @@ -0,0 +1,44 @@ +package com.gci.boot.modules.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import lombok.Data; +import com.alibaba.excel.annotation.ExcelProperty; + +/** + *

+ * + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@Data +@TableName("sys_user_depart") +public class SysUserDepart implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @ExcelProperty("id") + @TableId(type = IdType.ASSIGN_ID) + private String id; + + /** + * 用户id + */ + @ExcelProperty("用户id") + private String userId; + + /** + * 部门id + */ + @ExcelProperty("部门id") + private String depId; + + +} diff --git a/src/main/java/com/gci/boot/modules/system/entity/SysUserRole.java b/src/main/java/com/gci/boot/modules/system/entity/SysUserRole.java new file mode 100644 index 0000000..2bab1b2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/entity/SysUserRole.java @@ -0,0 +1,39 @@ +package com.gci.boot.modules.system.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 用户角色表 + *

+ * + * @author chenzhiwei + * @since 2023-08-22 + */ +@Getter +@Setter +@TableName("sys_user_role") +@ApiModel(value = "SysUserRole对象", description = "用户角色表") +public class SysUserRole implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("用户id") + private String userId; + + @ApiModelProperty("角色id") + private String roleId; + + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysDepartMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysDepartMapper.java new file mode 100644 index 0000000..f8e6b89 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysDepartMapper.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.system.entity.SysDepart; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 组织机构表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-31 + */ +public interface SysDepartMapper extends BaseMapper { + + List getDepartByUserId(@Param("userId") String userId); +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysDictItemMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysDictItemMapper.java new file mode 100644 index 0000000..42ce59d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysDictItemMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysDictItem; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +public interface SysDictItemMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysDictMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysDictMapper.java new file mode 100644 index 0000000..0b37839 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysDictMapper.java @@ -0,0 +1,36 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysDict; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.system.vo.DictModel; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +public interface SysDictMapper extends BaseMapper { + + List queryDictItemsByCode(@Param("code") String code); + + List queryDictByValue(@Param("code") String code, @Param("key") String key); + + List queryDictByText(@Param("code") String code, @Param("key") String key); + + List queryTableDictByValue(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("key") String key); + + List queryTableDictByText(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("key") String key); + + List queryTableDictItemsByCode(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql); + + List queryNoDelTableDictByValue(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("key") String key); + + String queryDictDelFlag(@Param("table") String table); + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysLogMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysLogMapper.java new file mode 100644 index 0000000..85a8f8f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysLogMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 系统日志表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-09-08 + */ +public interface SysLogMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysPermissionMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysPermissionMapper.java new file mode 100644 index 0000000..c13bf8b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysPermissionMapper.java @@ -0,0 +1,32 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysPermission; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + *

+ * 菜单权限表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface SysPermissionMapper extends BaseMapper { + + /** + * 根据用户查询用户权限 + */ + List queryByUser(@Param("username") String username); + + /** + * 根据角色id查询权限编码 + * @param roleIds + * @return + */ + Set getPermCodeSetByroleIds(@Param("roleIds") Collection roleIds); +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysRoleMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysRoleMapper.java new file mode 100644 index 0000000..defeb70 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysRoleMapper.java @@ -0,0 +1,23 @@ +package com.gci.boot.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.system.entity.SysRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Set; + +/** + *

+ * 角色表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface SysRoleMapper extends BaseMapper { + + Set getRoleCodeSetByUserId(@Param("userId") String userId); + + List getRoleByUserId(@Param("userId") String userId); +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysRolePermissionMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysRolePermissionMapper.java new file mode 100644 index 0000000..ce8fe88 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysRolePermissionMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysRolePermission; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 角色权限表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface SysRolePermissionMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysUserDepartMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysUserDepartMapper.java new file mode 100644 index 0000000..95bcc73 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysUserDepartMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysUserDepart; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-09-04 + */ +public interface SysUserDepartMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysUserMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..b5b6822 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysUserMapper.java @@ -0,0 +1,25 @@ +package com.gci.boot.modules.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.system.entity.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.HashSet; +import java.util.List; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-17 + */ +public interface SysUserMapper extends BaseMapper { + + List queryInnerUserList(Page page, @Param("user")SysUser user); + + IPage queryPageListV2(@Param("user") SysUser user,@Param("sysUserRoleIds")List sysUserRoleIds,@Param("sysUserDepartIds") List sysUserDepartIds,@Param("fromColumn") String column,@Param("orders") String order,@Param("page") Page page); +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/SysUserRoleMapper.java b/src/main/java/com/gci/boot/modules/system/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..754919d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.mapper; + +import com.gci.boot.modules.system.entity.SysUserRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 用户角色表 Mapper 接口 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface SysUserRoleMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDepartMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDepartMapper.xml new file mode 100644 index 0000000..570cdad --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDepartMapper.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictItemMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictItemMapper.xml new file mode 100644 index 0000000..6df6499 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictItemMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictMapper.xml new file mode 100644 index 0000000..43d1a0a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysDictMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysLogMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysLogMapper.xml new file mode 100644 index 0000000..71e0661 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysPermissionMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysPermissionMapper.xml new file mode 100644 index 0000000..7b1d17f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysPermissionMapper.xml @@ -0,0 +1,32 @@ + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysRoleMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysRoleMapper.xml new file mode 100644 index 0000000..7f69cb1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysRoleMapper.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysRolePermissionMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysRolePermissionMapper.xml new file mode 100644 index 0000000..734296b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysRolePermissionMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserDepartMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserDepartMapper.xml new file mode 100644 index 0000000..6994e76 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserDepartMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserMapper.xml new file mode 100644 index 0000000..96bdfbc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserMapper.xml @@ -0,0 +1,126 @@ + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserRoleMapper.xml b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserRoleMapper.xml new file mode 100644 index 0000000..3ae7565 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/mapper/xml/SysUserRoleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysDepartService.java b/src/main/java/com/gci/boot/modules/system/service/ISysDepartService.java new file mode 100644 index 0000000..5f2d258 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysDepartService.java @@ -0,0 +1,28 @@ +package com.gci.boot.modules.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.system.entity.SysDepart; + +import java.util.List; + +/** + *

+ * 组织机构表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-31 + */ +public interface ISysDepartService extends IService { + + void deleteWithChildren(String id); + + void deleteBatchWithChildren(List ids); + + /** + * 根据userId查询部门信息 + * @param userId + * @return + */ + List getDepartByUserId(String userId); +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysDictItemService.java b/src/main/java/com/gci/boot/modules/system/service/ISysDictItemService.java new file mode 100644 index 0000000..95f91a1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysDictItemService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.modules.system.entity.SysDictItem; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +public interface ISysDictItemService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysDictService.java b/src/main/java/com/gci/boot/modules/system/service/ISysDictService.java new file mode 100644 index 0000000..2e1dbd7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysDictService.java @@ -0,0 +1,36 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.system.entity.SysDict; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.system.vo.DictModel; +import org.springframework.cache.annotation.Cacheable; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +public interface ISysDictService extends IService { + + List queryDictItemsByCode(String code); + + List queryTableDictItemsByCodeAndFilter(String table, String text, String code, String filterSql); + + List queryTableDictItemsByCode(String table, String text, String code); + + String queryTableDictTextByKey(String table, String text, String code, String key); + + String queryDictTextByKey(String code, String key); + + String queryDictValueByText(String code, String key); + + String queryTableDictValueByText(String table, String text, String code, String key); + + String queryTableDictTextByKey(String table, String text, String code, String key,boolean hasDelFlag); +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysLogService.java b/src/main/java/com/gci/boot/modules/system/service/ISysLogService.java new file mode 100644 index 0000000..ab4065f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysLogService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.modules.system.entity.SysLog; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 系统日志表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-09-08 + */ +public interface ISysLogService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysPermissionService.java b/src/main/java/com/gci/boot/modules/system/service/ISysPermissionService.java new file mode 100644 index 0000000..0f5bc4d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysPermissionService.java @@ -0,0 +1,35 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.system.entity.SysPermission; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.exception.GciBootException; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + *

+ * 菜单权限表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface ISysPermissionService extends IService { + + List queryByUser(String username); + + void addPermission(SysPermission sysPermission) throws GciBootException; + + @CacheEvict(value = CacheConstant.SYS_DATA_PERMISSIONS_CACHE,allEntries=true) + void editPermission(SysPermission sysPermission) throws GciBootException; + + @Transactional + void deletePermission(String id) throws GciBootException; + + Set getPermCodeSetByroleIds(Collection roleIds); +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysRolePermissionService.java b/src/main/java/com/gci/boot/modules/system/service/ISysRolePermissionService.java new file mode 100644 index 0000000..775e4f6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysRolePermissionService.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.modules.system.entity.SysRolePermission; +import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 角色权限表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface ISysRolePermissionService extends IService { + + @Transactional(rollbackFor = Exception.class) + void saveRolePermission(String roleId, String permissionIds, String lastPermissionIds); +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysRoleService.java b/src/main/java/com/gci/boot/modules/system/service/ISysRoleService.java new file mode 100644 index 0000000..10da913 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysRoleService.java @@ -0,0 +1,34 @@ +package com.gci.boot.modules.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.system.entity.SysRole; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Set; + +/** + *

+ * 角色表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface ISysRoleService extends IService { + + @Transactional(rollbackFor = Exception.class) + boolean deleteRole(String roleid); + + @Transactional(rollbackFor = Exception.class) + boolean deleteBatchRole(String[] roleIds); + + Set getRoleCodeSetByUserId(String userId); + + /** + * 根据userId查询角色信息 + * @param userId + * @return + */ + List getRoleByUserId(String userId); +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysUserDepartService.java b/src/main/java/com/gci/boot/modules/system/service/ISysUserDepartService.java new file mode 100644 index 0000000..02a70b2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysUserDepartService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.modules.system.entity.SysUserDepart; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-09-04 + */ +public interface ISysUserDepartService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysUserRoleService.java b/src/main/java/com/gci/boot/modules/system/service/ISysUserRoleService.java new file mode 100644 index 0000000..60626e4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysUserRoleService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.modules.system.entity.SysUserRole; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 用户角色表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +public interface ISysUserRoleService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/ISysUserService.java b/src/main/java/com/gci/boot/modules/system/service/ISysUserService.java new file mode 100644 index 0000000..1197d16 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/ISysUserService.java @@ -0,0 +1,71 @@ +package com.gci.boot.modules.system.service; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.system.entity.SysUser; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author chenzhiwei + * @since 2023-08-17 + */ +public interface ISysUserService extends IService { + + SysUser getByUsername(String username); + + @Transactional(rollbackFor = Exception.class) + void addUserEncryptPassword(SysUser user, List roleIds, List departIds); + + @Transactional(rollbackFor = Exception.class) + void editUserEncryptPassword(SysUser user, List roleIds, List departIds); + + @Transactional(rollbackFor = Exception.class) + void addUser(SysUser user, List roleIds, List departIds); + + @Transactional(rollbackFor = Exception.class) + void addInnerUser(SysUser user, List roleIds, List departIds, List projectIds); + + @Transactional(rollbackFor = Exception.class) + void editUser(SysUser user, List roleIds, List departIds); + + @Transactional(rollbackFor = Exception.class) + void editInnerUser(SysUser user, List roleIds, List departIds, List projectIds); + + String processPhone(SysUser user); + + void resetPassword(String username, String oldpassword, String newpassword, String confirmpassword); + + Set getUserRolesSet(String username); + + Set getUserRoleIdsSet(String username); + + Set getUserPermissionsSet(String username); + + Map getUserRoleIds(List userIdList); + + List getByRoleCode(String roleCode); + + void deleteBatch(List userIds); + + @Transactional(rollbackFor = Exception.class) + void delete(String userId); + + /** + * 分页查询内部用户列表 + * @param user + * @return + */ + IPage queryInnerUserList(Page page, SysUser user); + + IPage queryPageListV2(SysUser user, String roleName, String departName, String column, String order, Page page); +} diff --git a/src/main/java/com/gci/boot/modules/system/service/LoginTimesValidateService.java b/src/main/java/com/gci/boot/modules/system/service/LoginTimesValidateService.java new file mode 100644 index 0000000..728ca8d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/LoginTimesValidateService.java @@ -0,0 +1,36 @@ +package com.gci.boot.modules.system.service; + +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.system.entity.LoginTimesValidate; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +/** + * @Author: lyz + * @Description: TODO:(用一句话描述该文件做什么) + * @version: v1.0 + * @Modified by: + **/ +@Service +public class LoginTimesValidateService +{ + public LoginTimesValidate getManageTimes(String loginUser){ + LoginTimesValidate act = null; + Object timesJson = RedisUtil.get(CacheConstant.LOGIN_TIMES_VALIDATE_PC+loginUser); + if(Objects.nonNull(timesJson)){ + act = JsonUtil.json2Object(timesJson.toString(),LoginTimesValidate.class); + }else{ + act = new LoginTimesValidate(loginUser); + } + return act; + } + + public void saveManageTimes(LoginTimesValidate at) { + at.addTimes(); + String timesJson = JsonUtil.object2Json(at); + RedisUtil.set(CacheConstant.LOGIN_TIMES_VALIDATE_PC+at.getLoginUser(),timesJson,at.getSecond()); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysDepartServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysDepartServiceImpl.java new file mode 100644 index 0000000..2393960 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysDepartServiceImpl.java @@ -0,0 +1,60 @@ +package com.gci.boot.modules.system.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.system.entity.SysDepart; +import com.gci.boot.modules.system.mapper.SysDepartMapper; +import com.gci.boot.modules.system.service.ISysDepartService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 组织机构表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-31 + */ +@Service +public class SysDepartServiceImpl extends ServiceImpl implements ISysDepartService { + + @Autowired + private SysDepartMapper sysDepartMapper; + + @Override + public void deleteWithChildren(String id){ + SysDepart depart = getById(id); + if(depart != null) { + deleteChildren(depart); + removeById(depart.getId()); + } + } + + @Override + public void deleteBatchWithChildren(List ids){ + List list = lambdaQuery().in(SysDepart::getId, ids).list(); + if(list.size()>0) { + list.forEach(d -> deleteChildren(d)); + removeByIds(list.stream().map(SysDepart::getId).collect(Collectors.toList())); + } + } + + @Override + public List getDepartByUserId(String userId) { + return sysDepartMapper.getDepartByUserId(userId); + } + + private void deleteChildren(SysDepart depart){ + if(depart != null){ + List list = lambdaQuery().eq(SysDepart::getParentId, depart.getId()) + .list(); + if(list.size()>0) { + list.forEach(d->deleteChildren(d)); + removeByIds(list.stream().map(SysDepart::getId).collect(Collectors.toList())); + } + } + } +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysDictItemServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysDictItemServiceImpl.java new file mode 100644 index 0000000..aa58e01 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysDictItemServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.system.service.impl; + +import com.gci.boot.modules.system.entity.SysDictItem; +import com.gci.boot.modules.system.mapper.SysDictItemMapper; +import com.gci.boot.modules.system.service.ISysDictItemService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +@Service +public class SysDictItemServiceImpl extends ServiceImpl implements ISysDictItemService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysDictServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysDictServiceImpl.java new file mode 100644 index 0000000..b36f623 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysDictServiceImpl.java @@ -0,0 +1,126 @@ +package com.gci.boot.modules.system.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.dict.excel.DictParser; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.system.entity.SysDict; +import com.gci.boot.modules.system.mapper.SysDictMapper; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; + +/** + *

+ * 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-25 + */ +@Service +public class SysDictServiceImpl extends ServiceImpl implements ISysDictService, DictParser { + + @Override + public List queryDictItemsByCode(String code) { + return baseMapper.queryDictItemsByCode(code); + } + + @Override + public List queryTableDictItemsByCodeAndFilter(String table, String text, String code, String filterSql) { + return baseMapper.queryTableDictItemsByCode(table, text, code, filterSql); + } + @Override + public List queryTableDictItemsByCode(String table, String text, String code) { + return baseMapper.queryTableDictItemsByCode(table, text, code, null); + } + + @Override + public String queryTableDictTextByKey(String table, String text, String code, String key) { + return queryTableDictTextByKey( table, text, code, key,false); + } + + /** + * 通过查询指定table的 text code 获取字典值text + * dictTableCache采用redis缓存有效期10分钟 + * hasDelFlag 是否要判断删除字段 + * @param table + * @param text + * @param code + * @param key + * @return + */ + @Override + @Cacheable(value = CacheConstant.SYS_DICT_TABLE_CACHE, key = "#table+':'+#code+':'+#key+':'+#hasDelFlag") + public String queryTableDictTextByKey(String table, String text, String code, String key,boolean hasDelFlag) { + if (StringUtils.isBlank(key)) { + return null; + } + List dictModels = new ArrayList<>(); + if(hasDelFlag) { + //判断表是否有delFlag字段 + String delFlag = queryDictDelFlag(table); + hasDelFlag = StringUtils.isNotBlank(delFlag); + } + if(hasDelFlag) { + dictModels = baseMapper.queryNoDelTableDictByValue(table, text, code, key); + }else { + dictModels = baseMapper.queryTableDictByValue(table, text, code, key); + } + + if (dictModels.size() == 0) { + return null; + } + return dictModels.get(0).getText(); + } + + @Override + @Cacheable(value = CacheConstant.SYS_DICT_CACHE, key = "#code+':'+#key") + public String queryDictTextByKey(String code, String key) { + if (StringUtils.isBlank(key)) { + return null; + } + List dictModels = baseMapper.queryDictByValue(code, key); + if (dictModels.size() == 0) { + return null; + } + return dictModels.get(0).getText(); + } + + @Override + @Cacheable(value = CacheConstant.SYS_DICT_CACHE_TEXTKEY, key = "#code+':'+#key") + public String queryDictValueByText(String code, String key) { + if (StringUtils.isBlank(key)) { + return null; + } + List dictModels = baseMapper.queryDictByText(code, key); + if (dictModels.size() == 0) { + return null; + } + return dictModels.get(0).getValue(); + } + + @Override + @Cacheable(value = CacheConstant.SYS_DICT_TABLE_CACHE_TEXTKEY, key = "#table+':'+#text+':'+#key") + public String queryTableDictValueByText(String table, String text, String code, String key) { + if (StringUtils.isBlank(key)) { + return null; + } + List dictModels = baseMapper.queryTableDictByText(table, text, code, key); + if (dictModels.size() == 0) { + return null; + } + return dictModels.get(0).getValue(); + } + + @Cacheable(value = CacheConstant.SYS_DICT_DELFLAG_CACHE, key = "#table") + public String queryDictDelFlag(String table) { + return baseMapper.queryDictDelFlag(table); + } + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysLogServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysLogServiceImpl.java new file mode 100644 index 0000000..5d4fcc2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysLogServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.system.service.impl; + +import com.gci.boot.modules.system.entity.SysLog; +import com.gci.boot.modules.system.mapper.SysLogMapper; +import com.gci.boot.modules.system.service.ISysLogService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 系统日志表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-09-08 + */ +@Service +public class SysLogServiceImpl extends ServiceImpl implements ISysLogService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysPermissionServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysPermissionServiceImpl.java new file mode 100644 index 0000000..0fc87ae --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysPermissionServiceImpl.java @@ -0,0 +1,126 @@ +package com.gci.boot.modules.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.entity.SysPermission; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.system.entity.SysRolePermission; +import com.gci.boot.modules.system.mapper.SysPermissionMapper; +import com.gci.boot.modules.system.service.ISysPermissionService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.system.service.ISysRolePermissionService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + *

+ * 菜单权限表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@Service +public class SysPermissionServiceImpl extends ServiceImpl implements ISysPermissionService { + + @Autowired + private ISysRolePermissionService sysRolePermissionService; + + @Override + public List queryByUser(String username) { + return this.baseMapper.queryByUser(username); + } + + @Override + public void addPermission(SysPermission sysPermission) throws GciBootException { + //---------------------------------------------------------------------- + //判断是否是一级菜单,是的话清空父菜单 + if(CommonConstant.MENU_TYPE_MAIN.equals(sysPermission.getMenuType())) { + sysPermission.setParentId(null); + } + //---------------------------------------------------------------------- + String pid = sysPermission.getParentId(); + if(StringUtils.isNotBlank(pid)) { + //设置父节点不为叶子节点 + lambdaUpdate().eq(SysPermission::getId, pid).set(SysPermission::getIsLeaf, 0).update(); + } + sysPermission.setCreateTime(new Date()); + sysPermission.setIsLeaf(1); + this.save(sysPermission); + } + + @Override + public void editPermission(SysPermission sysPermission) throws GciBootException { + SysPermission p = this.getById(sysPermission.getId()); + //TODO 该节点判断是否还有子节点 + if(p==null) { + throw new GciBootException("未找到菜单信息"); + }else { + sysPermission.setUpdateTime(new Date()); + //---------------------------------------------------------------------- + //Step1.判断是否是一级菜单,是的话清空父菜单ID + if(CommonConstant.MENU_TYPE_MAIN.equals(sysPermission.getMenuType())) { + sysPermission.setParentId(""); + } + //Step2.判断菜单下级是否有菜单,无则设置为叶子节点 + int count = this.count(new QueryWrapper().lambda().eq(SysPermission::getParentId, sysPermission.getId())); + if(count==0) { + sysPermission.setIsLeaf(1); + } + //---------------------------------------------------------------------- + this.updateById(sysPermission); + + //如果当前菜单的父菜单变了,则需要修改新父菜单和老父菜单的,叶子节点状态 + String pid = sysPermission.getParentId(); + if((StringUtils.isNotBlank(pid) && !pid.equals(p.getParentId())) || StringUtils.isBlank(pid)&&StringUtils.isNotBlank(p.getParentId())) { + //a.设置新的父菜单不为叶子节点 + lambdaUpdate().eq(SysPermission::getId, pid).set(SysPermission::getIsLeaf, 0).update(); + //b.判断老的菜单下是否还有其他子菜单,没有的话则设置为叶子节点 + int cc = this.count(new QueryWrapper().lambda().eq(SysPermission::getParentId, p.getParentId())); + if(cc==0) { + if(StringUtils.isNotBlank(p.getParentId())) { + lambdaUpdate().eq(SysPermission::getId, p.getParentId()).set(SysPermission::getIsLeaf, 1).update(); + } + } + + } + } + + } + + + @Override + @Transactional + public void deletePermission(String id) throws GciBootException { + SysPermission sysPermission = this.getById(id); + if(sysPermission==null) { + throw new GciBootException("未找到菜单信息"); + } + String pid = sysPermission.getParentId(); + if(StringUtils.isNotBlank(pid)) { + int count = lambdaQuery().eq(SysPermission::getParentId, pid).count(); + if(count==1) { + //若父节点无其他子节点,则该父节点是叶子节点 + lambdaUpdate().eq(SysPermission::getId, pid).set(SysPermission::getIsLeaf, 1); + } + } + baseMapper.deleteById(id); + // 该节点可能是子节点但也可能是其它节点的父节点,所以需要级联删除 + lambdaQuery().eq(SysPermission::getParentId, sysPermission.getId()).list() + .forEach(p -> deletePermission(p.getId())); + //删除角色授权表 + sysRolePermissionService.lambdaUpdate().eq(SysRolePermission::getPermissionId, id).remove(); + } + + @Override + public Set getPermCodeSetByroleIds(Collection roleIds){ + return baseMapper.getPermCodeSetByroleIds(roleIds); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysRolePermissionServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysRolePermissionServiceImpl.java new file mode 100644 index 0000000..5fa3745 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysRolePermissionServiceImpl.java @@ -0,0 +1,78 @@ +package com.gci.boot.modules.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.gci.boot.modules.system.entity.SysRolePermission; +import com.gci.boot.modules.system.mapper.SysRolePermissionMapper; +import com.gci.boot.modules.system.service.ISysRolePermissionService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +/** + *

+ * 角色权限表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@Service +public class SysRolePermissionServiceImpl extends ServiceImpl implements ISysRolePermissionService { + + @Transactional(rollbackFor = Exception.class) + @Override + public void saveRolePermission(String roleId, String permissionIds, String lastPermissionIds) { + List add = getDiff(lastPermissionIds,permissionIds); + if(add!=null && add.size()>0) { + List list = new ArrayList(); + for (String p : add) { + if(StringUtils.isNotBlank(p)) { + SysRolePermission rolepms = new SysRolePermission(); + rolepms.setRoleId(roleId); + rolepms.setPermissionId(p); + list.add(rolepms); + } + } + this.saveBatch(list); + } + + List delete = getDiff(permissionIds,lastPermissionIds); + if(delete!=null && delete.size()>0) { + for (String permissionId : delete) { + this.remove(new QueryWrapper().lambda().eq(SysRolePermission::getRoleId, roleId).eq(SysRolePermission::getPermissionId, permissionId)); + } + } + } + + /** + * 从diff中找出main中没有的元素 + * @param main + * @param diff + * @return + */ + private List getDiff(String main,String diff){ + if(StringUtils.isBlank(diff)) { + return null; + } + if(StringUtils.isBlank(main)) { + return Arrays.asList(diff.split(",")); + } + + String[] mainArr = main.split(","); + String[] diffArr = diff.split(","); + Map map = new HashMap<>(); + for (String string : mainArr) { + map.put(string, 1); + } + List res = new ArrayList(); + for (String key : diffArr) { + if(StringUtils.isNotBlank(key) && !map.containsKey(key)) { + res.add(key); + } + } + return res; + } +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysRoleServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..5d734a4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,68 @@ +package com.gci.boot.modules.system.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.entity.SysRolePermission; +import com.gci.boot.modules.system.entity.SysUserRole; +import com.gci.boot.modules.system.mapper.SysRoleMapper; +import com.gci.boot.modules.system.service.ISysRolePermissionService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.service.ISysUserRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + *

+ * 角色表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@Service +public class SysRoleServiceImpl extends ServiceImpl implements ISysRoleService { + + @Autowired + private ISysUserRoleService sysUserRoleService; + @Autowired + private ISysRolePermissionService sysRolePermissionService; + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteRole(String roleid) { + //1.删除角色和用户关系 + sysUserRoleService.lambdaUpdate().eq(SysUserRole::getRoleId, roleid).remove(); + //2.删除角色和权限关系 + sysRolePermissionService.lambdaUpdate().eq(SysRolePermission::getRoleId, roleid).remove(); + //3.删除角色 + this.removeById(roleid); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteBatchRole(String[] roleIds) { + //1.删除角色和用户关系 + sysUserRoleService.lambdaUpdate().in(SysUserRole::getRoleId, roleIds).remove(); + //2.删除角色和权限关系 + sysRolePermissionService.lambdaUpdate().in(SysRolePermission::getRoleId, roleIds).remove(); + //3.删除角色 + this.removeByIds(Arrays.asList(roleIds)); + return true; + } + + @Override + public Set getRoleCodeSetByUserId(String userId){ + return baseMapper.getRoleCodeSetByUserId(userId); + } + + @Override + public List getRoleByUserId(String userId) { + return baseMapper.getRoleByUserId(userId); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysUserDepartServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysUserDepartServiceImpl.java new file mode 100644 index 0000000..027b1b0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysUserDepartServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.system.service.impl; + +import com.gci.boot.modules.system.entity.SysUserDepart; +import com.gci.boot.modules.system.mapper.SysUserDepartMapper; +import com.gci.boot.modules.system.service.ISysUserDepartService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-09-04 + */ +@Service +public class SysUserDepartServiceImpl extends ServiceImpl implements ISysUserDepartService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysUserRoleServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysUserRoleServiceImpl.java new file mode 100644 index 0000000..cae6e29 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysUserRoleServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.system.service.impl; + +import com.gci.boot.modules.system.entity.SysUserRole; +import com.gci.boot.modules.system.mapper.SysUserRoleMapper; +import com.gci.boot.modules.system.service.ISysUserRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户角色表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-18 + */ +@Service +public class SysUserRoleServiceImpl extends ServiceImpl implements ISysUserRoleService { + +} diff --git a/src/main/java/com/gci/boot/modules/system/service/impl/SysUserServiceImpl.java b/src/main/java/com/gci/boot/modules/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..fb6a02c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,352 @@ +package com.gci.boot.modules.system.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.ParamsCheckUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.projects.entity.ProjectUserRel; +import com.gci.boot.modules.projects.service.IProjectUserRelService; +import com.gci.boot.modules.system.entity.*; +import com.gci.boot.modules.system.mapper.SysUserMapper; +import com.gci.boot.modules.system.service.*; +import com.gci.boot.modules.system.util.AesEncryptUtil; +import com.gci.boot.modules.system.util.PasswordUtil; +import com.gci.boot.modules.system.util.QsEncodeUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author chenzhiwei + * @since 2023-08-17 + */ +@Service +public class SysUserServiceImpl extends ServiceImpl implements ISysUserService { + + @Autowired + private ISysUserRoleService sysUserRoleService; + + @Autowired + private ISysUserDepartService sysUserDepartService; + + @Autowired + private ISysRoleService sysRoleService; + + @Autowired + private ISysPermissionService sysPermissionService; + + @Autowired + private ISysDepartService sysDepartService; + + @Autowired + private SysUserMapper sysUserMapper; + + @Autowired + private IProjectUserRelService projectUserRelService; + + @Override + public SysUser getByUsername(String username){ + return lambdaQuery().eq(SysUser::getUsername, username).one(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addUserEncryptPassword(SysUser user, List roleIds, List departIds){ + ParamsCheckUtil.paramsAssert().notBlank(user.getUsername(), "【用户名】不能为空!") + .notBlank(user.getPassword(), "【密码】不能为空!") + .isTrue(lambdaQuery().eq(SysUser::getUsername, user.getUsername()).count() == 0, String.format("用户名【%s】已存在!", user.getUsername())) + .isTrue(PasswordUtil.checkPassword(user.getPassword()), "密码必须由8-12位数字、大小写字母和特殊符号组成") + ; + + user.setCreateTime(new Date());//设置创建时间 + String salt = PasswordUtil.generateSalt(8); + user.setSalt(salt); + String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt); + user.setPassword(passwordEncode); + addUser(user, roleIds, departIds); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void editUserEncryptPassword(SysUser user, List roleIds, List departIds){ + ParamsCheckUtil.paramsAssert().notBlank(user.getUsername(), "【用户名】不能为空!") + .isTrue(lambdaQuery().ne(SysUser::getId, user.getId()).eq(SysUser::getUsername, user.getUsername()).count() == 0, String.format("用户名【%s】已存在!", user.getUsername())); + + if(StringUtils.isNotBlank(user.getPassword())) { + ParamsCheckUtil.assertTrue(PasswordUtil.checkPassword(user.getPassword()), "密码必须由8-12位数字、大小写字母和特殊符号组成"); + String salt = PasswordUtil.generateSalt(8); + user.setSalt(salt); + String passwordEncode = PasswordUtil.encrypt(user.getUsername(), user.getPassword(), salt); + user.setPassword(passwordEncode); + } + editUser(user, roleIds, departIds); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void addUser(SysUser user, List roleIds, List departIds){ + if(departIds != null && departIds.size()>0){ + SysDepart depart = sysDepartService.getById(departIds.get(0)); + if(depart != null){ + user.setOrgCode(depart.getOrgCode()); + } + } + save(user); + addUserRoleAndDepart(user.getId(), roleIds, departIds); + } + + @Override + public void addInnerUser(SysUser user, List roleIds, List departIds, List projectIds) { + addUser(user,roleIds,departIds); + //新增内部员工和部门的关系数据 + if(projectIds != null && projectIds.size()>0){ + List relList = new ArrayList<>(); + for(String id:projectIds){ + ProjectUserRel projUserRel = new ProjectUserRel(); + projUserRel.setUserId(user.getId()); + projUserRel.setProjectId(id); + relList.add(projUserRel); + } + projectUserRelService.saveBatch(relList); + } + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void editUser(SysUser user, List roleIds, List departIds){ + if (StringUtils.isBlank(user.getOrgCode()) && departIds != null && departIds.size() > 0) { + SysDepart depart = sysDepartService.getById(departIds.get(0)); + if (depart != null) { + user.setOrgCode(depart.getOrgCode()); + } + } + updateById(user); + sysUserRoleService.lambdaUpdate().eq(SysUserRole::getUserId, user.getId()).remove(); + sysUserDepartService.lambdaUpdate().eq(SysUserDepart::getUserId, user.getId()).remove(); + addUserRoleAndDepart(user.getId(), roleIds, departIds); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void editInnerUser(SysUser user, List roleIds, List departIds, List projectIds) { + editUser(user,roleIds,departIds); + projectUserRelService.lambdaUpdate().eq(ProjectUserRel::getUserId, user.getId()).remove(); + //新增内部员工和部门的关系数据 + if(projectIds != null && projectIds.size()>0){ + List relList = new ArrayList<>(); + for(String id:projectIds){ + ProjectUserRel projUserRel = new ProjectUserRel(); + projUserRel.setUserId(user.getId()); + projUserRel.setProjectId(id); + relList.add(projUserRel); + } + projectUserRelService.saveBatch(relList); + } + } + + private void addUserRoleAndDepart(String userId, List roleIds, List departIds){ + if(roleIds != null && roleIds.size() > 0){ + List roleList = new ArrayList<>(); + for(String id:roleIds){ + SysUserRole sysUserRole = new SysUserRole(); + sysUserRole.setUserId(userId); + sysUserRole.setRoleId(id); + roleList.add(sysUserRole); + } + sysUserRoleService.saveBatch(roleList); + } + if(departIds != null && departIds.size()>0){ + List depList = new ArrayList<>(); + for(String id:departIds){ + SysUserDepart sysUserDepart = new SysUserDepart(); + sysUserDepart.setUserId(userId); + sysUserDepart.setDepId(id); + depList.add(sysUserDepart); + } + sysUserDepartService.saveBatch(depList); + } + } + + + @Override + public String processPhone(SysUser user) { + // 优先取phone字段 + if (StringUtils.isNotBlank(user.getPhone())) { + return user.getPhone(); + } + // 其次取解密后字段 + if (StringUtils.isNotBlank(user.getEncryptPhone()) && StringUtils.isNotBlank(user.getSecretPhone())) { + try { + return QsEncodeUtil.aesDecrypt(user.getEncryptPhone(), user.getSecretPhone()); + } catch (Exception e) { + log.error("SysUser手机号解密失败,", e); + return null; + } + } + return null; + } + + @Override + public void resetPassword(String username, String oldPassword, String newPassword, String confirmPassword) { + SysUser user = getByUsername(username); + if (StrUtil.isBlank(oldPassword)) { + throw new GciBootException("旧密码不能为空!"); + } + if (StringUtils.isBlank(newPassword)) { + throw new GciBootException("新密码不允许为空!"); + } + if (!newPassword.equals(confirmPassword)) { + throw new GciBootException("两次输入密码不一致!"); + } + try { + oldPassword = AesEncryptUtil.desEncrypt(oldPassword.replaceAll("%2B", "\\+")).trim(); + newPassword = AesEncryptUtil.desEncrypt(newPassword.replaceAll("%2B", "\\+")).trim(); + confirmPassword = AesEncryptUtil.desEncrypt(confirmPassword.replaceAll("%2B", "\\+")).trim(); + } catch (Exception e) { + e.printStackTrace(); + log.error("修改密码解密错误!",e); + throw new GciBootException("旧密码输入错误!"); + } + String passwordEncode = PasswordUtil.encrypt(username, oldPassword, user.getSalt()); + if (!user.getPassword().equals(passwordEncode)) { + throw new GciBootException("旧密码输入错误!"); + } + if(!PasswordUtil.checkPassword(newPassword)){ + throw new GciBootException("密码必须由8-12位数字、大小写字母和特殊符号组成!"); + } + String password = PasswordUtil.encrypt(username, newPassword, user.getSalt()); + + lambdaUpdate().eq(SysUser::getId, user.getId()) + .set(SysUser::getPassword, password) + .set(SysUser::getPasswordUpdateTime, new Date()) + .update(); + } + @Override + public Set getUserRolesSet(String username){ + SysUser user = getByUsername(username); + if(user != null) { + return sysRoleService.getRoleCodeSetByUserId(user.getId()); + } + return new HashSet<>(); + } + + @Override + public Set getUserRoleIdsSet(String username){ + SysUser user = getByUsername(username); + if(user != null) { + List roles = sysRoleService.getRoleByUserId(user.getId()); + return roles.stream().map(role-> role.getId()).collect(Collectors.toSet()); + } + return new HashSet<>(); + } + + @Override + public Set getUserPermissionsSet(String username) { + Set roleIds = getUserRoleIdsSet(username); + if(roleIds.size()>0) { + return sysPermissionService.getPermCodeSetByroleIds(roleIds); + } + return new HashSet<>(); + } + + @Override + public Map getUserRoleIds(List userIdList){ + QueryWrapper q = new QueryWrapper<>(); + q.select("string_agg(role_id,',') as role_id", "user_id"); + q.groupBy("user_id"); + q.in("user_id", userIdList); + List roles = sysUserRoleService.list(q); + Map res = new LinkedHashMap<>(); + for(SysUserRole sur:roles){ + if(StringUtils.isBlank(sur.getRoleId())){ + continue; + } + res.put(sur.getUserId(), sur.getRoleId()); + } + return res; + } + + /** + * 根据角色编码获取用户 + */ + @Override + public List getByRoleCode(String roleCode){ + if(StringUtils.isBlank(roleCode)) { + roleCode = CommonConstant.MAINTENANCE_ADMIN_ROLE_CODE; + } + String sql = "select 1 from sys_role r join sys_user_role ur on r.id = ur.role_id where sys_user.id = ur.user_id and r.role_code='"+roleCode+"'"; + return lambdaQuery().exists(sql).list(); + } + + + @Transactional(rollbackFor = Exception.class) + @Override + public void deleteBatch(List userIds){ + removeByIds(userIds); + sysUserRoleService.lambdaUpdate().in(SysUserRole::getUserId, userIds).remove(); + sysUserDepartService.lambdaUpdate().in(SysUserDepart::getUserId, userIds).remove(); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public void delete(String userId){ + removeById(userId); + sysUserRoleService.lambdaUpdate().eq(SysUserRole::getUserId, userId).remove(); + sysUserDepartService.lambdaUpdate().eq(SysUserDepart::getUserId, userId).remove(); + } + + @Override + public IPage queryInnerUserList(Page page, SysUser user) { + return page.setRecords(sysUserMapper.queryInnerUserList(page,user)); + } + + @Override + public IPage queryPageListV2(SysUser user, String roleName, String departName, String column, String order, Page page) { + List roles = sysRoleService.lambdaQuery().like(StringUtils.isNotBlank(roleName),SysRole::getRoleName,roleName).list(); + List roleIds = roles.stream().map(SysRole::getId).collect(Collectors.toList()); + List sysUserRoles = new ArrayList<>(); + if (ObjectUtil.isNotEmpty(roleIds)) { + sysUserRoles = sysUserRoleService.lambdaQuery().in(SysUserRole::getRoleId, roleIds).list(); + } + + List departs = sysDepartService.lambdaQuery().like(StringUtils.isNotBlank(departName), SysDepart::getDepartName, departName).list(); + List departIds = departs.stream().map(SysDepart::getId).collect(Collectors.toList()); + List sysUserDeparts = new ArrayList<>(); + if (ObjectUtil.isNotEmpty(departIds)) { + sysUserDeparts = sysUserDepartService.lambdaQuery().in(SysUserDepart::getDepId, departIds).list(); + } + + List allUserIdList = list().stream().map(SysUser::getId).collect(Collectors.toList()); + + List sysUserRoleIds; + + if (StrUtil.isBlank(roleName)) { + sysUserRoleIds = allUserIdList; + } else { + sysUserRoleIds = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList()); + } + + List sysUserDepartIds; + if (StrUtil.isBlank(departName)) { + sysUserDepartIds = allUserIdList; + } else { + sysUserDepartIds = sysUserDeparts.stream().map(SysUserDepart::getUserId).collect(Collectors.toList()); + } + + return sysUserMapper.queryPageListV2(user,sysUserRoleIds,sysUserDepartIds,column,order,page); + } + +} diff --git a/src/main/java/com/gci/boot/modules/system/shiro/authc/CustomShiroFilterFactoryBean.java b/src/main/java/com/gci/boot/modules/system/shiro/authc/CustomShiroFilterFactoryBean.java new file mode 100644 index 0000000..5b2962e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/authc/CustomShiroFilterFactoryBean.java @@ -0,0 +1,75 @@ +package com.gci.boot.modules.system.shiro.authc; + +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.filter.InvalidRequestFilter; +import org.apache.shiro.web.filter.mgt.DefaultFilter; +import org.apache.shiro.web.filter.mgt.FilterChainManager; +import org.apache.shiro.web.filter.mgt.FilterChainResolver; +import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver; +import org.apache.shiro.web.mgt.WebSecurityManager; +import org.apache.shiro.web.servlet.AbstractShiroFilter; +import org.springframework.beans.factory.BeanInitializationException; + +import javax.servlet.Filter; +import java.util.Map; + +/** + * 自定义ShiroFilterFactoryBean解决资源中文路径问题 + */ +@Slf4j +public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean { + @Override + public Class getObjectType() { + return MySpringShiroFilter.class; + } + + @Override + protected AbstractShiroFilter createInstance() throws Exception { + + SecurityManager securityManager = getSecurityManager(); + if (securityManager == null) { + String msg = "SecurityManager property must be set."; + throw new BeanInitializationException(msg); + } + + if (!(securityManager instanceof WebSecurityManager)) { + String msg = "The security manager does not implement the WebSecurityManager interface."; + throw new BeanInitializationException(msg); + } + + FilterChainManager manager = createFilterChainManager(); + //Expose the constructed FilterChainManager by first wrapping it in a + // FilterChainResolver implementation. The AbstractShiroFilter implementations + // do not know about FilterChainManagers - only resolvers: + PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver(); + chainResolver.setFilterChainManager(manager); + + Map filterMap = manager.getFilters(); + Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name()); + if (invalidRequestFilter instanceof InvalidRequestFilter) { + //此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug + ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false); + } + //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built + //FilterChainResolver. It doesn't matter that the instance is an anonymous inner class + //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts + //injection of the SecurityManager and FilterChainResolver: + return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver); + } + + private static final class MySpringShiroFilter extends AbstractShiroFilter { + protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) { + if (webSecurityManager == null) { + throw new IllegalArgumentException("WebSecurityManager property cannot be null."); + } else { + this.setSecurityManager(webSecurityManager); + if (resolver != null) { + this.setFilterChainResolver(resolver); + } + + } + } + } +} diff --git a/src/main/java/com/gci/boot/modules/system/shiro/authc/JwtToken.java b/src/main/java/com/gci/boot/modules/system/shiro/authc/JwtToken.java new file mode 100644 index 0000000..e714c43 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/authc/JwtToken.java @@ -0,0 +1,28 @@ +package com.gci.boot.modules.system.shiro.authc; + +import org.apache.shiro.authc.AuthenticationToken; + +/** + * @Author Scott + * @create 2018-07-12 15:19 + * @desc + **/ +public class JwtToken implements AuthenticationToken { + + private static final long serialVersionUID = 1L; + private String token; + + public JwtToken(String token) { + this.token = token; + } + + @Override + public Object getPrincipal() { + return token; + } + + @Override + public Object getCredentials() { + return token; + } +} diff --git a/src/main/java/com/gci/boot/modules/system/shiro/authc/ShiroRealm.java b/src/main/java/com/gci/boot/modules/system/shiro/authc/ShiroRealm.java new file mode 100644 index 0000000..058ebda --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/authc/ShiroRealm.java @@ -0,0 +1,203 @@ +package com.gci.boot.modules.system.shiro.authc; + +import com.alibaba.excel.util.StringUtils; +import com.gci.boot.common.util.CacheUtil; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.constant.CacheConstant; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.util.JwtUtil; +import com.gci.boot.modules.system.vo.LoginUser; +import lombok.AllArgsConstructor; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.modules.system.service.ISysUserService; +import org.springframework.beans.BeanUtils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.Set; + +/** + * @Description: 用户登录鉴权和获取用户授权 + * @Author: Scott + * @Date: 2019-4-23 8:13 + * @Version: 1.1 + */ +@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") +@Slf4j +@AllArgsConstructor +@Component +public class ShiroRealm extends AuthorizingRealm { + + private ISysUserService sysUserService; + + private long expireTime; + + /** + * 必须重写此方法,不然Shiro会报错 + */ + @Override + public boolean supports(AuthenticationToken token) { + return token instanceof JwtToken; + } + + /** + * 权限信息认证(包括角色以及权限)是用户访问controller的时候才进行验证(redis存储的此处权限信息) + * 触发检测用户权限时才会调用此方法,例如checkRole,checkPermission + * + * @param principals 身份信息 + * @return AuthorizationInfo 权限信息 + */ + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + log.info("===============Shiro权限认证开始============ [ roles、permissions]=========="); + if (principals != null) { + LoginUser sysUser = (LoginUser) principals.getPrimaryPrincipal(); + SimpleAuthorizationInfo info = CacheUtil.get(CacheConstant.SYS_AUTHORIZATION_CACHE, sysUser.getUsername(), SimpleAuthorizationInfo.class); + if(info == null) { + info = new SimpleAuthorizationInfo(); + String username = sysUser.getUsername(); + // 设置用户拥有的角色集合,比如“admin,test” + Set roleSet = sysUserService.getUserRolesSet(username); + info.setRoles(roleSet); + + // 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add” + Set permissionSet = sysUserService.getUserPermissionsSet(username); + info.addStringPermissions(permissionSet); + //加入缓存 + CacheUtil.put(CacheConstant.SYS_AUTHORIZATION_CACHE, sysUser.getUsername(), info); + } + log.info("===============Shiro权限认证成功=============="); + return info; + } + return null; + } + + /** + * 用户信息认证是在用户进行登录的时候进行验证 + * 也就是说验证用户输入的账号和密码是否正确,错误抛出异常 + * + * @param auth 用户登录的账号密码信息 + * @return 返回封装了用户信息的 AuthenticationInfo 实例 + * @throws AuthenticationException + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth){ + try { + String token = (String) auth.getCredentials(); + if (token == null) { + log.info("————————身份认证失败——————————IP地址: "+ getIpAddrByRequest(SpringContextUtil.getHttpServletRequest())); + throw new AuthenticationException("token为空!"); + } + // 校验token有效性 + LoginUser loginUser = this.checkUserTokenIsEffect(token); + return new SimpleAuthenticationInfo(loginUser, token, getName()); + } catch (AuthenticationException e) { + log.error("", e); + throw new AuthenticationException(e.getMessage()); + } + } + + private String getIpAddrByRequest(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + /** + * 校验token的有效性 + * + * @param token + */ + public LoginUser checkUserTokenIsEffect(String token) throws AuthenticationException { + // 解密获得username,用于和数据库进行对比 + String username = JwtUtil.getUsername(token); + if (username == null) { + throw new AuthenticationException("token非法无效!"); + } + + // 查询用户信息 + log.debug("———校验token是否有效————checkUserTokenIsEffect——————— "+ token); + SysUser user = CacheUtil.get(CacheConstant.SYS_USERS_CACHE, username, SysUser.class); + if(user == null){ + user = sysUserService.getByUsername(username); + CacheUtil.put(CacheConstant.SYS_USERS_CACHE, username, user); + } + if (user == null) { + throw new AuthenticationException("用户不存在!"); + } + // 判断用户状态 + if (user.getStatus() != 1) { + throw new AuthenticationException("账号已被锁定,请联系管理员!"); + } + // 校验token是否超时失效 & 或者账号密码是否错误 + jwtTokenRefresh(token, username, user.getPassword()); + LoginUser loginUser = new LoginUser(); + BeanUtils.copyProperties(user, loginUser); + return loginUser; + } + + /** + * JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能) + * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍 + * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证 + * 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算 + * 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。 + * 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。 + * 用户过期时间 = Jwt有效时间 * 2。 + * + * @return + */ + private void jwtTokenRefresh(String token, String username, String secret) { + String cacheToken = String.valueOf(RedisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token)); + //获取携带的token是否存在缓存,如果不存在,说明token过期,需要判断是自然失效还是互斥影响失效 + if(StringUtils.isBlank(cacheToken) || "null".equalsIgnoreCase(cacheToken)){ + //获取该用户最近登陆保存的token. + String pcToken = String.valueOf(RedisUtil.get(CommonConstant.PREFIX_PC_USER + username)); + //如果不存在pc-token 或者 + if((StringUtils.isNotBlank(pcToken) || "null".equalsIgnoreCase(pcToken)) && !pcToken.equals(token)){ + throw new AuthenticationException("您的账号已在其他设备登录!"); + }else{ + throw new AuthenticationException("Token失效,请重新登录!"); + } + } + //如果存在且未超过有效期 + // 如果token未超过有效期,重设redis过期时间 + if (JwtUtil.verify(token, username)) { + RedisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, expireTime / 1000); + } else {//如果token超过有效期,刷新token + String newToken = JwtUtil.sign(username, secret); + RedisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newToken, expireTime / 1000); + } + log.debug("——————————用户在线操作,更新token保证不掉线—————————jwtTokenRefresh——————— " + token); + } + + /** + * 清除当前用户的权限认证缓存 + * + * @param principals 权限信息 + */ + @Override + public void clearCache(PrincipalCollection principals) { + super.clearCache(principals); + } + +} diff --git a/src/main/java/com/gci/boot/modules/system/shiro/authc/aop/JwtFilter.java b/src/main/java/com/gci/boot/modules/system/shiro/authc/aop/JwtFilter.java new file mode 100644 index 0000000..6a74db5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/authc/aop/JwtFilter.java @@ -0,0 +1,112 @@ +package com.gci.boot.modules.system.shiro.authc.aop; + +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.util.RedisUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.shiro.authc.JwtToken; +import com.gci.boot.modules.system.shiro.vo.DefContants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Writer; + +/** + * @Description: 鉴权登录拦截器 + * @Author: Scott + * @Date: 2018/10/7 + **/ +@Slf4j +public class JwtFilter extends BasicHttpAuthenticationFilter { + + /** + * 执行登录认证 + * + * @param request + * @param response + * @param mappedValue + * @return + */ + @Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { + try { + executeLogin(request, response); + return true; + }catch (AuthenticationException e){ + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setCharacterEncoding("UTF-8"); + httpResponse.setContentType("application/json; charset=utf-8"); + httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); + try { + Writer writer = httpResponse.getWriter(); + writer.write(JsonUtil.object2Json(Result.unauthorized(e.getMessage()))); + writer.flush(); + writer.close(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + return false; + } catch (Exception e) { + return false; + } + } + + /** + * + */ + @Override + protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + String token = httpServletRequest.getHeader(DefContants.X_ACCESS_TOKEN); + + JwtToken jwtToken = new JwtToken(token); + // 提交给realm进行登入,如果错误他会抛出异常并被捕获 + getSubject(request, response).login(jwtToken); + // 如果没有抛出异常则代表登入成功,返回true + return true; + } + + /** + * 对跨域提供支持 + */ + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { + HttpServletRequest httpServletRequest = (HttpServletRequest) request; + HttpServletResponse httpServletResponse = (HttpServletResponse) response; + httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); + httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE"); + httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers")); + // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态 + if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { + httpServletResponse.setStatus(HttpStatus.OK.value()); + return false; + } + return super.preHandle(request, response); + } + + /** + * 如果没有登录,直接返回401未授权提示 + */ + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setCharacterEncoding("UTF-8"); + httpResponse.setContentType("application/json; charset=utf-8"); + httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); + try { + httpResponse.getWriter().write(JsonUtil.object2Json(Result.unauthorized("Token失效,请重新登录!"))); + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/src/main/java/com/gci/boot/modules/system/shiro/authc/aop/ResourceCheckFilter.java b/src/main/java/com/gci/boot/modules/system/shiro/authc/aop/ResourceCheckFilter.java new file mode 100644 index 0000000..fbece12 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/authc/aop/ResourceCheckFilter.java @@ -0,0 +1,68 @@ +package com.gci.boot.modules.system.shiro.authc.aop; + +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.AccessControlFilter; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @Author Scott + * @create 2019-02-01 15:56 + * @desc 鉴权请求URL访问权限拦截器 + */ +@Slf4j +public class ResourceCheckFilter extends AccessControlFilter { + + private String errorUrl; + + public String getErrorUrl() { + return errorUrl; + } + + public void setErrorUrl(String errorUrl) { + this.errorUrl = errorUrl; + } + + /** + * 表示是否允许访问 ,如果允许访问返回true,否则false; + * + * @param servletRequest + * @param servletResponse + * @param o 表示写在拦截器中括号里面的字符串 mappedValue 就是 [urls] 配置中拦截器参数部分 + * @return + * @throws Exception + */ + @Override + protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception { + Subject subject = getSubject(servletRequest, servletResponse); + String url = getPathWithinApplication(servletRequest); + log.info("当前用户正在访问的 url => " + url); + return subject.isPermitted(url); + } + + /** + * onAccessDenied:表示当访问拒绝时是否已经处理了; 如果返回 true 表示需要继续处理; 如果返回 false + * 表示该拦截器实例已经处理了,将直接返回即可。 + * + * @param servletRequest + * @param servletResponse + * @return + * @throws Exception + */ + @Override + protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { + log.info("当 isAccessAllowed 返回 false 的时候,才会执行 method onAccessDenied "); + + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + response.sendRedirect(request.getContextPath() + this.errorUrl); + + // 返回 false 表示已经处理,例如页面跳转啥的,表示不在走以下的拦截器了(如果还有配置的话) + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/system/shiro/vo/DefContants.java b/src/main/java/com/gci/boot/modules/system/shiro/vo/DefContants.java new file mode 100644 index 0000000..9c5ecd3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/vo/DefContants.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.system.shiro.vo; + +public class DefContants { + + public final static String X_ACCESS_TOKEN = "X-Access-Token"; + +} diff --git a/src/main/java/com/gci/boot/modules/system/shiro/vo/ResponseBean.java b/src/main/java/com/gci/boot/modules/system/shiro/vo/ResponseBean.java new file mode 100644 index 0000000..9aa3a63 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/vo/ResponseBean.java @@ -0,0 +1,42 @@ +package com.gci.boot.modules.system.shiro.vo; +public class ResponseBean { + + // http 状态码 + private int code; + + // 返回信息 + private String msg; + + // 返回的数据 + private Object data; + + public ResponseBean(int code, String msg, Object data) { + this.code = code; + this.msg = msg; + this.data = data; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/system/shiro/vo/UserBean.java b/src/main/java/com/gci/boot/modules/system/shiro/vo/UserBean.java new file mode 100644 index 0000000..0de05f4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/shiro/vo/UserBean.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.system.shiro.vo; + +import lombok.Data; + +import java.util.HashSet; +import java.util.Set; + +@Data +public class UserBean { + private String username; + private String password; + private Set roles = new HashSet<>(); //用户所有角色值,用于shiro做角色权限的判断 + private Set perms = new HashSet<>(); //用户所有权限值,用于shiro做资源权限的判断 +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/system/util/AesEncryptUtil.java b/src/main/java/com/gci/boot/modules/system/util/AesEncryptUtil.java new file mode 100644 index 0000000..bebedf9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/util/AesEncryptUtil.java @@ -0,0 +1,101 @@ +package com.gci.boot.modules.system.util; + +import org.apache.shiro.codec.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * AES 加密 + */ +public class AesEncryptUtil { + + //使用AES-128-CBC加密模式,key需要为16位,key和iv可以相同! + public static String key = "1234567890adbcde"; + public static String iv = "1234567890hjlkew"; + + /** + * 加密方法 + * @param data 要加密的数据 + * @param key 加密key + * @param iv 加密iv + * @return 加密的结果 + * @throws Exception + */ + public static String encrypt(String data, String key, String iv) throws Exception { + try { + + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//"算法/模式/补码方式"NoPadding PkcsPadding + int blockSize = cipher.getBlockSize(); + + byte[] dataBytes = data.getBytes(); + int plaintextLength = dataBytes.length; + if (plaintextLength % blockSize != 0) { + plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize)); + } + + byte[] plaintext = new byte[plaintextLength]; + System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length); + + SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); + IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); + + cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); + byte[] encrypted = cipher.doFinal(plaintext); + + return Base64.encodeToString(encrypted); + + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 解密方法 + * @param data 要解密的数据 + * @param key 解密key + * @param iv 解密iv + * @return 解密的结果 + * @throws Exception + */ + public static String desEncrypt(String data, String key, String iv) throws Exception { + try { + byte[] encrypted1 = Base64.decode(data); + + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); + SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); + IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); + + cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); + + byte[] original = cipher.doFinal(encrypted1); + String originalString = new String(original); + return originalString; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 使用默认的key和iv加密 + * @param data + * @return + * @throws Exception + */ + public static String encrypt(String data) throws Exception { + return encrypt(data, key, iv); + } + + /** + * 使用默认的key和iv解密 + * @param data + * @return + * @throws Exception + */ + public static String desEncrypt(String data) throws Exception { + return desEncrypt(data, key, iv); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/util/GciDataAutorUtils.java b/src/main/java/com/gci/boot/modules/system/util/GciDataAutorUtils.java new file mode 100644 index 0000000..fc8e7b8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/util/GciDataAutorUtils.java @@ -0,0 +1,87 @@ +package com.gci.boot.modules.system.util; + +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.modules.system.vo.SysPermissionDataRuleModel; +import com.gci.boot.modules.system.vo.SysUserCacheInfo; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName: GciDataAutorUtils + * @Description: 数据权限查询规则容器工具类 + * @Author: 张代浩 + * @Date: 2012-12-15 下午11:27:39 + * + */ +public class GciDataAutorUtils { + + public static final String MENU_DATA_AUTHOR_RULES = "MENU_DATA_AUTHOR_RULES"; + + public static final String MENU_DATA_AUTHOR_RULE_SQL = "MENU_DATA_AUTHOR_RULE_SQL"; + + public static final String SYS_USER_INFO = "SYS_USER_INFO"; + + /** + * 往链接请求里面,传入数据查询条件 + * + * @param request + * @param dataRules + */ + public static synchronized void installDataSearchConditon(HttpServletRequest request, List dataRules) { + @SuppressWarnings("unchecked") + List list = (List)loadDataSearchConditon();// 1.先从request获取MENU_DATA_AUTHOR_RULES,如果存则获取到LIST + if (list==null) { + // 2.如果不存在,则new一个list + list = new ArrayList(); + } + for (SysPermissionDataRuleModel tsDataRule : dataRules) { + list.add(tsDataRule); + } + request.setAttribute(MENU_DATA_AUTHOR_RULES, list); // 3.往list里面增量存指 + } + + /** + * 获取请求对应的数据权限规则 + * + * @return + */ + @SuppressWarnings("unchecked") + public static synchronized List loadDataSearchConditon() { + return (List) SpringContextUtil.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULES); + + } + + /** + * 获取请求对应的数据权限SQL + * + * @return + */ + public static synchronized String loadDataSearchConditonSQLString() { + return (String) SpringContextUtil.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULE_SQL); + } + + /** + * 往链接请求里面,传入数据查询条件 + * + * @param request + * @param sql + */ + public static synchronized void installDataSearchConditon(HttpServletRequest request, String sql) { + String ruleSql = (String)loadDataSearchConditonSQLString(); + if (!StringUtils.hasText(ruleSql)) { + request.setAttribute(MENU_DATA_AUTHOR_RULE_SQL,sql); + } + } + + public static synchronized void installUserInfo(HttpServletRequest request, SysUserCacheInfo userinfo) { + request.setAttribute(SYS_USER_INFO, userinfo); + } + + public static synchronized SysUserCacheInfo loadUserInfo() { + return (SysUserCacheInfo) SpringContextUtil.getHttpServletRequest().getAttribute(SYS_USER_INFO); + + } +} diff --git a/src/main/java/com/gci/boot/modules/system/util/JwtUtil.java b/src/main/java/com/gci/boot/modules/system/util/JwtUtil.java new file mode 100644 index 0000000..eca4e14 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/util/JwtUtil.java @@ -0,0 +1,340 @@ +package com.gci.boot.modules.system.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTCreator; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.gci.boot.constant.DataBaseConstant; +import com.gci.boot.common.util.SpringContextUtil; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.system.vo.SysUserCacheInfo; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.formula.functions.T; +import org.apache.shiro.SecurityUtils; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author Scott + * @Date 2018-07-12 14:23 + * @Desc JWT工具类 + **/ +@Slf4j +public class JwtUtil { + + // Token过期时间30分钟(用户登录过期时间是此时间的两倍,以token在reids缓存时间为准) + public static long DEFAULT_EXPIRE_TIME = 30 * 60 * 1000; + + public static String secret; + + public void setExpireTime(long expireTime) { + JwtUtil.DEFAULT_EXPIRE_TIME = expireTime; + } + + public void setSecret(String secret){ + JwtUtil.secret = secret; + } + + /** + * 校验token是否正确 + * + * @param token 密钥 + * @param secret 用户的密码 + * @return 是否正确 + */ + public static boolean verify(String token, String username, String secret) { + try { + // 根据密码生成JWT效验器 + Algorithm algorithm = Algorithm.HMAC256(secret); + JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build(); + // 效验TOKEN + DecodedJWT jwt = verifier.verify(token); + return true; + } catch (Exception exception) { + return false; + } + } + + /** + * 校验token是否正确 + * + * @param token 密钥 + * @return 是否正确 + */ + public static boolean verify(String token, String username) { + return verify(token, username, secret); + } + + /** + * 获得token中的信息无需secret解密也能获得 + * + * @return token中包含的用户名 + */ + public static String getUsername(String token) { + try { + DecodedJWT jwt = JWT.decode(token); + return jwt.getClaim("username").asString(); + } catch (JWTDecodeException e) { + return null; + } + } + + public static T getObject(String token, Class tClass) { + try { + DecodedJWT jwt = JWT.decode(token); + T t = tClass.newInstance(); + Field[] fields = tClass.getDeclaredFields(); + for(Field f:fields){ + f.setAccessible(true); + String name = f.getName(); + Class type = f.getType(); + if("java.lang.String".equals(type.getName())){ + f.set(t,jwt.getClaim(name).asString()); + }else if("java.Util.Date".equals(type.getName())){ + f.set(t,jwt.getClaim(name).asDate()); + }else if("java.lang.Integer".equals(type.getName()) || "int".equals(type.getName())) { + f.set(t, jwt.getClaim(name).asInt()); + }else if("java.lang.Long".equals(type.getName()) || "long".equals(type.getName())) { + f.set(t, jwt.getClaim(name).asLong()); + }else if("java.lang.Double".equals(type.getName()) || "double".equals(type.getName())) { + f.set(t, jwt.getClaim(name).asDouble()); + }else if("java.lang.Boolean".equals(type.getName()) || "boolean".equals(type.getName())) { + f.set(t, jwt.getClaim(name).asBoolean()); + }else if("java.util.List".equals(type.getName())) { + Type genericType = f.getGenericType(); + Type[] typeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); + f.set(t, jwt.getClaim(name).asList((Class)typeArguments[0])); + }else if("java.util.Map".equals(type.getName())) { + f.set(t, jwt.getClaim(name).asMap()); + } + f.setAccessible(false); + } + return t; + } catch (Exception e) { + log.error("", e); + return null; + } + } + + + /** + * 生成签名,使用配置密钥,默认过期时间 + * @param username + * @return + */ + public static String sign(String username) { + return sign(username, secret, DEFAULT_EXPIRE_TIME); + } + + /** + * 生成签名,使用默认过期时间 + * + * @param username 用户名 + * @param secret 用户的密码 + * @return 加密的token + */ + public static String sign(String username, String secret) { + return sign(username, secret, DEFAULT_EXPIRE_TIME); + } + + /** + * 生成签名,自定义过期时间 + * @param username + * @param secret + * @param expire + * @return + */ + public static String sign(String username, String secret, long expire) { + Date date = new Date(System.currentTimeMillis() + expire); + Algorithm algorithm = Algorithm.HMAC256(secret); + // 附带username信息 + return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm); + } + + /** + * 生成签名,自定义过期时间 + * @param claims + * @param secret + * @param expire + * @return + */ + public static String sign(Map claims, String secret, long expire) { + Date date = new Date(System.currentTimeMillis() + expire); + Algorithm algorithm = Algorithm.HMAC256(secret); + // 附带信息 + JWTCreator.Builder builder = JWT.create(); + if(claims != null){ + claims.forEach((k, v)->{ + if(v instanceof String){ + builder.withClaim(k, (String)v); + }else if(v instanceof Integer){ + builder.withClaim(k, (Integer)v); + }else if(v instanceof Date){ + builder.withClaim(k, (Date)v); + }else if(v instanceof Long){ + builder.withClaim(k, (Long)v); + }else if(v instanceof Double){ + builder.withClaim(k, (Double)v); + }else if(v instanceof Boolean){ + builder.withClaim(k, (boolean)v); + } + }); + } + return builder.withExpiresAt(date).sign(algorithm); + } + + /** + * 生成签名,自定义过期时间 + * @param claims + * @param secret + * @return + */ + public static String sign(Map claims, String secret) { + return sign(claims, secret, DEFAULT_EXPIRE_TIME); + } + + /** + * 生成签名,自定义过期时间 + * @param claims + * @return + */ + public static String sign(Map claims) { + return sign(claims, secret, DEFAULT_EXPIRE_TIME); + } + + /** + * 根据request中的token获取用户账号 + * + * @param request + * @return + * @throws GciBootException + */ + public static String getUserNameByToken(HttpServletRequest request) throws GciBootException { + String accessToken = request.getHeader("X-Access-Token"); + String username = getUsername(accessToken); + if (StringUtils.isBlank(username)) { + throw new GciBootException("未获取到用户"); + } + return username; + } + + /** + * 从session中获取变量 + * @param key + * @return + */ + public static String getSessionData(String key) { + //${myVar}% + //得到${} 后面的值 + String moshi = ""; + if(key.indexOf("}")!=-1){ + moshi = key.substring(key.indexOf("}")+1); + } + String returnValue = null; + if (key.contains("#{")) { + key = key.substring(2,key.indexOf("}")); + } + if (StringUtils.isNotBlank(key)) { + HttpSession session = SpringContextUtil.getHttpServletRequest().getSession(); + returnValue = (String) session.getAttribute(key); + } + //结果加上${} 后面的值 + if(returnValue!=null){returnValue = returnValue + moshi;} + return returnValue; + } + + /** + * 从当前用户中获取变量 + * @param key + * @param user + * @return + */ + //TODO 急待改造 sckjkdsjsfjdk + public static String getUserSystemData(String key, SysUserCacheInfo user) { + if(user==null) { + user = GciDataAutorUtils.loadUserInfo(); + } + //#{sys_user_code}% + + // 获取登录用户信息 + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + String moshi = ""; + if(key.indexOf("}")!=-1){ + moshi = key.substring(key.indexOf("}")+1); + } + String returnValue = null; + //针对特殊标示处理#{sysOrgCode},判断替换 + if (key.contains("#{")) { + key = key.substring(2,key.indexOf("}")); + } else { + key = key; + } + //替换为系统登录用户帐号 + if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) { + if(user==null) { + returnValue = sysUser.getUsername(); + }else { + returnValue = user.getSysUserCode(); + } + } + //替换为系统登录用户真实名字 + else if (key.equals(DataBaseConstant.SYS_USER_NAME)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_NAME_TABLE)) { + if(user==null) { + returnValue = sysUser.getRealname(); + }else { + returnValue = user.getSysUserName(); + } + } + + //替换为系统用户登录所使用的机构编码 + else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) { + if(user==null) { + returnValue = sysUser.getOrgCode(); + }else { + returnValue = user.getSysOrgCode(); + } + } + //替换为系统用户所拥有的所有机构编码 + else if (key.equals(DataBaseConstant.SYS_MULTI_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE)) { + if(user.isOneDepart()) { + returnValue = user.getSysMultiOrgCode().get(0); + }else { + returnValue = user.getSysMultiOrgCode().stream().collect(Collectors.joining(",")); + } + } + //替换为当前系统时间(年月日) + else if (key.equals(DataBaseConstant.SYS_DATE)|| key.toLowerCase().equals(DataBaseConstant.SYS_DATE_TABLE)) { + returnValue = user.getSysDate(); + } + //替换为当前系统时间(年月日时分秒) + else if (key.equals(DataBaseConstant.SYS_TIME)|| key.toLowerCase().equals(DataBaseConstant.SYS_TIME_TABLE)) { + returnValue = user.getSysTime(); + } + //流程状态默认值(默认未发起) + else if (key.equals(DataBaseConstant.BPM_STATUS)|| key.toLowerCase().equals(DataBaseConstant.BPM_STATUS_TABLE)) { + returnValue = "1"; + } + if(returnValue!=null){returnValue = returnValue + moshi;} + return returnValue; + } + + public static void main(String[] args) { + String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0"; + System.out.println(JwtUtil.getUsername(token)); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/util/PasswordUtil.java b/src/main/java/com/gci/boot/modules/system/util/PasswordUtil.java new file mode 100644 index 0000000..d2593ed --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/util/PasswordUtil.java @@ -0,0 +1,207 @@ +package com.gci.boot.modules.system.util; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import java.security.Key; +import java.security.SecureRandom; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PasswordUtil { + + /** + * JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES + * PBEWITHSHAANDDESEDE PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1 + * */ + + /** + * 定义使用的算法为:PBEWITHMD5andDES算法 + */ + public static final String ALGORITHM = "PBEWithMD5AndDES";//加密算法 + public static final String Salt = "63293188";//密钥 + + /** + * 定义迭代次数为1000次 + */ + private static final int ITERATIONCOUNT = 1000; + + /** + * 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节 + * + * @return byte[] 盐值 + * */ + public static byte[] getSalt() throws Exception { + // 实例化安全随机数 + SecureRandom random = new SecureRandom(); + // 产出盐 + return random.generateSeed(8); + } + + public static byte[] getStaticSalt() { + // 产出盐 + return Salt.getBytes(); + } + + /** + * 根据PBE密码生成一把密钥 + * + * @param password + * 生成密钥时所使用的密码 + * @return Key PBE算法密钥 + * */ + private static Key getPBEKey(String password) { + // 实例化使用的算法 + SecretKeyFactory keyFactory; + SecretKey secretKey = null; + try { + keyFactory = SecretKeyFactory.getInstance(ALGORITHM); + // 设置PBE密钥参数 + PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); + // 生成密钥 + secretKey = keyFactory.generateSecret(keySpec); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return secretKey; + } + + /** + * 加密明文字符串 + * + * @param plaintext + * 待加密的明文字符串 + * @param password + * 生成密钥时所使用的密码 + * @param salt + * 盐值 + * @return 加密后的密文字符串 + * @throws Exception + */ + public static String encrypt(String plaintext, String password, String salt) { + + Key key = getPBEKey(password); + byte[] encipheredData = null; + PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT); + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + + cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec); + //update-begin-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7 + encipheredData = cipher.doFinal(plaintext.getBytes("utf-8")); + //update-end-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7 + } catch (Exception e) { + } + return bytesToHexString(encipheredData); + } + + /** + * 解密密文字符串 + * + * @param ciphertext + * 待解密的密文字符串 + * @param password + * 生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致) + * @param salt + * 盐值(如需解密,该参数需要与加密时使用的一致) + * @return 解密后的明文字符串 + * @throws Exception + */ + public static String decrypt(String ciphertext, String password, String salt) { + + Key key = getPBEKey(password); + byte[] passDec = null; + PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT); + try { + Cipher cipher = Cipher.getInstance(ALGORITHM); + + cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec); + + passDec = cipher.doFinal(hexStringToBytes(ciphertext)); + } + + catch (Exception e) { + // TODO: handle exception + } + return new String(passDec); + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param src + * 字节数组 + * @return + */ + public static String bytesToHexString(byte[] src) { + StringBuilder stringBuilder = new StringBuilder(""); + if (src == null || src.length <= 0) { + return null; + } + for (int i = 0; i < src.length; i++) { + int v = src[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + return stringBuilder.toString(); + } + + /** + * 将十六进制字符串转换为字节数组 + * + * @param hexString + * 十六进制字符串 + * @return + */ + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || hexString.equals("")) { + return null; + } + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + + private static byte charToByte(char c) { + return (byte) "0123456789ABCDEF".indexOf(c); + } + + + public static String generateSalt(int place) { + String base = "qwertyuioplkjhgfdsazxcvbnmQAZWSXEDCRFVTGBYHNUJMIKLOP0123456789"; + StringBuffer sb = new StringBuffer(); + Random rd = new Random(); + for(int i=0;iqinfeng + * @since:2017-6-29 下午07:59:38 + * @version:1.0 + */ + +import org.apache.commons.lang3.StringUtils; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.spec.SecretKeySpec; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.Base64; +import java.util.Random; + +/** + * 编码工具类 + * 1.将byte[]转为各种进制的字符串 + * 2.base 64 encode + * 3.base 64 decode + * 4.获取byte[]的md5值 + * 5.获取字符串md5值 + * 6.结合base64实现md5加密 + * 7.AES加密 + * 8.AES加密为base 64 code + * 9.AES解密 + * 10.将base 64 code AES解密 + * @author uikoo9 + * @version 0.0.7.20140601 + */ +public class QsEncodeUtil { + + /** + * 将byte[]转为各种进制的字符串 + * @param bytes byte[] + * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制 + * @return 转换后的字符串 + */ + public static String binary(byte[] bytes, int radix){ + return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数 + } + + /** + * base 64 encode + * @param bytes 待编码的byte[] + * @return 编码后的base 64 code + */ + public static String base64Encode(byte[] bytes){ + return Base64.getEncoder().encodeToString(bytes); + } + + /** + * base 64 decode + * @param base64Code 待解码的base 64 code + * @return 解码后的byte[] + * @throws Exception + */ + public static byte[] base64Decode(String base64Code) throws Exception{ + return StringUtils.isBlank(base64Code) ? null : Base64.getDecoder().decode(base64Code); + } + + /** + * 获取byte[]的md5值 + * @param bytes byte[] + * @return md5 + * @throws Exception + */ + public static byte[] md5(byte[] bytes) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(bytes); + + return md.digest(); + } + + /** + * 获取字符串md5值 + * @param msg + * @return md5 + * @throws Exception + */ + public static byte[] md5(String msg) throws Exception { + return StringUtils.isBlank(msg) ? null : md5(msg.getBytes()); + } + + /** + * 结合base64实现md5加密 + * @param msg 待加密字符串 + * @return 获取md5后转为base64 + * @throws Exception + */ + public static String md5Encrypt(String msg) throws Exception{ + return StringUtils.isBlank(msg) ? null : base64Encode(md5(msg)); + } + + /** + * AES加密 + * @param content 待加密的内容 + * @param encryptKey 加密密钥 + * @return 加密后的byte[] + * @throws Exception + */ + public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception { + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + //kgen.init(128, new SecureRandom(encryptKey.getBytes())); + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG") ; + secureRandom.setSeed(encryptKey.getBytes("utf-8")); + kgen.init(128, secureRandom); + + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES")); + + return cipher.doFinal(content.getBytes("utf-8")); + } + + /** + * AES加密为base 64 code + * @param content 待加密的内容 + * @param encryptKey 加密密钥 + * @return 加密后的base 64 code + * @throws Exception + */ + public static String aesEncrypt(String content, String encryptKey) throws Exception { + return base64Encode(aesEncryptToBytes(content, encryptKey)); + } + + /** + * AES解密 + * @param encryptBytes 待解密的byte[] + * @param decryptKey 解密密钥 + * @return 解密后的String + * @throws Exception + */ + public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception { + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + //kgen.init(128, new SecureRandom(decryptKey.getBytes())); + // 修复linux解密失败问题 + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG") ; + secureRandom.setSeed(decryptKey.getBytes("utf-8")); + kgen.init(128, secureRandom); + + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES")); + byte[] decryptBytes = cipher.doFinal(encryptBytes); + + return new String(decryptBytes); + } + + /** + * 将base 64 code AES解密 + * @param encryptStr 待解密的base 64 code + * @param decryptKey 解密密钥 + * @return 解密后的string + * @throws Exception + */ + public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception { + return StringUtils.isBlank(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey); + } + + public static void main(String[] args) throws Exception { + String str = aesEncrypt("18520191072", "123456"); + System.out.println(str); + str = aesDecrypt("s76Os0tvQ/3nM+S6I6HSFg==", "123456"); + System.out.println(str); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/util/RandImageUtil.java b/src/main/java/com/gci/boot/modules/system/util/RandImageUtil.java new file mode 100644 index 0000000..7131765 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/util/RandImageUtil.java @@ -0,0 +1,140 @@ +package com.gci.boot.modules.system.util; + +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Base64; +import java.util.Random; + +/** + * 登录验证码工具类 + */ +public class RandImageUtil { + + public static final String key = "JEECG_LOGIN_KEY"; + + /** + * 定义图形大小 + */ + private static final int width = 105; + /** + * 定义图形大小 + */ + private static final int height = 35; + + /** + * 定义干扰线数量 + */ + private static final int count = 100; + + /** + * 干扰线的长度=1.414*lineWidth + */ + private static final int lineWidth = 2; + + /** + * 图片格式 + */ + private static final String IMG_FORMAT = "JPEG"; + + /** + * base64 图片前缀 + */ + private static final String BASE64_PRE = "data:image/jpg;base64,"; + + /** + * 直接通过response 返回图片 + * @param response + * @param resultCode + * @throws IOException + */ + public static void generate(HttpServletResponse response, String resultCode) throws IOException { + BufferedImage image = getImageBuffer(resultCode); + // 输出图象到页面 + ImageIO.write(image, IMG_FORMAT, response.getOutputStream()); + } + + /** + * 生成base64字符串 + * @param resultCode + * @return + * @throws IOException + */ + public static String generate(String resultCode) throws IOException { + BufferedImage image = getImageBuffer(resultCode); + + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + //写入流中 + ImageIO.write(image, IMG_FORMAT, byteStream); + //转换成字节 + byte[] bytes = byteStream.toByteArray(); + //转换成base64串 + String base64 = Base64.getEncoder().encodeToString(bytes).trim(); + base64 = base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n + + //写到指定位置 + //ImageIO.write(bufferedImage, "png", new File("")); + + return BASE64_PRE+base64; + } + + private static BufferedImage getImageBuffer(String resultCode){ + // 在内存中创建图象 + final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + // 获取图形上下文 + final Graphics2D graphics = (Graphics2D) image.getGraphics(); + // 设定背景颜色 + graphics.setColor(Color.WHITE); // ---1 + graphics.fillRect(0, 0, width, height); + // 设定边框颜色 +// graphics.setColor(getRandColor(100, 200)); // ---2 + graphics.drawRect(0, 0, width - 1, height - 1); + + final Random random = new Random(); + // 随机产生干扰线,使图象中的认证码不易被其它程序探测到 + for (int i = 0; i < count; i++) { + graphics.setColor(getRandColor(150, 200)); // ---3 + + final int x = random.nextInt(width - lineWidth - 1) + 1; // 保证画在边框之内 + final int y = random.nextInt(height - lineWidth - 1) + 1; + final int xl = random.nextInt(lineWidth); + final int yl = random.nextInt(lineWidth); + graphics.drawLine(x, y, x + xl, y + yl); + } + // 取随机产生的认证码 + for (int i = 0; i < resultCode.length(); i++) { + // 将认证码显示到图象中,调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成 + // graphics.setColor(new Color(20 + random.nextInt(130), 20 + random + // .nextInt(130), 20 + random.nextInt(130))); + // 设置字体颜色 + graphics.setColor(Color.BLACK); + // 设置字体样式 +// graphics.setFont(new Font("Arial Black", Font.ITALIC, 18)); + graphics.setFont(new Font("Times New Roman", Font.BOLD, 24)); + // 设置字符,字符间距,上边距 + graphics.drawString(String.valueOf(resultCode.charAt(i)), (23 * i) + 8, 26); + } + // 图象生效 + graphics.dispose(); + return image; + } + + private static Color getRandColor(int fc, int bc) { // 取得给定范围随机颜色 + final Random random = new Random(); + if (fc > 255) { + fc = 255; + } + if (bc > 255) { + bc = 255; + } + + final int r = fc + random.nextInt(bc - fc); + final int g = fc + random.nextInt(bc - fc); + final int b = fc + random.nextInt(bc - fc); + + return new Color(r, g, b); + } +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/ApiTokenModel.java b/src/main/java/com/gci/boot/modules/system/vo/ApiTokenModel.java new file mode 100644 index 0000000..cda5cca --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/ApiTokenModel.java @@ -0,0 +1,35 @@ +package com.gci.boot.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * + * + * @Author scott + * @since 2019-01-18 + */ +@ApiModel(value="获取apiToken对象", description="获取apiToken对象") +public class ApiTokenModel { + + @ApiModelProperty(value = "appId") + private String appId; + @ApiModelProperty(value = "appKey") + private String appKey; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/DictModel.java b/src/main/java/com/gci/boot/modules/system/vo/DictModel.java new file mode 100644 index 0000000..9e68bf0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/DictModel.java @@ -0,0 +1,42 @@ +package com.gci.boot.modules.system.vo; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DictModel implements Serializable{ + private static final long serialVersionUID = 1L; + + public DictModel() { + } + + public DictModel(String value, String text) { + this.value = value; + this.text = text; + } + + /** + * 字典value + */ + private String value; + /** + * 字典文本 + */ + private String text; + + /** + * 特殊用途: JgEditableTable + * @return + */ + public String getTitle() { + return this.text; + } + +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/LimitRequest.java b/src/main/java/com/gci/boot/modules/system/vo/LimitRequest.java new file mode 100644 index 0000000..6cd2662 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/LimitRequest.java @@ -0,0 +1,17 @@ +package com.gci.boot.modules.system.vo; + +import lombok.Data; + +import java.util.Date; + +@Data +public class LimitRequest { + /** + * 日期 + */ + private String time; + /** + * 次数 + */ + private int count = 0; +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/LoginUser.java b/src/main/java/com/gci/boot/modules/system/vo/LoginUser.java new file mode 100644 index 0000000..95d3751 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/LoginUser.java @@ -0,0 +1,94 @@ +package com.gci.boot.modules.system.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 在线用户信息 + *

+ * + * @Author scott + * @since 2018-12-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +public class LoginUser implements Serializable { + + /** + * 登录人id + */ + private String id; + + /** + * 登录人账号 + */ + private String username; + + /** + * 登录人名字 + */ + private String realname; + + /** + * 当前登录部门code + */ + private String orgCode; + + + /** + * 生日 + */ + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date birthday; + + /** + * 性别(1:男 2:女) + */ + private Integer sex; + + /** + * 电子邮件 + */ + private String email; + + /** + * 电话 + */ + private String phone; + + /** + * 状态(1:正常 2:冻结 ) + */ + private Integer status; + + private Integer delFlag; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 职务 + */ + private String post; + + /** + * 座机号 + */ + private String telephone; + + /** + * 角色 + */ + private String roles; +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/SysDepartTreeModel.java b/src/main/java/com/gci/boot/modules/system/vo/SysDepartTreeModel.java new file mode 100644 index 0000000..3f57c1b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/SysDepartTreeModel.java @@ -0,0 +1,64 @@ +package com.gci.boot.modules.system.vo; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class SysDepartTreeModel { + @ApiModelProperty("ID") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("父机构ID") + private String parentId; + + @ApiModelProperty("机构/部门名称") + private String departName; + + @ApiModelProperty("排序") + private Integer departOrder; + + @ApiModelProperty("描述") + private String description; + + @ApiModelProperty("机构类别") + private Integer orgCategory; + + @ApiModelProperty("机构编码") + private String orgCode; + + @ApiModelProperty("联系电话") + private String mobile; + + @ApiModelProperty("传真") + private String fax; + + @ApiModelProperty("地址") + private String address; + + @ApiModelProperty("备注") + private String memo; + + @ApiModelProperty("状态(1启用,0不启用)") + private Integer status; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("创建日期") + private Date createTime; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("更新日期") + private Date updateTime; + + @ApiModelProperty("下级机构") + private List children; +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/SysLoginModel.java b/src/main/java/com/gci/boot/modules/system/vo/SysLoginModel.java new file mode 100644 index 0000000..bcf5a13 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/SysLoginModel.java @@ -0,0 +1,55 @@ +package com.gci.boot.modules.system.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * 登录表单 + * + * @Author scott + * @since 2019-01-18 + */ +@ApiModel(value="登录对象", description="登录对象") +public class SysLoginModel { + @ApiModelProperty(value = "账号") + private String username; + @ApiModelProperty(value = "密码") + private String password; + @ApiModelProperty(value = "验证码") + private String captcha; + @ApiModelProperty(value = "验证码key") + private String checkKey; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getCaptcha() { + return captcha; + } + + public void setCaptcha(String captcha) { + this.captcha = captcha; + } + + public String getCheckKey() { + return checkKey; + } + + public void setCheckKey(String checkKey) { + this.checkKey = checkKey; + } + +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/system/vo/SysPermissionDataRuleModel.java b/src/main/java/com/gci/boot/modules/system/vo/SysPermissionDataRuleModel.java new file mode 100644 index 0000000..7aebe83 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/SysPermissionDataRuleModel.java @@ -0,0 +1,144 @@ +package com.gci.boot.modules.system.vo; + +import java.util.Date; + +/** + *

+ * 菜单权限规则表 + *

+ * + * @Author huangzhilin + * @since 2019-03-29 + */ +public class SysPermissionDataRuleModel { + + /** + * id + */ + private String id; + + /** + * 对应的菜单id + */ + private String permissionId; + + /** + * 规则名称 + */ + private String ruleName; + + /** + * 字段 + */ + private String ruleColumn; + + /** + * 条件 + */ + private String ruleConditions; + + /** + * 规则值 + */ + private String ruleValue; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 创建人 + */ + private String createBy; + + /** + * 修改时间 + */ + private Date updateTime; + + /** + * 修改人 + */ + private String updateBy; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getPermissionId() { + return permissionId; + } + + public void setPermissionId(String permissionId) { + this.permissionId = permissionId; + } + + public String getRuleName() { + return ruleName; + } + + public void setRuleName(String ruleName) { + this.ruleName = ruleName; + } + + public String getRuleColumn() { + return ruleColumn; + } + + public void setRuleColumn(String ruleColumn) { + this.ruleColumn = ruleColumn; + } + + public String getRuleConditions() { + return ruleConditions; + } + + public void setRuleConditions(String ruleConditions) { + this.ruleConditions = ruleConditions; + } + + public String getRuleValue() { + return ruleValue; + } + + public void setRuleValue(String ruleValue) { + this.ruleValue = ruleValue; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/SysPermissionTree.java b/src/main/java/com/gci/boot/modules/system/vo/SysPermissionTree.java new file mode 100644 index 0000000..3136585 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/SysPermissionTree.java @@ -0,0 +1,334 @@ +package com.gci.boot.modules.system.vo; + +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.modules.system.entity.SysPermission; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Data +public class SysPermissionTree implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + private String id; + + private String key; + private String title; + + /** + * 父id + */ + private String parentId; + + /** + * 菜单名称 + */ + private String name; + + /** + * 菜单权限编码 + */ + private String perms; + /** + * 权限策略1显示2禁用 + */ + private String permsType; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 组件 + */ + private String component; + + /** + * 跳转网页链接 + */ + private String url; + + /** + * 一级菜单跳转地址 + */ + private String redirect; + + /** + * 菜单排序 + */ + private Double sortNo; + + /** + * 类型(0:一级菜单;1:子菜单 ;2:按钮权限) + */ + private Integer menuType; + + /** + * 是否叶子节点: 1:是 0:不是 + */ + private Integer isLeaf; + + + + /** + * 描述 + */ + private String description; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新人 + */ + private String updateBy; + + /** + * 更新时间 + */ + private Date updateTime; + + + /** + * 按钮权限状态(0无效1有效) + */ + private String status; + + /** + * 是否隐藏路由: 0否,1是 + */ + private Integer hidden; + + /** + * 外链菜单打开方式 0/内部打开 1/外部打开 + */ + private Integer internalOrExternal; + + public SysPermissionTree() { + } + + public SysPermissionTree(SysPermission permission) { + this.key = permission.getId(); + this.id = permission.getId(); + this.perms = permission.getPerms(); + this.permsType = permission.getPermsType(); + this.component = permission.getComponent(); + this.createBy = permission.getCreateBy(); + this.createTime = permission.getCreateTime(); + this.description = permission.getDescription(); + this.icon = permission.getIcon(); + this.isLeaf = permission.getIsLeaf(); + this.menuType = permission.getMenuType(); + this.name = permission.getName(); + this.parentId = permission.getParentId(); + this.sortNo = permission.getSortNo(); + this.updateBy = permission.getUpdateBy(); + this.updateTime = permission.getUpdateTime(); + this.redirect = permission.getRedirect(); + this.url = permission.getUrl(); + /*update_end author:wuxianquan date:20190908 for:赋值 */ + this.title = permission.getName(); + if (permission.getIsLeaf() == null || permission.getIsLeaf() != 1) { + this.children = new ArrayList(); + } + this.status = permission.getStatus(); + this.internalOrExternal = permission.getInternalOrExternal(); + this.hidden = permission.getHidden(); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + private List children; + + public boolean isLeaf() { + return isLeaf == 1; + } + + public void setLeaf(Integer leaf) { + isLeaf = leaf; + } + + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public String getRedirect() { + return redirect; + } + + public void setRedirect(String redirect) { + this.redirect = redirect; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Double getSortNo() { + return sortNo; + } + + public void setSortNo(Double sortNo) { + this.sortNo = sortNo; + } + + public Integer getMenuType() { + return menuType; + } + + public void setMenuType(Integer menuType) { + this.menuType = menuType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getPerms() { + return perms; + } + + public void setPerms(String perms) { + this.perms = perms; + } + + public boolean getIsLeaf() { + return isLeaf == 1; + } + + public void setIsLeaf(Integer isLeaf) { + this.isLeaf = isLeaf; + } + + public String getPermsType() { + return permsType; + } + + public void setPermsType(String permsType) { + this.permsType = permsType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/system/vo/SysUserCacheInfo.java b/src/main/java/com/gci/boot/modules/system/vo/SysUserCacheInfo.java new file mode 100644 index 0000000..380736c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/SysUserCacheInfo.java @@ -0,0 +1,67 @@ +package com.gci.boot.modules.system.vo; + +import com.gci.boot.common.util.DateUtils; + +import java.util.List; + +public class SysUserCacheInfo { + + private String sysUserCode; + + private String sysUserName; + + private String sysOrgCode; + + private List sysMultiOrgCode; + + private boolean oneDepart; + + public boolean isOneDepart() { + return oneDepart; + } + + public void setOneDepart(boolean oneDepart) { + this.oneDepart = oneDepart; + } + + public String getSysDate() { + return DateUtils.formatDate(); + } + + public String getSysTime() { + return DateUtils.now(); + } + + public String getSysUserCode() { + return sysUserCode; + } + + public void setSysUserCode(String sysUserCode) { + this.sysUserCode = sysUserCode; + } + + public String getSysUserName() { + return sysUserName; + } + + public void setSysUserName(String sysUserName) { + this.sysUserName = sysUserName; + } + + public String getSysOrgCode() { + return sysOrgCode; + } + + public void setSysOrgCode(String sysOrgCode) { + this.sysOrgCode = sysOrgCode; + } + + public List getSysMultiOrgCode() { + return sysMultiOrgCode; + } + + public void setSysMultiOrgCode(List sysMultiOrgCode) { + this.sysMultiOrgCode = sysMultiOrgCode; + } + +} diff --git a/src/main/java/com/gci/boot/modules/system/vo/TreeModel.java b/src/main/java/com/gci/boot/modules/system/vo/TreeModel.java new file mode 100644 index 0000000..bb40bf9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/system/vo/TreeModel.java @@ -0,0 +1,186 @@ +package com.gci.boot.modules.system.vo; + +import com.gci.boot.modules.system.entity.SysPermission; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 树形列表用到 + */ +public class TreeModel implements Serializable { + + private static final long serialVersionUID = 4013193970046502756L; + + private String key; + + private String title; + + private String slotTitle; + + private boolean isLeaf; + + private String icon; + + private Integer ruleFlag; + + private Map scopedSlots; + + /** + * 是否隐藏路由: 0否,1是 + */ + private Integer hidden; + + /** + * 外链菜单打开方式 0/内部打开 1/外部打开 + */ + private Integer internalOrExternal; + + public Map getScopedSlots() { + return scopedSlots; + } + + public void setScopedSlots(Map scopedSlots) { + this.scopedSlots = scopedSlots; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public boolean getIsLeaf() { + return isLeaf; + } + + public void setIsLeaf(boolean isLeaf) { + this.isLeaf = isLeaf; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + private List children; + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public TreeModel() { + + } + + public TreeModel(SysPermission permission) { + this.key = permission.getId(); + this.icon = permission.getIcon(); + this.parentId = permission.getParentId(); + this.title = permission.getName(); + this.slotTitle = permission.getName(); + this.value = permission.getId(); + this.isLeaf = permission.getIsLeaf() != null && permission.getIsLeaf() == 1; + this.label = permission.getName(); + if(permission.getIsLeaf() == null || permission.getIsLeaf() != 1) { + this.children = new ArrayList<>(); + } + this.internalOrExternal = permission.getInternalOrExternal(); + this.hidden = permission.getHidden(); + } + + public TreeModel(String key, String parentId, String slotTitle, Integer ruleFlag, Integer isLeaf) { + this.key = key; + this.parentId = parentId; + this.ruleFlag=ruleFlag; + this.slotTitle = slotTitle; + Map map = new HashMap(); + map.put("title", "hasDatarule"); + this.scopedSlots = map; + this.isLeaf = isLeaf == 1; + this.value = key; + if(isLeaf != 1) { + this.children = new ArrayList<>(); + } + } + + private String parentId; + + private String label; + + private String value; + + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * @param value the value to set + */ + public void setValue(String value) { + this.value = value; + } + + public String getSlotTitle() { + return slotTitle; + } + + public void setSlotTitle(String slotTitle) { + this.slotTitle = slotTitle; + } + + public Integer getRuleFlag() { + return ruleFlag; + } + + public void setRuleFlag(Integer ruleFlag) { + this.ruleFlag = ruleFlag; + } + +} diff --git a/src/main/java/com/gci/boot/modules/task/customer/SchedulePlanTask.java b/src/main/java/com/gci/boot/modules/task/customer/SchedulePlanTask.java new file mode 100644 index 0000000..1e72a95 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/task/customer/SchedulePlanTask.java @@ -0,0 +1,33 @@ +package com.gci.boot.modules.task.customer; + + +import com.gci.boot.modules.customer.service.ITbScheduledPlanService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +@EnableScheduling +@Slf4j +public class SchedulePlanTask { + @Autowired + private ITbScheduledPlanService scheduledPlanService; + + /** + * 每月一号 + */ + @Scheduled(cron = "0 0 0 1 * ? ") + public void init () { + long l = System.currentTimeMillis(); + log.info("定时每月一号生成巡检任务和客户回访开始"); + try { + scheduledPlanService.initPlan(); + } catch (Exception e) { + e.printStackTrace(); + log.error("定时每月一号生成巡检任务和客户回访生成失败",e); + } + log.info("定时每月一号生成巡检任务和客户回访结束,耗时:{}",l - System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/gci/boot/modules/task/gps/GisGpsAnalysisTask.java b/src/main/java/com/gci/boot/modules/task/gps/GisGpsAnalysisTask.java new file mode 100644 index 0000000..52cc9d3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/task/gps/GisGpsAnalysisTask.java @@ -0,0 +1,104 @@ +package com.gci.boot.modules.task.gps; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.RedisKey; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.gis.service.GisRoadMileLogService; +import com.gci.boot.modules.gis.service.GpsConsumerService; +import com.gci.boot.modules.gis.service.IGisGpsAnalysisService; +import com.gci.boot.modules.gis.vo.FenceSpeedBeanVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Date; +import java.util.List; + +/** + * @author lyz + * @date 2023/9/14 15:37 + */ +@Configuration +@EnableScheduling +@Slf4j +public class GisGpsAnalysisTask { + + @Autowired + private GisRoadMileLogService gisRoadMileLogService; + + @Autowired + private ITbVehicleService tbVehicleService; + + @Autowired + private IGisGpsAnalysisService gisGpsAnalysisService; + + @Autowired + private StringRedisTemplate redisTemplate; + + /** + * 每天凌晨三点半执行 + */ + @Scheduled(cron = "0 30 03 * * ?") + public void gpsAnalysisData() { + LocalDate date = LocalDate.now().minusDays(1); + log.info("定时任务每日gps数据分析开始{}", date); + Long startMl = System.currentTimeMillis(); + LocalDateTime start = LocalDateTime.of(date, LocalTime.of(0, 0, 0)); + LocalDateTime end = LocalDateTime.of(date, LocalTime.of(23, 59, 59)); + Date startTime = DateUtils.convertLocalDateTimeToDate(start); + Date endTime = DateUtils.convertLocalDateTimeToDate(end); + List list = tbVehicleService.list(); + list.parallelStream().forEach(vehicle -> { + try{ + String s = redisTemplate.opsForValue().get(RedisKey.PROJECT_GIS_SOURCE + vehicle.getProjectId()); + if (Convert.toBool(s,false)) { + gisGpsAnalysisService.gpsDataAnalysisByVehicle(vehicle, startTime, endTime,true); + } else { + gisGpsAnalysisService.gpsDataAnalysisByVehicleBy808(vehicle, startTime, endTime); + } + }catch (Exception e){ + e.printStackTrace(); + log.error("执行gps分析失败,车牌号{}",vehicle.getPlateNumber()); + } + }); + Long endMl = System.currentTimeMillis(); + log.info("定时任务每日gps数据分析完成{},耗时-{}ms", date,endMl-startMl); + } + + + + /** + * 每天凌晨二点执行 + */ + @Scheduled(cron = "0 08 02 * * ?") + public void consumeRoadMileData() { + LocalDate date = LocalDate.now().minusDays(1); + log.info("定时任务每日计算能耗开始{}", date); + Long startMl = System.currentTimeMillis(); + LocalDateTime start = LocalDateTime.of(date, LocalTime.of(0, 0, 0)); + LocalDateTime end = LocalDateTime.of(date, LocalTime.of(23, 59, 59)); + Date startTime = DateUtils.convertLocalDateTimeToDate(start); + Date endTime = DateUtils.convertLocalDateTimeToDate(end); + List list = tbVehicleService.list(); + list.parallelStream().forEach(vehicle -> { + try{ + gisRoadMileLogService.coverGpsToRoadMile(vehicle, startTime, endTime); + }catch (Exception e){ + e.printStackTrace(); + log.error("执行计算能耗失败,车牌号{}",vehicle.getPlateNumber()); + } + }); + Long endMl = System.currentTimeMillis(); + log.info("定时任务每日计算能耗完成{},耗时-{}ms", date,endMl-startMl); + } +} diff --git a/src/main/java/com/gci/boot/modules/task/gps/GisGpsStatisticsTask.java b/src/main/java/com/gci/boot/modules/task/gps/GisGpsStatisticsTask.java new file mode 100644 index 0000000..cf2d416 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/task/gps/GisGpsStatisticsTask.java @@ -0,0 +1,32 @@ +package com.gci.boot.modules.task.gps; + +import com.gci.boot.modules.gis.service.ITbGisGpsStatisticsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +@EnableScheduling +@Slf4j +public class GisGpsStatisticsTask { + @Autowired + private ITbGisGpsStatisticsService gisGpsStatisticsService; + + /** + * 每日凌晨一点半生成昨天的数据 + */ + @Scheduled(cron = "0 30 01 * * ? ") + public void gen () { + long l = System.currentTimeMillis(); + log.info("定时每日凌晨一点半生成昨日gps分析数据任务开始"); + try { + gisGpsStatisticsService.gen(); + } catch (Exception e) { + e.printStackTrace(); + log.error("定时每日凌晨一点半生成昨日gps分析数据任务失败",e); + } + log.info("定时每日凌晨一点半生成昨日gps分析数据任务结束,耗时:{}",l - System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/gci/boot/modules/task/gps/GisSpeedingThresholdTask.java b/src/main/java/com/gci/boot/modules/task/gps/GisSpeedingThresholdTask.java new file mode 100644 index 0000000..cc5928a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/task/gps/GisSpeedingThresholdTask.java @@ -0,0 +1,34 @@ +package com.gci.boot.modules.task.gps; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import com.gci.boot.modules.gis.service.ITbGisSpeedingThresholdService; + +import lombok.extern.slf4j.Slf4j; + +@Configuration +@EnableScheduling +@Slf4j +public class GisSpeedingThresholdTask { + @Autowired + private ITbGisSpeedingThresholdService gisSpeedingThresholdService; + + /** + * 每次启动生成数据 + */ + @Scheduled(initialDelay = 10000, fixedDelay = 1000 * 60 * 60 * 24) + public void gen() { + long l = System.currentTimeMillis(); + log.info("每次启动生成超速规则数据任务开始"); + try { + gisSpeedingThresholdService.rel(); + } catch (Exception e) { + e.printStackTrace(); + log.error("每次启动生成超速规则数据任务失败", e); + } + log.info("每次启动生成超速规则数据任务结束,耗时:{}", l - System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/gci/boot/modules/task/gps/SpeedingAndFenceAlarmTask.java b/src/main/java/com/gci/boot/modules/task/gps/SpeedingAndFenceAlarmTask.java new file mode 100644 index 0000000..b18892d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/task/gps/SpeedingAndFenceAlarmTask.java @@ -0,0 +1,46 @@ +package com.gci.boot.modules.task.gps; + +import cn.hutool.json.JSONUtil; +import com.gci.boot.common.util.RedisKey; +import com.gci.boot.modules.gis.service.GpsConsumerService; +import com.gci.boot.modules.gis.vo.FenceSpeedBeanVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * @author lyz + * @date 2023/9/14 15:37 + */ +@Configuration +@EnableScheduling +@Slf4j +public class SpeedingAndFenceAlarmTask { + + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private GpsConsumerService gpsConsumerService; + + @Scheduled(fixedRate = 10000) + public void consumeActSafetyFileData() { + String data = redisTemplate.opsForList().rightPop(RedisKey.FENCE_SPEED_ALARM_BEAN); + if (data != null) { + log.info("开始消费数据-{}", data); + try { + FenceSpeedBeanVO vo = JSONUtil.toBean(data, FenceSpeedBeanVO.class); + gpsConsumerService.saveHandle(vo); + } catch (Exception e) { + log.error("获取GPS告警(围栏告警、超速告警)数据消息失败 , data = {}, msg = {}", JSONUtil.formatJsonStr(data), e.getMessage()); + } + } + } +} diff --git a/src/main/java/com/gci/boot/modules/task/vehicles/AnnualInspectionRemindTask.java b/src/main/java/com/gci/boot/modules/task/vehicles/AnnualInspectionRemindTask.java new file mode 100644 index 0000000..cbebfe5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/task/vehicles/AnnualInspectionRemindTask.java @@ -0,0 +1,32 @@ +package com.gci.boot.modules.task.vehicles; + +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionRemindService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +@EnableScheduling +@Slf4j +public class AnnualInspectionRemindTask { + @Autowired + private ITbAnnualInspectionRemindService annualInspectionRemindService; + + /** + * 每日凌晨更新年检提醒数据 + */ + @Scheduled(cron = "30 0 00 * * ? ") + public void init () { + long l = System.currentTimeMillis(); + log.info("每日凌晨更新年检提醒数据开始"); + try { + annualInspectionRemindService.updateDate(); + } catch (Exception e) { + e.printStackTrace(); + log.error("每日凌晨更新年检提醒数据生成失败",e); + } + log.info("每日凌晨更新年检提醒数据结束,耗时:{}",l - System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/gci/boot/modules/test/TestController.java b/src/main/java/com/gci/boot/modules/test/TestController.java new file mode 100644 index 0000000..c55fcfd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/test/TestController.java @@ -0,0 +1,117 @@ +package com.gci.boot.modules.test; + + +import cn.hutool.core.collection.CollectionUtil; +import com.gci.boot.modules.gis.mapper.TbGisRunningbusMapper; +import com.gci.boot.modules.vehicles.service.ITbViolationRecordService; +import com.gci.boot.modules.vehicles.vo.MsgImportFailVO; +import com.gci.boot.modules.vehicles.vo.RepairImportVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +@RestController +@RequestMapping("/test") +@Slf4j +public class TestController { + + @Autowired + private TbGisRunningbusMapper runningbusMapper; + @Autowired + private ITbViolationRecordService violationRecordService; + + /** + * 添加 + */ + @PostMapping(value = "/tet") + public Object tet(TestVO vo) { +// List msgList = new ArrayList<>(); +// msgList.add("【成都交警】川AAP8022于2023-10-30在瑞星路与琼楼路交叉路口实施机动车通过有灯控路口时,不按所需行进方向驶入导向车道的违法行为,请三十日内到交警部门接受处理。该车有18笔违法记录未处理,请及时处理。(更多请关注蓉E行)"); +// msgList.add("【四川交警】您的小型新能源汽车川A08668D于2023-11-07 13:10在成都市二环路西二段与战旗东路交叉路口,被交通技术监控设备记录了『不按导向车道行驶』的违法行为。请于收到本告知之日起30日内接受处理。"); +// msgList.add("【四川交警】您的小型新能源汽车川AAP0633于2023-08-19 09:10在成都市二环路西二段与战旗东路交叉路口,被交通技术监控设备记录了『不按导向车道行驶』的违法行为。请于收到本告知之日起30日内接受处理。"); +// msgList.add("【成都交警】川AAP8022于2023-10-30在瑞星路与琼楼路交叉路口实施机动车通过有灯控路口时,不按所需行进方向驶入导向车道的违法行为,请三十日内到交警部门接受处理。该车有18笔违法记录未处理,请及时处理。(更多请关注蓉E行)"); +// List list = violationRecordService.importViolationMessage(msgList); + + RepairImportVO v = new RepairImportVO(); + v.setPhone("12345678900"); + v.setRepairTime("2033-09-09 11:30"); + v.setQuantity("d7"); + v.validate(); + System.out.println(v); + return v; + } + + + public static class TrafficJamSection { + public Date startTime; + public Date endTime; + + public TrafficJamSection(Date startTime, Date endTime) { + this.startTime = startTime; + this.endTime = endTime; + } + } + + public static int calculateTotalMinutes(List trafficJamList) { + int totalMinutes = 0; + List newTrafficJamList = new ArrayList<>(); + + for (TrafficJamSection currentSection : trafficJamList) { + boolean isOverlapped = false; + + for (TrafficJamSection existingSection : newTrafficJamList) { + if (isTimeOverlapping(currentSection, existingSection)) { + isOverlapped = true; + + if (currentSection.startTime.compareTo(existingSection.startTime) < 0) { + existingSection.startTime = currentSection.startTime; + } + + if (currentSection.endTime.compareTo(existingSection.endTime) > 0) { + existingSection.endTime = currentSection.endTime; + } + + break; + } + } + + if (!isOverlapped) { + newTrafficJamList.add(currentSection); + } + } + + for (TrafficJamSection section : newTrafficJamList) { + totalMinutes += calculateMinutes(section.startTime, section.endTime); + } + + return totalMinutes; + } + + private static boolean isTimeOverlapping(TrafficJamSection section1, TrafficJamSection section2) { + return section1.startTime.before(section2.endTime) && section1.endTime.after(section2.startTime); + } + + private static int calculateMinutes(Date startTime, Date endTime) { + long durationMillis = endTime.getTime() - startTime.getTime(); + return (int) (durationMillis / (1000 * 60)); + } + + public static void main(String[] args) { + List trafficJamList = new ArrayList<>(); + trafficJamList.add(new TrafficJamSection(new Date(2023, 8, 25, 10, 30), new Date(2023, 8, 25, 12, 30))); + trafficJamList.add(new TrafficJamSection(new Date(2023, 8, 25, 9, 30), new Date(2023, 8, 25, 11, 30))); + trafficJamList.add(new TrafficJamSection(new Date(2023, 8, 25, 7, 0), new Date(2023, 8, 26, 8, 0))); + trafficJamList.add(new TrafficJamSection(new Date(2023, 8, 25, 9, 45), new Date(2023, 8, 25, 10, 43))); + + int totalMinutes = calculateTotalMinutes(trafficJamList); + System.out.println("Total minutes: " + totalMinutes); + } +} diff --git a/src/main/java/com/gci/boot/modules/test/TestVO.java b/src/main/java/com/gci/boot/modules/test/TestVO.java new file mode 100644 index 0000000..0949e3a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/test/TestVO.java @@ -0,0 +1,9 @@ +package com.gci.boot.modules.test; + +import lombok.Data; + +@Data +public class TestVO { + + private String template; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/BacklogController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/BacklogController.java new file mode 100644 index 0000000..4100590 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/BacklogController.java @@ -0,0 +1,51 @@ +package com.gci.boot.modules.vehicles.controller; + +import cn.hutool.core.collection.CollectionUtil; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; + +import com.gci.boot.modules.vehicles.service.BacklogService; +import com.gci.boot.modules.vehicles.vo.BacklogStatisVO; +import com.gci.boot.modules.vehicles.vo.RepairInfoListVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Api(tags="待办") +@Slf4j +@RestController +@RequestMapping("/vehicles/backlog") +public class BacklogController { + @Autowired + private BacklogService backlogService; + + @PostMapping(value = "/test") + public Result test() { + Map> object = backlogService.getUserBacklogButton(); + return Result.ok(object); + } + + //1出险 2违章 3事故 4维修 5_保养台账 6年检 7_保养计划 + @AddSysLog("PC待办-获取对应tab分页") + @GetMapping(value = "/getBacklogPage") + public Result getBacklogPage(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + @RequestParam(name = "type", defaultValue = "1") String type, + HttpServletRequest req) { + return backlogService.getBacklogPageList(pageNo,pageSize,type,req); + } + + @AddSysLog("PC待办-数量查询") + @GetMapping(value = "/getBacklogStatis") + public Result getBacklogCount(HttpServletRequest req) { + List result = backlogService.getBacklogStatis(req); + return Result.ok(result); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/RepairController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/RepairController.java new file mode 100644 index 0000000..2822c56 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/RepairController.java @@ -0,0 +1,518 @@ +package com.gci.boot.modules.vehicles.controller; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbRepairShopArchives; +import com.gci.boot.modules.basedata.service.ITbRepairShopArchivesService; +import com.gci.boot.modules.msg.enums.SenderTypeEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper; +import com.gci.boot.modules.vehicles.service.*; +import com.gci.boot.modules.vehicles.vo.*; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.multipart.MultipartResolver; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +@Api(tags="维修") +@Slf4j +@RestController +@RequestMapping("/vehicles/repair") +public class RepairController { + + @Autowired + private ITbRepairAssignService repairAssignService; + @Autowired + private ITbRepairCheckService repairCheckService; + @Autowired + private ITbRepairInfoService repairInfoService; + @Autowired + private ITbRepairOfferService repairOfferService; + @Autowired + private TbViolationRecordMapper violationRecordMapper; + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private IProjectsService projectsService; + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private MinioUtils minioUtils; + @Autowired + private ISysUserService sysUserService; + @Autowired + private ISysRoleService sysRoleService; + @Autowired + private ITbRepairShopArchivesService tbRepairShopArchivesService; + @Autowired + private IRepairUpkeepImportService repairUpkeepImportService; + @Value("${failExcel}") + private String failExcel; + @Autowired + private MsgPushService msgPushService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("维修-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(RepairInfoListVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //处理司机身份和维修厂身份的过滤:优先司机,不考虑重叠的情况 + Integer departCategory = projectsService.judgeDepartCategory(); + //超级管理员查询全部数据 + if(departCategory != 5){ + //内部员工按项目列表过滤* + if(departCategory == 1 || departCategory == 4){ + List listProjectStaff = projectsService.queryProjectListOfUser(); + if(CollectionUtils.isNotEmpty(listProjectStaff)){ + vo.setListProject(listProjectStaff); + }else { + vo.setProjectId("no permission"); + } + }else if(departCategory == 3){ + if(StringUtils.isNotEmpty(sysUser.getUsername())){ + vo.setDriverParam(sysUser.getUsername()); + }else { + vo.setProjectId("no permission"); + } + }else if(departCategory == 2){ + List listRepairShop = tbRepairShopArchivesService.getRepairShopByUserId(sysUser.getId()); + List listRepairShopIds = listRepairShop.stream().map(TbRepairShopArchives::getId).collect(Collectors.toList()); + if(CollectionUtils.isNotEmpty(listRepairShopIds)){ + vo.setListRepairShop(listRepairShopIds); + }else { + vo.setProjectId("no permission"); + } + }else{ + vo.setProjectId("no permission"); + } + } + Page page = new Page(pageNo, pageSize); + IPage pageList = repairInfoService.getRepairInfoList(page, vo); + return Result.ok(pageList); + } + + + /** + * 获取报修信息所属项目下拉列表 + */ + @AddSysLog("维修-获取报修信息所属项目下拉列表") + @GetMapping(value = "/queryProjects") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.queryProjects"}) + public Result queryProjects() { + List list = violationRecordMapper.queryProjects(0,0); + return Result.ok(list); + } + + /** + * 获取报修信息车牌号及车辆信息列表 + */ + @AddSysLog("维修-获取报修信息车牌号及车辆信息列表") + @GetMapping(value = "/queryVehicleInfoByProjectId") + public Result queryVehicleInfoByProjectId(String projectId) { + List list = repairInfoMapper.findVehicleInfoByProjectId(projectId); + return Result.ok(list); + } + + /** + * 添加 + */ + @AddSysLog("维修-添加编辑维修信息") + @PostMapping(value = "/addOrEdit") + public Result add(@RequestBody @Validated(SaveValidated.class) TbRepairInfo tbRepairInfo) { + Projects projects = projectsService.getById(tbRepairInfo.getProjectId()); + if(Objects.nonNull(projects)){ + tbRepairInfo.setProjectName(projects.getProjectName()); + } + if(StrUtil.isNotBlank(tbRepairInfo.getId())){ + repairInfoService.updateById(tbRepairInfo); + return Result.ok("操作成功!"); + } + tbRepairInfo.setFlowStatus(2); + tbRepairInfo.setFlowNode(1); + tbRepairInfo.setAddType(2); + //报修时间 + if(Objects.isNull(tbRepairInfo.getRepairTime())){ + tbRepairInfo.setRepairTime(new Date()); + } + + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + tbRepairInfo.setOrderNo(format); + + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String username = ""; + if(Objects.nonNull(sysUser)){ + username = sysUser.getUsername(); + } + tbRepairInfo.setCreateBy(username); + + repairInfoService.save(tbRepairInfo); + //补充节点操作人 + TbRepairCheck repairCheck = new TbRepairCheck(); + repairCheck.setRepairId(tbRepairInfo.getId()); + if(Objects.nonNull(sysUser)){ + repairCheck.setCheckPeople(sysUser.getRealname()); + } + repairCheck.setCheckTime(new Date()); + repairCheck.setCheckPeopleType("4"); + repairCheckService.save(repairCheck); + + //推送微信消息 + ThreadUtil.execAsync(()->{ + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),tbRepairInfo.getId(), + tbRepairInfo.getProjectId(), WorkOrderType.REPAIR.getType(),"待派单", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + return Result.ok("操作成功!"); + } + + /** + * 编辑 + */ + @AddSysLog("维修-编辑维修信息") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbRepairInfo tbRepairInfo) { + Projects projects = projectsService.getById(tbRepairInfo.getProjectId()); + if(Objects.nonNull(projects)){ + tbRepairInfo.setProjectName(projects.getProjectName()); + } + repairInfoService.updateById(tbRepairInfo); + return Result.ok("编辑成功!"); + } + + + /** + * 删除 + */ + @AddSysLog("维修-删除维修信息") + @DeleteMapping(value = "/realDelete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + repairInfoService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * 作废 + */ + @AddSysLog("维修-作废维修信息") + @PostMapping(value = "/cancel") + public Result cancel(@RequestBody CancelVO vo) { + String arg = StringUtil.checkString(vo.getCancelIdea(),200); + if(StrUtil.isNotBlank(arg)){ + return Result.error(101,"作废原因 " + arg); + } + String realName = ""; + if(StrUtil.isNotBlank(vo.getRealname())){ + realName = vo.getRealname(); + }else{ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + } + + repairInfoService.update(new LambdaUpdateWrapper().eq(TbRepairInfo::getId,vo.getId()) + .set(TbRepairInfo::getFlowStatus,9) + .set(TbRepairInfo::getFlowNode,4) + .set(TbRepairInfo::getCancelIdea,vo.getCancelIdea()) + .set(TbRepairInfo::getCancelPeople,realName) + .set(TbRepairInfo::getCancelTime,new Date())); + return Result.ok("作废成功!"); + } + + /** + * 导出 + * @return + */ + @AddSysLog("维修-导出维修信息") + @GetMapping("/export") + public Result export(RepairInfoListVO vo, HttpServletResponse response){ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //处理司机身份和维修厂身份的过滤:优先司机,不考虑重叠的情况 + Integer departCategory = projectsService.judgeDepartCategory(); + //超级管理员查询全部数据 + if(departCategory != 5){ + //内部员工按项目列表过滤* + if(departCategory == 1 || departCategory == 4){ + List listProjectStaff = projectsService.queryProjectListOfUser(); + if(CollectionUtils.isNotEmpty(listProjectStaff)){ + vo.setListProject(listProjectStaff); + }else { + vo.setProjectId("no permission"); + } + }else if(departCategory == 3){ + if(StringUtils.isNotEmpty(sysUser.getUsername())){ + vo.setDriverParam(sysUser.getUsername()); + }else { + vo.setProjectId("no permission"); + } + }else if(departCategory == 2){ + List listRepairShop = tbRepairShopArchivesService.getRepairShopByUserId(sysUser.getId()); + List listRepairShopIds = listRepairShop.stream().map(TbRepairShopArchives::getId).collect(Collectors.toList()); + if(CollectionUtils.isNotEmpty(listRepairShopIds)){ + vo.setListRepairShop(listRepairShopIds); + }else { + vo.setProjectId("no permission"); + } + }else{ + vo.setProjectId("no permission"); + } + } + + try (OutputStream output = response.getOutputStream()){ + + String fileName = "车辆维修.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List list = repairInfoMapper.findRepairInfoAllList(vo); + EasyExcel.write(output, RepairInfoListVO.class).sheet("车辆维修").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + /** + * 根据维修单id获取维修弹窗详情 + */ + @AddSysLog("维修-根据维修单id获取维修弹窗详情") + @GetMapping(value = "/getRepairObjectById") + public Result getRepairObjectById(String id) { + RepairObjectVO vo = repairInfoService.getRepairObjectById(id); + return Result.ok(vo); + } + + /** + * 数据录入 + */ + @AddSysLog("维修-数据录入") + @PostMapping(value = "/addDataEntry") + public Result addDataEntry(@RequestBody @Validated(SaveValidated.class) RepairDataEntryVO vo) { + String result = repairInfoService.addDataEntry(vo,"0"); + if(StrUtil.isNotBlank(result)){ + return Result.error(101,result); + }else{ + return Result.ok("添加成功!"); + } + } + + /** + * 维修单流程提交 + */ + @AddSysLog("维修-维修单流程提交") + @PostMapping(value = "/submitRepairObject") + public Result submitRepairObject(@RequestBody @Validated(SaveValidated.class) RepairObjectVO vo, HttpServletRequest request) { + + if(redisTemplate.hasKey(vo.getId()+"_submitRepairObject")){ + return Result.error(101,"该维修单正在被操作中,无法操作,请刷新!"); + }else{ + redisTemplate.opsForValue().set(vo.getId()+"_submitRepairObject", vo.getId(), 10, TimeUnit.SECONDS); + } + String result = ""; + try { + result = repairInfoService.submitRepairObject(vo,request); + }catch (Exception e){ + e.printStackTrace(); + return Result.error(101,"提交失败:" + e.getMessage()); + }finally { + redisTemplate.delete(vo.getId()+"_submitRepairObject"); + } + if(StrUtil.isNotBlank(result)){ + return Result.error(101,result); + }else{ + return Result.ok("提交成功!"); + } + } + + /** + * 获取指派信息维修厂列表 + */ + @AddSysLog("维修-获取指派信息维修厂列表") + @GetMapping(value = "/getRepairShop") + public Result getRepairShop(String id) { + List list = repairInfoMapper.findRepairShop(); + return Result.ok(list); + } + + /** + * 文件上传 + */ + @AddSysLog("维修-文件上传") + @PostMapping("/fileUpload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + List fileTypes = new ArrayList<>(); + for(String type:FileExtension.PIC.getNameList()) { + fileTypes.add(type); + } + for(String type:FileExtension.DOC.getNameList()) { + fileTypes.add(type); + } + return Result.ok(minioUtils.uploadFileV2Valid(file, fileTypes)); + } + + /** + * 导入 + */ + @AddSysLog(value = "维修-导入") + @PostMapping("/import") + public Result repairImport(HttpServletRequest request) throws IOException { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if(!ValidatorUtil.isExcelFile(file)){ + return Result.error("导入文件必须为excel!"); + } + + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(RepairImportVO.class).sheet().doReadSync(); + if(CollectionUtils.isEmpty(list) || ValidatorUtil.allFieldsAreNullInList(list)){ + return Result.error("导入车辆维修数据不能为空!请检查导入模板!"); + } + return repairUpkeepImportService.repairImport(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + + /** + * 导入错误信息下载 + */ + @AddSysLog(value = "维修-导入错误信息下载") + @GetMapping("/downFail") + public Result downFail(HttpServletResponse response,String path) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + String fullPath = failExcel + path; + try (InputStream stream = ResourceUtil.getStream(fullPath)) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("违章信息导入异常数据", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + // 下载完成后删除文件 + new Thread(() -> { + try { + //延迟 3 秒,避免文件被占用 + Thread.sleep(3000); + ValidatorUtil.deleteFile(fullPath); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + } catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } + + /** + * 导入模板下载 + */ + @AddSysLog(value = "维修-导入模板下载") + @GetMapping("/downTemplate") + public Result downImport(HttpServletResponse response) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + try (InputStream stream = ResourceUtil.getStream("excelTemplate/车辆维修导入模板.xlsx")) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("车辆维修导入模板", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + } catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbAccidentInfoController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbAccidentInfoController.java new file mode 100644 index 0000000..5cfcfb9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbAccidentInfoController.java @@ -0,0 +1,169 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.modules.gis.entity.TbGisVehicleFaultAlarm; +import com.gci.boot.modules.gis.query.GisVehicleFaultQuery; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.query.AccidentInfoQuery; +import com.gci.boot.modules.vehicles.service.ITbAccidentInfoService; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Arrays; + +/** + *

+ * 事故信息基础表 前端控制器 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@RestController +@RequestMapping("/vehicles/accidentInfo") +public class TbAccidentInfoController { + @Autowired + private ITbAccidentInfoService iTbAccidentInfoService; + @Autowired + private MinioUtils minioUtils; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "事故信息-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="tai.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper.pageBuild"}) + public Result queryPageList(AccidentInfoQuery query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = iTbAccidentInfoService.pageBuild(page, query); + return Result.ok(pageList); + } + + /** + * 添加 + */ + @AddSysLog(value = "事故信息-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbAccidentInfo tbAccidentInfo) { + iTbAccidentInfoService.saveItem(tbAccidentInfo); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog(value = "事故信息-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbAccidentInfo tbAccidentInfo) { + iTbAccidentInfoService.updateItem(tbAccidentInfo); + return Result.ok("编辑成功!"); + } + + /** + * 删除 + */ + @AddSysLog(value = "事故信息-删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + iTbAccidentInfoService.removeItem(id); + return Result.ok("删除成功!"); + } + + /** + * 批量删除 + */ + @AddSysLog(value = "事故信息-批量删除") +// @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + iTbAccidentInfoService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } + + /** + * 文件上传 + */ + @AddSysLog(value = "事故信息-文件上传") + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.PIC.getNameList())); + } + + /** + * 文件上传视频 + */ + @AddSysLog(value = "事故信息-文件上传视频") + @PostMapping("/uploadVideo") + public Result uploadVideo(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.VID.getNameList())); + } + + /** + * 导出 + */ + @AddSysLog(value = "事故信息-导出") + @GetMapping("/export") + @DataPermission(item="tai.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper.pageBuild"}) + public Result export(HttpServletResponse response, AccidentInfoQuery query) { + try (OutputStream output = response.getOutputStream()) { + String fileName = "车辆事故.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + IPage pageList = iTbAccidentInfoService.pageBuild(page, query); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + Workbook sheets = ExcelExportUtil.exportExcel(exportParams, TbAccidentInfo.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionInfoController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionInfoController.java new file mode 100644 index 0000000..d6b1c0d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionInfoController.java @@ -0,0 +1,322 @@ +package com.gci.boot.modules.vehicles.controller; + +import java.io.*; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.resource.ResourceUtil; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.exception.GciBootException; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionInfoService; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; + +/** + *

+ * 年检信息表 前端控制器 + *

+ * + * @author 2464 + * @since 2023-09-20 + */ +@RestController +@RequestMapping("/vehicles/annualInspectionInfo") +public class TbAnnualInspectionInfoController { + @Autowired + private ITbAnnualInspectionInfoService iTbAnnualInspectionInfoService; + @Autowired + private MinioUtils minioUtils; + + @Value("${failExcel}") + private String failExcel; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "年检信息-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item = "tv.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.pageBuild"}) + public Result queryPageList(AnnualInspectionInfoQuery query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = iTbAnnualInspectionInfoService.pageBuild(page, query); + return Result.ok(pageList); + } + + @AddSysLog(value = "年检信息-待办") + @GetMapping(value = "/remindList") + @DataPermission(item = "g.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.remindList"}) + public Result remindList(AnnualInspectionInfoQuery query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage pageList = iTbAnnualInspectionInfoService.remindList(page, query); + return Result.ok(pageList); + } + + /** + * 添加 + */ + @AddSysLog(value = "年检信息-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbAnnualInspectionInfo tbAnnualInspectionInfo) { + if (!tbAnnualInspectionInfo.getMiscellaneousFee().add(tbAnnualInspectionInfo.getServiceFee()) + .add(tbAnnualInspectionInfo.getTestingFee()).equals(tbAnnualInspectionInfo.getTotalFee())) { + return Result.error("费用合计错误!"); + } + iTbAnnualInspectionInfoService.saveItem(tbAnnualInspectionInfo); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog(value = "年检信息-编辑") + @PutMapping(value = "/edit") + public Result + edit(@RequestBody @Validated(UpdateValidated.class) TbAnnualInspectionInfo tbAnnualInspectionInfo) { + if (!tbAnnualInspectionInfo.getMiscellaneousFee().add(tbAnnualInspectionInfo.getServiceFee()) + .add(tbAnnualInspectionInfo.getTestingFee()).equals(tbAnnualInspectionInfo.getTotalFee())) { + return Result.error("费用合计错误!"); + } + iTbAnnualInspectionInfoService.updateItem(tbAnnualInspectionInfo); + return Result.ok("编辑成功!"); + } + + /** + * 删除 + */ + @AddSysLog(value = "年检信息-删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + iTbAnnualInspectionInfoService.removeItem(id); + return Result.ok("删除成功!"); + } + + /** + * 批量删除 + */ + @AddSysLog(value = "年检信息-批量删除") + // @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + iTbAnnualInspectionInfoService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } + + /** + * 获取上一年数据 + */ + @GetMapping("/getLastYear") + public Result getLastYear(@RequestParam(name = "plateNumber") String plateNumber) { + TbAnnualInspectionInfo lastYear = iTbAnnualInspectionInfoService.getLastYear(plateNumber); + return Result.ok(lastYear); + } + + /** + * 文件上传 + */ + @AddSysLog(value = "年检信息-文件上传") + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + ArrayList strings = ListUtil.toList(FileExtension.EXE.getNameList()); + strings.addAll(FileExtension.OTH.getNameList()); + return Result.ok(minioUtils.uploadFileValidNotIn(file, strings)); + } + + /** + * 导出 + */ + @AddSysLog(value = "年检信息-导出") + @GetMapping("/list/export") + @DataPermission(item = "tv.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.pageBuild"}) + public Result listExport(HttpServletResponse response, AnnualInspectionInfoQuery query) { + try (OutputStream output = response.getOutputStream()) { + String fileName = "车辆年检.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", + "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + IPage pageList = iTbAnnualInspectionInfoService.pageBuild(page, query); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + ArrayList strings = new ArrayList<>(); + strings.add("逾期类型"); + strings.add("将要逾期天数"); + strings.add("逾期天数"); + strings.add("所属项目"); + strings.add("错误信息"); + exportParams.setExclusions(strings.toArray(new String[0])); + Workbook sheets = + ExcelExportUtil.exportExcel(exportParams, TbAnnualInspectionInfo.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + /** + * 导入模板下载 + */ + @AddSysLog(value = "年检信息-导入模板下载") + @GetMapping("/list/downImport") + public void downImport(HttpServletResponse response) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + try (InputStream stream = ResourceUtil.getStream("excelTemplate/年检导入模板.xlsx")) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("年检导入模板", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 导入 + */ +// @AddSysLog(value = "年检信息-导入") + @PostMapping("/list/import") + @DataPermission(item = "A.projectId", + sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getAllProjects"}) + public Result listImport(HttpServletRequest request) throws IOException { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + if(!ValidatorUtil.isExcelFile(file)){ + return Result.error("导入文件必须为excel!"); + } + + return iTbAnnualInspectionInfoService.listImport(file); + } + + /** + * 导入错误信息下载 + */ + @AddSysLog(value = "年检信息-导入错误信息下载") + @GetMapping("/list/downFail") + public void downFail(HttpServletResponse response,@RequestParam("path")String path) { + // 设置输出的格式 + File file = FileUtil.file(failExcel + path); + if (file == null) { + throw new GciBootException("文件名称错误"); + } + try (BufferedInputStream inputStream = FileUtil.getInputStream(file); ServletOutputStream outputStream = response.getOutputStream()) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("车辆年检导出错误", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + IoUtil.copy(inputStream, outputStream); + } catch (IOException e) { + e.printStackTrace(); + throw new GciBootException("下载导入错误下信息失败!"); + } finally { + FileUtil.del(file); + } + } + + /** + * 导出 + */ + @AddSysLog(value = "年检信息-导出") + @GetMapping("/remindList/export") + @DataPermission(item = "g.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.remindList"}) + public Result remindListExport(HttpServletResponse response, AnnualInspectionInfoQuery query) { + try (OutputStream output = response.getOutputStream()) { + String fileName = "车辆提醒.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", + "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + IPage pageList = iTbAnnualInspectionInfoService.remindList(page, query); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + ArrayList strings = new ArrayList<>(); + strings.add("处理人"); + strings.add("办理日期"); + strings.add("年审地点"); + strings.add("备注"); + strings.add("检测费"); + strings.add("手续费"); + strings.add("杂费"); + strings.add("费用合计"); + strings.add("所属项目"); + strings.add("错误信息"); + exportParams.setExclusions(strings.toArray(new String[strings.size()])); + exportParams.setAutoSize(true); + Workbook sheets = + ExcelExportUtil.exportExcel(exportParams, TbAnnualInspectionInfo.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @GetMapping(value = "init") + public Result init() { + iTbAnnualInspectionInfoService.init(); + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionRemindController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionRemindController.java new file mode 100644 index 0000000..d642eac --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbAnnualInspectionRemindController.java @@ -0,0 +1,156 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionRemind; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import com.gci.boot.modules.vehicles.query.AnnualInspectionRemindQuery; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionInfoService; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionRemindService; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; + +/** + *

+ * 年检提醒 前端控制器 + *

+ * + * @author 2464 + * @since 2023-11-16 + */ +@RestController +@RequestMapping("/vehicles/annualInspectionRemind") +public class TbAnnualInspectionRemindController { + @Autowired + private ITbAnnualInspectionRemindService iTbAnnualInspectionRemindService; + @Autowired + private ITbAnnualInspectionInfoService iTbAnnualInspectionInfoService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "年检提醒-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item = "tv.projectId",sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionRemindMapper.pageBuild"}) + public Result queryPageList(AnnualInspectionRemindQuery query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbAnnualInspectionRemind.class,query); + IPage pageList = iTbAnnualInspectionRemindService.pageBuild(page, lambdaQueryWrapper); + return Result.ok(pageList); + } + + /** + * 添加 + */ +// @PostMapping(value = "/add") + public Result add(@RequestBody TbAnnualInspectionRemind tbAnnualInspectionRemind) { + iTbAnnualInspectionRemindService.save(tbAnnualInspectionRemind); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ +// @PutMapping(value = "/edit") + public Result edit(@RequestBody TbAnnualInspectionRemind tbAnnualInspectionRemind) { + iTbAnnualInspectionRemindService.updateById(tbAnnualInspectionRemind); + return Result.ok("编辑成功!"); + } + + /** + * 删除 + */ +// @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + iTbAnnualInspectionRemindService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * 批量删除 + */ +// @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + iTbAnnualInspectionRemindService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } + + @GetMapping(value = "/init") + public Result init() { + iTbAnnualInspectionRemindService.init(); + return Result.ok(); + } + + /** + * 导出 + */ + @AddSysLog(value = "年检提醒-导出") + @GetMapping("/export") + @DataPermission(item = "g.projectId",sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper.remindList"}) + public Result remindListExport(HttpServletResponse response, AnnualInspectionRemindQuery query) { + try (OutputStream output = response.getOutputStream()) { + String fileName = "年检提醒.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbAnnualInspectionRemind.class, query); + IPage pageList = iTbAnnualInspectionRemindService.pageBuild(page, lambdaQueryWrapper); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + Workbook sheets = ExcelExportUtil.exportExcel(exportParams, TbAnnualInspectionRemind.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + /** + * 根据infoId获取年检信息 + */ + @GetMapping("/getByInfoId") + public Result getByInfoId (@RequestParam(name = "infoId")String infoId) { + TbAnnualInspectionInfo info = iTbAnnualInspectionInfoService.getById(infoId); + if(Objects.nonNull(info) && Objects.nonNull(info.getValidityPeriod())){ + info.setValidityPeriod(DateUtil.offset(info.getValidityPeriod(), DateField.YEAR,1)); + } + return Result.ok(info); + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplateController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplateController.java new file mode 100644 index 0000000..1d013fa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplateController.java @@ -0,0 +1,145 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplate; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import com.gci.boot.modules.vehicles.query.ConsumablesTemplateQuery; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplateService; +import com.gci.boot.modules.vehicles.vo.ConsumablesTemplateVo; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; + +/** + *

+ * 耗材模板 前端控制器 + *

+ * + * 弃用啦 + * + * @author 2464 + * @since 2023-09-12 + */ +@RestController +@RequestMapping("/vehicles/consumablesTemplate") +public class TbConsumablesTemplateController { + @Autowired + private ITbConsumablesTemplateService iTbConsumablesTemplateService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "耗材模板-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item = "tct.projectId",sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplateMapper.listVo"}) + public Result queryPageList(ConsumablesTemplateQuery query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage list = iTbConsumablesTemplateService.pageBuild(page,query); + return Result.ok(list); + } + + /** + * 添加 + */ + @AddSysLog(value = "耗材模板-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbConsumablesTemplate tbConsumablesTemplate) { + iTbConsumablesTemplateService.saveItem(tbConsumablesTemplate); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog(value = "耗材模板-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbConsumablesTemplate tbConsumablesTemplate) { + iTbConsumablesTemplateService.updateItem(tbConsumablesTemplate); + return Result.ok("编辑成功!"); + } + + /** + * 根据id获取信息 + */ + @AddSysLog(value = "耗材模板-根据id获取信息") + @GetMapping("/getByProjectIdAndVehicleType") + public Result getByProjectId(@RequestParam("projectId") String projectId,@RequestParam("vehicleType")String vehicleType) { + TbConsumablesTemplate tbConsumablesTemplate = iTbConsumablesTemplateService.getByProjectIdAndVehicleType(projectId,vehicleType); + return Result.ok(tbConsumablesTemplate); + } + /** + * 删除 + */ + @AddSysLog(value = "耗材模板-删除") + @DeleteMapping(value = "/deleteByProjectIdAndVehicleType") + public Result deleteByProjectId(@RequestParam(name = "projectId", required = true) String projectId,@RequestParam("vehicleType")String vehicleType) { + iTbConsumablesTemplateService.removeItem(projectId,vehicleType); + return Result.ok("删除成功!"); + } + + /** + * 批量删除 + */ + @AddSysLog(value = "耗材模板-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + iTbConsumablesTemplateService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } + + /** + * 导出 + */ + @AddSysLog(value = "耗材模板-导出") + @GetMapping("/export") + @DataPermission(item = "tct.projectId",sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplateMapper.listVo"}) + public Result export(HttpServletResponse response, ConsumablesTemplateQuery query) { + try (OutputStream output = response.getOutputStream()) { + String fileName = "耗材管理.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + IPage pageList = iTbConsumablesTemplateService.pageBuild(page, query); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + Workbook sheets = ExcelExportUtil.exportExcel(exportParams, ConsumablesTemplateVo.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplatePartController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplatePartController.java new file mode 100644 index 0000000..9d9fe09 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbConsumablesTemplatePartController.java @@ -0,0 +1,190 @@ +package com.gci.boot.modules.vehicles.controller; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplateOutPart; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplatePart; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplatePartService; + +/** + *

+ * 耗材详情 前端控制器 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@RestController +@RequestMapping("/vehicles/consumablesPart") +public class TbConsumablesTemplatePartController { + @Autowired + private ITbConsumablesTemplatePartService iTbConsumablesTemplatePartService; + + @GetMapping("/init") + public Result init() { + iTbConsumablesTemplatePartService.init(); + return Result.ok(); + } + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "耗材详情-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item = "tb_consumables_template_part.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplatePartMapper.selectPage"}) + public Result queryPageList(TbConsumablesTemplatePart query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = + QueryGenerator.initQueryWrapper(TbConsumablesTemplatePart.class, query); + IPage pageList = + iTbConsumablesTemplatePartService.pageBuild(page, lambdaQueryWrapper,false); + return Result.ok(pageList); + } + + @AddSysLog(value = "耗材详情-分页列表查询") + @GetMapping(value = "/listHadQuantity") + @DataPermission(item = "tb_consumables_template_part.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplatePartMapper.selectPage"}) + public Result listHadQuantity(TbConsumablesTemplatePart query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = + QueryGenerator.initQueryWrapper(TbConsumablesTemplatePart.class, query); + IPage pageList = + iTbConsumablesTemplatePartService.pageBuild(page, lambdaQueryWrapper,true); + return Result.ok(pageList); + } + + /** + * 入库 + */ + @AddSysLog(value = "耗材详情-入库") + @PostMapping(value = "/inStorage") + public Result addInStorage(@RequestBody @Validated(SaveValidated.class) List partList) { + iTbConsumablesTemplatePartService.inStorage(partList); + return Result.ok("入库成功!"); + } + + /** + * 出库 + */ + @AddSysLog(value = "耗材详情-出库") + @PostMapping(value = "/outStorage") + public Result addOutStorage(@RequestBody @Validated(SaveValidated.class) List outPartList) { + iTbConsumablesTemplatePartService.outStorage(outPartList); + return Result.ok("出库成功!"); + } + + /** + * 同时更新入库或者出库 + */ + @AddSysLog(value = "耗材详情-出库") + @PostMapping(value = "/inAndOutStorage") + public Result editInAndOutStorage(@RequestBody @Validated(UpdateValidated.class) TbConsumablesTemplatePart partList) { + iTbConsumablesTemplatePartService.inAndOutStorage(partList); + return Result.ok("更新库存成功!"); + } + + /** + * 导出 + */ + @AddSysLog(value = "耗材详情-导出") + @GetMapping(value = "/export") + @DataPermission(item = "tb_consumables_template_part.projectId", + sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplatePartMapper.selectPage"}) + public Result export(HttpServletResponse response, TbConsumablesTemplatePart query) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + try (OutputStream output = response.getOutputStream()) { + String fileName = "耗材管理.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + LambdaQueryWrapper lambdaQueryWrapper = + QueryGenerator.initQueryWrapper(TbConsumablesTemplatePart.class, query); + IPage pageList = + iTbConsumablesTemplatePartService.pageBuild(page, lambdaQueryWrapper,false); + + List records = pageList.getRecords(); + ArrayList outParts = new ArrayList<>(); + for (TbConsumablesTemplatePart record : records) { + if (ObjectUtil.isNotEmpty(record.getOutPartList())) { + outParts.addAll(record.getOutPartList()); + } + } + + + //创建总的集合存放每一页的数据集合 + List> sheetsList = new ArrayList<>(); + // 使用map 创建sheet1 + Map sheetMap1 = new HashMap<>(); + ExportParams exportParams1 = new ExportParams(); + exportParams1.setDictHandler(new MyExcelDictHandleImpl()); + exportParams1.setSheetName("总览"); + exportParams1.setTitle("查询时间:" + new DateTime().toString() + " 查询人:" + sysUser.getRealname()); + sheetMap1.put("title",exportParams1); + sheetMap1.put("entity",TbConsumablesTemplatePart.class); + sheetMap1.put("data",records); + // 使用map 创建sheet2 + Map sheetMap2 = new HashMap<>(); + ExportParams exportParams2 = new ExportParams(); + exportParams2.setDictHandler(new MyExcelDictHandleImpl()); + exportParams2.setSheetName("出库"); + sheetMap2.put("title",exportParams2); + sheetMap2.put("entity",TbConsumablesTemplateOutPart.class); + sheetMap2.put("data",outParts); + sheetsList.add(sheetMap1); + sheetsList.add(sheetMap2); + + Workbook sheets = ExcelExportUtil.exportExcel(sheetsList, ExcelType.XSSF); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplateController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplateController.java new file mode 100644 index 0000000..995b382 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplateController.java @@ -0,0 +1,144 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.dict.excel.MyExcelDictHandleImpl; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplate; +import com.gci.boot.modules.vehicles.query.ConsumablesTemplateQuery; +import com.gci.boot.modules.vehicles.query.CustomizedTemplateQuery; +import com.gci.boot.modules.vehicles.service.ITbCustomizedTemplateService; +import com.gci.boot.modules.vehicles.vo.ConsumablesTemplateVo; +import com.gci.boot.modules.vehicles.vo.CustomizedTemplateVo; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Arrays; + +/** + *

+ * 定制件模板 前端控制器 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@RestController +@RequestMapping("/vehicles/customizedTemplate") +public class TbCustomizedTemplateController { + @Autowired + private ITbCustomizedTemplateService iTbCustomizedTemplateService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "定制件模板-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item = "tct.projectId",sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbCustomizedTemplateMapper.listVo"}) + public Result queryPageList(CustomizedTemplateQuery query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + IPage list = iTbCustomizedTemplateService.pageBuild(page,query); + return Result.ok(list); + } + + /** + * 添加 + */ + @AddSysLog(value = "定制件模板-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbCustomizedTemplate tbCustomizedTemplate) { + iTbCustomizedTemplateService.saveItem(tbCustomizedTemplate); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog(value = "定制件模板-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbCustomizedTemplate tbCustomizedTemplate) { + iTbCustomizedTemplateService.updateItem(tbCustomizedTemplate); + return Result.ok("编辑成功!"); + } + + /** + * 根据id获取信息 + */ + @AddSysLog(value = "定制件模板-根据id获取信息") + @GetMapping("/getByProjectIdAndVehicleType") + public Result getByProjectIdAndVehicleType(@RequestParam("projectId") String projectId,@RequestParam("vehicleType") String vehicleType) { + TbCustomizedTemplate tbCustomizedTemplate = iTbCustomizedTemplateService.getByProjectIdAndVehicleType(projectId,vehicleType); + return Result.ok(tbCustomizedTemplate); + } + + /** + * 删除 + */ + @AddSysLog(value = "定制件模板-删除") + @DeleteMapping(value = "/deleteByProjectIdAndVehicleType") + public Result deleteByProjectIdAndVehicleType(@RequestParam(name = "projectId") String projectId,@RequestParam("vehicleType") String vehicleType) { + iTbCustomizedTemplateService.removeItem(projectId,vehicleType); + return Result.ok("删除成功!"); + } + + /** + * 批量删除 + */ + @AddSysLog(value = "定制件模板-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + iTbCustomizedTemplateService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } + + /** + * 导出 + */ + @AddSysLog(value = "定制件模板-导出") + @GetMapping("/export") + @DataPermission(item = "tct.projectId",sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbCustomizedTemplateMapper.listVo"}) + public Result export(HttpServletResponse response, CustomizedTemplateQuery query) { + try (OutputStream output = response.getOutputStream()) { + String fileName = "定制件管理.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + Page page = new Page(1, -1); + IPage pageList = iTbCustomizedTemplateService.pageBuild(page, query); + ExportParams exportParams = new ExportParams(); + exportParams.setDictHandler(new MyExcelDictHandleImpl()); + exportParams.setAutoSize(true); + Workbook sheets = ExcelExportUtil.exportExcel(exportParams, CustomizedTemplateVo.class, pageList.getRecords()); + sheets.write(output); + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplatePartController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplatePartController.java new file mode 100644 index 0000000..f7b2701 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbCustomizedTemplatePartController.java @@ -0,0 +1,90 @@ +package com.gci.boot.modules.vehicles.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplatePart; +import com.gci.boot.modules.vehicles.service.ITbCustomizedTemplatePartService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; + +/** + *

+ * 定制件详情表 前端控制器 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@RestController +@RequestMapping("/tb-customized-template-part") +public class TbCustomizedTemplatePartController { + @Autowired + private ITbCustomizedTemplatePartService iTbCustomizedTemplatePartService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog(value = "定制件详情-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList( + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper(); + IPage pageList = iTbCustomizedTemplatePartService.page(page, lambdaQueryWrapper); + return Result.ok(pageList); + } + + /** + * 添加 + */ + @AddSysLog(value = "定制件详情-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody TbCustomizedTemplatePart tbCustomizedTemplatePart) { + iTbCustomizedTemplatePartService.save(tbCustomizedTemplatePart); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog(value = "定制件详情-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody TbCustomizedTemplatePart tbCustomizedTemplatePart) { + iTbCustomizedTemplatePartService.updateById(tbCustomizedTemplatePart); + return Result.ok("编辑成功!"); + } + + /** + * 删除 + */ + @AddSysLog(value = "定制件详情-删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + iTbCustomizedTemplatePartService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * 批量删除 + */ + @AddSysLog(value = "定制件详情-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + iTbCustomizedTemplatePartService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceController.java new file mode 100644 index 0000000..6cd13e8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceController.java @@ -0,0 +1,390 @@ +package com.gci.boot.modules.vehicles.controller; + + +import java.io.*; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.io.resource.ResourceUtil; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.driver.vo.DriverImportVO; +import com.gci.boot.modules.vehicles.vo.InsuranceImportVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.StringUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.util.ZipUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.service.ITbInsuranceRemindService; +import com.gci.boot.modules.vehicles.service.ITbInsuranceService; + +import cn.hutool.core.util.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 保险信息 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Slf4j +@RestController +@RequestMapping("/vehicles/insurance") +public class TbInsuranceController { + + @Autowired + private ITbInsuranceService tbInsuranceService; + @Autowired + private MinioUtils minioUtils; + + @Value("${failExcel}") + private String failExcel; + + @Autowired + private ITbInsuranceRemindService insuranceRemindService; + + @AddSysLog(value = "保险信息-列表查询") + @GetMapping("/list") + @DataPermission(item="tb_insurance.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper.selectList"}) + public Result list(TbInsurance item) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbInsurance.class, item); + queryWrapper.ge(item.getCompulsoryValidTimeStart()!=null,TbInsurance::getCompulsoryValidTime, item.getCompulsoryValidTimeStart()); + queryWrapper.le(item.getCompulsoryValidTimeEnd()!=null,TbInsurance::getCompulsoryValidTime, item.getCompulsoryValidTimeEnd()); + queryWrapper.ge(item.getCommercialValidTimeStart()!=null,TbInsurance::getCommercialValidTime, item.getCommercialValidTimeStart()); + queryWrapper.le(item.getCommercialValidTimeEnd()!=null,TbInsurance::getCommercialValidTime, item.getCommercialValidTimeEnd()); + queryWrapper.orderByDesc(TbInsurance::getCreateTime); + List list = tbInsuranceService.list(queryWrapper); + for (TbInsurance tbInsurance : list) { + tbInsurance.init(); + } + return Result.ok(list); + } + + @AddSysLog(value = "保险信息-分页查询") + @GetMapping("/page") + @DataPermission(item="tb_insurance.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper.selectPage"}) + public Result page(TbInsurance item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbInsurance.class, item); + queryWrapper.ge(item.getCompulsoryValidTimeStart()!=null,TbInsurance::getCompulsoryValidTime, item.getCompulsoryValidTimeStart()); + queryWrapper.le(item.getCompulsoryValidTimeEnd()!=null,TbInsurance::getCompulsoryValidTime, item.getCompulsoryValidTimeEnd()); + queryWrapper.ge(item.getCommercialValidTimeStart()!=null,TbInsurance::getCommercialValidTime, item.getCommercialValidTimeStart()); + queryWrapper.le(item.getCommercialValidTimeEnd()!=null,TbInsurance::getCommercialValidTime, item.getCommercialValidTimeEnd()); + queryWrapper.orderByDesc(TbInsurance::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = tbInsuranceService.page(page,queryWrapper); + for (TbInsurance tbInsurance : pageList.getRecords()) { + tbInsurance.init(); + } + return Result.ok(pageList); + } + + @AddSysLog(value = "保险信息-新增") + @PostMapping("/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbInsurance item){ + if(!"1".equals(item.getHasCompulsoryInsurance())&&!"1".equals(item.getHasCommercialInsurance())) { + return Result.error("交强险和商业保险不能都为空"); + } + String error = tbInsuranceService.checkItem(item); + if(StringUtils.hasLength(error)) { + return Result.error(error); + } + if("1".equals(item.getHasCommercialInsurance())) { + item.setCommercialCompanyId(item.getCompulsoryCompanyId()); + item.setCommercialStartTime(item.getCompulsoryStartTime()); + item.setCommercialValidTime(item.getCompulsoryValidTime()); + } + tbInsuranceService.save(item); + insuranceRemindService.updateRemind(); + return Result.ok(); + } + + @AddSysLog(value = "保险信息-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbInsurance item){ + if(!"1".equals(item.getHasCompulsoryInsurance())&&!"1".equals(item.getHasCommercialInsurance())) { + return Result.error("交强险和商业保险不能都为空"); + } + String error = tbInsuranceService.checkItem(item); + if(StringUtils.hasLength(error)) { + return Result.error(error); + } + if("1".equals(item.getHasCommercialInsurance())) { + item.setCommercialCompanyId(item.getCompulsoryCompanyId()); + item.setCommercialStartTime(item.getCompulsoryStartTime()); + item.setCommercialValidTime(item.getCompulsoryValidTime()); + } + tbInsuranceService.updateById(item); + insuranceRemindService.updateRemind(); + return Result.ok(); + } + + @AddSysLog(value = "保险信息-删除") + @DeleteMapping("/delete") + public Result delete(TbInsurance item){ + tbInsuranceService.removeById(item.getId()); + return Result.ok(); + } + + + + /** + * 导入模板下载 + */ + @AddSysLog(value = "保险信息-导入模板下载") + @GetMapping("/V2/downImport") + public void downImport(HttpServletResponse response) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + try (InputStream stream = ResourceUtil.getStream("excelTemplate/保险导入模板.xlsx")) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("保险导入模板", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 导入 + */ + @AddSysLog(value = "保险信息-导入") + @PostMapping("/V2/import") + @DataPermission(item = "A.projectId", + sqlIds = {"com.gci.boot.modules.projects.mapper.ProjectsMapper.getAllProjects"}) + public Result listImport(HttpServletRequest request) throws IOException { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if(!ValidatorUtil.isExcelFile(file)){ + return Result.error("导入文件必须为excel!"); + } + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(InsuranceImportVO.class).sheet().doReadSync(); + return tbInsuranceService.listImport(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + + /** + * 导入错误信息下载 + */ + @AddSysLog(value = "保险信息-导入失败文件下载") + @GetMapping("/V2/downFail") + public void downFail(HttpServletResponse response,@RequestParam("path")String path) { + // 设置输出的格式 + File file = FileUtil.file(failExcel + path); + if (file == null) { + throw new GciBootException("文件名称错误,未找到该文件"); + } + try (BufferedInputStream inputStream = FileUtil.getInputStream(file); ServletOutputStream outputStream = response.getOutputStream()) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(CommonConstant.INSURANCE_IMPORT_FAIL_EXCEL_NAME, "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + IoUtil.copy(inputStream, outputStream); + }catch (IORuntimeException e){ + e.printStackTrace(); + throw new GciBootException("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + throw new GciBootException("下载导入错误下信息失败!"); + } finally { + FileUtil.del(file); + } + } + + + + /** + * 文件上传 + */ + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.getCommonFileTypes())); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "保险信息-导出") + @GetMapping("/simple/export") + @DataPermission(item="tb_insurance.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper.selectList"}) + public Result export(TbInsurance item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "保险.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result result = list(item); + List list = (List)result.getResult(); + EasyExcel.write(output, TbInsurance.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "保险信息-分页导出") + @GetMapping("/multi/export") + @DataPermission(item="tb_insurance.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper.selectPage"}) + public Result multiExport(TbInsurance item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "车辆验收.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, TbInsurance.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages simpleImport(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(TbInsurance.class).sheet().doReadSync(); + log.info("数据量:{}",list.size()); + tbInsuranceService.saveBatch(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + return Result.ok(); + } + + //保险附件批量上传 + @PostMapping("/uploadFiles") + public Result uploadFiles(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + minioUtils.checkType(file, FileExtension.COM.getNameList()); + int count = 0; + try { + InputStream inputStream = file.getInputStream(); + String path = "template/"+System.currentTimeMillis(); + ClassPathResource xlsx = new ClassPathResource(path); + ZipUtil.unzip(inputStream, xlsx.getPath()); + File folder = new File(xlsx.getPath()); + Map fileMap = new HashMap<>(); + if (folder.isDirectory()) { + readFile(folder,fileMap); + } + String type = "1"; + if(file.getOriginalFilename().contains("商业保险")||file.getOriginalFilename().contains("商业险")) { + type = "0"; + } + count = tbInsuranceService.uploadFiles(fileMap, type); + } catch (IOException e) { + log.error("保险附件上传失败:", e); + return Result.error("保险附件上传失败!"); + } + + return Result.ok("成功上传"+count+"个附件"); + } + + private void readFile(File folder,Map fileMap) { + File[] files = folder.listFiles(); + for (File f : files) { + if (f.isFile()) { + fileMap.put(f.getName().toUpperCase(), f); + }else if (f.isDirectory()) { + readFile(f,fileMap); + } + } + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceRecordController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceRecordController.java new file mode 100644 index 0000000..93f4606 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbInsuranceRecordController.java @@ -0,0 +1,190 @@ +package com.gci.boot.modules.vehicles.controller; + + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.gci.boot.annotation.permission.DataPermission; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord; +import com.gci.boot.modules.vehicles.service.ITbInsuranceRecordService; + +import cn.hutool.core.util.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 出险管理 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-22 + */ +@Slf4j +@RestController +@RequestMapping("/vehicles/insuranceRecord") +public class TbInsuranceRecordController { + + @Autowired + private ITbInsuranceRecordService tbInsuranceRecordService; + @Autowired + private MinioUtils minioUtils; + + @AddSysLog(value = "出险管理-列表查询") + @GetMapping("/list") + @DataPermission(item="tb_insurance_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper.selectList"}) + public Result list(TbInsuranceRecord item) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbInsuranceRecord.class, item); + queryWrapper.ge(item.getInsuranceDateStart()!=null,TbInsuranceRecord::getInsuranceDate, item.getInsuranceDateStart()); + queryWrapper.le(item.getInsuranceDateEnd()!=null,TbInsuranceRecord::getInsuranceDate, item.getInsuranceDateEnd()); + queryWrapper.orderByDesc(TbInsuranceRecord::getCreateTime); + List list = tbInsuranceRecordService.list(queryWrapper); + return Result.ok(list); + } + + @AddSysLog(value = "出险管理-分页查询") + @GetMapping("/page") + @DataPermission(item="tb_insurance_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper.selectPage"}) + public Result page(TbInsuranceRecord item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbInsuranceRecord.class, item); + queryWrapper.ge(item.getInsuranceDateStart()!=null,TbInsuranceRecord::getInsuranceDate, item.getInsuranceDateStart()); + queryWrapper.le(item.getInsuranceDateEnd()!=null,TbInsuranceRecord::getInsuranceDate, item.getInsuranceDateEnd()); + queryWrapper.orderByDesc(TbInsuranceRecord::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = tbInsuranceRecordService.page(page,queryWrapper); + return Result.ok(pageList); + } + + @AddSysLog(value = "出险管理-新增") + @PostMapping("/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbInsuranceRecord item){ + tbInsuranceRecordService.saveItem(item); + return Result.ok(); + } + + @AddSysLog(value = "出险管理-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbInsuranceRecord item){ + tbInsuranceRecordService.updateItem(item); + return Result.ok(); + } + + @AddSysLog(value = "出险管理-删除") + @DeleteMapping("/delete") + public Result delete(TbInsuranceRecord item){ + tbInsuranceRecordService.removeById(item.getId()); + return Result.ok(); + } + + /** + * 文件上传 + */ + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.getCommonFileTypes())); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "出险管理-导出") + @GetMapping("/simple/export") + @DataPermission(item="tb_insurance_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper.selectList"}) + public Result export(TbInsuranceRecord item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "司机打卡.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result result = list(item); + List list = (List)result.getResult(); + EasyExcel.write(output, TbInsuranceRecord.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "出险管理-分页导出") + @GetMapping("/multi/export") + @DataPermission(item="tb_insurance_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper.selectPage"}) + public Result multiExport(TbInsuranceRecord item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "司机打卡.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, TbInsuranceRecord.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages + * 保险逾期提醒 前端控制器 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Slf4j +@RestController +@RequestMapping("/vehicles/insuranceRemind") +public class TbInsuranceRemindController { + + @Autowired + private ITbInsuranceRemindService insuranceRemindService; + + @AddSysLog(value = "保险逾期提醒-列表查询") + @GetMapping("/list") + @DataPermission(item="tb_insurance_remind.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRemindMapper.selectList"}) + public Result list(TbInsuranceRemind item) { + IPage pageList = new Page<>(1, -1); + IPage list = insuranceRemindService.getRemindPage(item,pageList); + return Result.ok(list.getRecords()); + } + + @AddSysLog(value = "保险逾期提醒-分页查询") + @GetMapping("/page") + @DataPermission(item="tb_insurance_remind.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRemindMapper.selectList"}) + public Result page(TbInsuranceRemind item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + IPage pageList = new Page<>(pageNo, pageSize); + IPage list = insuranceRemindService.getRemindPage(item,pageList); + return Result.ok(list); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "保险逾期提醒-导出") + @GetMapping("/simple/export") + @DataPermission(item="tb_insurance_remind.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRemindMapper.selectList"}) + public Result export(TbInsuranceRemind item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "保险提醒.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result result = list(item); + List list = (List)result.getResult(); + EasyExcel.write(output, TbInsuranceRemind.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "保险逾期提醒-分页导出") + @GetMapping("/multi/export") + @DataPermission(item="tb_insurance_remind.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbInsuranceRemindMapper.selectList"}) + public Result multiExport(TbInsuranceRemind item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "保险提醒.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, TbInsuranceRemind.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages updateRemind() { + insuranceRemindService.updateRemind(); + return Result.ok(); + } + + @AddSysLog(value = "保险逾期提醒-创建") + @GetMapping("/createRemind") + public Result createRemind() { + insuranceRemindService.createRemind(); + return Result.ok(); + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbRefuelChargeRecordController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbRefuelChargeRecordController.java new file mode 100644 index 0000000..ff65937 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbRefuelChargeRecordController.java @@ -0,0 +1,244 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.driver.vo.DriverImportVO; +import com.gci.boot.modules.vehicles.entity.TbRefuelChargeRecord; +import com.gci.boot.modules.vehicles.service.ITbRefuelChargeRecordService; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; +import com.gci.boot.modules.vehicles.vo.TbRefuelChargeRecordImportVo; +import com.gci.boot.modules.vehicles.vo. TbRefuelChargeRecordVo; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +/** + *

+ * 加油充电登记 前端控制器 + *

+ * + * @author admin + * @since 2023-11-30 + */ +@Slf4j +@RestController +@RequestMapping("/gis/refuelChargeRecord") +public class TbRefuelChargeRecordController { + + @Autowired + private ITbRefuelChargeRecordService refuelChargeRecordService; + @Value("${failExcel}") + private String failExcel; + + @AddSysLog(value = "加油充电登记-列表查询") + @GetMapping("/list") + @DataPermission(item="tb_refuel_charge_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbRefuelChargeRecordMapper.selectList"},stringIn = true) + public Result list(TbRefuelChargeRecord item) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbRefuelChargeRecord.class, item); + queryWrapper.ge(item.getDateStart()!=null,TbRefuelChargeRecord::getRecordDate, item.getDateStart()); + queryWrapper.le(item.getDateEnd()!=null,TbRefuelChargeRecord::getRecordDate, item.getDateEnd()); + queryWrapper.orderByDesc(TbRefuelChargeRecord::getCreateTime); + List list = refuelChargeRecordService.list(queryWrapper); + return Result.ok(list); + } + + @AddSysLog(value = "加油充电登记-分页列表查询") + @GetMapping("/page") + @DataPermission(item="tb_refuel_charge_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbRefuelChargeRecordMapper.selectPage"}) + public Result page(TbRefuelChargeRecord item,@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) { + + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbRefuelChargeRecord.class, item); + queryWrapper.ge(item.getDateStart()!=null,TbRefuelChargeRecord::getRecordDate, item.getDateStart()); + queryWrapper.le(item.getDateEnd()!=null,TbRefuelChargeRecord::getRecordDate, item.getDateEnd()); + queryWrapper.orderByDesc(TbRefuelChargeRecord::getCreateTime); + Page page = new Page(pageNo, pageSize); + IPage pageList = refuelChargeRecordService.page(page,queryWrapper); + return Result.ok(pageList); + } + + @AddSysLog(value = "加油充电登记-添加") + @PostMapping("/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbRefuelChargeRecord item){ + refuelChargeRecordService.saveItem(item); + return Result.ok(); + } + + @AddSysLog(value = "加油充电登记-编辑") + @PutMapping("/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbRefuelChargeRecord item){ + refuelChargeRecordService.saveItem(item); + return Result.ok(); + } + + @AddSysLog(value = "加油充电登记-删除") + @DeleteMapping("/delete") + public Result delete(TbRefuelChargeRecord item){ + refuelChargeRecordService.removeById(item.getId()); + return Result.ok(); + } + + /** + * simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大时要 重复多次写入 + * @param response + */ + @AddSysLog(value = "加油充电登记-导出") + @GetMapping("/simple/export") + @DataPermission(item="tb_refuel_charge_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbRefuelChargeRecordMapper.selectList"},stringIn = true) + public Result export(TbRefuelChargeRecord item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "加油充电登记.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + Result result = list(item); + List list = (List)result.getResult(); + + EasyExcel.write(output, TbRefuelChargeRecord.class).sheet("sheet1").doWrite(list); + + } catch (IOException e) { + log.error(e.getMessage(), e); + return Result.error("导出错误!"); + } + return Result.ok(); + } + + @AddSysLog(value = "加油充电登记-分页导出") + @GetMapping("/multi/export") + @DataPermission(item="tb_refuel_charge_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbRefuelChargeRecordMapper.selectPage"}) + public Result multiExport(TbRefuelChargeRecord item,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + String fileName = "加油充电登记.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + int pages = 1; + try (ExcelWriter excelWriter = EasyExcel.write(output, TbRefuelChargeRecord.class).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build(); + for (int i = 0; i < pages; i++) { + Result result = page(item,i+1, 10); + IPage page = (IPage)result.getResult(); + List data = page.getRecords(); + int temp = (int)page.getPages(); + if(pages simpleImport(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if(!ValidatorUtil.isExcelFile(file)){ + return Result.error("导入文件必须为excel!"); + } + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(TbRefuelChargeRecordImportVo.class).sheet().doReadSync(); + if(CollectionUtils.isEmpty(list) || ValidatorUtil.allFieldsAreNullInList(list)){ + return Result.error("导入加油充电登记数据不能为空!请检查导入模板!"); + } + return refuelChargeRecordService.saveItemBatch(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + + + + /** + * 导入错误信息下载 + */ + @AddSysLog(value = "加油充电登记-导入错误信息下载") + @GetMapping("/downFail") + public Result downFail(HttpServletResponse response,String path) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + String fullPath = failExcel + path; + try (InputStream stream = ResourceUtil.getStream(fullPath)) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("加油充电登记导入异常数据", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + // 下载完成后删除文件 + new Thread(() -> { + try { + //延迟 3 秒,避免文件被占用 + Thread.sleep(3000); + ValidatorUtil.deleteFile(fullPath); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + }catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/TbViolationRecordController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/TbViolationRecordController.java new file mode 100644 index 0000000..a2df0e3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/TbViolationRecordController.java @@ -0,0 +1,378 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.modules.driver.service.ITbDriverSignInService; +import com.gci.boot.modules.msg.enums.SenderTypeEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.service.ITbViolationRecordService; +import com.gci.boot.modules.vehicles.vo.MessageVO; +import com.gci.boot.modules.vehicles.vo.RegexTemplateVO; +import com.gci.boot.modules.vehicles.vo.VehicleProjectVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.web.servlet.ShiroHttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +@Api(tags="违章记录表对象") +@Slf4j +@RestController +@RequestMapping("/vehicles/violation") +public class TbViolationRecordController { + @Autowired + private ITbViolationRecordService violationRecordService; + @Autowired + private IProjectsService projectsService; + @Autowired + private MinioUtils minioUtils; + @Autowired + private ITbDriverSignInService driverSignInService; + @Autowired + private MsgPushService msgPushService; + @Value("${failExcel}") + private String failExcel; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("违章记录-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="tb_violation_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.selectPage"}) + public Result queryPageList(TbViolationRecord violationRecord, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbViolationRecord.class, violationRecord); + IPage pageList = violationRecordService.page(page, lambdaQueryWrapper); + return Result.ok(pageList); + } + + /** + * 添加 + */ + @AddSysLog("违章记录-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbViolationRecord violationRecord) { + Projects projects = projectsService.getById(violationRecord.getProjectId()); + if(Objects.nonNull(projects)){ + violationRecord.setProjectName(projects.getProjectName()); + } + violationRecordService.save(violationRecord); + //推送微信消息 + ThreadUtil.execAsync(()->{ + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType() +","+SenderTypeEnum.CUSTOMER.getSendType(),violationRecord.getId(), + violationRecord.getProjectId(), WorkOrderType.VIOLATION.getType(),"未处理", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "新增违章,请及时查看")); + }); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog("违章记录-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbViolationRecord violationRecord) { + Projects projects = projectsService.getById(violationRecord.getProjectId()); + if(Objects.nonNull(projects)){ + violationRecord.setProjectName(projects.getProjectName()); + } + if(Objects.nonNull(violationRecord.getHandleResult()) && 1==violationRecord.getHandleResult()){ + if(Objects.isNull(violationRecord.getHandleTime()) || Objects.isNull(violationRecord.getHandleVoucher())){ + return Result.error(101,"请选择处理时间及上传处理凭证!"); + } + } + violationRecordService.updateById(violationRecord); + return Result.ok("编辑成功!"); + } + + /** + * 删除 + */ + @AddSysLog("违章记录-删除") + @DeleteMapping(value = "/realDelete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + violationRecordService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * 作废 + */ + @AddSysLog("违章记录-作废") + @DeleteMapping(value = "/cancel") + public Result cancel(@RequestParam(name = "id", required = true) String id) { + violationRecordService.update(new LambdaUpdateWrapper().eq(TbViolationRecord::getId,id).set(TbViolationRecord::getCancelFlag,1)); + return Result.ok("作废成功!"); + } + + /** + * 恢复 + */ + @AddSysLog("违章记录-恢复") + @DeleteMapping(value = "/unCancel") + public Result unCancel(@RequestParam(name = "id", required = true) String id) { + violationRecordService.update(new LambdaUpdateWrapper().eq(TbViolationRecord::getId,id).set(TbViolationRecord::getCancelFlag,0)); + return Result.ok("作废成功!"); + } + + /** + * 批量删除 + */ + @AddSysLog("违章记录-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result realDeleteBatch(@RequestParam(name = "ids", required = true) String ids) { + violationRecordService.removeByIds(Arrays.asList(ids.split(","))); + return Result.ok("批量删除成功!"); + } + + /** + * 文件上传 + */ + @AddSysLog("违章记录-文件上传") + @PostMapping("/upload") + public Result upload(HttpServletRequest request) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + return Result.ok(minioUtils.uploadFileValid(file, FileExtension.PIC.getNameList())); + } + + /** + * 导出 + * @return + */ + @AddSysLog("违章记录-导出") + @GetMapping("/export") + @DataPermission(item="tb_violation_record.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.selectList"}) + public Result export(TbViolationRecord violationRecord,HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "违章记录表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbViolationRecord.class, violationRecord); + List list = violationRecordService.list(lambdaQueryWrapper); + EasyExcel.write(output, TbViolationRecord.class).sheet("违章记录").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + /** + * 获取车牌-项目-责任人列表 + */ + @AddSysLog("违章记录-获取车牌-项目-责任人列表") + @GetMapping(value = "/queryVehicleProject") + public Result queryVehicleProject() { + List list = violationRecordService.queryVehicleProject(); + return Result.ok(list); + } + + /** + * 获取车牌下拉列表 + */ + @AddSysLog("违章记录-获取车牌下拉列表") + @GetMapping(value = "/queryAllVehicle") + public Result queryAllVehicle() { + List list = violationRecordService.queryAllVehicle(); + return Result.ok(list); + } + + /** + * 获取项目下拉列表 + */ + @AddSysLog("违章记录-获取项目下拉列表") + @GetMapping(value = "/queryAllProject") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.queryProjects"}) + public Result queryAllProject() { + List list = violationRecordService.queryAllProject(); + return Result.ok(list); + } + + /** + * 解析短信获取车牌、时间、地点、违章分类 + */ + @AddSysLog("违章记录-解析短信获取车牌、时间、地点、违章分类") + @PostMapping(value = "/analyzeMessage") + public Result analyzeMessage(@RequestBody RegexTemplateVO templateVO) { + if(Objects.isNull(templateVO) || StrUtil.isBlank(templateVO.getTemplate())){ + return Result.error(101,"违章短信不能为空!"); + } + String str = StringUtil.checkString2(templateVO.getTemplate(),500); + if(StrUtil.isNotBlank(str)){ + return Result.error(101,str); + } + + MessageVO vo = violationRecordService.analyzeMessage(templateVO.getTemplate()); + return Result.ok(vo); + } + + /** + * 新增违章行为 + */ + @AddSysLog("违章记录-新增违章行为") + @PostMapping(value = "/addViolationBehavior") + public Result addViolationBehavior(@RequestBody MessageVO vo) { + String str = violationRecordService.addViolationBehavior(vo); + if(StrUtil.isNotBlank(str) && str.contains("存在")){ + return Result.error(101,str); + }else{ + return Result.ok(str); + } + } + + /** + * 车牌、时间获取打卡司机 + */ + @AddSysLog("违章记录-车牌、时间获取打卡司机") + @GetMapping(value = "/queryDriverByPlateNumberAndTime") + public Result queryDriverByPlateNumberAndTime(String plateNumber, String time) { + String name = driverSignInService.queryDriverByPlateNumberAndTime(plateNumber, time); + return Result.ok(name); + } + + /** + * 导入 + */ + @AddSysLog(value = "违章-导入") + @PostMapping("/import") + public Result listImport(HttpServletRequest request) throws IOException { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if (ObjectUtil.isEmpty(file)) { + return Result.error("请正确上传文件!"); + } + if(!ValidatorUtil.isExcelFile(file)){ + return Result.error("导入文件必须为excel!"); + } + return violationRecordService.msgImport(file); + } + + /** + * 导入错误信息下载 + */ + @AddSysLog(value = "违章-导入错误信息下载") + @GetMapping("/downFail") + public Result downFail(HttpServletResponse response,String path) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + String fullPath = failExcel + path; + try (InputStream stream = ResourceUtil.getStream(fullPath)) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("维修信息导入异常数据", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + // 下载完成后删除文件 + new Thread(() -> { + try { + //延迟 3 秒,避免文件被占用 + Thread.sleep(3000); + ValidatorUtil.deleteFile(fullPath); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + } catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } + + /** + * 导入模板下载 + */ + @AddSysLog(value = "违章-导入模板下载") + @GetMapping("/downTemplate") + public Result downImport(HttpServletResponse response) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + try (InputStream stream = ResourceUtil.getStream("excelTemplate/违章短信导入模板.xlsx")) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("违章短信导入模板", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + } catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepBillController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepBillController.java new file mode 100644 index 0000000..de9178c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepBillController.java @@ -0,0 +1,354 @@ +package com.gci.boot.modules.vehicles.controller; + + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.basedata.entity.TbRepairShopArchives; +import com.gci.boot.modules.basedata.service.ITbRepairShopArchivesService; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbUpkeepBill; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan; +import com.gci.boot.modules.vehicles.service.IRepairUpkeepImportService; +import com.gci.boot.modules.vehicles.service.ITbUpkeepBillService; +import com.gci.boot.modules.vehicles.vo.*; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +@Api(tags="保养台账") +@Slf4j +@RestController +@RequestMapping("/vehicles/upkeepBill") +public class UpKeepBillController { + + @Autowired + private ITbUpkeepBillService upkeepBillService; + @Autowired + private ISysUserService sysUserService; + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private ITbGisRunningbusService gisRunningbusService; + @Autowired + private ISysRoleService sysRoleService; + @Autowired + private ITbRepairShopArchivesService tbRepairShopArchivesService; + @Autowired + private IProjectsService projectsService; + @Autowired + private IRepairUpkeepImportService repairUpkeepImportService; + @Value("${failExcel}") + private String failExcel; + @Autowired + private MsgPushService msgPushService; + + /** + * 数据录入 + */ + @AddSysLog("保养台账-数据录入") + @PostMapping(value = "/addDataEntry") + public Result addDataEntry(@RequestBody @Validated(SaveValidated.class) UpkeepDataEntryVO vo) { + String result = upkeepBillService.addDataEntry(vo,"0"); + if(StrUtil.isNotBlank(result)){ + return Result.error(101,result); + } + return Result.ok("添加成功!"); + } + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("保养台账-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(UpkeepInfoListVO vo, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //识别身份:需处理内部员工身份和维修厂身份的过滤 + Integer departCategory = projectsService.judgeDepartCategory(); + //超级管理员查询全部数据 + if(departCategory != 5){ + //内部员工按项目列表过滤 + if(departCategory == 1 || departCategory == 4){ + List listProjectStaff = projectsService.queryProjectListOfUser(); + if(CollectionUtils.isNotEmpty(listProjectStaff)){ + vo.setListProject(listProjectStaff); + }else { + vo.setProjectId("no permission"); + } + }else if(departCategory == 2){ + List listRepairShop = tbRepairShopArchivesService.getRepairShopByUserId(sysUser.getId()); + List listRepairShopIds = listRepairShop.stream().map(TbRepairShopArchives::getId).collect(Collectors.toList()); + if(CollectionUtils.isNotEmpty(listRepairShopIds)){ + vo.setListRepairShop(listRepairShopIds); + }else { + vo.setProjectId("no permission"); + } + }else{ + vo.setProjectId("no permission"); + } + } + Page page = new Page(pageNo, pageSize); + IPage pageList = upkeepBillService.getUpkeepBillList(page, vo); + return Result.ok(pageList); + } + + /** + * 导出 + * @return + */ + @AddSysLog("保养台账-导出") + @GetMapping("/export") + public Result export(UpkeepInfoListVO vo, HttpServletResponse response){ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //识别身份:需处理内部员工身份和维修厂身份的过滤 + Integer departCategory = projectsService.judgeDepartCategory(); + //超级管理员查询全部数据 + if(departCategory != 5){ + //内部员工按项目列表过滤 + if(departCategory == 1 || departCategory == 4){ + List listProjectStaff = projectsService.queryProjectListOfUser(); + if(CollectionUtils.isNotEmpty(listProjectStaff)){ + vo.setListProject(listProjectStaff); + }else { + vo.setProjectId("no permission"); + } + }else if(departCategory == 2){ + List listRepairShop = tbRepairShopArchivesService.getRepairShopByUserId(sysUser.getId()); + List listRepairShopIds = listRepairShop.stream().map(TbRepairShopArchives::getId).collect(Collectors.toList()); + if(CollectionUtils.isNotEmpty(listRepairShopIds)){ + vo.setListRepairShop(listRepairShopIds); + }else { + vo.setProjectId("no permission"); + } + }else{ + vo.setProjectId("no permission"); + } + } + + try (OutputStream output = response.getOutputStream()){ + String fileName = "保养台账表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + List list = upkeepBillService.getAllUpkeepBillList(vo); + EasyExcel.write(output, UpkeepInfoListVO.class).sheet("保养台账").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + /** + * 作废 + */ + @AddSysLog("保养台账-作废") + @PostMapping(value = "/cancel") + public Result cancel(@RequestBody CancelVO vo) { + String arg = StringUtil.checkString(vo.getCancelIdea(),200); + if(StrUtil.isNotBlank(arg)){ + return Result.error(101,"作废原因 " + arg); + } + String realName = ""; + if(StrUtil.isNotBlank(vo.getRealname())){ + realName = vo.getRealname(); + }else{ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + } + //查当前总里程 + TbUpkeepBill tbUpkeepBill = upkeepBillService.getById(vo.getId()); + LambdaQueryWrapper busQuery = new LambdaQueryWrapper<>(); + busQuery.eq(TbGisRunningbus::getPlateNumber,tbUpkeepBill.getPlateNumber()).last(" limit 1 "); + upkeepBillService.update(new LambdaUpdateWrapper().eq(TbUpkeepBill::getId,vo.getId()) + .set(TbUpkeepBill::getFlowStatus,9) + .set(TbUpkeepBill::getFlowNode,4) + .set(TbUpkeepBill::getCancelIdea,vo.getCancelIdea()) + .set(TbUpkeepBill::getCancelPeople,realName) + .set(TbUpkeepBill::getCancelTime,new Date())); + return Result.ok("作废成功!"); + } + + /** + * 根据保养单id获取保养弹窗详情 + */ + @AddSysLog("保养台账-根据保养单id获取保养弹窗详情") + @GetMapping(value = "/getUpkeepObjectById") + public Result getUpkeepObjectById(String id) { + UpkeepObjectVO vo = upkeepBillService.getUpkeepObjectById(id); + return Result.ok(vo); + } + + /** + * 保养台账流程提交 + */ + @AddSysLog("保养台账-保养台账流程提交") + @PostMapping(value = "/submitUpkeepObject") + public Result submitUpkeepObject(@RequestBody @Validated(SaveValidated.class) UpkeepObjectVO vo, HttpServletRequest request) { + + if(redisTemplate.hasKey(vo.getId()+"_submitRepairObject")){ + return Result.error(101,"该保养单正在被操作中,无法操作,请刷新!"); + }else{ + redisTemplate.opsForValue().set(vo.getId()+"_submitUpkeepObject", vo.getId(), 10, TimeUnit.SECONDS); + } + + String result = ""; + try { + result = upkeepBillService.submitUpkeepObject(vo,request); + }catch (Exception e){ + e.printStackTrace(); + return Result.error(101,"提交失败:" + e.getMessage()); + }finally { + redisTemplate.delete(vo.getId()+"_submitUpkeepObject"); + } + if(StrUtil.isNotBlank(result)){ + return Result.error(101,result); + } + return Result.ok("提交成功!"); + } + + /** + * 导入 + */ + @AddSysLog(value = "保养-导入") + @PostMapping("/import") + public Result upkeepImport(HttpServletRequest request) throws IOException { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)request; + MultipartFile file = multipartRequest.getFile("file"); + if(!ValidatorUtil.isExcelFile(file)){ + return Result.error("导入文件必须为excel!"); + } + try(InputStream input = file.getInputStream()) { + List list = EasyExcel.read(input).head(UpkeepImportVO.class).sheet().doReadSync(); + if(CollectionUtils.isEmpty(list) || ValidatorUtil.allFieldsAreNullInList(list)){ + return Result.error("导入保养台账数据不能为空!请检查导入模板!"); + } + return repairUpkeepImportService.upkeepImport(list); + }catch (IOException e){ + log.error(e.getMessage(), e); + return Result.error("导入错误!"); + } + } + + /** + * 导入错误信息下载 + */ + @AddSysLog(value = "保养-导入错误信息下载") + @GetMapping("/downFail") + public Result downFail(HttpServletResponse response,String path) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + String fullPath = failExcel + path; + try (InputStream stream = ResourceUtil.getStream(fullPath)) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("保养信息导入异常数据", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + // 下载完成后删除文件 + new Thread(() -> { + try { + //延迟 3 秒,避免文件被占用 + Thread.sleep(3000); + ValidatorUtil.deleteFile(fullPath); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + }catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } + + /** + * 导入模板下载 + */ + @AddSysLog(value = "保养-导入模板下载") + @GetMapping("/downTemplate") + public Result downImport(HttpServletResponse response) throws IOException { + // 设置输出的格式 + // 循环取出流中的数据 + try (InputStream stream = ResourceUtil.getStream("excelTemplate/保养台账导入模板.xlsx")) { + response.setCharacterEncoding("utf-8"); + response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("保养台账导入模板", "utf-8")); + response.setContentType("application/x-xls;"); + response.setHeader("content-type", "application/octet-stream"); + byte[] b = new byte[1024 * 10]; + int len; + while ((len = stream.read(b)) > 0) { + response.getOutputStream().write(b, 0, len); + } + } catch (IORuntimeException e){ + e.printStackTrace(); + return Result.error("文件不存在!"); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("导出异常!"); + } + return Result.ok(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepPlanController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepPlanController.java new file mode 100644 index 0000000..dda9eb1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepPlanController.java @@ -0,0 +1,283 @@ +package com.gci.boot.modules.vehicles.controller; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.msg.enums.SenderTypeEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.entity.TbUpkeepBill; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan; +import com.gci.boot.modules.vehicles.enums.UpkeepPlanStatusEnumEmployee; +import com.gci.boot.modules.vehicles.enums.UpkeepPlanStatusEnumLeader; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper; +import com.gci.boot.modules.vehicles.service.ITbUpkeepPlanService; +import com.gci.boot.modules.vehicles.vo.CancelVO; +import com.gci.boot.modules.vehicles.vo.UpkeepInfoListVO; +import com.gci.boot.modules.vehicles.vo.UpkeepPlanObjectVO; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.checkerframework.checker.units.qual.A; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@Api(tags="保养计划") +@Slf4j +@RestController +@RequestMapping("/vehicles/upkeepPlan") +public class UpKeepPlanController { + + @Autowired + private ITbUpkeepPlanService upkeepPlanService; + @Autowired + private IProjectsService projectsService; + @Autowired + private ISysUserService sysUserService; + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private TbUpkeepPlanMapper upkeepPlanMapper; + @Autowired + private MsgPushService msgPushService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("保养计划-分页列表查询") + @GetMapping(value = "/list") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper.findUpkeepPlanList"}) + public Result queryPageList(TbUpkeepPlan tbUpkeepPlan, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + + Page page = new Page(pageNo, pageSize); + IPage pageList = upkeepPlanService.getUpkeepPlanList(page, tbUpkeepPlan); + return Result.ok(pageList); + } + + /** + * 添加 + */ + @AddSysLog("保养计划-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbUpkeepPlan tbUpkeepPlan) { + Projects projects = projectsService.getById(tbUpkeepPlan.getProjectId()); + if(Objects.nonNull(projects)){ + tbUpkeepPlan.setProjectName(projects.getProjectName()); + } + //手动生成 + tbUpkeepPlan.setSaveType(2); + tbUpkeepPlan.setAuditStatus("1"); + tbUpkeepPlan.setPlanSaveTime(new Date()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String username = ""; + if(Objects.nonNull(sysUser)){ + username = sysUser.getUsername(); + } + if(Objects.nonNull(tbUpkeepPlan.getAttachmentList()) && tbUpkeepPlan.getAttachmentList().size()>0){ + tbUpkeepPlan.setAttachmentJson(JSONUtil.toJsonPrettyStr(tbUpkeepPlan.getAttachmentList())); + } + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + tbUpkeepPlan.setOrderNo(format); + + tbUpkeepPlan.setCreateBy(username); + upkeepPlanService.save(tbUpkeepPlan); + //推送微信消息 + ThreadUtil.execAsync(()->{ + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),tbUpkeepPlan.getId(), + tbUpkeepPlan.getProjectId(), WorkOrderType.UPKEEP_PLAN.getType(),"未审批", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + return Result.ok("添加成功!"); + } + + /** + * 编辑 + */ + @AddSysLog("保养计划-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbUpkeepPlan tbUpkeepPlan) { + Projects projects = projectsService.getById(tbUpkeepPlan.getProjectId()); + if(Objects.nonNull(projects)){ + tbUpkeepPlan.setProjectName(projects.getProjectName()); + } + //审核未通过的编辑-》状态跳回未审核? + TbUpkeepPlan one = upkeepPlanService.getById(tbUpkeepPlan.getId()); + + if("3".equals(one.getAuditStatus())){ + tbUpkeepPlan.setAuditStatus("1"); + } + if(Objects.nonNull(tbUpkeepPlan.getAttachmentList()) && tbUpkeepPlan.getAttachmentList().size()>0){ + tbUpkeepPlan.setAttachmentJson(JSONUtil.toJsonPrettyStr(tbUpkeepPlan.getAttachmentList())); + } + upkeepPlanService.updateById(tbUpkeepPlan); + return Result.ok("编辑成功!"); + } + + /** + * 删除 + */ + @AddSysLog("保养计划-删除") + @DeleteMapping(value = "/realDelete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + upkeepPlanService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * 作废 + */ + @AddSysLog("保养计划-作废") + @PostMapping(value = "/cancel") + public Result cancel(@RequestBody CancelVO vo) { + String arg = StringUtil.checkString(vo.getCancelIdea(),200); + if(StrUtil.isNotBlank(arg)){ + return Result.error(101,"作废原因 " + arg); + } + String realName = ""; + if(StrUtil.isNotBlank(vo.getRealname())){ + realName = vo.getRealname(); + }else{ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + } + //批量作废 + List ids = Arrays.asList(vo.getId().split(",")); + for(String oneId : ids){ + upkeepPlanService.update(new LambdaUpdateWrapper().eq(TbUpkeepPlan::getId,oneId) + .set(TbUpkeepPlan::getAuditStatus,"4") + .set(TbUpkeepPlan::getCancelIdea,vo.getCancelIdea()) + .set(TbUpkeepPlan::getCancelPeople,realName) + .set(TbUpkeepPlan::getCancelTime,new Date())); + } + return Result.ok("作废成功!"); + } + + + /** + * 导出 + * @return + */ + @AddSysLog("保养计划-导出") + @GetMapping("/export") + @DataPermission(item="A.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper.findUpkeepAllList"}) + public Result export(TbUpkeepPlan tbUpkeepPlan, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "保养计划表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + List list = upkeepPlanMapper.findUpkeepAllList(tbUpkeepPlan); + EasyExcel.write(output, TbUpkeepPlan.class).sheet("保养计划").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + + /** + * 根据保养单id获取保养计划弹窗详情 + */ + @AddSysLog("保养计划-根据保养单id获取保养计划弹窗详情") + @GetMapping(value = "/getUpkeepPlanObjectById") + public Result getUpkeepPlanObjectById(String id) { + UpkeepPlanObjectVO vo = upkeepPlanService.getUpkeepPlanObjectById(id); + return Result.ok(vo); + } + + /** + * 保养计划审核提交 + */ + @AddSysLog("保养计划-保养计划审核提交") + @PostMapping(value = "/submitUpkeepPlan") + public Result submitUpkeepPlan(@RequestBody @Validated(SaveValidated.class) UpkeepPlanObjectVO vo) { + + if(redisTemplate.hasKey(vo.getId()+"_submitUpkeepPlan")){ + return Result.error(101,"该保养计划正在被操作中,无法操作,请刷新!"); + }else{ + redisTemplate.opsForValue().set(vo.getId()+"_submitUpkeepPlan", vo.getId(), 10, TimeUnit.SECONDS); + } + + String result = ""; + try { + result = upkeepPlanService.submitUpkeepPlan(vo); + }catch (Exception e){ + e.printStackTrace(); + return Result.error(101,"提交失败:" + e.getMessage()); + }finally { + redisTemplate.delete(vo.getId()+"_submitUpkeepPlan"); + } + if(StrUtil.isNotBlank(result)){ + return Result.error(101,result); + } + return Result.ok("提交成功!"); + } + + /** + * 规则生成保养计划 + */ + @AddSysLog("保养计划-规则生成保养计划") + @GetMapping(value = "/ruleCreatePlan") + public Result ruleCreatePlan() { + String str = upkeepPlanService.ruleCreatePlan(); + return Result.ok(str); + } + + /** + * 定时任务 规则生成保养计划 每天凌晨1点 + */ + @Scheduled(cron = "0 0 1 * * ?") + public void scheduledRuleCreatePlan() { + upkeepPlanService.ruleCreatePlan(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepRuleController.java b/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepRuleController.java new file mode 100644 index 0000000..032e57d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/controller/UpKeepRuleController.java @@ -0,0 +1,184 @@ +package com.gci.boot.modules.vehicles.controller; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.service.ITbUpkeepRuleService; +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; +import java.util.Objects; + +@Api(tags="保养规则") +@Slf4j +@RestController +@RequestMapping("/vehicles/upkeepRule") +public class UpKeepRuleController { + + @Autowired + private ITbUpkeepRuleService upkeepRuleService; + + /** + * 分页列表查询 + * + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AddSysLog("保养规则-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(TbUpkeepRule tbUpkeepRule, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + Page page = new Page(pageNo, pageSize); + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbUpkeepRule.class, tbUpkeepRule); + lambdaQueryWrapper.orderByDesc(TbUpkeepRule::getCreateTime); + IPage pageList = upkeepRuleService.page(page, lambdaQueryWrapper); + return Result.ok(pageList); + } + + /** + * 添加 + */ + @AddSysLog("保养规则-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody @Validated(SaveValidated.class) TbUpkeepRule tbUpkeepRule) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(TbUpkeepRule::getVehicleBrand,tbUpkeepRule.getVehicleBrand()) + .eq(TbUpkeepRule::getVehicleModel,tbUpkeepRule.getVehicleModel()) + .eq(TbUpkeepRule::getVehicleType,tbUpkeepRule.getVehicleType()) + .eq(TbUpkeepRule::getRuleType,tbUpkeepRule.getRuleType()); + int count = upkeepRuleService.count(lambdaQueryWrapper); + if(count > 0){ + return Result.error(101,"存在相同的 车种、车型、品牌 规则,请修改!"); + }else{ + LambdaQueryWrapper nameQuery = new LambdaQueryWrapper<>(); + nameQuery.eq(TbUpkeepRule::getName,tbUpkeepRule.getName()); + int nameCount = upkeepRuleService.count(nameQuery); + if(nameCount > 0){ + return Result.error(101,"存在相同的规则名称,请修改!"); + } + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String username = ""; + if(Objects.nonNull(sysUser)){ + username = sysUser.getUsername(); + if(StrUtil.isBlank(tbUpkeepRule.getCreateBy())){ + tbUpkeepRule.setCreateBy(username); + } + } + + upkeepRuleService.save(tbUpkeepRule); + return Result.ok("添加成功!"); + } + } + + /** + * 编辑 + */ + @AddSysLog("保养规则-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody @Validated(UpdateValidated.class) TbUpkeepRule tbUpkeepRule) { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(TbUpkeepRule::getVehicleBrand,tbUpkeepRule.getVehicleBrand()) + .eq(TbUpkeepRule::getVehicleModel,tbUpkeepRule.getVehicleModel()) + .eq(TbUpkeepRule::getVehicleType,tbUpkeepRule.getVehicleType()) + .eq(TbUpkeepRule::getRuleType,tbUpkeepRule.getRuleType()) + .ne(TbUpkeepRule::getId,tbUpkeepRule.getId()); + int count = upkeepRuleService.count(lambdaQueryWrapper); + if(count > 0){ + return Result.error(101,"存在相同的 车种、车型、品牌 规则,请修改!"); + }else{ + LambdaQueryWrapper nameQuery = new LambdaQueryWrapper<>(); + nameQuery.eq(TbUpkeepRule::getName,tbUpkeepRule.getName()).ne(TbUpkeepRule::getId,tbUpkeepRule.getId()); + int nameCount = upkeepRuleService.count(nameQuery); + if(nameCount > 0){ + return Result.error(101,"存在相同的规则名称,请修改!"); + } + upkeepRuleService.updateById(tbUpkeepRule); + return Result.ok("编辑成功!"); + } + } + + /** + * 删除 + */ + @AddSysLog("保养规则-删除") + @DeleteMapping(value = "/realDelete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + upkeepRuleService.removeById(id); + return Result.ok("删除成功!"); + } + + /** + * 禁用 + */ + @AddSysLog("保养规则-禁用") + @DeleteMapping(value = "/cancel") + public Result cancel(@RequestParam(name = "id", required = true) String id) { + upkeepRuleService.update(new LambdaUpdateWrapper().eq(TbUpkeepRule::getId,id).set(TbUpkeepRule::getRuleStatus,2)); + return Result.ok("禁用成功!"); + } + + /** + * 启用 + */ + @AddSysLog("保养规则-启用") + @DeleteMapping(value = "/unCancel") + public Result unCancel(@RequestParam(name = "id", required = true) String id) { + upkeepRuleService.update(new LambdaUpdateWrapper().eq(TbUpkeepRule::getId,id).set(TbUpkeepRule::getRuleStatus,1)); + return Result.ok("启用成功!"); + } + + /** + * 导出 + * @return + */ + @AddSysLog("保养规则-导出") + @GetMapping("/export") + public Result export(TbUpkeepRule tbUpkeepRule, HttpServletResponse response){ + try (OutputStream output = response.getOutputStream()){ + + String fileName = "保养规则表.xlsx"; + try { + fileName = URLEncoder.encode(fileName, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); + + LambdaQueryWrapper lambdaQueryWrapper = QueryGenerator.initQueryWrapper(TbUpkeepRule.class, tbUpkeepRule); + List list = upkeepRuleService.list(lambdaQueryWrapper); + EasyExcel.write(output, TbUpkeepRule.class).sheet("保养规则").doWrite(list); + + } catch (IOException e) { + return Result.error("导出错误!"); + } + return Result.ok(); + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInfo.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInfo.java new file mode 100644 index 0000000..2d2596d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInfo.java @@ -0,0 +1,230 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import cn.afterturn.easypoi.excel.annotation.ExcelEntity; +import com.baomidou.mybatisplus.annotation.*; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +/** + *

+ * 事故信息基础表 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@Data +@TableName("tb_accident_info") +@ApiModel(value = "TbAccidentInfo对象", description = "事故信息基础表") +@TableRepeat(aClass = TbAccidentInfo.class,groups = {SaveValidated.class,UpdateValidated.class}) +public class TbAccidentInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @JsonPropertyDescription("id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @SelectQuery + @Pattern(message = "车牌号格式错误!",regexp = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "车牌号",orderNum = "0") + private String plateNumber; + + @ApiModelProperty("所属项目") + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @Excel(name = "所属项目",dict = "tb_projects,project_name,id",orderNum = "1") + private String projectId; + + @ApiModelProperty("处理人") + @NotBlank(message = "处理人不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "处理人",orderNum = "2") + private String processedPerson; + + @ApiModelProperty("事故号") + @Size(max = 32,message = "事故号不能超过32位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "事故号",orderNum = "3") + @FieldRepeat(message = "事故号不能重复!") + private String reportNumber; + + @ApiModelProperty("事故发生时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @NotNull(message = "事故发生时间不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "事故发生时间",format = "yyyy-MM-dd HH:mm:ss",orderNum = "4") + private Date accidentTime; + + @ApiModelProperty("驾驶员") + @Size(max = 32,message = "驾驶员名称不能超过32位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "驾驶员",orderNum = "5") + private String driver; + + @ApiModelProperty("驾驶员证件号") + @Size(max = 32,message = "驾驶员证件号不能超过32位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "驾驶员证件号",orderNum = "6") + private String driverLicenseNumber; + + @ApiModelProperty("驾驶员电话") + @Pattern(regexp = "^$|^(?:(?:\\+|00)86)?1\\d{10}$",message = "驾驶员电话格式错误!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "驾驶员电话",orderNum = "7") + private String driverPhoneNumber; + + @ApiModelProperty("第三方车牌号") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Pattern(message = "第三方车牌号格式错误!",regexp = "^$|^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "第三方车牌号",orderNum = "8") + private String thirdPlateNumber; + + @ApiModelProperty("第三方保险公司") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Size(max = 32,message = "第三方保险公司不能超过32位字符!") + @Excel(name = "第三方保险公司",orderNum = "9") + private String thirdInsuranceCompany; + + @ApiModelProperty("第三方电话号码") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Pattern(regexp = "^$|^(?:(?:\\+|00)86)?1\\d{10}$",message = "第三方电话格式错误!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "第三方电话号码",orderNum = "10") + private String thirdPhoneNumber; + + @ApiModelProperty("事故发生地点") + @NotBlank(message = "事故发生地点不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Size(max = 64,message = "事故发生地点不能超过64位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "事故发生地点",orderNum = "11") + private String accidentLocation; + + @ApiModelProperty("事故发生经过") + @NotBlank(message = "事故发生经过不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Size(max = 512,message = "事故发生经过不能超过512位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "事故发生经过",orderNum = "12") + private String accidentDetails; + + @ApiModelProperty("事故预估损失") + @NotBlank(message = "事故预估损失不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Size(max = 512,message = "事故预估损失不能超过512位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "事故预估损失",orderNum = "13") + private String accidentEstimatedLoss; + + @ApiModelProperty("需要更换的配件") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Size(max = 32,message = "需要更换配件描述不能超过32位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "需要更换的配件",orderNum = "14") + private String replacedParts; + + @ApiModelProperty("事故发生类型") + @Dict(dicCode = "accident_form") + @Excel(name = "事故发生类型",dict = "accident_form",orderNum = "15") + private String accidentForm; + + @ApiModelProperty("事故发生类型其他描述") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Size(max = 16,message = "事故发生类似其他描述不能超过16位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "事故发生其他类型描述",orderNum = "16") + private String accidentFormOther; + + @ApiModelProperty("事故类型") + @Dict(dicCode = "accident_type") + @Excel(name = "事故类型",dict = "accident_type",orderNum = "17") + private String accidentType; + + @ApiModelProperty("事故伤亡类型") + @Dict(dicCode = "accident_injury_type") + @Excel(name = "事故伤亡类型",dict = "accident_injury_type",orderNum = "18") + private String accidentInjuryType; + + @ApiModelProperty("初步预估责任") + @Dict(dicCode = "liability_type") + @Excel(name = "初步预估责任",dict = "liability_type",orderNum = "19") + private String liabilityEstimate; + + @ApiModelProperty("初步预估性质") + @Dict(dicCode = "nature_type") + @Excel(name = "初步预估责任",dict = "nature_type",orderNum = "20") + private String natureEstimate; + + @ApiModelProperty("事故现场图片") + @Size(max = 5000,message = "事故现场图片文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @NotBlank(message = "事故现场图片不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @FileUrl + private String accidentScenePhoto; + + @ApiModelProperty("事故现场视频") + @Size(max = 5000,message = "事故现场视频文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String accidentSceneVideo; + + @ApiModelProperty("保险公司现场勘察报告") + @Size(max = 5000,message = "保险公司现场勘察报告图片文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @NotBlank(message = "保险公司现场勘察报告不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String insuranceInvestigationReport; + + @ApiModelProperty("事故损失类型") + @Dict(dicCode = "accident_loss_type") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Excel(name = "事故损失类型",dict = "accident_loss_type",orderNum = "21") + private String accidentLossType; + + @ApiModelProperty("事故损失类型 前端用") + @TableField(exist = false) + private List accidentLossTypeList; + + @ApiModelProperty("保险信息") + @TableField(exist = false) + @Valid + @ExcelEntity + private TbAccidentInsuranceInfo accidentInsuranceInfo = new TbAccidentInsuranceInfo(); + + @ApiModelProperty("案件进度") + @TableField(exist = false) + @Valid + @ExcelEntity + private TbAccidentProgress accidentProgress = new TbAccidentProgress(); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInsuranceInfo.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInsuranceInfo.java new file mode 100644 index 0000000..7f86e85 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentInsuranceInfo.java @@ -0,0 +1,174 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.baomidou.mybatisplus.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.*; + +/** + *

+ * 事故保险信息 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("tb_accident_insurance_info") +@ApiModel(value = "TbAccidentInsuranceInfo对象", description = "事故保险信息") +public class TbAccidentInsuranceInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("事故信息主表id") + private String infoId; + + @ApiModelProperty("交案回执单号") + @Size(max = 32,message = "交案回执单号不能超过32位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Excel(name = "交案回执单号",groupName = "保险信息",orderNum = "22") + private String caseReceiptNumber; + + @ApiModelProperty("确认事故责任") + @Dict(dicCode = "liability_type") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Excel(name = "确认事故责任",dict = "liability_type",groupName = "保险信息",orderNum = "23") + private String liabilityConfirm; + + @ApiModelProperty("确认事故性质") + @Dict(dicCode = "nature_type") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Excel(name = "确认事故性质",dict = "nature_type",groupName = "保险信息",orderNum = "27") + private String natureConfirm; + + @ApiModelProperty("标的车损失金额") + @Digits(integer = 9,fraction = 2,message = "标的车损失金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "标的车损失金额",groupName = "保险信息",orderNum = "28") + private BigDecimal vehicleLossAmount; + + @ApiModelProperty("标的车人伤金额") + @Digits(integer = 9,fraction = 2,message = "标的车人伤金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "标的车人伤金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "标的车人伤金额",groupName = "保险信息",orderNum = "29") + private BigDecimal vehiclePersonalInjuryAmount; + + @ApiModelProperty("第三方物损金额") + @Digits(integer = 9,fraction = 2,message = "第三方物损金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "第三方物损金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "第三方物损金额",groupName = "保险信息",orderNum = "30") + private BigDecimal thirdPropertyDamageAmount; + + @ApiModelProperty("第三方人伤金额") + @Digits(integer = 9,fraction = 2,message = "第三方人伤金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "第三方人伤金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "第三方人伤金额",groupName = "保险信息",orderNum = "31") + private BigDecimal thirdPersonalInjuryAmount; + + @ApiModelProperty("预估损失总金额") + @Digits(integer = 10,fraction = 2,message = "预估损失总金额整数部分不能大于10位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "预估损失总金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "预估损失总金额",groupName = "保险信息",orderNum = "32") + private BigDecimal estimatedTotalLossAmount; + + @ApiModelProperty("理赔至公司账户日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @Excel(name = "理赔至公司账户日期",format = "yyyy-MM-dd",groupName = "保险信息",orderNum = "33") + private Date claimToCompanyAccountDate; + + @ApiModelProperty("理赔至公司账户金额") + @Digits(integer = 9,fraction = 2,message = "理赔至公司账户金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "理赔至公司账户金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "理赔至公司账户金额",groupName = "保险信息",orderNum = "34") + private BigDecimal claimToCompanyAccountAmount; + + @ApiModelProperty("理赔至第三方账户日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Excel(name = "理赔至第三方账户日期",format = "yyyy-MM-dd",groupName = "保险信息",orderNum = "35") + private Date claimToThirdAccountDate; + + @ApiModelProperty("理赔至第三方账户金额") + @Digits(integer = 9,fraction = 2,message = "理赔至第三方账户金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "理赔至第三方账户金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "理赔至第三方账户金额",groupName = "保险信息",orderNum = "36") + private BigDecimal claimToThirdAccountAmount; + + @ApiModelProperty("赔偿单据图片") + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String documentImage; + + @ApiModelProperty("出险赔偿总金额") + @Digits(integer = 10,fraction = 2,message = "出险赔偿总金额部分不能大于10位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "出险赔偿总金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "出险赔偿总金额",groupName = "保险信息",orderNum = "37") + private BigDecimal totalCompensationAmount; + + @ApiModelProperty("出险未赔偿金额") + @Digits(integer = 9,fraction = 2,message = "出险未赔偿金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "出险未赔偿金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "出险未赔偿金额",groupName = "保险信息",orderNum = "38") + private BigDecimal uncompensatedAmount; + + @ApiModelProperty("案件实际发生总金额") + @Digits(integer = 10,fraction = 2,message = "案件实际发生总金额整数部分不能大于10位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "案件实际发生总金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "案件实际发生总金额",groupName = "保险信息",orderNum = "39") + private BigDecimal totalAmountActuallyIncurred; + + @ApiModelProperty("是否同步出险") + @Dict(dicCode = "yes_no") + @NotNull(message = "是否同步出险不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "是否同步出险",dict = "yes_no",groupName = "保险信息",orderNum = "24") + private String isRecord; + + @ApiModelProperty("保险公司") + @Dict(dictTable = "tb_insurance_company_archives", dicText = "name", dicCode = "id") + @Excel(name = "保险公司",dict = "tb_insurance_company_archives,name,id",groupName = "保险信息",orderNum = "25") + private String companyId; + + @ApiModelProperty("出险日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @Excel(name = "出险日期",format = "yyyy-MM-dd",groupName = "保险信息",orderNum = "26") + private Date insuranceDate; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentProgress.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentProgress.java new file mode 100644 index 0000000..b322fff --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAccidentProgress.java @@ -0,0 +1,108 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.baomidou.mybatisplus.annotation.*; + +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Size; + +/** + *

+ * 事件进度信息 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("tb_accident_progress") +@ApiModel(value = "TbAccidentProgress对象", description = "事件进度信息") +public class TbAccidentProgress implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("事故信息主表id") + private String infoId; + + @ApiModelProperty("是否结案") + @Dict(dicCode = "yes_no") + @Excel(name = "是否结案",dict = "yes_no",groupName = "案件进度",orderNum = "40") + private String caseClosed; + + @ApiModelProperty("结案时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @Excel(name = "结案时间",format = "yyyy-MM-dd",groupName = "案件进度",orderNum = "41") + private Date closingTime; + + @ApiModelProperty("备注") + @Size(max = 512,message = "备注不能超过512位字符!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "备注",groupName = "案件进度",orderNum = "42") + private String remarks; + + @ApiModelProperty("事故认定书") +// @Size(max = 5000,message = "事故认定书图片文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @TableField(updateStrategy = FieldStrategy.IGNORED) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String accidentCertificatePhoto; + + @ApiModelProperty("赔偿协议书") +// @Size(max = 5000,message = "赔偿协议书图片文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @TableField(updateStrategy = FieldStrategy.IGNORED) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String compensationAgreementPhoto; + + @ApiModelProperty("定损单") +// @Size(max = 5000,message = "定损单图片文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @TableField(updateStrategy = FieldStrategy.IGNORED) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String lossAssessmentPhoto; + + @ApiModelProperty("其他") +// @Size(max = 5000,message = "其他图片文件名过长请修改!",groups = {SaveValidated.class, UpdateValidated.class}) + @TableField(updateStrategy = FieldStrategy.IGNORED) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String otherPhoto; + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionInfo.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionInfo.java new file mode 100644 index 0000000..719d501 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionInfo.java @@ -0,0 +1,254 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; + +import cn.afterturn.easypoi.handler.inter.IExcelDataModel; +import cn.afterturn.easypoi.handler.inter.IExcelModel; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.baomidou.mybatisplus.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.ImportValidated; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.*; + +/** + *

+ * 年检信息表 + *

+ * + * @author 2464 + * @since 2023-09-20 + */ +@Data +@TableName("tb_annual_inspection_info") +@ApiModel(value = "TbAnnualInspectionInfo对象", description = "年检信息表") +@TableRepeat(aClass = TbAnnualInspectionInfo.class, + groups = {SaveValidated.class, UpdateValidated.class}) +public class TbAnnualInspectionInfo implements Serializable, IExcelModel, IExcelDataModel { + + private static final long serialVersionUID = 1L; + + @JsonPropertyDescription("id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!", groups = {UpdateValidated.class}) + private String id; + + @JsonPropertyDescription("所属机构") + private String sysOrgCode; + + @JsonPropertyDescription("创建时间") + private Date createTime; + + @JsonPropertyDescription("创建人") + private String createBy; + + @JsonPropertyDescription("更新时间") + private Date updateTime; + + @JsonPropertyDescription("更新人") + private String updateBy; + + @JsonPropertyDescription("车牌号") + @NotBlank(message = "车牌号不能为空!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Pattern(message = "车牌号格式错误!", + regexp = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$", + groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @FieldRepeat(message = "车牌号不能重复!", other = "validityPeriod") + @Excel(name = "车牌号", orderNum = "1") + private String plateNumber; + + @JsonPropertyDescription("所属项目") + @NotBlank(message = "所属项目不能为空!", groups = {SaveValidated.class, UpdateValidated.class}) + @Dict(dicCode = "id", dictTable = "tb_projects", dicText = "project_name") + @Excel(name = "所属项目", dict = "tb_projects,project_name,id", orderNum = "0") + private String projectId; + + @JsonPropertyDescription("处理人") + @NotBlank(message = "处理人不能为空!", groups = {SaveValidated.class, UpdateValidated.class}) + @Size(max = 32, message = "处理人不能超过32位字符!", groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "处理人", orderNum = "2") + private String processedPerson; + + @JsonPropertyDescription("办理日期") + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "办理日期不能为空!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @PastOrPresent(message = "办理日期必须为当天或过去的时间!", groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "办理日期", format = "yyyy-MM-dd", orderNum = "3") + private Date handlingDate; + + @JsonPropertyDescription("年检有效期") + @NotNull(message = "年检有效期不能为空!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @Future(message = "年检有效期必须为将来的时间!", groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "年检有效期", format = "yyyy-MM-dd", orderNum = "4") + private Date validityPeriod; + + @JsonPropertyDescription("年检地点") + @Size(max = 64, message = "年检地点不能超过64位字符!", + groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Excel(name = "年检地点", orderNum = "5") + private String location; + + @JsonPropertyDescription("年检人员") + @Excel(name = "年检人员",orderNum = "5") + @Size(max = 32, message = "年检人员不能超过32位字符!", + groups = {SaveValidated.class, UpdateValidated.class}) + private String personnel; + + @JsonPropertyDescription("年检项目") + @Excel(name = "年检项目",orderNum = "5") + @Size(max = 32, message = "年检项目不能超过32位字符!", + groups = {SaveValidated.class, UpdateValidated.class}) + private String items; + + @JsonPropertyDescription("备注") + @Size(max = 500, message = "备注不能超过500位字符!", groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "备注", orderNum = "6") + private String remark; + + @JsonPropertyDescription("检测费") + @Digits(integer = 9, fraction = 2, message = "检测费金额整数部分不能大于9位,小数部分不能大于2位", + groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Min(value = 0, message = "检测费最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @NotNull(message = "检测费不能为空!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Excel(name = "检测费", orderNum = "7") + private BigDecimal testingFee; + + @JsonPropertyDescription("手续费") + @Digits(integer = 9, fraction = 2, message = "手续费金额整数部分不能大于9位,小数部分不能大于2位", + groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Min(value = 0, message = "手续费最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @NotNull(message = "手续费不能为空!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Excel(name = "手续费", orderNum = "8") + private BigDecimal serviceFee; + + @JsonPropertyDescription("杂费") + @Digits(integer = 9, fraction = 2, message = "杂费金额整数部分不能大于9位,小数部分不能大于2位", + groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Min(value = 0, message = "杂费最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @NotNull(message = "杂费不能为空!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Excel(name = "杂费", orderNum = "9") + private BigDecimal miscellaneousFee; + + @JsonPropertyDescription("费用合计") + @Digits(integer = 10, fraction = 2, message = "费用合计金额整数部分不能大于10位,小数部分不能大于2位", + groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0, message = "费用合计最小值为0!", groups = {SaveValidated.class, UpdateValidated.class}) + @NotNull(message = "费用合计不能为空!", groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "费用合计", orderNum = "10") + private BigDecimal totalFee; + + @JsonPropertyDescription("行驶证") + @Size(max = 5000, message = "行驶证图片文件名过长请修改!", groups = {SaveValidated.class, UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String drivingLicense; + + @JsonPropertyDescription("车辆合格标") + @Size(max = 5000, message = "车辆合格标图片文件名过长请修改!", groups = {SaveValidated.class, UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String vehicleQualificationMark; + + @JsonPropertyDescription("年检费用明细表") + @Size(max = 5000, message = "年检费用明细表图片文件名过长请修改!", groups = {SaveValidated.class, UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String detailsTable; + + @JsonPropertyDescription("其他") + @Size(max = 5000, message = "其他图片文件名过长请修改!", groups = {SaveValidated.class, UpdateValidated.class}) + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String other; + + @ApiModelProperty("来源(1车辆档案,2采购交车)") + @ExcelIgnore + private String sourceType; + + @Dict(dicCode = "vehicle_type") + @TableField(exist = false) + @JsonPropertyDescription("车辆种类") + @Excel(name = "车辆种类", dict = "vehicle_type", orderNum = "2") + private String vehicleType; + + @JsonPropertyDescription("逾期类型") + @TableField(exist = false) + @Dict(dicCode = "overdue_type") + @Excel(name = "逾期类型", dict = "overdue_type", orderNum = "11") + private String overdueType; + + @JsonPropertyDescription("将要逾期天数") + @TableField(exist = false) + @Excel(name = "将要逾期天数", orderNum = "12") + private Integer daysToOverdue = 0; + + @JsonPropertyDescription("逾期天数") + @TableField(exist = false) + @Excel(name = "逾期天数", orderNum = "13") + private Integer overdueDays = 0; + + @JsonPropertyDescription("天数") + @TableField(exist = false) + private Integer days; + + @JsonPropertyDescription("违章未处理数") + @TableField(exist = false) + private Integer violationCount; + + @JsonPropertyDescription("事故未处理数") + @TableField(exist = false) + private Integer accidentCount; + + @ApiModelProperty("删除标志") + private Integer delFlag; + + @TableField(exist = false) + private int rowNum; + + @TableField(exist = false) + @Excel(name = "错误信息",width = 20) + private String errorMsg; + + @Override + public Integer getRowNum() { + return rowNum; + } + + @Override + public void setRowNum(Integer integer) { + this.rowNum = integer; + } + + @Override + public String getErrorMsg() { + return errorMsg; + } + + @Override + public void setErrorMsg(String s) { + this.errorMsg = s; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionRemind.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionRemind.java new file mode 100644 index 0000000..d6e3ea3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbAnnualInspectionRemind.java @@ -0,0 +1,110 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +/** + *

+ * 年检提醒 + *

+ * + * @author 2464 + * @since 2023-11-16 + */ +@Getter +@Setter +@TableName("tb_annual_inspection_remind") +@ApiModel(value = "TbAccidentInsuranceRemind对象", description = "年检提醒") +public class TbAnnualInspectionRemind implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("车牌号") + @Excel(name = "车牌号",orderNum = "0") + private String plateNumber; + + @ApiModelProperty("年审有效期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @Excel(name = "年审有效期",format = "yyyy-MM-dd",width = 15,orderNum = "2") + private Date validityPeriod; + + /** + * 1-将要逾期 + * 2-已逾期 + */ + @ApiModelProperty("逾期状态") + @Dict(dicCode = "overdue_type") + @Excel(name = "逾期状态",dict = "overdue_type",width = 15,orderNum = "3") + private String overdueType; + + @ApiModelProperty("将要逾期天数") + @Excel(name = "将要逾期天数",width = 15,orderNum = "4") + private Integer daysToOverdue; + + @ApiModelProperty("逾期天数") + @Excel(name = "逾期天数",width = 15,orderNum = "5") + private Integer overdueDays; + + /** + * 1-提醒中 + * 0-已过期 + */ + @ApiModelProperty("提醒状态 1-提醒中 0-已过期") + @Dict(dicCode = "remind_status") + @Excel(name = "提醒状态",dict = "remind_status",width = 15,orderNum = "6") + private String remindStatus; + + @ApiModelProperty("年检台账id") + private String infoId; + + @ApiModelProperty("删除标志") + private Integer delFlag; + + @Dict(dicCode = "vehicle_type") + @TableField(exist = false) + @JsonPropertyDescription("车辆种类") + @Excel(name = "车辆种类",dict = "vehicle_type",width = 15,orderNum = "1") + private String vehicleType; + + @JsonPropertyDescription("违章未处理数") + @TableField(exist = false) + private Integer violationCount; + + @JsonPropertyDescription("事故未处理数") + @TableField(exist = false) + private Integer accidentCount; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplate.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplate.java new file mode 100644 index 0000000..7a14bde --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplate.java @@ -0,0 +1,86 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + *

+ * 耗材模板 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Getter +@Setter +@TableName("tb_consumables_template") +@ApiModel(value = "TbConsumablesTemplate对象", description = "耗材模板") +@TableRepeat(aClass = TbConsumablesTemplate.class,groups = {SaveValidated.class,UpdateValidated.class}) +public class TbConsumablesTemplate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + private String id; + + @ApiModelProperty("车辆种类") + @NotBlank(message = "车辆种类不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "vehicle_type") + @FieldRepeat(message = "相同项目内车辆种类不能重复!",other = "projectId") + private String vehicleType; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @ExcelProperty(value = "更新人",converter = DictConverter.class) + private String updateBy; + + @ApiModelProperty("所属项目id") + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + private String projectId; + + @TableField(exist = false) + @Valid + @NotEmpty(message = "耗材列表不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private List partList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplateOutPart.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplateOutPart.java new file mode 100644 index 0000000..6b6e79b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplateOutPart.java @@ -0,0 +1,116 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @author 24642 + */ +@Getter +@Setter +@TableName("tb_consumables_template_out_part") +@ApiModel(value = "TbConsumablesTemplatePart对象", description = "耗材出库") +public class TbConsumablesTemplateOutPart implements Serializable { + + private static final long serialVersionUID = 1L; + + @JsonPropertyDescription("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @Excel(name = "更新时间",format = "yyyy-MM-dd HH:mm:ss",orderNum = "10") + private Date updateTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @Excel(name = "更新人",dict = "sys_user,username,realname",orderNum = "9") + private String updateBy; + + @TableField(exist = false) + @Excel(name = "所属项目",dict = "tb_projects,project_name,id",orderNum = "0") + private String projectId; + + @ApiModelProperty("名称") + @TableField(exist = false) + @Excel(name = "名称",orderNum = "1") + private String name; + + @TableField(exist = false) + @Excel(name = "入库数量",orderNum = "2") + private Integer quantity; + + @ApiModelProperty("单位") + @TableField(exist = false) + @Excel(name = "单位",orderNum = "3") + private String units; + + @ApiModelProperty("规格") + @TableField(exist = false) + @Excel(name = "规格",orderNum = "4") + private String specification; + + @Excel(name = "供应商",orderNum = "5") + @TableField(exist = false) + private String supplier; + + @ApiModelProperty("出库时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "出库时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "出库时间",format = "yyyy-MM-dd",orderNum = "6") + private Date outStorageTime; + + @ApiModelProperty("出库数量") + @NotNull(message = "出库数量不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Min(value = 1,message = "出库数量最小值为1",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "出库数量",orderNum = "7") + private Integer outQuantity; + + @ApiModelProperty("经办人") + @NotBlank(message = "经办人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "经办人不能超过32位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "出库经办人",orderNum = "8") + private String outResponsiblePerson; + + @ApiModelProperty("入库记录id") + @NotBlank(message = "入库对应id不能为空!",groups = {SaveValidated.class}) + private String partId; + + + + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplatePart.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplatePart.java new file mode 100644 index 0000000..2b9fa81 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbConsumablesTemplatePart.java @@ -0,0 +1,179 @@ +package com.gci.boot.modules.vehicles.entity; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.*; + +/** + *

+ * 耗材详情 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Getter +@Setter +@TableName("tb_consumables_template_part") +@ApiModel(value = "TbConsumablesTemplatePart对象", description = "耗材详情") +@TableRepeat(aClass = TbConsumablesTemplatePart.class,groups = {SaveValidated.class,UpdateValidated.class}) +public class TbConsumablesTemplatePart implements Serializable { + + private static final long serialVersionUID = 1L; + + @JsonPropertyDescription("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("名称") + @NotBlank(message = "耗材名称不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Length(max = 64,message = "耗材名称不能超过64位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @SelectQuery + @Excel(name = "耗材名称",orderNum = "2") + private String name; + + @ApiModelProperty("规格") + @NotBlank(message = "规格不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 64,message = "规格不能超过64位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "规格",orderNum = "7") + private String specification; + + @ApiModelProperty("排序") + private Integer sort; + + @ApiModelProperty("模板id") + private String templateId; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @Excel(name = "更新时间",format = "yyyy-MM-dd HH:mm:ss",orderNum = "14") + private Date updateTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新人") + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + @Excel(name = "更新人",dict = "sys_user,realname,username",orderNum = "13") + private String updateBy; + + @ApiModelProperty("所属项目id") + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @FieldRepeat(message = "所属项目,耗材名称,入库时间,规格,供应商不能重复!",other = "name,storageTime,supplier,specification") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @OrderQuery + @Excel(name = "所属项目",dict = "tb_projects,project_name,id",orderNum = "1") + private String projectId; + + @ApiModelProperty("入库数量") + @NotNull(message = "入库数量不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Max(value = 2147483647,message = "入库数量最大值不能超过2147483647!",groups = {SaveValidated.class,UpdateValidated.class}) + @Min(value = 0,message = "入库数量最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "入库数量",orderNum = "3") + private Integer quantity; + + @ApiModelProperty("单位") + @Dict(dicCode = "units") + @NotBlank(message = "单位不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "单位",dict = "units",orderNum = "6") + private String units; + + @ApiModelProperty("入库时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "入库时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "入库时间",format = "yyyy-MM-dd",orderNum = "12") + private Date storageTime; + + @TableField(exist = false) + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @SelectQuery(PropName = "storageTime",Type = SelectQuery.SelectType.BETWEEN) + private List time; + + @ApiModelProperty("经办人") + @NotBlank(message = "经办人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "经办人不能超过32位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "经办人",orderNum = "10") + private String responsiblePerson; + + @ApiModelProperty("供应商") + @NotBlank(message = "供应商不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "供应商不能超过32位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "供应商",orderNum = "11") + private String supplier; + + @ApiModelProperty("单价") + @NotNull(message = "单价不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Min(value = 0,message = "单价最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Digits(integer = 10,fraction = 2,message = "单价整数部分不能大于10位,小数部分不能大于2位!") + @Excel(name = "单价",numFormat = "#.##",orderNum = "8") + private BigDecimal unitPrice; + + @ApiModelProperty("总价") + @NotNull(message = "总价不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Min(value = 0,message = "总价最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @Digits(integer = 10,fraction = 2,message = "单价整数部分不能大于10位,小数部分不能大于2位!") + @Excel(name = "总价",numFormat = "#.##",orderNum = "9") + private BigDecimal totalPrice; + + @ApiModelProperty("库存数量") + @Excel(name = "库存数量",orderNum = "5") + private Integer remainingQuantity; + + @ApiModelProperty("出库数量总计") + @TableField(exist = false) + @Excel(name = "出库数量",orderNum = "4") + private Integer outQuantityCount = 0; + + @ApiModelProperty("备注") + @Length(max = 500,message = "备注不能超过500字符!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "备注",orderNum = "15") + private String remark; + + @ApiModelProperty("出库记录") + @TableField(exist = false) + private List outPartList; + + /** + * 库存数量查询 + */ + @TableField(exist = false) + @SelectQuery(Type = SelectQuery.SelectType.GE,PropName = "remainingQuantity") + private Integer remainingQuantityStart; + @TableField(exist = false) + @SelectQuery(Type = SelectQuery.SelectType.LE,PropName = "remainingQuantity") + private Integer remainingQuantityEnd; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplate.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplate.java new file mode 100644 index 0000000..458684f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplate.java @@ -0,0 +1,80 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; + +/** + *

+ * 定制件模板 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Getter +@Setter +@TableName("tb_customized_template") +@ApiModel(value = "TbCustomizedTemplate对象", description = "定制件模板") +@TableRepeat(aClass = TbCustomizedTemplate.class,groups = {SaveValidated.class,UpdateValidated.class}) +public class TbCustomizedTemplate implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + private String id; + + @ApiModelProperty("车辆种类") + @NotBlank(message = "车辆种类不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "vehicle_type") + @FieldRepeat(message = "相同项目内车辆种类不能重复!",other = "projectId") + private String vehicleType; + + @ApiModelProperty("备注") + private String remark; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("所属项目id") + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + private String projectId; + + @TableField(exist = false) + @Valid + @NotEmpty(message = "定制件列表不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private List partList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplatePart.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplatePart.java new file mode 100644 index 0000000..e8b964a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbCustomizedTemplatePart.java @@ -0,0 +1,100 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + *

+ * 定制件详情表 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Getter +@Setter +@TableName("tb_customized_template_part") +@ApiModel(value = "TbCustomizedTemplatePart对象", description = "定制件详情表") +public class TbCustomizedTemplatePart implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + private String id; + + @ApiModelProperty("名称") + @NotBlank(message = "定制件名称不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Length(max = 64,message = "定制件名称不能超过64位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + private String name; + + @ApiModelProperty("规格") + @NotBlank(message = "规格不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 64,message = "规格不能超过64位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + private String specification; + + @ApiModelProperty("排序") + @NotNull(message = "排序不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private Integer sort; + + @ApiModelProperty("模板id") + private String templateId; + + @ApiModelProperty("所属机构") + private String sysOrgCode; + + @ApiModelProperty("创建时间") + private Date createTime; + + @ApiModelProperty("更新时间") + private Date updateTime; + + @ApiModelProperty("创建人") + private String createBy; + + @ApiModelProperty("更新人") + private String updateBy; + + @ApiModelProperty("数量") + @NotNull(message = "数量不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Max(value = 2147483647,message = "数量最大值不能超过2147483647!",groups = {SaveValidated.class,UpdateValidated.class}) + @Min(value = 0,message = "数量最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + private Integer quantity; + + @ApiModelProperty("单位") + @Dict(dicCode = "units") + @NotBlank(message = "单位不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String units; + + @ApiModelProperty("入库时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "入库时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private Date storageTime; + + @ApiModelProperty("经办人") + @NotBlank(message = "经办人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "经办人不能超过32位字符!",groups = {SaveValidated.class,UpdateValidated.class}) + private String responsiblePerson; + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsurance.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsurance.java new file mode 100644 index 0000000..ed28ea5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsurance.java @@ -0,0 +1,328 @@ +package com.gci.boot.modules.vehicles.entity; + +import java.io.Serializable; +import java.util.Date; +import java.util.Objects; + +import javax.validation.constraints.NotBlank; + +import cn.hutool.core.date.DateUtil; +import com.gci.boot.modules.vehicles.vo.InsuranceImportVO; +import org.hibernate.validator.constraints.Length; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 保险信息 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Getter +@Setter +@TableName("tb_insurance") +@ApiModel(value = "TbInsurance对象", description = "保险信息") +@ColumnWidth(20) +public class TbInsurance implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属车辆") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleId; + + @ExcelProperty(value = "车牌号", index = 1) + @SelectQuery + private String plateNumber; + + @ApiModelProperty("所属项目") + //@ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 0) + @ExcelIgnore + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String projectId; + + @ApiModelProperty("是否购买交强险(0,1)") + @ExcelIgnore + private String hasCompulsoryInsurance; + + @ApiModelProperty("交强险保险单号") + @SelectQuery + @ExcelProperty(value = "交强险保险单号", index = 8) + private String compulsoryInsuranceNo; + + @ApiModelProperty("交强险办理日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date compulsoryCreateDate; + + @ApiModelProperty("交强险保险公司") + @ExcelProperty(value = "保险公司", converter = DictConverter.class, index = 5) + @Dict(dictTable = "tb_insurance_company_archives", dicText = "name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String compulsoryCompanyId; + + @ApiModelProperty("交强险保险金额") + @ExcelProperty(value = "交强险保险金额", index = 9) + private Double compulsoryPrice; + + @ApiModelProperty("车船税") + @ExcelProperty(value = "车船税", index = 3) + private Double vehicleVesselTax; + + @ApiModelProperty("交强险起保日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "起保日期", index = 6) + private Date compulsoryStartTime; + + @ApiModelProperty("交强险有效日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "有效日期", index = 7) + private Date compulsoryValidTime; + + @ApiModelProperty("交强险附件") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String compulsoryUrl; + + @ApiModelProperty("是否购买商业保险(0,1)") + @ExcelIgnore + private String hasCommercialInsurance; + + @ApiModelProperty("商业保险单号") + @SelectQuery + @ExcelProperty(value = "商业保险单号", index = 10) + private String commercialInsuranceNo; + + @ApiModelProperty("商业保险办理日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date commercialCreateDate; + + @ApiModelProperty("商业保险公司") + @ExcelIgnore + @Dict(dictTable = "tb_insurance_company_archives", dicText = "name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String commercialCompanyId; + + @ApiModelProperty("商业保险费合计") + @ExcelProperty(value = "商业保险费合计", index = 11) + private Double commercialPrice; + + @ApiModelProperty("商业保险起保日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date commercialStartTime; + + @ApiModelProperty("商业保险有效日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date commercialValidTime; + + @ApiModelProperty("商业保险附件") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String commercialUrl; + + @ApiModelProperty("备注") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String remark; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + + @ApiModelProperty("车辆型号") + @SelectQuery + @ExcelIgnore + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "车辆种类", converter = DictConverter.class, index = 2) + private String vehicleType; + + @ApiModelProperty("车架号") + @SelectQuery + @ExcelProperty(value = "车架号", index = 4) + private String frameNumber; + + @ApiModelProperty("所属合同") + @ExcelProperty(value = "所属合同", converter = DictConverter.class, index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_contract", dicText = "name", dicCode = "id") + private String contractId; + + + @ApiModelProperty("交强险有效日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date compulsoryValidTimeStart; + + @ApiModelProperty("交强险有效日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date compulsoryValidTimeEnd; + + @ApiModelProperty("商业保险有效日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date commercialValidTimeStart; + + @ApiModelProperty("商业保险有效日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date commercialValidTimeEnd; + //1将逾期,2已逾期 + @TableField(exist = false) + @ExcelIgnore + private Integer isOverTime; + + public Date getMaxMonth() { + if(DateUtils.compareTo(this.getCompulsoryValidTime(), this.getCommercialValidTime())>0) { + return this.getCompulsoryValidTime(); + } + return this.getCommercialValidTime(); + } + + public void init() { + /*if("0".equals(this.hasCompulsoryInsurance)) { + this.compulsoryInsuranceNo = null; + this.compulsoryCreateDate = null; + this.compulsoryCompanyId = null; + this.compulsoryPrice = null; + this.vehicleVesselTax = null; + this.compulsoryStartTime = null; + this.compulsoryValidTime = null; + this.compulsoryUrl = null; + } + if("0".equals(this.hasCommercialInsurance)) { + this.commercialInsuranceNo = null; + this.commercialCreateDate = null; + this.commercialCompanyId = null; + this.commercialPrice = null; + this.commercialStartTime = null; + this.commercialValidTime = null; + this.commercialUrl = null; + }*/ + } + + public static TbInsurance buildByImportVo(InsuranceImportVO vo){ + TbInsurance insurance = new TbInsurance(); + insurance.setVehicleId(vo.getVehicleId()); + insurance.setProjectId(vo.getProjectId()); + + + //保险公司跟有效日期 默认给交强险 + insurance.setCompulsoryCompanyId(vo.getCompulsoryCompanyId()); + insurance.setCompulsoryStartTime(DateUtil.parseDate(vo.getCompulsoryStartTime())); + insurance.setCompulsoryValidTime(DateUtil.parseDate(vo.getCompulsoryValidTime())); + + if(Objects.equals("是",vo.getHasCompulsoryInsurance())){ + insurance.setHasCompulsoryInsurance("1"); + insurance.setCompulsoryInsuranceNo(vo.getCompulsoryInsuranceNo()); + insurance.setCompulsoryCreateDate(DateUtil.parseDate(vo.getCompulsoryStartTime())); + insurance.setCompulsoryPrice(vo.getCompulsoryPrice()); + insurance.setVehicleVesselTax(vo.getVehicleVesselTax()); + } + if(Objects.equals("是",vo.getHasCommercialInsurance())){ + insurance.setHasCommercialInsurance("1"); + insurance.setCommercialInsuranceNo(vo.getCommercialInsuranceNo()); + insurance.setCommercialCreateDate(DateUtil.parseDate(vo.getCompulsoryStartTime())); + insurance.setCommercialPrice(vo.getCommercialPrice()); + //如果商业险录入了。额外把交强险内容赋值给商业险。 + insurance.setCommercialCompanyId(vo.getCompulsoryCompanyId()); + insurance.setCommercialStartTime(DateUtil.parseDate(vo.getCompulsoryStartTime())); + insurance.setCommercialValidTime(DateUtil.parseDate(vo.getCompulsoryValidTime())); + } + insurance.setSysOrgCode(vo.getSysOrgCode()); + insurance.setCreateBy(vo.getCreateBy()); + insurance.setCreateTime(new Date()); + insurance.setDelFlag(0); + insurance.setVehicleModel(vo.getVehicleModel()); + insurance.setVehicleType(vo.getVehicleType()); + insurance.setRemark(vo.getRemark()); + insurance.setContractId(vo.getContractId()); + insurance.setFrameNumber(vo.getFrameNumber()); + insurance.setPlateNumber(vo.getPlateNumber()); + return insurance; + } + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRecord.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRecord.java new file mode 100644 index 0000000..1ea8164 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRecord.java @@ -0,0 +1,290 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.*; + +/** + *

+ * 出险管理 + *

+ * + * @author xushuhan + * @since 2023-09-22 + */ +@Getter +@Setter +@TableName("tb_insurance_record") +@ApiModel(value = "TbInsuranceRecord对象", description = "出险管理") +@ColumnWidth(20) +@TableRepeat(aClass = TbInsuranceRecord.class,groups = {SaveValidated.class,UpdateValidated.class}) +public class TbInsuranceRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属车辆") + @ExcelProperty(value = "车牌号", converter = DictConverter.class, index = 1) + @Dict(dictTable = "tb_vehicle", dicText = "plate_number", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @NotBlank(message = "所属车辆不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleId; + + @ApiModelProperty("所属项目") + @ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 0) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String projectId; + + @ApiModelProperty("车辆型号") + //@ExcelProperty(value = "车辆型号", index = 2) + @ExcelIgnore + @SelectQuery + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "车辆种类", converter = DictConverter.class, index = 2) + @NotBlank(message = "车辆种类不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleType; + + @ApiModelProperty("出险日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "出险日期", index = 4) + @NotNull(message = "出险日期不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private Date insuranceDate; + + @ApiModelProperty("保险公司") + @ExcelProperty(value = "保险公司", converter = DictConverter.class, index = 3) + @Dict(dictTable = "tb_insurance_company_archives", dicText = "name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @NotBlank(message = "保险公司不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String companyId; + + @ApiModelProperty("事故号") + @ExcelProperty(value = "事故号", index = 5) + @NotBlank(message = "事故号不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @FieldRepeat(message = "事故号不能重复!") + private String insuranceNo; + + @ExcelIgnore + @ApiModelProperty("案件实际发生总金额") + @Digits(integer = 10,fraction = 2,message = "案件实际发生总金额整数部分不能大于10位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "案件实际发生总金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "案件实际发生总金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private BigDecimal insurancePrice; + + @ApiModelProperty("处理人") + @ExcelProperty(value = "处理人", index = 6) + @NotBlank(message = "处理人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String handleUser; + + @ApiModelProperty("处理结果") + @ExcelProperty(value = "处理结果", converter = DictConverter.class, index = 7) + @Dict(dicCode = "handle_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @NotBlank(message = "处理结果不能为空!") + private String handleStatus; + + @ApiModelProperty("事故认定书") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String accidentUrl; + + @ApiModelProperty("赔偿协议书") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String compensateAgreementUrl; + + @ApiModelProperty("定损单") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String lossAssessmentUrl; + + @ApiModelProperty("赔偿单据") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String compensateUrl; + + @ApiModelProperty("其他") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String otherUrl; + + @ApiModelProperty("备注") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String remark; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + @ApiModelProperty("出险日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date insuranceDateStart; + + @ApiModelProperty("出险日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date insuranceDateEnd; + + @ApiModelProperty("来源(1后台,2小程序)") + @ExcelIgnore + private String sourceType; + + @ApiModelProperty("标的车损失金额") + @Digits(integer = 9,fraction = 2,message = "标的车损失金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @NotNull(message = "标的车损失金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal vehicleLossAmount; + + @ApiModelProperty("标的车人伤金额") + @Digits(integer = 9,fraction = 2,message = "标的车人伤金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "标的车人伤金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "标的车人伤金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal vehiclePersonalInjuryAmount; + + @ApiModelProperty("第三方物损金额") + @Digits(integer = 9,fraction = 2,message = "第三方物损金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "第三方物损金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "第三方物损金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal thirdPropertyDamageAmount; + + @ApiModelProperty("第三方人伤金额") + @Digits(integer = 9,fraction = 2,message = "第三方人伤金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "第三方人伤金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "第三方人伤金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal thirdPersonalInjuryAmount; + + @ApiModelProperty("预估损失总金额") + @Digits(integer = 10,fraction = 2,message = "预估损失总金额整数部分不能大于10位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "预估损失总金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "预估损失总金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal estimatedTotalLossAmount; + + @ApiModelProperty("理赔至公司账户日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "理赔至公司账户日期不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private Date claimToCompanyAccountDate; + + @ApiModelProperty("理赔至公司账户金额") + @Digits(integer = 9,fraction = 2,message = "理赔至公司账户金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "理赔至公司账户金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "理赔至公司账户金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal claimToCompanyAccountAmount; + + @ApiModelProperty("理赔至第三方账户日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(updateStrategy = FieldStrategy.IGNORED) + @NotNull(message = "理赔至第三方账户日期不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private Date claimToThirdAccountDate; + + @ApiModelProperty("理赔至第三方账户金额") + @Digits(integer = 9,fraction = 2,message = "理赔至第三方账户金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "理赔至第三方账户金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "理赔至第三方账户金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal claimToThirdAccountAmount; + + @ApiModelProperty("出险赔偿总金额") + @Digits(integer = 10,fraction = 2,message = "出险赔偿总金额部分不能大于10位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "出险赔偿总金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "出险赔偿总金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal totalCompensationAmount; + + @ApiModelProperty("出险未赔偿金额") + @Digits(integer = 9,fraction = 2,message = "出险未赔偿金额整数部分不能大于9位,小数部分不能大于2位",groups = {SaveValidated.class, UpdateValidated.class}) + @Min(value = 0,message = "出险未赔偿金额最小值为0!",groups = {SaveValidated.class,UpdateValidated.class}) + @NotNull(message = "出险未赔偿金额不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private BigDecimal uncompensatedAmount; + + @ApiModelProperty("事故信息主表id") + @ExcelIgnore + private String infoId; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRemind.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRemind.java new file mode 100644 index 0000000..7118240 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbInsuranceRemind.java @@ -0,0 +1,214 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; + +import java.io.Serializable; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 保险提醒 + *

+ * + * @author xushuhan + * @since 2023-11-07 + */ +@Getter +@Setter +@TableName("tb_insurance_remind") +@ApiModel(value = "TbInsuranceRemind对象", description = "保险提醒") +@ColumnWidth(20) +public class TbInsuranceRemind implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属车辆") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleId; + + @ExcelProperty(value = "车牌号", index = 1) + @SelectQuery + private String plateNumber; + + @ApiModelProperty("所属项目") + @ExcelIgnore + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String projectId; + + @ApiModelProperty("是否购买交强险(0,1)") + @ExcelIgnore + private String hasCompulsoryInsurance; + + @ApiModelProperty("交强险保险单号") + @SelectQuery + @ExcelIgnore + private String compulsoryInsuranceNo; + + @ApiModelProperty("起保日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date compulsoryStartTime; + + @ApiModelProperty("有效日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "有效日期", index = 3) + private Date compulsoryValidTime; + + @ApiModelProperty("是否购买商业保险(0,1)") + @ExcelIgnore + private String hasCommercialInsurance; + + @ApiModelProperty("商业保险单号") + @SelectQuery + @ExcelIgnore + private String commercialInsuranceNo; + + @ApiModelProperty("提醒保险id") + @ExcelIgnore + private String insuranceId; + + @ApiModelProperty("提醒状态(0已过期,1提醒中)") + @ExcelProperty(value = "提醒状态", converter = DictConverter.class, index = 6) + @Dict(dicCode = "remind_status") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String status; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + + @ApiModelProperty("车辆型号") + //@ExcelProperty(value = "车辆型号", index = 2) + @ExcelIgnore + @SelectQuery + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "车辆种类", converter = DictConverter.class, index = 2) + private String vehicleType; + + @ApiModelProperty("车架号") + @SelectQuery + @ExcelIgnore + private String frameNumber; + + @ApiModelProperty("所属合同") + @ExcelProperty(value = "所属合同", converter = DictConverter.class, index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_contract", dicText = "name", dicCode = "id") + private String contractId; + + @TableField(exist = false) + @ExcelProperty(value = "到期天数", index = 4) + public String compulsorySurplusDay = "-"; + + @TableField(exist = false) + @ExcelProperty(value = "逾期天数", index = 5) + public String compulsoryOverDay = "-"; + + @TableField(exist = false) + @ExcelProperty(value = "出险次数", index = 7) + public String occurrenceNum; + + @TableField(exist = false) + @ExcelProperty(value = "本期保费(元)", index = 8) + public String currentPremium; + + @TableField(exist = false) + @ExcelProperty(value = "下期保费(元)", index = 9) + public String nextPremium; + + @TableField(exist = false) + @ExcelIgnore + public String commercialSurplusDay = "-"; + + @TableField(exist = false) + @ExcelIgnore + public String commercialOverDay = "-"; + + @ApiModelProperty("交强险有效日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date compulsoryValidTimeStart; + + @ApiModelProperty("交强险有效日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date compulsoryValidTimeEnd; + + @ApiModelProperty("商业保险有效日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date commercialValidTimeStart; + + @ApiModelProperty("商业保险有效日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date commercialValidTimeEnd; + //1将逾期,2已逾期 + @TableField(exist = false) + @ExcelIgnore + private String isOverTime; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbRefuelChargeRecord.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRefuelChargeRecord.java new file mode 100644 index 0000000..3e5b030 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRefuelChargeRecord.java @@ -0,0 +1,232 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.ImportValidated; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + *

+ * 加油充电登记 + *

+ * + * @author admin + * @since 2023-11-30 + */ +@Getter +@Setter +@TableName("tb_refuel_charge_record") +@ApiModel(value = "TbRefuelChargeRecord对象", description = "加油充电记录") +@ColumnWidth(20) +public class TbRefuelChargeRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @ExcelProperty(value = "日期", index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private Date recordDate; + + @ApiModelProperty("单号") + @ExcelProperty(value = "单号", index = 1) + @SelectQuery() + @Length(max = 64,message = "单号不能超过64位!",groups = {SaveValidated.class, UpdateValidated.class}) + private String orderNo; + + @ApiModelProperty("开始时间") + @JsonFormat(timezone = "GMT+8",pattern = "HH:mm:ss") + @DateTimeFormat("HH:mm:ss") + @org.springframework.format.annotation.DateTimeFormat(pattern="HH:mm:ss") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "开始时间", index = 2) + private Date startTime; + + @ApiModelProperty("结束时间") + @JsonFormat(timezone = "GMT+8",pattern = "HH:mm:ss") + @DateTimeFormat("HH:mm:ss") + @org.springframework.format.annotation.DateTimeFormat(pattern="HH:mm:ss") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "结束时间", index = 3) + private Date endTime; + + @ApiModelProperty("所属项目") + @ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 5) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectId; + + @ApiModelProperty("车辆id") + @ExcelIgnore + private String vehicleId; + + @ApiModelProperty("车架号") + @ExcelIgnore + + @SelectQuery() + private String frameNumber; + + @ApiModelProperty("车辆型号") + @ExcelIgnore + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类",converter = DictConverter.class, index = 8) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleType; + + @ApiModelProperty("车牌号") + @ExcelProperty(value = "车牌号", index = 6) + @SelectQuery() + private String plateNumber; + + @ApiModelProperty("燃料类型") + @Dict(dicCode = "fuel_type") + @ExcelProperty(value = "燃料类型",converter = DictConverter.class, index = 9) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String fuelType; + + @ApiModelProperty("油卡卡号") + @ExcelProperty(value = "卡号", index = 7) + @SelectQuery(Type = SelectQuery.SelectType.LIKE) + @Length(max = 32,message = "油卡卡号不能超过32位!",groups = {SaveValidated.class, UpdateValidated.class}) + private String oilCard; + + @ApiModelProperty("油品规格1:0号 车用柴油(Ⅵ),2:92号 车用汽油(ⅥB),3:95号 车用汽油(ⅥB),4:充电") + @Dict(dicCode = "oil_type") + @ExcelProperty(value = "油品规格",converter = DictConverter.class, index = 10) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String oilType; + + @ApiModelProperty("单价") + @ExcelProperty(value = "单价", index = 11) + @Min(value = 0, message = "油卡余额(元)最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Max(value = 999999, message = "油卡余额(元)最大值为999999!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @TableField(updateStrategy = FieldStrategy.IGNORED) + private BigDecimal price; + + @ApiModelProperty("数量") + @ExcelProperty(value = "数量(升/度)", index = 12) + @Min(value = 0, message = "油卡余额(元)最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Max(value = 999999, message = "油卡余额(元)最大值为999999!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + private BigDecimal amount; + + @ApiModelProperty("金额") + @ExcelProperty(value = "金额(元)", index = 13) + @Min(value = 0, message = "油卡余额(元)最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Max(value = 999999, message = "油卡余额(元)最大值为999999!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + private BigDecimal totalPrice; + + @ApiModelProperty("加油(充电)时里程km") + @ExcelProperty(value = "加油(充电)时里程(km)", index = 14) + @Min(value = 0, message = "油卡余额(元)最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Max(value = 999999, message = "油卡余额(元)最大值为999999!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + private BigDecimal mileage; + + @ApiModelProperty("备注") + @ExcelProperty(value = "备注", index = 15) + @Length(max = 1000,message = "备注不能超过1000位!",groups = {SaveValidated.class, UpdateValidated.class}) + private String remark; + + @ApiModelProperty("所属机构") + @Dict(dictTable = "sys_depart", dicCode = "org_code", dicText = "depart_name") + @ExcelProperty(value = "所属机构", converter = DictConverter.class, index = 4) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + @ApiModelProperty("记录类型(1加油,2充电)") + @ExcelIgnore + private String refuelType; + + @ApiModelProperty("来源(1后台,2小程序,3后台导入)") + @ExcelIgnore + private String sourceType; + + @ApiModelProperty("日期开始") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date dateStart; + + @ApiModelProperty("日期结束") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @TableField(exist = false) + @ExcelIgnore + private Date dateEnd; + + + @ApiModelProperty("驾驶员") + @Length(max = 64,message = "驾驶员不能超过64位!",groups = {SaveValidated.class, UpdateValidated.class}) + @ExcelProperty(value = "驾驶员", index = 16) + private String driver; + @ApiModelProperty("加油站") + @Length(max = 64,message = "加油站不能超过64位!",groups = {SaveValidated.class, UpdateValidated.class}) + @ExcelProperty(value = "加油站", index = 17) + private String oilStation; + @ApiModelProperty("卡余额(元)") + @Min(value = 0, message = "卡余额(元)最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Max(value = 999999, message = "卡余额(元)最大值为999999!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @ExcelProperty(value = "卡余额(元)", index = 18) + private BigDecimal oilCardBalance; + @ExcelIgnore + @ApiModelProperty("附件URL") + private String attachmentUrl; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairAssign.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairAssign.java new file mode 100644 index 0000000..5e06d1f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairAssign.java @@ -0,0 +1,94 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_repair_assign") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "维修指派信息表", description = "维修指派信息表") +@TableRepeat(aClass = TbRepairAssign.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbRepairAssign implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联维修信息表id") + private String repairId; + + @ApiModelProperty("维修厂") + @NotBlank(message = "维修厂不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_repair_shop_archives",dicText = "name") + private String repairShop; + + @ApiModelProperty("联系人") + private String contact; + + @ApiModelProperty("联系电话") + @Pattern(regexp = "^(?:(?:\\+|00)86)?1\\d{10}$",message = "联系电话格式错误!",groups = {SaveValidated.class,UpdateValidated.class}) + private String contactPhone; + + @ApiModelProperty("是否维修质保(0-否,1-是)") + @Dict(dicCode = "yes_no") + private String isGuarantee; + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; + + /** + * 维修厂名称 + */ + @TableField(exist = false) + @ExcelIgnore + private String repairShopName; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairCheck.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairCheck.java new file mode 100644 index 0000000..6c816fb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairCheck.java @@ -0,0 +1,93 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_repair_check") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "维修审核信息表", description = "维修审核信息表") +@TableRepeat(aClass = TbRepairCheck.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbRepairCheck implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联维修信息表id") + private String repairId; + + @ApiModelProperty("审核结果12/维修结果34/保养结果56") + @Dict(dicCode = "repair_check_result") + private String checkResult; + + @ApiModelProperty("审批人") + private String checkPeople; + + @ApiModelProperty("审核人类型 审核人-1 审批人-2 复核人-3 提交人-4 派单人-5 报价人-6 维修人-7 保养人-8") + @Dict(dicCode = "check_people_type") + private String checkPeopleType; + + @ApiModelProperty("审批时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date checkTime; + + @ApiModelProperty("审核意见") + private String checkIdea; + + @ApiModelProperty("审批类型 1-审核结果,2-领导审批,3-维修结果, 4-保养结果, 5-复核结果") + @Dict(dicCode = "repair_check") + private String checkType; + + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairInfo.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairInfo.java new file mode 100644 index 0000000..d4525a7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairInfo.java @@ -0,0 +1,168 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_repair_info") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "维修基础信息表", description = "维修基础信息表") +@TableRepeat(aClass = TbRepairInfo.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbRepairInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + //1待提交 - 2待派单 - 3待报价 - 4待审核报价 - 5待审批报价 - 6维修中 - 7待确认结果 - 8已归档 -9作废 + @ApiModelProperty("流程状态") + @Dict(dicCode = "repair_status") + private Integer flowStatus = 1; + //1运营维保部 - 2维修厂 - 3领导审批 - 4结束 + @ApiModelProperty("流程节点") + @Dict(dicCode = "repair_node") + private Integer flowNode; + + @ApiModelProperty("工单号") + private String orderNo; + + @ApiModelProperty("所属项目") + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + private String projectId; + + @ApiModelProperty("项目名称") + @ExcelIgnore + private String projectName; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + private String plateNumber; + + @ApiModelProperty("交车时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date deliveryTime; + + @ApiModelProperty("车架号") + @Length(max = 32,message = "车架号长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String frameNumber; + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + @Length(max = 32,message = "车辆品牌长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + @Length(max = 32,message = "车辆型号长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @Length(max = 32,message = "车辆种类长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String vehicleType; + + @ApiModelProperty("VIN码") + @Length(max = 32,message = "VIN码长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String vinCode; + + @ApiModelProperty("发动机码") + @Length(max = 32,message = "发动机码长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String engineNumber; + + @ApiModelProperty("报修人") + @Length(max = 32,message = "报修人长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + private String repairPeople; + + @ApiModelProperty("联系电话") +// @Pattern(regexp = "^(?:(?:\\+|00)86)?1\\d{10}$",message = "联系电话格式错误!",groups = {SaveValidated.class,UpdateValidated.class}) + private String phone; + + @ApiModelProperty("报修时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date repairTime; + + @ApiModelProperty("报修分类") + @NotBlank(message = "报修分类不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "repair_class") + private String repairClass; + + @ApiModelProperty("报修内容") + @NotBlank(message = "报修内容不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 200,message = "报修内容长度不能超过200位",groups = {SaveValidated.class,UpdateValidated.class}) + private String repairContent; + + @ApiModelProperty("报修图片") + private String repairImgUrl; + + @ApiModelProperty("作废意见") + @Length(max = 200,message = "作废意见长度不能超过200位",groups = {SaveValidated.class,UpdateValidated.class}) + private String cancelIdea; + + @ApiModelProperty("作废人") + private String cancelPeople; + + @ApiModelProperty("作废时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date cancelTime; + + @ApiModelProperty("1-数据录入,,2-走流程的") + @ExcelIgnore + private Integer addType = 2; + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairOffer.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairOffer.java new file mode 100644 index 0000000..bdc4b6d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbRepairOffer.java @@ -0,0 +1,125 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; +import com.gci.boot.modules.vehicles.vo.RepairDetailVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +@TableName("tb_repair_offer") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "维修报价表", description = "维修报价表") +@TableRepeat(aClass = TbRepairOffer.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbRepairOffer implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联维修信息表id") + private String repairId; + + @ApiModelProperty("维修厂") + @Dict(dicCode = "id",dictTable = "tb_repair_shop_archives",dicText = "name") + private String repairShop; + + @ApiModelProperty("维修明细") + private String repairDetailJson; + + @ApiModelProperty("维修明细---对象数组") + @TableField(exist = false) + private List repairDetailList; + + @ApiModelProperty("总计工时") + @NotBlank(message = "总计工时不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Range(min = 0, max = 99999999, message = "总计工时在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Double totalWorkHours; + + @ApiModelProperty("工时费用总计") + @NotBlank(message = "工时费用总计不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Range(min = 0, max = 99999999, message = "工时费用总计在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Double totalWorkHoursCost; + + @ApiModelProperty("联维修报价") + @NotBlank(message = "联维修报价不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Range(min = 0, max = 99999999, message = "联维修报价在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Double repairCost; + + @ApiModelProperty("总计材料费") + @NotBlank(message = "总计材料费不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Range(min = 0, max = 99999999, message = "联维修报价在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Double materialCost; + + @ApiModelProperty("内容说明") + @NotBlank(message = "内容说明不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 100,message = "报修内容长度不能超过100位",groups = {SaveValidated.class,UpdateValidated.class}) + private String content; + + @ApiModelProperty("维修中图片") + private String inRepairImgUrl; + + @ApiModelProperty("维修后图片") + private String afterRepairImgUrl; + + @ApiModelProperty("单据附件JSON") + private String attachmentJson; + + @ApiModelProperty("单据附件列表") + @TableField(exist = false) + private List attachmentList; + + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepAssign.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepAssign.java new file mode 100644 index 0000000..1661ca9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepAssign.java @@ -0,0 +1,79 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_upkeep_assign") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养指派信息表", description = "保养指派信息表") +@TableRepeat(aClass = TbUpkeepAssign.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepAssign implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联保养台账id") + private String upkeepBillId; + + @ApiModelProperty("维修厂") + @Dict(dicCode = "id",dictTable = "tb_repair_shop_archives",dicText = "name") + private String repairShop; + + @ApiModelProperty("联系人") + private String contact; + + @ApiModelProperty("联系电话") + private String contactPhone; + + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepBill.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepBill.java new file mode 100644 index 0000000..0299563 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepBill.java @@ -0,0 +1,208 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +@TableName("tb_upkeep_bill") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养台账表", description = "保养台账表") +@TableRepeat(aClass = TbUpkeepRule.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepBill implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + //1-未审核,2-审核通过,3-审核未通过,4-已作废, 5-已归档 + @ApiModelProperty("审核状态") + @Dict(dicCode = "upkeep_audit_status") + private String auditStatus; + + @ApiModelProperty("流程状态") + private Integer flowStatus; + + @ApiModelProperty("流程节点") + private Integer flowNode; + + @ApiModelProperty("工单号") + private String orderNo; + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + private String projectId; + + @ApiModelProperty("项目名称") + @ExcelIgnore + private String projectName; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("交车时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date deliveryTime; + + @ApiModelProperty("车架号") + private String frameNumber; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("车辆型号") + private String vehicleModel; + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + private String vehicleBrand; + + @ApiModelProperty("车辆识别代码(VIN码)") + private String vinCode; + + @ApiModelProperty("发动机号码") + private String engineNumber; + + @ApiModelProperty("上次保养时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date lastTime; + + @ApiModelProperty("上次保养里程") + private Integer lastMileage; + + @ApiModelProperty("预计保养时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date predictTime; + + @ApiModelProperty("预计保养里程") + private Integer predictMileage; + + @ApiModelProperty("保养内容") + private String content; + + @ApiModelProperty("附件/照片JSON") + private String attachmentJson; + + @ApiModelProperty("附件/照片列表") + @TableField(exist = false) + private List attachmentList; + + @ApiModelProperty("作废意见") + private String cancelIdea; + + @ApiModelProperty("作废人") + private String cancelPeople; + + @ApiModelProperty("作废时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date cancelTime; + + @ApiModelProperty("生成类型 1-自动,2-手动") + private Integer saveType; + + @ApiModelProperty("规则id") + private String ruleId; + @ApiModelProperty("生成批次") + private Integer createNo; + + /**实际保养开始*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "实际保养开始") + @ExcelIgnore + private Date startTime; + + /**实际保养结束*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "实际保养结束") + @ExcelIgnore + private Date endTime; + + /**实际保养里程*/ + @ApiModelProperty("实际保养里程") + private Integer realMileage; + + /**计划生成日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "计划生成日期") + @ExcelIgnore + private Date planSaveTime; + @ApiModelProperty("保存类型 1-数据录入,,2-走流程的") + @ExcelIgnore + private Integer addType; + + + @Dict(dicCode = "overdue_status") + @ApiModelProperty("逾期状态") + @TableField(exist = false) + private String overdueStatus; + @ApiModelProperty("逾期天数") + @TableField(exist = false) + private String overdueDay; + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; +// /**作废标志--默认0-正常,1-作废*/ +// @ApiModelProperty(value = "作废标志") +// @ExcelProperty(value = "数据状态", converter = CancelConverter.class) +// @ColumnWidth(value = 15) +// private Integer cancelFlag; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepCheck.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepCheck.java new file mode 100644 index 0000000..5caceb8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepCheck.java @@ -0,0 +1,90 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_upkeep_check") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养台账审核表", description = "保养台账审核表") +@TableRepeat(aClass = TbUpkeepCheck.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepCheck implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联保养台账表id") + private String upkeepBillId; + + @ApiModelProperty("审核结果12/维修结果34/保养结果56") + @Dict(dicCode = "repair_check_result") + private String checkResult; + + @ApiModelProperty("审批人") + private String checkPeople; + + @ApiModelProperty("审核人类型 审核人-1 审批人-2 复核人-3 提交人-4 派单人-5 报价人-6 维修人-7 保养人-8") + @Dict(dicCode = "check_people_type") + private String checkPeopleType; + + @ApiModelProperty("审批时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date checkTime; + + @ApiModelProperty("审核意见") + private String checkIdea; + + @ApiModelProperty("审批类型 1-审核结果,2-领导审批,3-维修结果, 4-保养结果, 5-复核结果") + @Dict(dicCode = "repair_check") + private String checkType; + + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepOffer.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepOffer.java new file mode 100644 index 0000000..3354918 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepOffer.java @@ -0,0 +1,121 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; +import com.gci.boot.modules.vehicles.vo.RepairDetailVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Range; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +@TableName("tb_upkeep_offer") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养报价表", description = "保养报价表") +@TableRepeat(aClass = TbUpkeepOffer.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepOffer implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联保养台账id") + private String upkeepBillId; + + @ApiModelProperty("维修厂") + @Dict(dicCode = "id",dictTable = "tb_repair_shop_archives",dicText = "name") + private String repairShop; + + @ApiModelProperty("保养明细") + private String upkeepDetailJson; + @ApiModelProperty("保养明细---对象数组") + @TableField(exist = false) + private List repairDetailList; + + @ApiModelProperty("总计") + private Double totaCost; + + @ApiModelProperty("总计工时") + private Double totalWorkHours; + + @ApiModelProperty("工时费用总计") + private Double totalWorkHoursCost; + + @ApiModelProperty("总计材料费") + private Double materialCost; + + @ApiModelProperty("内容说明") + private String offerContent; + + @ApiModelProperty("保养前图片") + private String beforeUpkeepImgUrl; + + @ApiModelProperty("保养中图片") + private String inUpkeepImgUrl; + + @ApiModelProperty("保养后图片") + private String afterUpkeepImgUrl; + + @ApiModelProperty("单据附件JSON") + private String attachmentJson; + + @ApiModelProperty("单据附件列表") + @TableField(exist = false) + private List attachmentUpkeepList; + + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; + /**作废标志--默认0-正常,1-作废*/ + @ApiModelProperty(value = "作废标志") + @ExcelProperty(value = "数据状态", converter = CancelConverter.class) + @ColumnWidth(value = 15) + private Integer cancelFlag; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlan.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlan.java new file mode 100644 index 0000000..3fb3de5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlan.java @@ -0,0 +1,286 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import com.gci.boot.modules.vehicles.vo.AttachmentDetailVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +@TableName("tb_upkeep_plan") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养计划表", description = "保养计划表") +@TableRepeat(aClass = TbUpkeepPlan.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepPlan implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + //1-未审核,2-审核通过,3-审核未通过,4-已作废, 5-已归档 + @ApiModelProperty("审核状态") + @Dict(dicCode = "upkeep_audit_status") + @ExcelProperty(value = "状态",index = 7,converter = DictConverter.class) + @ColumnWidth(value = 15) + @SelectQuery + private String auditStatus; + + @ApiModelProperty("流程状态") + @ExcelIgnore + private Integer flowStatus; + + @ApiModelProperty("流程节点") + @ExcelIgnore + private Integer flowNode; + + @ApiModelProperty("工单号") + @ExcelIgnore + private String orderNo; + + @ApiModelProperty("所属项目") + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 0) + @ColumnWidth(value = 20) + @SelectQuery + private String projectId; + + @ApiModelProperty("项目名称") + @ExcelIgnore + private String projectName; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "车牌号",index = 1) + @ColumnWidth(value = 20) + @SelectQuery + private String plateNumber; + + @ApiModelProperty("交车时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ExcelIgnore + private Date deliveryTime; + + @ApiModelProperty("车架号") + @ExcelIgnore + private String frameNumber; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 15) + @SelectQuery + private String vehicleType; + + @ApiModelProperty("车辆型号") + @ExcelIgnore + private String vehicleModel; + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + @ExcelIgnore + private String vehicleBrand; + + @ApiModelProperty("车辆识别代码(VIN码)") + @ExcelIgnore + private String vinCode; + + @ApiModelProperty("发动机号码") + @ExcelIgnore + private String engineNumber; + + @ApiModelProperty("上次保养时间") + @NotNull(message = "上次保养时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "上次保养时间",index = 3) + @ColumnWidth(value = 20) + private Date lastTime; + + @ApiModelProperty("上次保养里程") + @NotNull(message = "上次保养里程不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Range(min = 0, max = 99999999, message = "上次保养里程在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "上次保养里程(KM)",index = 4) + @ColumnWidth(value = 20) + private Integer lastMileage; + + @ApiModelProperty("预计保养时间") + @NotNull(message = "预计保养时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "预计保养时间",index = 5) + @ColumnWidth(value = 20) + private Date predictTime; + + @ApiModelProperty("预计保养里程") + @NotNull(message = "预计保养里程不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Range(min = 0, max = 99999999, message = "预计保养里程在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "预计保养里程(KM)",index = 6) + @ColumnWidth(value = 20) + private Integer predictMileage; + + @ApiModelProperty("保养内容") + @NotBlank(message = "保养内容不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 250,message = "保养内容长度不能超过250位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private String content; + + @ApiModelProperty("附件/照片JSON") + @ExcelIgnore + private String attachmentJson; + + @ApiModelProperty("附件/照片列表") + @TableField(exist = false) + @ExcelIgnore + private List attachmentList; + + @ApiModelProperty("作废意见") + @ExcelIgnore + private String cancelIdea; + + @ApiModelProperty("作废人") + @ExcelIgnore + private String cancelPeople; + + @ApiModelProperty("作废时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date cancelTime; + + @ApiModelProperty("生成类型 1-自动,2-手动") + @Dict(dicCode = "upkeep_plan_save_type") + @ExcelIgnore + private Integer saveType; + + @ApiModelProperty("规则id") + @ExcelIgnore + private String ruleId; + @ApiModelProperty("生成批次") + @ExcelIgnore + private Integer createNo; + + /**实际保养开始*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date startTime; + + /**实际保养结束*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date endTime; + + /**实际保养里程*/ + @ApiModelProperty("实际保养里程") + @ExcelIgnore + private Integer realMileage; + + /**计划生成日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "计划生成日期") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty(value = "计划生成日期",index = 8) + @ColumnWidth(value = 30) + private Date planSaveTime; + @ApiModelProperty("保存类型 1-数据录入,,2-走流程的") + @ExcelIgnore + private Integer addType; + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; + + + @Dict(dicCode = "overdue_status") + @ApiModelProperty("逾期状态") + @TableField(exist = false) + @ExcelProperty(value = "逾期状态",index = 9,converter = DictConverter.class) + @ColumnWidth(value = 15) + private String overdueStatus; + @ApiModelProperty("逾期天数") + @TableField(exist = false) + @ExcelProperty(value = "逾期天数",index = 10) + @ColumnWidth(value = 15) + private String overdueDay; + //查看按钮 1-有 2-没有 + @ExcelIgnore + @TableField(exist = false) + private Integer checkButton; + // 作废按钮 1-有 2-没有 + @ExcelIgnore + @TableField(exist = false) + private Integer deleteButton; + //编辑按钮 1-有 2-没有 + @ExcelIgnore + @TableField(exist = false) + private Integer editButton; + // 审核按钮 1-有 2-没有 + @ExcelIgnore + @TableField(exist = false) + private Integer auditButton; + // 用户类型 1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + @ExcelIgnore + @TableField(exist = false) + private String userType; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlanCheck.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlanCheck.java new file mode 100644 index 0000000..7cdd9db --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepPlanCheck.java @@ -0,0 +1,90 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_upkeep_plan_check") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养台账审核表", description = "保养台账审核表") +@TableRepeat(aClass = TbUpkeepPlanCheck.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepPlanCheck implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("关联保养台账表id") + private String upkeepPlanId; + + @ApiModelProperty("审核结果12/维修结果34/保养结果56") + @Dict(dicCode = "repair_check_result") + private String checkResult; + + @ApiModelProperty("审批人") + private String checkPeople; + + //审核人-1 审批人-2 + @ApiModelProperty("审核人类型 审核人-1 审批人-2 复核人-3 提交人-4 派单人-5 报价人-6 维修人-7 保养人-8") + @Dict(dicCode = "check_people_type") + private String checkPeopleType; + + @ApiModelProperty("审批时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date checkTime; + + @ApiModelProperty("审核意见") + private String checkIdea; + + @ApiModelProperty("审批类型 1-审核结果,2-领导审批,3-维修结果, 4-保养结果, 5-复核结果") + @Dict(dicCode = "repair_check") + private String checkType; + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @ExcelIgnore + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepRule.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepRule.java new file mode 100644 index 0000000..75295b6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbUpkeepRule.java @@ -0,0 +1,143 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.config.CancelConverter; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_upkeep_rule") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "保养规则表", description = "保养规则表") +@TableRepeat(aClass = TbUpkeepRule.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbUpkeepRule implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("规则名称") + @NotBlank(message = "规则名称不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 128,message = "规则名称不能超过128位",groups = {SaveValidated.class,UpdateValidated.class}) + @SelectQuery + @ExcelProperty(value = "保养规则名称",index = 0) + @ColumnWidth(value = 30) + private String name; + + @ApiModelProperty("适用车种") + @NotBlank(message = "适用车种不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "适用车种",index = 1,converter = DictConverter.class) + @Dict(dicCode = "vehicle_type") + @ColumnWidth(value = 20) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleType; + + @ApiModelProperty("适用车型") + @NotBlank(message = "适用车型不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "适用车型不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "适用型号",index = 3) + @ColumnWidth(value = 30) + private String vehicleModel; + + @ApiModelProperty("适用品牌") + @NotBlank(message = "适用品牌不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "适用品牌",index = 2,converter = DictConverter.class) + @Dict(dicCode = "vehicle_brand") + @ColumnWidth(value = 20) + private String vehicleBrand; + + @ApiModelProperty("规则类型 1-按时间,2-按里程,3-按时间或里程") + @NotBlank(message = "规则类型不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "规则类型",index = 4,converter = DictConverter.class) + @SelectQuery + @Dict(dicCode = "upkeep_rule_type") + @ColumnWidth(value = 15) + private String ruleType; + + @ApiModelProperty("里程间隔设置") + @Range(min = 0, max = 99999999, message = "里程间隔设置在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "里程保养间隔规则(KM)",index = 5) + @ColumnWidth(value = 20) + private Integer mileage; + + @ApiModelProperty("时间间隔设置") + @Range(min = 0, max = 99999999, message = "时间间隔设置在[0,99999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "时间间隔保养规则(天)",index = 6) + @ColumnWidth(value = 25) + private Integer time; + + @ApiModelProperty("规则状态1-启用,2-禁用") + @NotBlank(message = "规则状态不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "状态",index = 7,converter = DictConverter.class) + @SelectQuery + @Dict(dicCode = "upkeep_rule_status") + @ColumnWidth(value = 15) + private String ruleStatus; + + @ApiModelProperty("备注") + @Length(max = 200,message = "备注不能超过200位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "备注") + @ColumnWidth(value = 30) + private String remark; + + + /**所属机构*/ + @ApiModelProperty(value = "所属部门") + @ExcelIgnore + private String sysOrgCode; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty(value = "创建时间",index = 8) + @ColumnWidth(value = 30) + private Date createTime; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + @ExcelIgnore + private Date updateTime; + /**创建人*/ + @ApiModelProperty(value = "创建人") + @ExcelIgnore + @Dict(dicCode = "username",dictTable = "sys_user",dicText = "realname") + private String createBy; + /**更新人*/ + @ApiModelProperty(value = "更新人") + @ExcelIgnore + private String updateBy; +// /**作废标志--默认0-正常,1-作废*/ +// @ApiModelProperty(value = "作废标志") +// @ExcelProperty(value = "数据状态", converter = CancelConverter.class) +// @ColumnWidth(value = 15) +// private Integer cancelFlag; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/entity/TbViolationRecord.java b/src/main/java/com/gci/boot/modules/vehicles/entity/TbViolationRecord.java new file mode 100644 index 0000000..748ab41 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/entity/TbViolationRecord.java @@ -0,0 +1,210 @@ +package com.gci.boot.modules.vehicles.entity; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.TableRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.annotation.ExcelEnum; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.dict.excel.EnumConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.*; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("tb_violation_record") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value = "违章记录表对象", description = "违章记录表对象") +@TableRepeat(aClass = TbViolationRecord.class,groups = {SaveValidated.class, UpdateValidated.class}) +public class TbViolationRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @NotBlank(message = "id不能为空!",groups = {UpdateValidated.class}) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属项目_id") + @SelectQuery + @NotBlank(message = "所属项目不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "所属项目长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 0,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + @ApiModelProperty("项目名称") + @SelectQuery +// @NotBlank(message = "项目名称不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) +// @Length(max = 255,message = "项目名称长度不能超过255位",groups = {SaveValidated.class,UpdateValidated.class}) +// @ExcelProperty(value = "所属项目") +// @ColumnWidth(value = 30) + @ExcelIgnore + private String projectName; + + @ApiModelProperty("车牌号") + @NotBlank(message = "车牌号不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @SelectQuery(Type = SelectQuery.SelectType.IN) + @Pattern(message = "车牌号格式错误",regexp = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "车牌号",index = 1) + @ColumnWidth(value = 15) + private String plateNumber; + + @ApiModelProperty("负责人") + @NotBlank(message = "负责人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 32,message = "负责人长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "负责人",index = 2) + @ColumnWidth(value = 15) + private String director; + + @ApiModelProperty("违章时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @NotNull(message = "违章时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd HH:mm") + @ExcelProperty(value = "违章时间",index = 3) + @ColumnWidth(value = 30) + private Date violationTime; + + @ApiModelProperty("违章地点") + @NotBlank(message = "违章地点不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 128,message = "违章地点长度不能超过128位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "违章地点",index = 4) + @ColumnWidth(value = 30) + private String violationAddress; + + @ApiModelProperty("违章行为") + @SelectQuery + @NotBlank(message = "违章行为不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Length(max = 16,message = "违章行为长度不能超过16位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "违章行为",index = 5,converter = DictConverter.class) + @ColumnWidth(value = 15) + @Dict(dicCode = "violation_behavior") + private String violationAct; + + @ApiModelProperty("违章行为描述") + @Length(max = 256,message = "违章行为描述长度不能超过256位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private String violationActDes; + + @ApiModelProperty("违章司机") + @Length(max = 32,message = "违章司机长度不能超过32位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelProperty(value = "违章司机",index = 6) + @ColumnWidth(value = 15) + private String violationDriver; + + @ApiModelProperty("违章计分") + @ExcelIgnore + @Range(min = 0, max = 32766, message = "违章计分在[0,32766]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Integer violationScore; + + @ApiModelProperty("违章费用") + @ExcelIgnore + @Range(min = 0, max = 999999, message = "违章费用在[0,999999]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Double violationCost; + + @ApiModelProperty("处理期限(天)") + @ExcelProperty(value = "处理期限(天)",index =7) + @ColumnWidth(value = 15) + @Range(min = 0, max = 32766, message = "处理期限(天)在[0,32766]之间!",groups = {SaveValidated.class,UpdateValidated.class}) + private Integer handleTerm; + + @ApiModelProperty("处理时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm") +// @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd HH:mm") +// @ExcelProperty(value = "处理时间") +// @ColumnWidth(value = 30) + @ExcelIgnore + private Date handleTime; + + @ApiModelProperty("处理结果(1-已处理、0-未处理)") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelEnum("0_未处理,1_已处理") + @ExcelProperty(value = "处理结果",index = 8,converter = EnumConverter.class) + @ColumnWidth(value = 15) + private Integer handleResult; + + @ApiModelProperty("处理凭证(附件url)") + @Length(max = 5000,message = "处理凭证长度不能超过5000位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private String handleVoucher; + + @ApiModelProperty("备注") + @Length(max = 256,message = "备注长度不能超过256位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private String remark; + + @ApiModelProperty("原始违章短信") + @Length(max = 512,message = "原始违章短信长度不能超过512位",groups = {SaveValidated.class,UpdateValidated.class}) + @ExcelIgnore + private String message; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @OrderQuery(sort = 1) + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ApiModelProperty("作废标志") + @Dict(dicCode = "cancel_flag") + @ExcelIgnore + private Integer cancelFlag; + + + @ApiModelProperty("开始时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @SelectQuery(Type = SelectQuery.SelectType.GE,PropName = "violationTime") + @ExcelIgnore + @TableField(exist = false) + private Date startTime; + @ApiModelProperty("结束时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @SelectQuery(Type = SelectQuery.SelectType.LE,PropName = "violationTime") + @ExcelIgnore + @TableField(exist = false) + private Date endTime; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/BacklogEnum.java b/src/main/java/com/gci/boot/modules/vehicles/enums/BacklogEnum.java new file mode 100644 index 0000000..4359243 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/BacklogEnum.java @@ -0,0 +1,62 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum BacklogEnum { + //1出险 2违章 3事故 4维修 5_保养台账 6年检 7_保养计划, 8保险 + //出险 + INSURANCE("insurance:output:update","出险",0), + //违章 + VIOLATION("Violation:handle","违章",0), + //事故 + ACCIDENT("accident:update","事故",0), + //年检 + INSPECTION("inspection:alarm:handle","年检",0), + //维修_派单、报价、审核、审批、维修、确认 + REPAIR_SEND("VehiclesMaintain:send","维修",2), + REPAIR_OFFER("VehiclesMaintain:offer","维修",3), + REPAIR_CHECK_OFFER("VehiclesMaintain:checkOffer","维修",4), + REPAIR_RECHECK_OFFER("VehiclesMaintain:recheckOffer","维修",10), + REPAIR_LEADER_CHECK_OFFER("VehiclesMaintain:leaderCheckOffer","维修",5), + REPAIR_SEND_REPAIRING("VehiclesMaintain:repairing","维修",6), + REPAIR_SEND_CONFIRM_RESULT("VehiclesMaintain:confirmResult","维修",7), + //保养台账_派单、报价、审核、保养、确认 + UPKEEP_BILL_SEND("UpkeepBill:send","保养台账",2), + UPKEEP_BILL_OFFER("UpkeepBill:offer","保养台账",3), + UPKEEP_BILL_CHECK_OFFER("UpkeepBill:checkOffer","保养台账",4), + UPKEEP_BILL_RECHECK_OFFER("UpkeepBill:recheckOffer","保养台账",10), + UPKEEP_BILL_REPAIRING("UpkeepBill:repairing","保养台账",6), + UPKEEP_BILL_CONFIRM_RESULT("UpkeepBill:comfirmResult","保养台账",7), + //保养计划_审批 + UPKEEP_PLAN_LEADER_CHECK_OFFER("UpkeepPlan:leaderCheckOffer","保养计划",1), + //保险 + INSURANCE_LEDGER("insurance:alarm:handle","保险",0) + ; + + /** + * 菜单按钮、对应功能、数据状态 + */ + @Getter + private String buttonAction; + + @Getter + private String menu; + + @Getter + private Integer dataStatus; + + BacklogEnum(String buttonAction, String menu,Integer dataStatus) { + this.buttonAction = buttonAction; + this.menu = menu; + this.dataStatus = dataStatus; + } + + public static BacklogEnum getEnum(String buttonAction){ + for (BacklogEnum backlogEnum : BacklogEnum.values()) { + if (backlogEnum.getButtonAction().equals(buttonAction)) { + return backlogEnum; + } + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/BacklogTabEnum.java b/src/main/java/com/gci/boot/modules/vehicles/enums/BacklogTabEnum.java new file mode 100644 index 0000000..708e259 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/BacklogTabEnum.java @@ -0,0 +1,47 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum BacklogTabEnum { + //1出险 2违章 3事故 4维修 5_保养台账 6年检 7_保养计划 8保险 + + //出险 + INSURANCE("1","出险"), + //违章 + VIOLATION("2","违章"), + //事故 + ACCIDENT("3","事故"), + //年检 + INSPECTION("6","年检"), + //维修 + REPAIR("4","维修"), + //保养台账 + UPKEEP_BILL("5","保养台账"), + //保养计划 + UPKEEP_PLAN("7","保养计划"), + + INSURANCE_LEDGER("8","保险"); + + /** + * 对应值、tab名称 + */ + @Getter + private String value; + + @Getter + private String type; + + BacklogTabEnum(String value, String type) { + this.value = value; + this.type = type; + } + + public static BacklogTabEnum getEnum(String value){ + for (BacklogTabEnum backlogEnum : BacklogTabEnum.values()) { + if (backlogEnum.getValue().equals(value)) { + return backlogEnum; + } + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusChangeEvent.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusChangeEvent.java new file mode 100644 index 0000000..6fa03e7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusChangeEvent.java @@ -0,0 +1,123 @@ +package com.gci.boot.modules.vehicles.enums; + +import com.gci.boot.modules.monitor.enums.DirectionEnum; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Optional; + +public enum RepairStatusChangeEvent { + + // 运营维保部 维修厂 运营维保部 领导审批 维修厂 运营维保部 结束 + // 1 2 3 4 5 6 7 8 + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + + // 1 2 3 4 5 + //运营维保部 维修厂 领导审批 结束 部门审批 + + // 审核状态 1-》通过, 2-》不通过 checkFlag + + /** + * 在 待审核报价 后面加一个 审核审批 的节点-10 待复核 + */ + //待提交 - 待派单 - 待报价 - 待审核报价 - <审核审批>- 待审批报价 - 维修中 - 待确认结果 - 已归档 + + /** + *提交 + */ + SUBMIT(1,1,2,1), + /** + *派单 + */ + SEND(2,1,3,2), + /** + *派单--质保期内的--直接到维修中 + */ + SEND_GUARANTEE(2,-1,6,2), + /** + *报价 + */ + OFFER(3,1,4,1), + /** + *审核通过(员工) + */ + EMPLOYEE_PASS(4,1,10,5), + /** + *审核不通过(员工) + */ + EMPLOYEE_NO_PASS(4,2,3,2), + + /** + * 审核审批--通过 + */ + EMPLOYEE_PASS_ADD(10,1,6,2), + /** + * 审核审批--超过两千 + */ + EMPLOYEE_PASS_2k_ADD(10,2000,5,3), + /** + *审核审批--不通过 + */ + EMPLOYEE_NO_PASS_ADD(10,2,4,1), + + /** + *审核通过(领导) + */ + LEADER_PASS(5,1,6,2), + /** + *审核不通过(领导) + */ + LEADER_NO_PASS(5,2,10,5), + /** + *完成维修 + */ + REPAIR_FINISH(6,1,7,1), + /** + *结果完成(归档) + */ + RESULT_PASS(7,1,8,4), + /** + *结果未完成(回维修中) + */ + RESULT_NO_PASS(7,2,6,2); + + + @Getter + private Integer flowStatus; + + @Getter + private Integer checkFlag; + + @Getter + private Integer nextFlowStatus; + + @Getter + private Integer nextNode; + + RepairStatusChangeEvent(Integer flowStatus, Integer checkFlag, Integer nextFlowStatus, Integer nextNode) { + this.flowStatus = flowStatus; + this.checkFlag = checkFlag; + this.nextFlowStatus = nextFlowStatus; + this.nextNode = nextNode; + } + + public static RepairStatusChangeEvent getEnum(Integer flowStatus, Integer checkFlag){ + +// Optional any = Arrays.stream(RepairStatusChangeEvent.class.getEnumConstants()) +// .filter(e -> e.getFlowStatus()==flowStatus && e.getCheckFlag() == checkFlag).findAny(); +// if (any.isPresent()){ +// return any.get(); +// } + + for (RepairStatusChangeEvent event : RepairStatusChangeEvent.values()) { + if (event.getFlowStatus().equals(flowStatus) && event.getCheckFlag().equals(checkFlag)) { + return event; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumDriver.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumDriver.java new file mode 100644 index 0000000..95aeb61 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumDriver.java @@ -0,0 +1,84 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum RepairStatusEnumDriver { + + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + + /** + * 待提交 + */ + WAIT_SUBMIT(1,"查看",2), + + /** + * 待派单 + */ + WAIT_SEND(2,"查看",2), + + /** + * 待报价 + */ + WAIT_OFFER(3,"查看",2), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"查看",2), + + /** + * 待审批报价 + */ + WAIT_LEADER_CHECK_OFFER(5,"查看",2), + + /** + * 维修中 + */ + REPAIRING(6,"查看",2), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"查看",2), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + RepairStatusEnumDriver(Integer flowStatus, String checkButton,Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static RepairStatusEnumDriver getEnum(Integer flowStatus){ + for (RepairStatusEnumDriver statusEnum : RepairStatusEnumDriver.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployee.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployee.java new file mode 100644 index 0000000..37a3a26 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployee.java @@ -0,0 +1,84 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum RepairStatusEnumEmployee { + + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + + /** + * 待提交 + */ + WAIT_SUBMIT(1,"提交",1), + + /** + * 待派单 + */ + WAIT_SEND(2,"派单",1), + + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",1), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"审核",1), + + /** + * 待审批报价 + */ + WAIT_LEADER_CHECK_OFFER(5,"查看",1), + + /** + * 维修中 + */ + REPAIRING(6,"维修",1), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"确认",1), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + RepairStatusEnumEmployee(Integer flowStatus, String checkButton,Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static RepairStatusEnumEmployee getEnum(Integer flowStatus){ + for (RepairStatusEnumEmployee statusEnum : RepairStatusEnumEmployee.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployeeAndLeader.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployeeAndLeader.java new file mode 100644 index 0000000..f1428f7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumEmployeeAndLeader.java @@ -0,0 +1,84 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum RepairStatusEnumEmployeeAndLeader { + + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + + /** + * 待提交 + */ + WAIT_SUBMIT(1,"提交",1), + + /** + * 待派单 + */ + WAIT_SEND(2,"派单",1), + + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",1), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"审核",1), + + /** + * 待审批报价 + */ + WAIT_LEADER_CHECK_OFFER(5,"审批",1), + + /** + * 维修中 + */ + REPAIRING(6,"维修",1), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"确认",1), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + RepairStatusEnumEmployeeAndLeader(Integer flowStatus, String checkButton, Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static RepairStatusEnumEmployeeAndLeader getEnum(Integer flowStatus){ + for (RepairStatusEnumEmployeeAndLeader statusEnum : RepairStatusEnumEmployeeAndLeader.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumLeader.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumLeader.java new file mode 100644 index 0000000..6f47442 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumLeader.java @@ -0,0 +1,84 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum RepairStatusEnumLeader { + + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + + /** + * 待提交 + */ + WAIT_SUBMIT(1,"提交",1), + + /** + * 待派单 + */ + WAIT_SEND(2,"派单",1), + + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",1), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"查看",1), + + /** + * 待审批报价 + */ + WAIT_LEADER_CHECK_OFFER(5,"审批",1), + + /** + * 维修中 + */ + REPAIRING(6,"维修",1), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"确认",1), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + RepairStatusEnumLeader(Integer flowStatus, String checkButton,Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static RepairStatusEnumLeader getEnum(Integer flowStatus){ + for (RepairStatusEnumLeader statusEnum : RepairStatusEnumLeader.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepair.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepair.java new file mode 100644 index 0000000..2f10326 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepair.java @@ -0,0 +1,84 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum RepairStatusEnumRepair { + + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + +// /** +// * 待提交 +// */ +// WAIT_SUBMIT(1,"查看",2), +// +// /** +// * 待派单 +// */ +// WAIT_SEND(2,"查看",2), + + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",2), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"查看",2), + + /** + * 待审批报价 + */ + WAIT_LEADER_CHECK_OFFER(5,"查看",2), + + /** + * 维修中 + */ + REPAIRING(6,"维修",2), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"查看",2), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + RepairStatusEnumRepair(Integer flowStatus, String checkButton,Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static RepairStatusEnumRepair getEnum(Integer flowStatus){ + for (RepairStatusEnumRepair statusEnum : RepairStatusEnumRepair.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepairAndDriver.java b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepairAndDriver.java new file mode 100644 index 0000000..6a45be8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/RepairStatusEnumRepairAndDriver.java @@ -0,0 +1,84 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum RepairStatusEnumRepairAndDriver { + + //待提交 - 待派单 - 待报价 - 待审核报价 - 待审批报价 - 维修中 - 待确认结果 - 已归档 + // 提交-> 派单-> 报价-> 审核(员工)-> 审批(领导)->完成维修-> 结果完成 + // 审核不通过 审核不通过 结果未完成 + // 超过两千 + +// /** +// * 待提交 +// */ +// WAIT_SUBMIT(1,"查看",2), +// + /** + * 待派单 + */ + WAIT_SEND(2,"查看",2), + + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",2), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"查看",2), + + /** + * 待审批报价 + */ + WAIT_LEADER_CHECK_OFFER(5,"查看",2), + + /** + * 维修中 + */ + REPAIRING(6,"维修",2), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"查看",2), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + RepairStatusEnumRepairAndDriver(Integer flowStatus, String checkButton, Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static RepairStatusEnumRepairAndDriver getEnum(Integer flowStatus){ + for (RepairStatusEnumRepairAndDriver statusEnum : RepairStatusEnumRepairAndDriver.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumEmployee.java b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumEmployee.java new file mode 100644 index 0000000..7862773 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumEmployee.java @@ -0,0 +1,78 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum UpkeepPlanStatusEnumEmployee { + + //领导 -- 作废、编辑、查看、审核 + //员工 编辑、查看 + //1-未审核,2-审核通过,3-审核未通过,4-已作废, 5-已归档 + + // 审核状态 1-》有, 2-》无 + // 查看 作废 编辑 审核 + + /** + * 未审核 + */ + NO_CHECK("1",2,2,1,2), + + /** + * 审核通过 + */ + CHECK_PASS("2",1,2,2,2), + + + /** + * 审核未通过 + */ + CHECK_NO_PASS("3",2,2,1,2), + + /** + * 已作废 + */ + CANCEL("4",1,2,2,2), + + /** + * 已归档 + */ + FINISH("5",1,2,2,2) + ; + /** + * 维修状态 + */ + @Getter + private String auditStatus; + + @Getter + private Integer checkButton; + + @Getter + private Integer deleteButton; + + @Getter + private Integer editButton; + // 审核按钮 1-有 2-没有 + @Getter + private Integer auditButton; + + + UpkeepPlanStatusEnumEmployee(String auditStatus, Integer checkButton, Integer deleteButton, + Integer editButton, Integer auditButton) { + this.auditStatus = auditStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + this.editButton = editButton; + this.auditButton = auditButton; + } + + public static UpkeepPlanStatusEnumEmployee getEnum(String auditStatus){ + for (UpkeepPlanStatusEnumEmployee statusEnum : UpkeepPlanStatusEnumEmployee.values()) { + if (statusEnum.getAuditStatus().equals(auditStatus)) { + return statusEnum; + } + } + return null; + } + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumLeader.java b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumLeader.java new file mode 100644 index 0000000..f837bdd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepPlanStatusEnumLeader.java @@ -0,0 +1,78 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum UpkeepPlanStatusEnumLeader { + + //领导 -- 作废、编辑、查看、审核 + //员工 编辑、查看 + //1-未审核,2-审核通过,3-审核未通过,4-已作废, 5-已归档 + + // 审核状态 1-》有, 2-》无 + // 查看 作废 编辑 审核 + + /** + * 未审核 + */ + NO_CHECK("1",2,1,1,1), + + /** + * 审核通过 + */ + CHECK_PASS("2",1,2,2,2), + + + /** + * 审核未通过 + */ + CHECK_NO_PASS("3",2,1,1,2), + + /** + * 已作废 + */ + CANCEL("4",1,2,2,2), + + /** + * 已归档 + */ + FINISH("5",1,2,2,2) + ; + /** + * 维修状态 + */ + @Getter + private String auditStatus; + + @Getter + private Integer checkButton; + + @Getter + private Integer deleteButton; + + @Getter + private Integer editButton; + // 审核按钮 1-有 2-没有 + @Getter + private Integer auditButton; + + + UpkeepPlanStatusEnumLeader(String auditStatus, Integer checkButton, Integer deleteButton, + Integer editButton, Integer auditButton) { + this.auditStatus = auditStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + this.editButton = editButton; + this.auditButton = auditButton; + } + + public static UpkeepPlanStatusEnumLeader getEnum(String auditStatus){ + for (UpkeepPlanStatusEnumLeader statusEnum : UpkeepPlanStatusEnumLeader.values()) { + if (statusEnum.getAuditStatus().equals(auditStatus)) { + return statusEnum; + } + } + return null; + } + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusChangeEvent.java b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusChangeEvent.java new file mode 100644 index 0000000..eb5ccb7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusChangeEvent.java @@ -0,0 +1,98 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum UpkeepStatusChangeEvent { + + // 2 3 4 6 7 8 9 + //流程状态: 待委派 待报价 待审核 保养中 待确认 结束 作废 + //流程节点: 运营维保部 维修厂 运营维保部 维修厂 运营维保部 结束 结束 + // 1 2 1 2 1 4 4 + + //待委派 待报价 待审核 保养中 待确认 结束 + // 派单-> 报价-> 审核-> 完成保养-> 结果完成 + // 审核不通过 结果未完成 + + // 审核状态 1-》通过, 2-》不通过 checkFlag + + /** + * 在 待审核报价 后面加一个 审核审批 的节点-10 待复核 + */ + //待委派 待报价 待审核 待复核 保养中 待确认 结束 + /** + *派单 + */ + SEND(2,1,3,2), + /** + *报价 + */ + OFFER(3,1,4,1), + /** + *审核通过 + */ + PASS(4,1,10,1), + /** + *审核不通过 + */ + NO_PASS(4,2,3,2), + + /** + *审核审批--通过 + */ + PASS_ADD(10,1,6,2), + /** + *审核审批--不通过 + */ + NO_PASS_ADD(10,2,4,1), + /** + *完成保养 + */ + REPAIR_FINISH(6,1,7,1), + /** + *结果完成(归档) + */ + RESULT_PASS(7,1,8,4), + /** + *结果未完成(回维修中) + */ + RESULT_NO_PASS(7,2,6,2); + + + @Getter + private Integer flowStatus; + + @Getter + private Integer checkFlag; + + @Getter + private Integer nextFlowStatus; + + @Getter + private Integer nextNode; + + UpkeepStatusChangeEvent(Integer flowStatus, Integer checkFlag, Integer nextFlowStatus, Integer nextNode) { + this.flowStatus = flowStatus; + this.checkFlag = checkFlag; + this.nextFlowStatus = nextFlowStatus; + this.nextNode = nextNode; + } + + + public static UpkeepStatusChangeEvent getEnum(Integer flowStatus, Integer checkFlag){ + +// Optional any = Arrays.stream(RepairStatusChangeEvent.class.getEnumConstants()) +// .filter(e -> e.getFlowStatus()==flowStatus && e.getCheckFlag() == checkFlag).findAny(); +// if (any.isPresent()){ +// return any.get(); +// } + + for (UpkeepStatusChangeEvent event : UpkeepStatusChangeEvent.values()) { + if (event.getFlowStatus().equals(flowStatus) && event.getCheckFlag().equals(checkFlag)) { + return event; + } + } + return null; + } + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumEmployeeAndLeader.java b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumEmployeeAndLeader.java new file mode 100644 index 0000000..75defe0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumEmployeeAndLeader.java @@ -0,0 +1,82 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum UpkeepStatusEnumEmployeeAndLeader { + + // 2 3 4 6 7 8 9 + //流程状态: 待委派 待报价 待审核 保养中 待确认 结束 作废 + //流程节点: 运营维保部 维修厂 运营维保部 维修厂 运营维保部 结束 结束 + // 1 2 4 4 + + //待委派 待报价 待审核 保养中 待确认 结束 + // 派单-> 报价-> 审核-> 完成保养-> 结果完成 + // 审核不通过 结果未完成 + + // 审核状态 1-》通过, 2-》不通过 checkFlag + + //维保部员工领导按钮 + /** + * 待派单 + */ + WAIT_SEND(2,"派单",1), + + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",1), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"审核",1), + + + /** + * 保养中 + */ + REPAIRING(6,"保养",1), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"确认",1), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + UpkeepStatusEnumEmployeeAndLeader(Integer flowStatus, String checkButton, Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static UpkeepStatusEnumEmployeeAndLeader getEnum(Integer flowStatus){ + for (UpkeepStatusEnumEmployeeAndLeader statusEnum : UpkeepStatusEnumEmployeeAndLeader.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumRepair.java b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumRepair.java new file mode 100644 index 0000000..ad0b2d4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/enums/UpkeepStatusEnumRepair.java @@ -0,0 +1,77 @@ +package com.gci.boot.modules.vehicles.enums; + +import lombok.Getter; + +public enum UpkeepStatusEnumRepair { + + // 2 3 4 6 7 8 9 + //流程状态: 待委派 待报价 待审核 保养中 待确认 结束 作废 + //流程节点: 运营维保部 维修厂 运营维保部 维修厂 运营维保部 结束 结束 + // 1 2 4 4 + + //待委派 待报价 待审核 保养中 待确认 结束 + // 派单-> 报价-> 审核-> 完成保养-> 结果完成 + // 审核不通过 结果未完成 + + // 审核状态 1-》通过, 2-》不通过 checkFlag + + //维修厂按钮 + /** + * 待报价 + */ + WAIT_OFFER(3,"报价",2), + + /** + * 待审核报价 + */ + WAIT_CHECK_OFFER(4,"查看",2), + + + /** + * 保养中 + */ + REPAIRING(6,"保养",2), + + /** + * 待确认结果 + */ + WAIT_CONFIRM_RESULT(7,"查看",2), + + /** + * 已归档 + */ + FINISH(8,"查看",2), + /** + * 已作废 + */ + CANCEL(9,"查看",2) + ; + /** + * 维修状态 + */ + @Getter + private Integer flowStatus; + + @Getter + private String checkButton; + + @Getter + private Integer deleteButton; + + + UpkeepStatusEnumRepair(Integer flowStatus, String checkButton, Integer deleteButton) { + this.flowStatus = flowStatus; + this.checkButton = checkButton; + this.deleteButton = deleteButton; + } + + public static UpkeepStatusEnumRepair getEnum(Integer flowStatus){ + for (UpkeepStatusEnumRepair statusEnum : UpkeepStatusEnumRepair.values()) { + if (statusEnum.getFlowStatus().equals(flowStatus)) { + return statusEnum; + } + } + return null; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInfoMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInfoMapper.java new file mode 100644 index 0000000..e9452d0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInfoMapper.java @@ -0,0 +1,34 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.AccidentInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 事故信息基础表 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +public interface TbAccidentInfoMapper extends BaseMapper { + + IPage pageBuild(@Param("page") Page page,@Param(Constants.WRAPPER) QueryWrapper query); + + Integer countAccidentNotClose(@Param(Constants.WRAPPER) QueryWrapper query); + + IPage findStatisAccidentInfoByDayMonthYear(@Param("page") Page page,@Param("vo") StatisParamVO vo); + + List findStatisAccidentInfoAll(@Param("vo") StatisParamVO vo); + + TbAccidentInfo getItemById(@Param("id") String id); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInsuranceInfoMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInsuranceInfoMapper.java new file mode 100644 index 0000000..ef17852 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentInsuranceInfoMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.gci.boot.modules.vehicles.entity.TbAccidentInsuranceInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 事故保险信息 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +public interface TbAccidentInsuranceInfoMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentProgressMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentProgressMapper.java new file mode 100644 index 0000000..b0fa35a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAccidentProgressMapper.java @@ -0,0 +1,21 @@ +package com.gci.boot.modules.vehicles.mapper; + +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.vehicles.entity.TbAccidentProgress; + +/** + *

+ * 事件进度信息 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +public interface TbAccidentProgressMapper extends BaseMapper { + + public List getCheckAccidentInfoCount(); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionInfoMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionInfoMapper.java new file mode 100644 index 0000000..db2f1ff --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionInfoMapper.java @@ -0,0 +1,42 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.AnnualInspectionInfoStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 年检信息表 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-20 + */ +public interface TbAnnualInspectionInfoMapper extends BaseMapper { + + IPage pageBuild(@Param("page") Page page,@Param("query") AnnualInspectionInfoQuery query); + + IPage remindList(@Param("page") Page page,@Param("query") AnnualInspectionInfoQuery query); + + IPage findStatisAnnualInspectionInfoByDayMonthYear(@Param("page") Page page,@Param("vo") StatisParamVO vo); + + List findStatisAnnualInspectionInfoAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + List findStatisAnnualInspectionInfoAndPlateNumberAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + List findStatisAnnualInspectionInfoAndPlateNumberAllHis(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + List findStatisAnnualInspectionInfoAndPlateNumber(@Param("vo") StatisParamVO vo); + + List findStatisAnnualInspectionInfoAllGroupByProject(@Param("vo") StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionRemindMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionRemindMapper.java new file mode 100644 index 0000000..c52eeb8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbAnnualInspectionRemindMapper.java @@ -0,0 +1,21 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionRemind; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 年检提醒 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-11-16 + */ +public interface TbAnnualInspectionRemindMapper extends BaseMapper { + + IPage pageBuild(@Param("page") Page page,@Param("ew") LambdaQueryWrapper lambdaQueryWrapper); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateMapper.java new file mode 100644 index 0000000..5dc0809 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateMapper.java @@ -0,0 +1,22 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.query.ConsumablesTemplateQuery; +import com.gci.boot.modules.vehicles.vo.ConsumablesTemplateVo; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 耗材模板 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface TbConsumablesTemplateMapper extends BaseMapper { + + IPage listVo(@Param("page") Page page,@Param("query") ConsumablesTemplateQuery query); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateOutPartMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateOutPartMapper.java new file mode 100644 index 0000000..cabdf32 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplateOutPartMapper.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplateOutPart; + +public interface TbConsumablesTemplateOutPartMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplatePartMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplatePartMapper.java new file mode 100644 index 0000000..7ed2cfc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbConsumablesTemplatePartMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplatePart; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 耗材详情 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface TbConsumablesTemplatePartMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplateMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplateMapper.java new file mode 100644 index 0000000..5dcb681 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplateMapper.java @@ -0,0 +1,22 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplate; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.query.CustomizedTemplateQuery; +import com.gci.boot.modules.vehicles.vo.CustomizedTemplateVo; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 定制件模板 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface TbCustomizedTemplateMapper extends BaseMapper { + + IPage listVo(@Param("page") Page page,@Param("query") CustomizedTemplateQuery query); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplatePartMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplatePartMapper.java new file mode 100644 index 0000000..fbbd46b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbCustomizedTemplatePartMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplatePart; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 定制件详情表 Mapper 接口 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface TbCustomizedTemplatePartMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceMapper.java new file mode 100644 index 0000000..d5db971 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceMapper.java @@ -0,0 +1,37 @@ +package com.gci.boot.modules.vehicles.mapper; + +import java.util.List; + +import com.gci.boot.modules.statis.vo.StatisParamVO; +import org.apache.ibatis.annotations.Param; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.InsuranceStatisVo; +import com.gci.boot.modules.vehicles.entity.TbInsurance; + +/** + *

+ * 保险信息 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +public interface TbInsuranceMapper extends BaseMapper { + + List findStatisInsuranceByDayMonthYear(@Param("page")Page page,@Param("vo") StatisParamVO vo); + + List findStatisInsuranceByProject(@Param("vo") StatisParamVO vo); + + List findStatisInsuranceAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + List findStatisInsuranceAndPlateNumberAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + List findStatisInsuranceAndPlateNumberAllHis(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + List findStatisInsuranceAndPlateNumber(@Param("vo") StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRecordMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRecordMapper.java new file mode 100644 index 0000000..fcbaafb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRecordMapper.java @@ -0,0 +1,39 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.vo.InsurancePriceVO; +import com.gci.boot.modules.vehicles.vo.InsuranceRecordStatisVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 出险管理 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-09-22 + */ +public interface TbInsuranceRecordMapper extends BaseMapper { + + /** + * 保险年度信息报表---出险为主 + */ + List findYearStatisInsuranceRecord(Page page, + @Param("vo") InsuranceRecordStatisVO vo); + + /** + * 保险年度信息报表---保险表为主 + */ + List findYearStatisInsuranceRecordV2(Page page, + @Param("vo") InsuranceRecordStatisVO vo); + + /** + * 年度保单保费 + */ + List findStatisInsurancePrice(); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRemindMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRemindMapper.java new file mode 100644 index 0000000..a30249f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbInsuranceRemindMapper.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.gci.boot.modules.vehicles.entity.TbInsuranceRemind; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 保险提醒 Mapper 接口 + *

+ * + * @author xushuhan + * @since 2023-11-07 + */ +public interface TbInsuranceRemindMapper extends BaseMapper { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRefuelChargeRecordMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRefuelChargeRecordMapper.java new file mode 100644 index 0000000..f5b9d31 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRefuelChargeRecordMapper.java @@ -0,0 +1,22 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbRefuelChargeRecord; +import com.gci.boot.modules.vehicles.vo.TbRefuelChargeRecordVo; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 加油充电记录 Mapper 接口 + *

+ * + * @author admin + * @since 2023-11-30 + */ +public interface TbRefuelChargeRecordMapper extends BaseMapper { + + public List getRefuelChargeStat(@Param("params") TbRefuelChargeRecord params); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairAssignMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairAssignMapper.java new file mode 100644 index 0000000..78ac0ed --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairAssignMapper.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; + +public interface TbRepairAssignMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairCheckMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairCheckMapper.java new file mode 100644 index 0000000..06f28ce --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairCheckMapper.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; + +public interface TbRepairCheckMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairInfoMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairInfoMapper.java new file mode 100644 index 0000000..738b884 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairInfoMapper.java @@ -0,0 +1,85 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.RepairStatisVO; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.vo.RepairInfoListVO; +import com.gci.boot.modules.vehicles.vo.VehicleInfoVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TbRepairInfoMapper extends BaseMapper { + + + List findRepairInfoList(Page page, + @Param("vo") RepairInfoListVO vo); + + List findRepairInfoAllList(@Param("vo") RepairInfoListVO vo); + + + List findVehicleInfoByProjectId(@Param("projectId") String projectId); + + List findRepairShop(); + + + List findVehicleInfoByTime(@Param("vehicleType") String vehicleType, + @Param("vehicleModel") String vehicleModel, + @Param("vehicleBrand") String vehicleBrand); + + List findVehicleInfoByMile(@Param("vehicleType") String vehicleType, + @Param("vehicleModel") String vehicleModel, + @Param("vehicleBrand") String vehicleBrand); + + + /** + * 维修统计 按天 月 年 + * @param page + * @param vo + * @return + */ + List findStatisRepairByDayMonthYear(Page page, + @Param("vo") StatisParamVO vo); + + + /** + * 维修统计 按天 月 年 + * @param vo + * @return + */ + List findStatisRepairAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + /** + * 维修统计全部 并 附带车牌号 + * @param vo + * @return + */ + List findStatisRepairAndPlateNumberAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + /** + * 维修统计全部 并 附带车牌号 项目以车辆表为准 + * @param vo + * @return + */ + List findStatisRepairAndPlateNumberAllHis(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + /** + * 根据车辆及时间统计 + * @param vo + * @return + */ + List findStatisRepairAndPlateNumber(@Param("vo") StatisParamVO vo); + + /** + * 维修统计根据项目统计 + * @param vo + * @return + */ + List findStatisRepairAllGroupByProject(@Param("vo") StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairOfferMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairOfferMapper.java new file mode 100644 index 0000000..cf1fe24 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbRepairOfferMapper.java @@ -0,0 +1,29 @@ +package com.gci.boot.modules.vehicles.mapper; + +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.dataview.vo.ProjectContractVo; +import com.gci.boot.modules.dataview.vo.RepairPayMonthVo; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; + +public interface TbRepairOfferMapper extends BaseMapper { + + //保险 + List getInsuranceTotalPrice(); + + //年检 + List getInspectionTotalPrice(); + + //维修 + List getRepairTotalPrice(); + + //保养 + List getUpkeepTotalPrice(); + + List getRepairPayMonth(String month); + + List getRepairPayQuarter(String month,String monthEnd); + + List getRepairPayYear(String year); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepAssignMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepAssignMapper.java new file mode 100644 index 0000000..8d39297 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepAssignMapper.java @@ -0,0 +1,8 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbUpkeepAssign; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; + +public interface TbUpkeepAssignMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepBillMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepBillMapper.java new file mode 100644 index 0000000..ed135fa --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepBillMapper.java @@ -0,0 +1,74 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.statis.vo.RepairStatisVO; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.UpkeepStatisVO; +import com.gci.boot.modules.vehicles.entity.TbUpkeepBill; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan; +import com.gci.boot.modules.vehicles.vo.RepairInfoListVO; +import com.gci.boot.modules.vehicles.vo.UpkeepInfoListVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TbUpkeepBillMapper extends BaseMapper { + + List findUpkeepBillList(Page page, + @Param("vo") UpkeepInfoListVO vo); + + List findAllUpkeepBillList(@Param("vo") UpkeepInfoListVO vo); + + /**最终结果通过,更新计划表的状态为已归档--5**/ + void updateFinshPlan(@Param("id") String id, + @Param("auditStatus") Integer auditStatus); + + /** + * 保养统计 按天 月 年 + * @param page + * @param vo + * @return + */ + List findStatisUpkeepByDayMonthYear(Page page, + @Param("vo") StatisParamVO vo); + + + /** + * 保养统计 按天 月 年 + * @param vo + * @return + */ + List findStatisUpkeepAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + /** + * 保养统计 并 附带车牌 + * @param vo + * @return + */ + List findStatisUpkeepAndPlateNumberAll(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + /** + * 保养统计 并 附带车牌 项目以车辆为主 + * @param vo + * @return + */ + List findStatisUpkeepAndPlateNumberAllHis(@Param("vo") StatisParamVO vo, + @Param("listProjectIds") List listProjectIds); + + /** + * 保养统计 并 附带车牌 根据车辆及时间统计 + * @param vo + * @return + */ + List findStatisUpkeepAndPlateNumber(@Param("vo") StatisParamVO vo); + + /** + * 保养根据项目统计 + * @param vo + * @return + */ + List findStatisUpkeepAllGroupByProject(@Param("vo") StatisParamVO vo); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepCheckMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepCheckMapper.java new file mode 100644 index 0000000..3a6af07 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepCheckMapper.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbUpkeepCheck; + +public interface TbUpkeepCheckMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepOfferMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepOfferMapper.java new file mode 100644 index 0000000..9b2384a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepOfferMapper.java @@ -0,0 +1,8 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbUpkeepOffer; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; + +public interface TbUpkeepOfferMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanCheckMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanCheckMapper.java new file mode 100644 index 0000000..e532b4b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanCheckMapper.java @@ -0,0 +1,8 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbUpkeepCheck; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlanCheck; + +public interface TbUpkeepPlanCheckMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanMapper.java new file mode 100644 index 0000000..adcda69 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepPlanMapper.java @@ -0,0 +1,25 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan; +import com.gci.boot.modules.vehicles.vo.UpkeepInfoListVO; +import org.apache.ibatis.annotations.Param; + +import java.util.ArrayList; +import java.util.List; + +public interface TbUpkeepPlanMapper extends BaseMapper { + + Integer findMaxPlanCreateNo(); + + List findUpkeepPlanList(Page page, + @Param("vo") TbUpkeepPlan vo); + + List findUpkeepAllList(@Param("vo") TbUpkeepPlan vo); + + /** + * 查找未完成的单 + */ + Integer findUnfinishCount(@Param("plateNumber") String plateNumber); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepRuleMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepRuleMapper.java new file mode 100644 index 0000000..3e9524d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbUpkeepRuleMapper.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; + +public interface TbUpkeepRuleMapper extends BaseMapper { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/TbViolationRecordMapper.java b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbViolationRecordMapper.java new file mode 100644 index 0000000..9de26a9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/TbViolationRecordMapper.java @@ -0,0 +1,76 @@ +package com.gci.boot.modules.vehicles.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.projects.entity.TbVehicleCheck; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.statis.vo.ViolationRecordStatisVO; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.vo.VehicleProjectVO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface TbViolationRecordMapper extends BaseMapper { + + /** + * 获取车牌-项目-责任人列表 + * @return + */ + List queryVehicleProject(); + + /** + * 获取所有车牌列表 + * @return + */ + List queryAllVehicle(); + + /** + * 获取所有项目列表(cancelFlag 废弃状态 0-正常 1-废弃) + * @return + */ + List queryProjects(@Param("cancelFlag") Integer cancelFlag, @Param("delFlag") Integer delFlag); + + /** + * 获取车牌-项目(车牌没项目的返回其它) + * @return + */ + List queryOtherVehicleProject(); + + + /** + * 违章统计 按天 月 年 + * @param page + * @param vo + * @return + */ + List findStatisViolationByDayMonthYear(Page page, + @Param("vo") StatisParamVO vo); + + + /** + * 违章统计 按天 月 年 + * @param vo + * @return + */ + List findStatisViolationAll(@Param("vo") StatisParamVO vo); + + /** + * 违章统计 按年 + * @param vo + * @param listProjectIds + * @return + */ + List findStatisViolationAndPlateNumberAll(@Param("vo") StatisParamVO vo,@Param("listProjectIds") List listProjectIds); + + /** + * 违章统计 按年 + * @param vo + * @param listProjectIds + * @return + */ + List findStatisViolationAndPlateNumberAllHis(@Param("vo") StatisParamVO vo,@Param("listProjectIds") List listProjectIds); + + public List getCheckViolationCount(); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInfoMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInfoMapper.xml new file mode 100644 index 0000000..ed5cef1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInfoMapper.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInsuranceInfoMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInsuranceInfoMapper.xml new file mode 100644 index 0000000..4b47f4f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentInsuranceInfoMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentProgressMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentProgressMapper.xml new file mode 100644 index 0000000..7ed19fe --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAccidentProgressMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionInfoMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionInfoMapper.xml new file mode 100644 index 0000000..745d93b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionInfoMapper.xml @@ -0,0 +1,345 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionRemindMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionRemindMapper.xml new file mode 100644 index 0000000..28b409c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbAnnualInspectionRemindMapper.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateMapper.xml new file mode 100644 index 0000000..9ca3f51 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateMapper.xml @@ -0,0 +1,37 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateOutPartMapper.tld b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateOutPartMapper.tld new file mode 100644 index 0000000..b9e86f0 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplateOutPartMapper.tld @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplatePartMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplatePartMapper.xml new file mode 100644 index 0000000..4648af8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbConsumablesTemplatePartMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplateMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplateMapper.xml new file mode 100644 index 0000000..82a146f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplateMapper.xml @@ -0,0 +1,37 @@ + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplatePartMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplatePartMapper.xml new file mode 100644 index 0000000..2752aab --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbCustomizedTemplatePartMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceMapper.xml new file mode 100644 index 0000000..7d46b14 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceMapper.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRecordMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRecordMapper.xml new file mode 100644 index 0000000..ced3140 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRecordMapper.xml @@ -0,0 +1,71 @@ + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRemindMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRemindMapper.xml new file mode 100644 index 0000000..4df8cbc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbInsuranceRemindMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRefuelChargeRecordMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRefuelChargeRecordMapper.xml new file mode 100644 index 0000000..53f1340 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRefuelChargeRecordMapper.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairAssignMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairAssignMapper.xml new file mode 100644 index 0000000..2f88829 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairAssignMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairCheckMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairCheckMapper.xml new file mode 100644 index 0000000..d38ca4f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairCheckMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairInfoMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairInfoMapper.xml new file mode 100644 index 0000000..2fc3657 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairInfoMapper.xml @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairOfferMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairOfferMapper.xml new file mode 100644 index 0000000..282ed51 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbRepairOfferMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepAssignMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepAssignMapper.xml new file mode 100644 index 0000000..83a1f9d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepAssignMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepBillMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepBillMapper.xml new file mode 100644 index 0000000..a06783b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepBillMapper.xml @@ -0,0 +1,296 @@ + + + + + + + + + + update tb_upkeep_plan set + audit_status = #{auditStatus} + where id=#{id} + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepCheckMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepCheckMapper.xml new file mode 100644 index 0000000..6282fdc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepCheckMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepOfferMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepOfferMapper.xml new file mode 100644 index 0000000..56f40f1 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepOfferMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanCheckMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanCheckMapper.xml new file mode 100644 index 0000000..1607886 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanCheckMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanMapper.xml new file mode 100644 index 0000000..4cc6464 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepPlanMapper.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepRuleMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepRuleMapper.xml new file mode 100644 index 0000000..577e9d6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbUpkeepRuleMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbViolationRecordMapper.xml b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbViolationRecordMapper.xml new file mode 100644 index 0000000..4405247 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/mapper/xml/TbViolationRecordMapper.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/gci/boot/modules/vehicles/query/AccidentInfoQuery.java b/src/main/java/com/gci/boot/modules/vehicles/query/AccidentInfoQuery.java new file mode 100644 index 0000000..8124f26 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/query/AccidentInfoQuery.java @@ -0,0 +1,55 @@ +package com.gci.boot.modules.vehicles.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.OrderQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class AccidentInfoQuery { + /** + * 项目id + */ + private String projectId; + /** + * 车牌号 + */ + private String plateNumber; + /** + * 事故性质 + */ + private String natureConfirm; + /** + * 事故责任 + */ + private String liabilityConfirm; + /** + * 事故发生时间 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private List accidentTime; + /** + * 结案时间 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private List closingTime; + /** + * 是否结案 + */ + private String caseClosed; + /** + * 是否出险 + */ + private String isRecord; + /** + * 创建时间 + */ + @OrderQuery(sort = 1) + private Date createTime; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionInfoQuery.java b/src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionInfoQuery.java new file mode 100644 index 0000000..85fb937 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionInfoQuery.java @@ -0,0 +1,38 @@ +package com.gci.boot.modules.vehicles.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +/** + * @author 24642 + */ +@Data +public class AnnualInspectionInfoQuery { + /** + * 车牌号 + */ + private String plateNumber; + /** + * 项目id + */ + private String projectId; + /** + * 车辆种类 + */ + private String vehicleType; + /** + * 年检有效期 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private List time; + /** + * 逾期状态 + */ + private String overdueType; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionRemindQuery.java b/src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionRemindQuery.java new file mode 100644 index 0000000..1dcbb1d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/query/AnnualInspectionRemindQuery.java @@ -0,0 +1,47 @@ +package com.gci.boot.modules.vehicles.query; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class AnnualInspectionRemindQuery { + /** + * 车牌号 + */ + @SelectQuery(Type = SelectQuery.SelectType.LIKE,PropName = "tair.plateNumber") + private String plateNumber; + /** + * 项目id + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.projectId") + private String projectId; + /** + * 车辆种类 + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tv.vehicleType") + private String vehicleType; + /** + * 年检有效期 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @SelectQuery(Type = SelectQuery.SelectType.BETWEEN,PropName = "tair.validityPeriod") + private List time; + /** + * 1-将要逾期 + * 2-已逾期 + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "tair.overdueType") + private String overdueType; + /** + * 1-提醒中 + * 0-已过期 + */ + @SelectQuery(Type = SelectQuery.SelectType.EQ,PropName = "remindStatus") + private String remindStatus; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/query/ConsumablesTemplateQuery.java b/src/main/java/com/gci/boot/modules/vehicles/query/ConsumablesTemplateQuery.java new file mode 100644 index 0000000..cee6374 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/query/ConsumablesTemplateQuery.java @@ -0,0 +1,22 @@ +package com.gci.boot.modules.vehicles.query; + +import lombok.Data; + +/** + * @author 24642 + */ +@Data +public class ConsumablesTemplateQuery { + /** + * 耗材名称 + */ + private String name; + /** + * 车辆种类 + */ + private String vehicleType; + /** + * 所属项目Id + */ + private String projectId; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/query/CustomizedTemplateQuery.java b/src/main/java/com/gci/boot/modules/vehicles/query/CustomizedTemplateQuery.java new file mode 100644 index 0000000..f034ecd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/query/CustomizedTemplateQuery.java @@ -0,0 +1,22 @@ +package com.gci.boot.modules.vehicles.query; + +import lombok.Data; + +/** + * @author 24642 + */ +@Data +public class CustomizedTemplateQuery { + /** + * 定制件名称 + */ + private String name; + /** + * 车辆种类 + */ + private String vehicleType; + /** + * 所属项目Id + */ + private String projectId; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/BacklogService.java b/src/main/java/com/gci/boot/modules/vehicles/service/BacklogService.java new file mode 100644 index 0000000..bfc824b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/BacklogService.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.vo.BacklogStatisVO; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Map; + +public interface BacklogService { + + //获取用户当前待办操作按钮 + Map> getUserBacklogButton(); + + //获取分页数据 + Result getBacklogPageList(Integer pageNo, Integer pageSize, String type, HttpServletRequest req); + + //获取统计分页总数 + List getBacklogStatis(HttpServletRequest req); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/CommonService.java b/src/main/java/com/gci/boot/modules/vehicles/service/CommonService.java new file mode 100644 index 0000000..46a3542 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/CommonService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +public interface CommonService { + + /**获取对应权限角色身份**/ + String getAuthority(String userName); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/IRepairUpkeepImportService.java b/src/main/java/com/gci/boot/modules/vehicles/service/IRepairUpkeepImportService.java new file mode 100644 index 0000000..2111408 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/IRepairUpkeepImportService.java @@ -0,0 +1,28 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.driver.vo.DriverImportVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.vehicles.vo.RepairImportVO; +import com.gci.boot.modules.vehicles.vo.UpkeepImportVO; + +import java.io.IOException; +import java.util.List; + +public interface IRepairUpkeepImportService { + + /** + * 维修导入-暂放这里,基础表那边方法太多了 + */ + Result repairImport(List list) throws IOException; + + /** + * 保养导入 + */ + Result upkeepImport(List list) throws IOException; + + /** + * 司机档案导入 + */ + Result driverImport(List list) throws IOException; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInfoService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInfoService.java new file mode 100644 index 0000000..68da6d6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInfoService.java @@ -0,0 +1,28 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.query.AccidentInfoQuery; + +/** + *

+ * 事故信息基础表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +public interface ITbAccidentInfoService extends IService { + + IPage pageBuild(Page page, AccidentInfoQuery query); + + void saveItem(TbAccidentInfo tbAccidentInfo); + + void updateItem(TbAccidentInfo tbAccidentInfo); + + void removeItem(String id); + + TbAccidentInfo getItemById(String id); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInsuranceInfoService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInsuranceInfoService.java new file mode 100644 index 0000000..2b30c37 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentInsuranceInfoService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.modules.vehicles.entity.TbAccidentInsuranceInfo; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 事故保险信息 服务类 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +public interface ITbAccidentInsuranceInfoService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentProgressService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentProgressService.java new file mode 100644 index 0000000..9f4516f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAccidentProgressService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.modules.vehicles.entity.TbAccidentProgress; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 事件进度信息 服务类 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +public interface ITbAccidentProgressService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionInfoService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionInfoService.java new file mode 100644 index 0000000..224ebfd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionInfoService.java @@ -0,0 +1,38 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +/** + *

+ * 年检信息表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-20 + */ +public interface ITbAnnualInspectionInfoService extends IService { + + IPage pageBuild(Page page, AnnualInspectionInfoQuery query); + + IPage remindList(Page page, AnnualInspectionInfoQuery query); + + void init(); + + TbAnnualInspectionInfo getLastYear(String plateNumber); + + void saveItem(TbAnnualInspectionInfo tbAnnualInspectionInfo); + + void updateItem(TbAnnualInspectionInfo tbAnnualInspectionInfo); + + void removeItem(String id); + + Result listImport(MultipartFile file) throws IOException; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionRemindService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionRemindService.java new file mode 100644 index 0000000..503a71f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbAnnualInspectionRemindService.java @@ -0,0 +1,52 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionRemind; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 年检提醒 服务类 + *

+ * + * @author 2464 + * @since 2023-11-16 + */ +public interface ITbAnnualInspectionRemindService extends IService { + + /** + * 根据车牌重算年检信息 + */ + void recalculate(String plateNumber); + + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper); + + /** + * 每日更新日期数据 + */ + void updateDate(); + + /** + * 初始化 + */ + void init(); + + /** + * 构建实体类 + * @param tbAnnualInspectionInfo + * @return + */ + TbAnnualInspectionRemind buildRemind(TbAnnualInspectionInfo tbAnnualInspectionInfo); + + /** + * 查找实体类 + * @param tbAnnualInspectionInfo + * @return + */ + TbAnnualInspectionRemind findRemind(TbAnnualInspectionInfo tbAnnualInspectionInfo); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateOutPartService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateOutPartService.java new file mode 100644 index 0000000..3098cf5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateOutPartService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplateOutPart; + +public interface ITbConsumablesTemplateOutPartService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplatePartService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplatePartService.java new file mode 100644 index 0000000..179bc34 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplatePartService.java @@ -0,0 +1,45 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplateOutPart; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplatePart; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 耗材详情 服务类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface ITbConsumablesTemplatePartService extends IService { + + void init(); + /** + * 耗材查询 + * @param page + * @param lambdaQueryWrapper + * @param onlyHadQuantity + * @return + */ + IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper, boolean onlyHadQuantity); + + /** + * 入库数据 + * @param partList + */ + void inStorage(List partList); + + /** + * 出库数据 + * @param partList + */ + void outStorage(List partList); + + void inAndOutStorage(TbConsumablesTemplatePart partList); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateService.java new file mode 100644 index 0000000..3f0b24c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbConsumablesTemplateService.java @@ -0,0 +1,34 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.query.ConsumablesTemplateQuery; +import com.gci.boot.modules.vehicles.vo.ConsumablesTemplateVo; + +/** + *

+ * 耗材模板 服务类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface ITbConsumablesTemplateService extends IService { + /** + * 返回列表Vo + * @param page + * @param query + * @return + */ + IPage pageBuild(Page page, ConsumablesTemplateQuery query); + + void saveItem(TbConsumablesTemplate tbConsumablesTemplate); + + void updateItem(TbConsumablesTemplate tbConsumablesTemplate); + + TbConsumablesTemplate getByProjectIdAndVehicleType(String id, String vehicleType); + + void removeItem(String projectId, String vehicleType); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplatePartService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplatePartService.java new file mode 100644 index 0000000..a8dda2d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplatePartService.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplatePart; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 定制件详情表 服务类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface ITbCustomizedTemplatePartService extends IService { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplateService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplateService.java new file mode 100644 index 0000000..a15899a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbCustomizedTemplateService.java @@ -0,0 +1,29 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplate; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.query.CustomizedTemplateQuery; +import com.gci.boot.modules.vehicles.vo.CustomizedTemplateVo; + +/** + *

+ * 定制件模板 服务类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +public interface ITbCustomizedTemplateService extends IService { + + IPage pageBuild(Page page, CustomizedTemplateQuery query); + + void saveItem(TbCustomizedTemplate tbCustomizedTemplate); + + void updateItem(TbCustomizedTemplate tbCustomizedTemplate); + + TbCustomizedTemplate getByProjectIdAndVehicleType(String projectId, String vehicleType); + + void removeItem(String projectId, String vehicleType); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRecordService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRecordService.java new file mode 100644 index 0000000..df3e46e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRecordService.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 出险管理 服务类 + *

+ * + * @author xushuhan + * @since 2023-09-22 + */ +public interface ITbInsuranceRecordService extends IService { + + void saveItem(TbInsuranceRecord item); + + void updateItem(TbInsuranceRecord item); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRemindService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRemindService.java new file mode 100644 index 0000000..eeeac48 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceRemindService.java @@ -0,0 +1,26 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.modules.vehicles.entity.TbInsuranceRemind; + +import java.util.List; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 保险提醒 服务类 + *

+ * + * @author xushuhan + * @since 2023-11-07 + */ +public interface ITbInsuranceRemindService extends IService { + + void createRemind(); + + void updateRemind(); + + IPage getRemindPage(TbInsuranceRemind item, IPage pageList); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceService.java new file mode 100644 index 0000000..f1e44cb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbInsuranceService.java @@ -0,0 +1,38 @@ +package com.gci.boot.modules.vehicles.service; + +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.statis.vo.InsuranceStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.vo.InsuranceImportVO; +import com.gci.boot.modules.vehicles.vo.TbInsuranceRemindVo; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * 保险信息 服务类 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +public interface ITbInsuranceService extends IService { + + List page(Page page, StatisParamVO vo); + + Map getLastInsurance(List vids); + + String checkItem(TbInsurance item); + + int uploadFiles(Map fileMap, String hasCompulsoryInsurance); + + Result listImport(List list) throws IOException; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbRefuelChargeRecordService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRefuelChargeRecordService.java new file mode 100644 index 0000000..66b6a62 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRefuelChargeRecordService.java @@ -0,0 +1,25 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbRefuelChargeRecord; +import com.gci.boot.modules.vehicles.vo.TbRefuelChargeRecordImportVo; +import com.gci.boot.modules.vehicles.vo.TbRefuelChargeRecordVo; + +import java.util.List; + +/** + *

+ * 加油充电记录 服务类 + *

+ * + * @author admin + * @since 2023-11-30 + */ +public interface ITbRefuelChargeRecordService extends IService { + + void saveItem(TbRefuelChargeRecord item); + + Result saveItemBatch(List list); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairAssignService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairAssignService.java new file mode 100644 index 0000000..6666406 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairAssignService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; + +public interface ITbRepairAssignService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairCheckService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairCheckService.java new file mode 100644 index 0000000..3c52f86 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairCheckService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; + +public interface ITbRepairCheckService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairInfoService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairInfoService.java new file mode 100644 index 0000000..a364dbd --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairInfoService.java @@ -0,0 +1,43 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.vo.RepairDataEntryVO; +import com.gci.boot.modules.vehicles.vo.RepairInfoListVO; +import com.gci.boot.modules.vehicles.vo.RepairObjectVO; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +public interface ITbRepairInfoService extends IService { + + /** + * 分页列表查询 + * @param page + * @param vo + * @return + */ + Page getRepairInfoList(Page page, RepairInfoListVO vo); + + /** + * 根据维修单id获取维修弹窗详情 + * @param id + * @return + */ + RepairObjectVO getRepairObjectById(String id); + + /** + * 数据录入 + * @param vo + * @param isGuarantee = "0",则校验附件单件是否为空 + */ + String addDataEntry(RepairDataEntryVO vo, String isGuarantee); + + /** + * 流程提交 + */ + String submitRepairObject(RepairObjectVO vo, HttpServletRequest request); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairOfferService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairOfferService.java new file mode 100644 index 0000000..f787080 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbRepairOfferService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; + +public interface ITbRepairOfferService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepAssignService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepAssignService.java new file mode 100644 index 0000000..fb935f6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepAssignService.java @@ -0,0 +1,8 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepAssign; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; + +public interface ITbUpkeepAssignService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepBillService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepBillService.java new file mode 100644 index 0000000..1b09129 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepBillService.java @@ -0,0 +1,47 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepBill; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan; +import com.gci.boot.modules.vehicles.vo.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +public interface ITbUpkeepBillService extends IService { + + /** + * 数据录入 + * @param vo + * @param isGuarantee "0",则校验附件单件是否为空 + */ + String addDataEntry(UpkeepDataEntryVO vo, String isGuarantee); + + /** + * 分页列表查询 + * @param page + * @param vo + * @return + */ + Page getUpkeepBillList(Page page, UpkeepInfoListVO vo); + + /** + * 查所有列表查询 + * @param vo + * @return + */ + List getAllUpkeepBillList(UpkeepInfoListVO vo); + + /** + * 根据保养单id获取保养弹窗详情 + * @param id + * @return + */ + UpkeepObjectVO getUpkeepObjectById(String id); + + /** + * 流程提交 + */ + String submitUpkeepObject(UpkeepObjectVO vo, HttpServletRequest request); +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepCheckService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepCheckService.java new file mode 100644 index 0000000..0185e44 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepCheckService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepCheck; + +public interface ITbUpkeepCheckService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepOfferService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepOfferService.java new file mode 100644 index 0000000..5bfe7de --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepOfferService.java @@ -0,0 +1,8 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepOffer; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; + +public interface ITbUpkeepOfferService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanCheckService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanCheckService.java new file mode 100644 index 0000000..5d04f00 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanCheckService.java @@ -0,0 +1,8 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepCheck; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlanCheck; + +public interface ITbUpkeepPlanCheckService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanService.java new file mode 100644 index 0000000..3439d5c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepPlanService.java @@ -0,0 +1,39 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlan; +import com.gci.boot.modules.vehicles.vo.UpkeepInfoListVO; +import com.gci.boot.modules.vehicles.vo.UpkeepObjectVO; +import com.gci.boot.modules.vehicles.vo.UpkeepPlanObjectVO; + +import javax.servlet.http.HttpServletRequest; + +public interface ITbUpkeepPlanService extends IService { + + /** + * 保养计划审核提交 + */ + String submitUpkeepPlan(UpkeepPlanObjectVO vo); + + /** + * 根据保养计划单id获取保养弹窗详情 + * @param id + * @return + */ + UpkeepPlanObjectVO getUpkeepPlanObjectById(String id); + + + /** + * 规则生成计划 + */ + String ruleCreatePlan(); + + + /** + * 分页 + * @return + */ + Page getUpkeepPlanList(Page page, TbUpkeepPlan upkeepPlan); + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepRuleService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepRuleService.java new file mode 100644 index 0000000..7bec607 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbUpkeepRuleService.java @@ -0,0 +1,7 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; + +public interface ITbUpkeepRuleService extends IService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/ITbViolationRecordService.java b/src/main/java/com/gci/boot/modules/vehicles/service/ITbViolationRecordService.java new file mode 100644 index 0000000..edec9a7 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/ITbViolationRecordService.java @@ -0,0 +1,52 @@ +package com.gci.boot.modules.vehicles.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.vo.MessageVO; +import com.gci.boot.modules.vehicles.vo.MsgImportFailVO; +import com.gci.boot.modules.vehicles.vo.VehicleProjectVO; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +public interface ITbViolationRecordService extends IService { + + /** + * 获取车牌-项目-责任人列表 + * @return + */ + List queryVehicleProject(); + /** + * 获取所有车牌列表 + * @return + */ + List queryAllVehicle(); + /** + * 获取所有项目列表 + * @return + */ + List queryAllProject(); + + /** + * 解析短信获取车牌、时间、地点 + * @param template + * @return + */ + MessageVO analyzeMessage(String template); + + /** + * 短信识别新的违章行为新增到字典 + */ + String addViolationBehavior(MessageVO vo); + + /** + * 违章短信导入数据处理 + */ + List importViolationMessage(List msgTemplates); + /** + * 导入 + */ + Result msgImport(MultipartFile file) throws IOException; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/BacklogServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/BacklogServiceImpl.java new file mode 100644 index 0000000..aa98d7c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/BacklogServiceImpl.java @@ -0,0 +1,304 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.entity.SysPermission; +import com.gci.boot.modules.system.service.ISysPermissionService; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.controller.*; +import com.gci.boot.modules.vehicles.entity.*; +import com.gci.boot.modules.vehicles.enums.BacklogEnum; +import com.gci.boot.modules.vehicles.enums.BacklogTabEnum; +import com.gci.boot.modules.vehicles.query.AccidentInfoQuery; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import com.gci.boot.modules.vehicles.query.AnnualInspectionRemindQuery; +import com.gci.boot.modules.vehicles.service.BacklogService; +import com.gci.boot.modules.vehicles.vo.BacklogStatisVO; +import com.gci.boot.modules.vehicles.vo.RepairInfoListVO; +import com.gci.boot.modules.vehicles.vo.UpkeepInfoListVO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; + +@Service +@Slf4j +public class BacklogServiceImpl implements BacklogService { + @Autowired + private ISysPermissionService sysPermissionService; + @Autowired + private RepairController repairController; + @Autowired + private UpKeepBillController upKeepBillController; + @Autowired + private UpKeepPlanController upKeepPlanController; + @Autowired + private TbInsuranceRecordController insuranceRecordController; + @Autowired + private TbViolationRecordController violationRecordController; + @Autowired + private TbAccidentInfoController accidentInfoController; + @Autowired + private TbAnnualInspectionRemindController annualInspectionRemindController; + @Autowired + private TbInsuranceRemindController insuranceRemindController; + + @Override + public Map> getUserBacklogButton() { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + List metaList = sysPermissionService.queryByUser(sysUser.getUsername()); + Map> map = new HashMap<>(); + for (SysPermission permission : metaList) { + if(permission.getMenuType()==null) { + continue; + } + if(permission.getMenuType().equals(CommonConstant.MENU_TYPE_BUTTON) &&CommonConstant.STATUS_1.equals(permission.getStatus())) { + BacklogEnum backlogEnum = BacklogEnum.getEnum(permission.getPerms()); + if(Objects.nonNull(backlogEnum)){ + List list = map.get(backlogEnum.getMenu()); + if(CollectionUtils.isEmpty(list)){ + map.put(backlogEnum.getMenu(), Collections.singletonList(backlogEnum.getDataStatus())); + }else{ + List tempList = new ArrayList<>(list); + tempList.add(backlogEnum.getDataStatus()); + map.put(backlogEnum.getMenu(), tempList); + } + } + } + } + return map; + } + + //1出险 2违章 3事故 4维修 5保养台账 6年检 7保养计划 + @Override + public Result getBacklogPageList(Integer pageNo, Integer pageSize, String type, HttpServletRequest req) { + //获取用户对应待办按钮 + Map> map = getUserBacklogButton(); + List statusList = map.getOrDefault(type,new ArrayList<>()); + //获取用户对用tab,没权限的不给查看 + List menuTabs = new ArrayList<>(); + if(map != null && !map.isEmpty()){ + menuTabs.addAll(map.keySet()); + } + if(!menuTabs.contains(type)){ + return Result.error(101,"没有权限!"); + } + + if(BacklogTabEnum.INSURANCE.getType().equals(type)){ + TbInsuranceRecord insuranceRecord = new TbInsuranceRecord(); + if(CollectionUtil.isEmpty(statusList)){ + insuranceRecord.setHandleStatus("-1"); + }else{ + insuranceRecord.setHandleStatus(statusList.get(0).toString()); + } + Result insuranceResult = insuranceRecordController.page(insuranceRecord, pageNo, pageSize); + return insuranceResult; + } + if(BacklogTabEnum.VIOLATION.getType().equals(type)){ + TbViolationRecord violationRecord = new TbViolationRecord(); + if(CollectionUtil.isEmpty(statusList)){ + violationRecord.setHandleResult(-1); + }else{ + violationRecord.setHandleResult(statusList.get(0)); + } + Result violationResult = violationRecordController.queryPageList(violationRecord, pageNo, pageSize,req); + return violationResult; + } + if(BacklogTabEnum.ACCIDENT.getType().equals(type)){ + AccidentInfoQuery accidentInfoQuery = new AccidentInfoQuery(); + if(CollectionUtil.isEmpty(statusList)){ + accidentInfoQuery.setCaseClosed("-1"); + }else{ + accidentInfoQuery.setCaseClosed(statusList.get(0).toString()); + } + Result accidentResult = accidentInfoController.queryPageList(accidentInfoQuery, pageNo, pageSize,req); + return accidentResult; + } + if(BacklogTabEnum.REPAIR.getType().equals(type)){ + if(CollectionUtil.isEmpty(statusList)){ + statusList.add(-1); + } + RepairInfoListVO vo = new RepairInfoListVO(); + vo.setFlowStatusList(statusList); + Result result = repairController.queryPageList(vo, pageNo, pageSize,req); + return result; + } + if(BacklogTabEnum.UPKEEP_BILL.getType().equals(type)){ + if(CollectionUtil.isEmpty(statusList)){ + statusList.add(-1); + } + UpkeepInfoListVO upkeepInfoListVO = new UpkeepInfoListVO(); + upkeepInfoListVO.setFlowStatusList(statusList); + Result upkeepBillResult = upKeepBillController.queryPageList(upkeepInfoListVO, pageNo, pageSize,req); + return upkeepBillResult; + } + if(BacklogTabEnum.INSPECTION.getType().equals(type)){ + AnnualInspectionRemindQuery query = new AnnualInspectionRemindQuery(); + if(CollectionUtil.isEmpty(statusList)){ + query.setRemindStatus("-1"); + }else{ + //提醒中 + query.setRemindStatus("1"); + } + + Result annualInspectionResult = annualInspectionRemindController.queryPageList(query, pageNo, pageSize,req); + return annualInspectionResult; + } + if(BacklogTabEnum.UPKEEP_PLAN.getType().equals(type)){ + TbUpkeepPlan tbUpkeepPlan = new TbUpkeepPlan(); + if(CollectionUtil.isEmpty(statusList)){ + tbUpkeepPlan.setAuditStatus("-1"); + }else{ + tbUpkeepPlan.setAuditStatus(statusList.get(0).toString()); + } + Result upkeepPlanResult = upKeepPlanController.queryPageList(tbUpkeepPlan, pageNo, pageSize,req); + return upkeepPlanResult; + } + if(BacklogTabEnum.INSURANCE_LEDGER.getType().equals(type)){ + TbInsuranceRemind tbInsuranceRecord = new TbInsuranceRemind(); + if(CollectionUtil.isEmpty(statusList)){ + tbInsuranceRecord.setStatus("-1"); + }else{ + //提醒中 + tbInsuranceRecord.setStatus("1"); + } + Result insuranceRemindResult = insuranceRemindController.page(tbInsuranceRecord, pageNo, pageSize); + return insuranceRemindResult; + } + + return null; + } + + @Override + public List getBacklogStatis(HttpServletRequest req) { + //获取用户对应待办按钮 + Map> map = getUserBacklogButton(); + List result = new ArrayList<>(); + //获取用户对用tab + List menuTabs = new ArrayList<>(); + if(map != null && !map.isEmpty()){ + menuTabs.addAll(map.keySet()); + } + + // 需要处理的 BacklogEnum 列表 + List backlogTabEnums = Arrays.asList( + BacklogTabEnum.INSURANCE_LEDGER, + BacklogTabEnum.INSURANCE, + BacklogTabEnum.VIOLATION, + BacklogTabEnum.ACCIDENT, + BacklogTabEnum.INSPECTION, + BacklogTabEnum.REPAIR, + BacklogTabEnum.UPKEEP_BILL, + BacklogTabEnum.UPKEEP_PLAN + ); + + for (BacklogTabEnum backlogTabEnum : backlogTabEnums) { + if(menuTabs.contains(backlogTabEnum.getType())){ + BacklogStatisVO backlogVo = new BacklogStatisVO(); + backlogVo.setType(backlogTabEnum.getType()); + backlogVo.setValue(backlogTabEnum.getValue()); + List statusList = map.getOrDefault(backlogTabEnum.getType(),new ArrayList<>()); + backlogVo.setStatisCount(getPageCount(backlogTabEnum,statusList,req)); + result.add(backlogVo); + } + } + return result; + } + + + private long getPageCount(BacklogTabEnum backlogEnum, List statusList,HttpServletRequest req) { + switch (backlogEnum) { + case INSURANCE: + TbInsuranceRecord insuranceRecord = new TbInsuranceRecord(); + if(CollectionUtil.isEmpty(statusList)){ + insuranceRecord.setHandleStatus("-1"); + }else{ + insuranceRecord.setHandleStatus(statusList.get(0).toString()); + } + Result insuranceResult = insuranceRecordController.page(insuranceRecord, 1, 1); + IPage insurancePageList = (IPage) insuranceResult.getResult(); + return insurancePageList.getTotal(); + case VIOLATION: + TbViolationRecord violationRecord = new TbViolationRecord(); + if(CollectionUtil.isEmpty(statusList)){ + violationRecord.setHandleResult(-1); + }else{ + violationRecord.setHandleResult(statusList.get(0)); + } + Result violationResult = violationRecordController.queryPageList(violationRecord, 1, 1,req); + IPage violationPageList = (IPage) violationResult.getResult(); + return violationPageList.getTotal(); + case ACCIDENT: + AccidentInfoQuery accidentInfoQuery = new AccidentInfoQuery(); + if(CollectionUtil.isEmpty(statusList)){ + accidentInfoQuery.setCaseClosed("-1"); + }else{ + accidentInfoQuery.setCaseClosed(statusList.get(0).toString()); + } + Result accidentResult = accidentInfoController.queryPageList(accidentInfoQuery, 1, 1,req); + IPage accidentPageList = (IPage) accidentResult.getResult(); + return accidentPageList.getTotal(); + case INSPECTION: + AnnualInspectionRemindQuery query = new AnnualInspectionRemindQuery(); + if(CollectionUtil.isEmpty(statusList)){ + query.setRemindStatus("-1"); + }else{ + //提醒中 + query.setRemindStatus("1"); + } + Result annualInspectionResult = annualInspectionRemindController.queryPageList(query, 1, 1,req); + IPage annualInspectionInfoIPage = (IPage) annualInspectionResult.getResult(); + return annualInspectionInfoIPage.getTotal(); + case REPAIR: + if(CollectionUtil.isEmpty(statusList)){ + statusList.add(-1); + } + RepairInfoListVO repairInfoListVO = new RepairInfoListVO(); + repairInfoListVO.setFlowStatusList(statusList); + Result repairResult = repairController.queryPageList(repairInfoListVO, 1, 1,req); + IPage repairPageList = (IPage) repairResult.getResult(); + return repairPageList.getTotal(); + case UPKEEP_BILL: + if(CollectionUtil.isEmpty(statusList)){ + statusList.add(-1); + } + UpkeepInfoListVO upkeepInfoListVO = new UpkeepInfoListVO(); + upkeepInfoListVO.setFlowStatusList(statusList); + Result upkeepBillResult = upKeepBillController.queryPageList(upkeepInfoListVO, 1, 1,req); + IPage upkeepBillPageList = (IPage) upkeepBillResult.getResult(); + return upkeepBillPageList.getTotal(); + case UPKEEP_PLAN: + TbUpkeepPlan tbUpkeepPlan = new TbUpkeepPlan(); + if(CollectionUtil.isEmpty(statusList)){ + tbUpkeepPlan.setAuditStatus("-1"); + }else{ + tbUpkeepPlan.setAuditStatus(statusList.get(0).toString()); + } + Result upkeepPlanResult = upKeepPlanController.queryPageList(tbUpkeepPlan, 1, 1,req); + IPage upkeepPlanPageList = (IPage) upkeepPlanResult.getResult(); + return upkeepPlanPageList.getTotal(); + case INSURANCE_LEDGER: + TbInsuranceRemind tbInsuranceRecord = new TbInsuranceRemind(); + if(CollectionUtil.isEmpty(statusList)){ + tbInsuranceRecord.setStatus("-1"); + }else{ + //提醒中 + tbInsuranceRecord.setStatus("1"); + } + Result insuranceRemindResult = insuranceRemindController.page(tbInsuranceRecord, 1, 1); + IPage insuranceRemindPageList = (IPage) insuranceRemindResult.getResult(); + return insuranceRemindPageList.getTotal(); + default: + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/CommonServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/CommonServiceImpl.java new file mode 100644 index 0000000..d11b870 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/CommonServiceImpl.java @@ -0,0 +1,105 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.entity.SysUserRole; +import com.gci.boot.modules.system.service.*; +import com.gci.boot.modules.vehicles.service.CommonService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class CommonServiceImpl implements CommonService { + + @Autowired + private ISysUserService sysUserService; + @Autowired + private ISysUserRoleService sysUserRoleService; + @Autowired + private ISysRoleService sysRoleService; + + + @Override + public String getAuthority(String userName) { + SysUser sysUser = sysUserService.getByUsername(userName); + if(Objects.isNull(sysUser)){ + return null; + } + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + //查用户角色 + LambdaQueryWrapper userRoleQuery = new LambdaQueryWrapper<>(); + userRoleQuery.eq(SysUserRole::getUserId,sysUser.getId()); + List sysUserRoleList = sysUserRoleService.list(userRoleQuery); + if(Objects.isNull(sysUserRoleList) || sysUserRoleList.size() == 0){ + return null; + } + List roleIds = sysUserRoleList.stream().filter(s-> StrUtil.isNotBlank(s.getRoleId())) + .map(SysUserRole::getRoleId).distinct().collect(Collectors.toList()); + if(Objects.isNull(roleIds) || roleIds.size() == 0){ + return null; + } + + LambdaQueryWrapper roleQuery = new LambdaQueryWrapper<>(); + roleQuery.in(SysRole::getId,roleIds); + List roleList = sysRoleService.list(roleQuery); + if(Objects.isNull(roleList) || roleList.size() == 0){ + return null; + } + List roleCodes = roleList.stream().map(SysRole::getRoleCode).distinct().collect(Collectors.toList()); + if(Objects.isNull(roleCodes) || roleList.size() == 0){ + return null; + } + return getAuthorityType(roleCodes); + } + + public String getAuthorityType(List roleCodes){ + boolean hasDriver = false; + boolean hasRepairAdmin = false; + boolean hasMaintenanceLeader = false; + boolean hasMaintenanceAdmin = false; + for (String roleCode : roleCodes) { + switch (roleCode) { + case CommonConstant.Driver: + hasDriver = true; + break; + case CommonConstant.Repair_admin: + hasRepairAdmin = true; + break; + case CommonConstant.Maintenance_leader: + hasMaintenanceLeader = true; + break; + case CommonConstant.Maintenance_admin: + hasMaintenanceAdmin = true; + break; + } + } + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + if (hasDriver && !hasRepairAdmin && !hasMaintenanceLeader && !hasMaintenanceAdmin) { + return "1"; + } else if (!hasDriver && hasRepairAdmin && !hasMaintenanceLeader && !hasMaintenanceAdmin) { + return "2"; + } else if (hasDriver && hasRepairAdmin && !hasMaintenanceLeader && !hasMaintenanceAdmin) { + return "3"; +// //多个身份的默认返回最高身份 +// return "2"; + }else if (!hasMaintenanceLeader && hasMaintenanceAdmin) { + return "4"; + } else if (hasMaintenanceLeader && !hasMaintenanceAdmin) { + return "5"; + } else if (hasMaintenanceLeader && hasMaintenanceAdmin) { + return "6"; +// //多个身份的默认返回最高身份 +// return "5"; + } + return null; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/RepairUpkeepImportServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/RepairUpkeepImportServiceImpl.java new file mode 100644 index 0000000..ede66b5 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/RepairUpkeepImportServiceImpl.java @@ -0,0 +1,641 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.assist.ISqlRunner; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.driver.service.ITbDriverService; +import com.gci.boot.modules.driver.vo.DriverImportVO; +import com.gci.boot.modules.driver.vo.DriverUserVo; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.mapper.ProjectsMapper; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.*; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.service.*; +import com.gci.boot.modules.vehicles.vo.*; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.text.DecimalFormat; +import java.time.LocalTime; +import java.util.*; +import java.util.stream.Collectors; + +@Service +public class RepairUpkeepImportServiceImpl implements IRepairUpkeepImportService { + @Value("${failExcel}") + private String failExcel; + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private ISysDictService sysDictService; + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbRepairInfoService repairInfoService; + @Autowired + private ITbVehicleService vehicleService; + @Autowired + private ITbUpkeepBillService upkeepBillService; + @Autowired + private ITbDriverService driverService; + @Autowired + private ISysUserService sysUserService; + + + @Override + public Result repairImport(List list) throws IOException { + //维修厂 + List repairShopList = repairInfoMapper.findRepairShop(); + //报修分类 + List repairClassList = sysDictService.queryDictItemsByCode("repair_class"); + Map repairClassMap = repairClassList.stream().collect(Collectors.toMap(DictModel::getText, DictModel::getValue)); + //查用户所有权限车牌 + List plateNumbers = projectsService.queryAllPlateNumberListOfUser(); + //重复项-车牌、时间、维修分类校验重复 + Map> repeatMap = ValidatorUtil.findDuplicates(list, "plateNumber","repairTime","repairClass"); + Set keys = repeatMap.keySet(); + //历史数据 + List historyList = repairInfoService.list(new LambdaQueryWrapper().ne(TbRepairInfo::getFlowStatus,9)); + //记录失败的数据 + List failList = new ArrayList<>(); + for(int i = 0; i< list.size(); i++){ + int flag = 0; + list.get(i).validate(); + if(CollectionUtil.isNotEmpty(list.get(i).getValidationErrors())){ + flag += 1; + } + if(!plateNumbers.contains(list.get(i).getPlateNumber())){ + flag += 1; + list.get(i).putErrorMsg("当前用户没有该车牌号权限或车辆不存在"); + list.get(i).setFormatErrors("1"); + } + if(StrUtil.isBlank(repairClassMap.getOrDefault(list.get(i).getRepairClass(), null))){ + flag += 1; + list.get(i).putErrorMsg("报修分类缺少对应字典"); + list.get(i).setFormatErrors("1"); + }else{ + list.get(i).setRepairClassValue(repairClassMap.getOrDefault(list.get(i).getRepairClass(), null)); + } + if(!checkRepairRepairShop(list.get(i), repairShopList)){ + flag += 1; + list.get(i).putErrorMsg("维修厂不存在"); + list.get(i).setFormatErrors("1"); + } + if(StrUtil.isBlank(repairClassMap.getOrDefault(list.get(i).getRepairClassV2(), null))){ + flag += 1; + list.get(i).putErrorMsg("维修分类缺少对应字典"); + list.get(i).setFormatErrors("1"); + }else{ + list.get(i).setRepairClassV2Value(repairClassMap.getOrDefault(list.get(i).getRepairClassV2(), null)); + } + if(Objects.nonNull(repeatMap) && repeatMap.containsKey(list.get(i).getPlateNumber() + list.get(i).getRepairTime() + list.get(i).getRepairClass())){ + flag += 1; + list.get(i).putErrorMsg("存在重复的'车牌号'、'报修时间'、'报修分类'"); + list.get(i).setRepeatErrors("1"); + } + RepairImportVO finalI = list.get(i); + if(StrUtil.isNotBlank(finalI.getPlateNumber()) && StrUtil.isNotBlank(finalI.getRepairTime()) && StrUtil.isNotBlank(finalI.getRepairClassValue())){ + //根据车牌号、报修时间、报修分类校验重复--与历史数据 + List historys = historyList.stream().filter(h -> finalI.getPlateNumber().equals(h.getPlateNumber()) + && finalI.getRepairClassValue().equals(h.getRepairClass()) + && finalI.getRepairTime().equals(DateUtil.format(h.getRepairTime(),"yyyy-MM-dd"))).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(historys)){ + flag += 1; + list.get(i).putErrorMsg("'车牌号'、'报修时间'、'报修分类'已存在重复历史记录"); + list.get(i).setRepeatErrors("1"); + } + } + if(flag == 0){ + try { + //保存数据 + this.saveRepair(list.get(i)); + }catch (Exception e){ + e.printStackTrace(); + list.get(i).putErrorMsg(e.getMessage()); + list.get(i).setFormatErrors("1"); + failList.add(list.get(i)); + } + }else{ + failList.add(list.get(i)); + } + } + //处理返回数据 + if (CollectionUtil.isNotEmpty(failList)) { + JSONObject entries = new JSONObject(); + String fielName = System.currentTimeMillis() + CommonConstant.REPAIR_IMPORT_FAIL_EXCEL_NAME; + //导出失败数据 + EasyExcel.write(failExcel + fielName, RepairImportVO.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("导入异常数据").doWrite(failList); + //格式异常行数 +// List indexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getFormatErrors())) { +// indexes.add(i+3); +// } +// } +// //数据重复 +// List repeatIndexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getRepeatErrors())) { +// repeatIndexes.add(i+3); +// } +// } + String errorMsg = "已导入"+ (list.size()-failList.size()) + "条;失败"+ failList.size() +"条;具体失败详情见失败导出信息表"; +// if(CollectionUtil.isNotEmpty(repeatIndexes)){ +// errorMsg += "第"+ repeatIndexes + "行数据重复;"; +// } +// if(CollectionUtil.isNotEmpty(indexes)){ +// errorMsg += "第"+ indexes + "行数据格式异常"; +// } + entries.set("msg",errorMsg); + entries.set("path",fielName); + return Result.ok(entries); + }else{ + return Result.ok(); + } + } + + @Override + public Result upkeepImport(List list) throws IOException { + //维修厂 + List repairShopList = repairInfoMapper.findRepairShop(); + //报修分类 + List repairClassList = sysDictService.queryDictItemsByCode("repair_class"); + Map repairClassMap = repairClassList.stream().collect(Collectors.toMap(DictModel::getText, DictModel::getValue)); + //查用户所有权限车牌 + List plateNumbers = projectsService.queryAllPlateNumberListOfUser(); + //查项目车牌上次保养里程等 + List vehicleInfoList = repairInfoMapper.findVehicleInfoByProjectId(null); + //重复项-车牌、实际保养里程校验重复 + Map> repeatMap = ValidatorUtil.findDuplicates(list,"plateNumber","realMileage"); + //记录失败的数据 + List failList = new ArrayList<>(); + Set keys = repeatMap.keySet(); + //历史数据 + List historyList = upkeepBillService.list(new LambdaQueryWrapper().ne(TbUpkeepBill::getFlowStatus,9)); + for(int i = 0; i< list.size(); i++){ + int flag = 0; + list.get(i).validate(); + if(CollectionUtil.isNotEmpty(list.get(i).getValidationErrors())){ + flag += 1; + } + if(!plateNumbers.contains(list.get(i).getPlateNumber())){ + flag += 1; + list.get(i).putErrorMsg("当前用户没有该车牌号权限或车辆不存在"); + list.get(i).setFormatErrors("1"); + } + if(StrUtil.isBlank(repairClassMap.getOrDefault(list.get(i).getRepairClass(), null))){ + flag += 1; + list.get(i).putErrorMsg("保养分类缺少对应字典"); + list.get(i).setFormatErrors("1"); + }else{ + list.get(i).setRepairClassValue(repairClassMap.getOrDefault(list.get(i).getRepairClass(), null)); + } + if(!checkUpkeepRepairShop(list.get(i), repairShopList)){ + flag += 1; + list.get(i).putErrorMsg("维修厂不存在"); + list.get(i).setFormatErrors("1"); + } + if(Objects.nonNull(repeatMap) && repeatMap.containsKey(list.get(i).getPlateNumber() + list.get(i).getRealMileage())){ + flag += 1; + list.get(i).putErrorMsg("存在重复的'车牌号'、'实际保养里程'"); + list.get(i).setRepeatErrors("1"); + } + UpkeepImportVO finalI = list.get(i); + if(StrUtil.isNotBlank(finalI.getPlateNumber()) && StrUtil.isNotBlank(finalI.getRealMileage())){ + //根据车牌号、实际保养里程校验重复--与历史数据 + List historys = historyList.stream().filter(h -> finalI.getPlateNumber().equals(h.getPlateNumber()) + && Objects.nonNull(h.getRealMileage()) && finalI.getRealMileage().equals(h.getRealMileage().toString())).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(historys)){ + flag += 1; + list.get(i).putErrorMsg("'车牌号'、'实际保养里程'已存在重复历史记录"); + list.get(i).setRepeatErrors("1"); + } + } + if(StrUtil.isNotEmpty(list.get(i).getStartTime()) && StrUtil.isNotBlank(list.get(i).getEndTime())){ + // 比较开始时间和结束时间 + if (DateUtil.parse(list.get(i).getStartTime(),"yyyy-MM-dd HH:mm:ss") + .compareTo(DateUtil.parse(list.get(i).getEndTime(),"yyyy-MM-dd HH:mm:ss")) > 0) { + flag += 1; + list.get(i).putErrorMsg("'实际保养开始时间'不能大于'实际保养完成时间'"); + list.get(i).setFormatErrors("1"); + } + } + if(flag == 0){ + try { + //保存数据 + this.saveUpkeep(list.get(i), vehicleInfoList); + }catch (Exception e){ + e.printStackTrace(); + list.get(i).setFormatErrors("1"); + list.get(i).putErrorMsg(e.getMessage()); + failList.add(list.get(i)); + } + }else{ + failList.add(list.get(i)); + } + } + //处理返回数据 + if (CollectionUtil.isNotEmpty(failList)) { + JSONObject entries = new JSONObject(); + String fielName = System.currentTimeMillis() + CommonConstant.UPKEEP_IMPORT_FAIL_EXCEL_NAME; + //导出失败数据 + EasyExcel.write(failExcel + fielName, UpkeepImportVO.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("导入异常数据").doWrite(failList); + //格式异常行数 +// List indexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getFormatErrors())) { +// indexes.add(i+3); +// } +// } +// //数据重复 +// List repeatIndexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getRepeatErrors())) { +// repeatIndexes.add(i+3); +// } +// } + String errorMsg = "已导入"+ (list.size()-failList.size()) + "条;失败"+ failList.size() +"条;具体失败详情见失败导出信息表"; +// if(CollectionUtil.isNotEmpty(repeatIndexes)){ +// errorMsg += "第"+ repeatIndexes + "行数据重复;"; +// } +// if(CollectionUtil.isNotEmpty(indexes)){ +// errorMsg += "第"+ indexes + "行数据格式异常"; +// } + entries.set("msg",errorMsg); + entries.set("path",fielName); + return Result.ok(entries); + }else{ + return Result.ok(); + } + } + + /** + * 维修-校验维修厂是否存在 + */ + private Boolean checkRepairRepairShop(RepairImportVO vo, List repairShopList) { + List repairShopNames = repairShopList.stream().map(TbRepairAssign::getRepairShopName).collect(Collectors.toList()); + if(Objects.nonNull(vo) && StrUtil.isNotBlank(vo.getRepairShop())){ + if (repairShopNames.contains(vo.getRepairShop().trim())) { + TbRepairAssign repairShop = repairShopList.stream().filter(item -> item.getRepairShopName().equals(vo.getRepairShop())).findFirst().get(); + vo.setRepairShopId(repairShop.getRepairShop()); + vo.setContact(repairShop.getContact()); + vo.setContactPhone(repairShop.getContactPhone()); + return true; + } + } + return false; + } + /** + * 维修-录入 + */ + public void saveRepair(RepairImportVO vo){ + TbRepairInfo repairInfo = new TbRepairInfo(); + TbRepairOffer repairOffer = new TbRepairOffer(); + TbRepairAssign repairAssign =new TbRepairAssign(); + //查车辆信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicle::getPlateNumber,vo.getPlateNumber()); + TbVehicle vehicle = vehicleService.getOne(queryWrapper); + //基本信息 + repairInfo.setPlateNumber(vehicle.getPlateNumber()); + repairInfo.setDeliveryTime(vehicle.getDeliveryTime()); + repairInfo.setEngineNumber(vehicle.getEngineNumber()); + repairInfo.setFrameNumber(vehicle.getFrameNumber()); + repairInfo.setVehicleBrand(vehicle.getVehicleBrand()); + repairInfo.setVehicleModel(vehicle.getVehicleModel()); + repairInfo.setVehicleType(vehicle.getVehicleType()); + repairInfo.setVinCode(vehicle.getVinCode()); + repairInfo.setProjectId(vehicle.getProjectId()); + repairInfo.setRepairPeople(vo.getRepairPeople()); + repairInfo.setPhone(vo.getPhone()); + repairInfo.setRepairTime(DateUtil.parse(vo.getRepairTime(),"yyyy-MM-dd")); + repairInfo.setRepairClass(vo.getRepairClassValue()); + repairInfo.setRepairContent(vo.getRepairContent()); + //指派信息 + repairAssign.setRepairShop(vo.getRepairShopId()); + repairAssign.setContact(vo.getContact()); + repairAssign.setContactPhone(vo.getContactPhone()); + if("是".equals(vo.getIsGuarantee())){ + repairAssign.setIsGuarantee("1"); + }else{ + repairAssign.setIsGuarantee("0"); + } + //报修信息 + RepairDetailVO repairDetail = new RepairDetailVO(); + repairDetail.setQuantity(Integer.valueOf(vo.getQuantity())); + repairDetail.setRepairClass(vo.getRepairClassV2Value()); + repairDetail.setRepairContent(vo.getRepairContentV2()); + repairDetail.setUnitPrice(Double.valueOf(vo.getUnitPrice())); + repairDetail.setWorkHours(Double.valueOf(vo.getWorkHours())); + repairDetail.setWorkHoursCost(Double.valueOf(vo.getWorkHoursCost())); + DecimalFormat df = new DecimalFormat("#.##"); + repairDetail.setTotalCost(Double.parseDouble(df.format(repairDetail.getQuantity() * repairDetail.getUnitPrice() + repairDetail.getWorkHours() * repairDetail.getWorkHoursCost()))); + List repairDetailList = CollectionUtil.newArrayList(repairDetail); + repairOffer.setContent(vo.getContent()); + repairOffer.setRepairDetailList(repairDetailList); + repairOffer.setMaterialCost(Double.parseDouble(df.format(repairDetail.getQuantity()*repairDetail.getUnitPrice()))); + repairOffer.setRepairCost(repairDetail.getTotalCost()); + repairOffer.setTotalWorkHours(repairDetail.getWorkHours()); + repairOffer.setTotalWorkHoursCost(Double.parseDouble(df.format(repairDetail.getWorkHours()*repairDetail.getWorkHoursCost()))); + //入库 + RepairDataEntryVO dataEntryVO = new RepairDataEntryVO(); + dataEntryVO.setRepairInfo(repairInfo); + dataEntryVO.setRepairAssign(repairAssign); + dataEntryVO.setRepairOffer(repairOffer); + String result = repairInfoService.addDataEntry(dataEntryVO,null); + if(StrUtil.isNotBlank(result)){ + throw new RuntimeException(result); + } + } + + /** + * 保养-校验维修厂是否存在 + */ + private Boolean checkUpkeepRepairShop(UpkeepImportVO vo, List repairShopList) { + List repairShopNames = repairShopList.stream().map(TbRepairAssign::getRepairShopName).collect(Collectors.toList()); + if(Objects.nonNull(vo) && StrUtil.isNotBlank(vo.getRepairShop())){ + if (repairShopNames.contains(vo.getRepairShop().trim())) { + TbRepairAssign repairShop = repairShopList.stream().filter(item -> item.getRepairShopName().equals(vo.getRepairShop())).findFirst().get(); + vo.setRepairShopId(repairShop.getRepairShop()); + vo.setContact(repairShop.getContact()); + vo.setContactPhone(repairShop.getContactPhone()); + return true; + } + } + return false; + } + + /** + * 保养--数据录入 + */ + public void saveUpkeep(UpkeepImportVO vo, List vehicleInfoList){ + TbUpkeepBill upkeepBill = new TbUpkeepBill(); + TbUpkeepOffer upkeepOffer = new TbUpkeepOffer(); + TbUpkeepAssign upkeepAssign = new TbUpkeepAssign(); + //查车辆信息 + VehicleInfoVO vehicle = vehicleInfoList.stream().filter(item -> item.getPlateNumber().equals(vo.getPlateNumber())).findFirst().get(); + //基本信息 + upkeepBill.setProjectId(vehicle.getProjectId()); + upkeepBill.setPlateNumber(vehicle.getPlateNumber()); + upkeepBill.setDeliveryTime(vehicle.getDeliveryTime()); + upkeepBill.setEngineNumber(vehicle.getEngineNumber()); + upkeepBill.setFrameNumber(vehicle.getFrameNumber()); + upkeepBill.setVinCode(vehicle.getVinCode()); + upkeepBill.setVehicleBrand(vehicle.getVehicleBrand()); + upkeepBill.setVehicleModel(vehicle.getVehicleModel()); + upkeepBill.setVehicleType(vehicle.getVehicleType()); + upkeepBill.setLastMileage(Objects.nonNull(vehicle.getLastMileage()) ? vehicle.getLastMileage() : 0); + upkeepBill.setLastTime(vehicle.getLastTime()); + upkeepBill.setStartTime(DateUtil.parse(vo.getStartTime(),"yyyy-MM-dd HH:mm:ss")); + upkeepBill.setEndTime(DateUtil.parse(vo.getEndTime(),"yyyy-MM-dd HH:mm:ss")); + upkeepBill.setRealMileage(Integer.valueOf(vo.getRealMileage())); + upkeepBill.setContent(vo.getContent()); + upkeepBill.setPredictTime(upkeepBill.getStartTime()); + upkeepBill.setPredictMileage(upkeepBill.getRealMileage()); + //指派信息 + upkeepAssign.setContact(vo.getContact()); + upkeepAssign.setContactPhone(vo.getContactPhone()); + upkeepAssign.setRepairShop(vo.getRepairShopId()); + //保养详情 + RepairDetailVO repairDetail = new RepairDetailVO(); + repairDetail.setQuantity(Integer.valueOf(vo.getQuantity())); + repairDetail.setRepairClass(vo.getRepairClassValue()); + repairDetail.setRepairContent(vo.getRepairContent()); + repairDetail.setUnitPrice(Double.valueOf(vo.getUnitPrice())); + repairDetail.setWorkHours(Double.valueOf(vo.getWorkHours())); + repairDetail.setWorkHoursCost(Double.valueOf(vo.getWorkHoursCost())); + DecimalFormat df = new DecimalFormat("#.##"); + repairDetail.setTotalCost(Double.parseDouble(df.format(repairDetail.getQuantity()*repairDetail.getUnitPrice() + repairDetail.getWorkHours()*repairDetail.getWorkHoursCost()))); + List repairDetailList = CollectionUtil.newArrayList(repairDetail); + upkeepOffer.setRepairDetailList(repairDetailList); + upkeepOffer.setOfferContent(vo.getOfferContent()); + upkeepOffer.setMaterialCost(Double.parseDouble(df.format(repairDetail.getQuantity()*repairDetail.getUnitPrice()))); + upkeepOffer.setTotalWorkHours(repairDetail.getWorkHours()); + upkeepOffer.setTotalWorkHoursCost(Double.parseDouble(df.format(repairDetail.getWorkHours()*repairDetail.getWorkHoursCost()))); + upkeepOffer.setTotaCost(upkeepOffer.getMaterialCost() + upkeepOffer.getTotalWorkHoursCost()); + //入库 + UpkeepDataEntryVO dataEntryVO = new UpkeepDataEntryVO(); + dataEntryVO.setUpkeepBill(upkeepBill); + dataEntryVO.setUpkeepAssign(upkeepAssign); + dataEntryVO.setUpkeepOffer(upkeepOffer); + String result = upkeepBillService.addDataEntry(dataEntryVO,null); + if(StrUtil.isNotBlank(result)){ + throw new RuntimeException(result); + } + } + + @Override + public Result driverImport(List list) throws IOException { + //获取用户项目权限 + List projectIds = projectsService.queryAllProjectListOfUser(); + //获取所有项目 + List allProjects = projectsService.listAll(); + //获取用户 + List userList = sysUserService.list(); + List userNames = userList.stream().map(SysUser::getUsername).collect(Collectors.toList()); + //重复项-姓名全程校验重复 + Map> repeatMap = ValidatorUtil.findDuplicates(list,"username"); + Set keys = repeatMap.keySet(); + //记录失败的数据 + List failList = new ArrayList<>(); + for(int i = 0; i< list.size(); i++){ + int flag = 0; + list.get(i).validate(); + if(CollectionUtil.isNotEmpty(list.get(i).getValidationErrors())){ + flag += 1; + } + //校验项目情况 + boolean dealFlag = this.dealProject(allProjects, projectIds, list.get(i)); + if(!dealFlag){ + flag += 1; + list.get(i).setFormatErrors("1"); + } + //记录重复 + if(keys.contains(list.get(i).getUsername())){ + flag += 1; + list.get(i).putErrorMsg("存在重复的'姓名全拼(小写)'"); + list.get(i).setRepeatErrors("1"); + } + //判断人存在不 + if(userNames.contains(list.get(i).getUsername())){ + flag += 1; + list.get(i).putErrorMsg("'姓名全拼(小写)'已存在重复历史记录"); + list.get(i).setRepeatErrors("1"); + } + if(flag == 0){ + try { + //保存数据 + this.saveDriver(list.get(i)); + }catch (Exception e){ + e.printStackTrace(); + list.get(i).putErrorMsg(e.getMessage()); + list.get(i).setFormatErrors("1"); + failList.add(list.get(i)); + } + }else{ + failList.add(list.get(i)); + } + } + + //处理返回数据 + if (CollectionUtil.isNotEmpty(failList)) { + JSONObject entries = new JSONObject(); + String fielName = System.currentTimeMillis() + CommonConstant.DRIVER_IMPORT_FAIL_EXCEL_NAME; + //导出失败数据 + EasyExcel.write(failExcel + fielName, DriverImportVO.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("导入异常数据").doWrite(failList); + //格式异常行数 +// List indexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getFormatErrors())) { +// indexes.add(i+2); +// } +// } +// //数据重复 +// List repeatIndexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getRepeatErrors())) { +// repeatIndexes.add(i+2); +// } +// } + String errorMsg = "已导入"+ (list.size()-failList.size()) + "条;失败"+ failList.size() +"条;具体失败详情见失败导出信息表"; +// if(CollectionUtil.isNotEmpty(repeatIndexes)){ +// errorMsg += "第"+ repeatIndexes + "行数据重复;"; +// } +// if(CollectionUtil.isNotEmpty(indexes)){ +// errorMsg += "第"+ indexes + "行数据格式异常"; +// } + entries.set("msg",errorMsg); + entries.set("path",fielName); + return Result.ok(entries); + }else{ + return Result.ok(); + } + } + + /** + * 处理项目相关,所属项目是否存在;多个项目是否对应同一客户;是否有项目权限 + */ + public boolean dealProject(List allProjects,List projectIds, DriverImportVO vo){ + boolean flag = true; + //中文逗号隔开 + List projectNames = new ArrayList<>(); + if(StrUtil.isNotBlank(vo.getProjectNames())){ + projectNames = Arrays.asList(vo.getProjectNames().split(",")); + } + //不存在的项目 + List notExistProject = new ArrayList<>(); + //没权限的项目 + List notAuthProject = new ArrayList<>(); + //客户id + List customerIds = new ArrayList<>(); + for(String name : projectNames){ + Projects project = allProjects.stream().filter(p->p.getProjectName().equals(name)).findFirst().orElse(null); + if(Objects.isNull(project)){ + notExistProject.add(name); + }else{ + customerIds.add(project.getCustomerId()); + if(!projectIds.contains(project.getId())){ + notAuthProject.add(name); + } + List ids = vo.getProjectIds(); + if(CollectionUtil.isNotEmpty(ids)){ + ids.add(project.getId()); + }else{ + ids = CollectionUtil.newArrayList(project.getId()); + } + vo.setProjectIds(ids); + } + } + if(CollectionUtil.isNotEmpty(notExistProject)){ + vo.putErrorMsg(notExistProject.stream().collect(Collectors.joining(",")) + "项目不存在;"); + flag = false; + } + if(CollectionUtil.isNotEmpty(notAuthProject)){ + vo.putErrorMsg(notAuthProject.stream().collect(Collectors.joining(",")) + "无项目权限;"); + flag = false; + } + customerIds = customerIds.stream().distinct().collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(customerIds) && customerIds.size()>1){ + vo.putErrorMsg("存在所属项目非同一客户"); + flag = false; + } + if(CollectionUtil.isNotEmpty(customerIds)){ + vo.setCustomerId(customerIds.get(0)); + } + return flag; + } + + /** + * 保存导入用户信息 + */ + public void saveDriver(DriverImportVO vo){ + DriverUserVo item = new DriverUserVo(); + item.setAddress(vo.getAddress()); + if(StrUtil.isNotBlank(vo.getBirthday())){ + item.setBirthday(DateUtil.parse(vo.getBirthday(),"yyyy-MM-dd")); + } + item.setCustomerId(vo.getCustomerId()); + item.setEntryStatus("1"); + item.setEntryTime(DateUtil.parse(vo.getEntryTime(),"yyyy-MM-dd")); + item.setIdCard(vo.getIdCard()); + item.setName(vo.getDriverName()); + item.setPassword("Htzl@123"); + item.setPhone(vo.getPhone()); + item.setRemark(vo.getRemark()); + item.setUsername(vo.getUsername()); + item.setWorkNo(vo.getWorkNo()); + item.setProjectId(String.join(",", vo.getProjectIds())); + if("男".equals(vo.getSex())){ + item.setSex("1"); + } + if("女".equals(vo.getSex())){ + item.setSex("0"); + } + item.setCompany(vo.getCompany()); + item.setEmployeeType(vo.getEmployeeType()); + item.setAge(StrUtil.isNotBlank(vo.getAge()) ? Integer.valueOf(vo.getAge()) : null); + item.setChildrens(StrUtil.isNotBlank(vo.getChildrens()) ? Integer.valueOf(vo.getChildrens()) : null); + item.setFileNumber(vo.getFileNumber()); + //是否定位 + if("是".equals(vo.getIsPosition())){ + item.setIsPosition("1"); + } + if("否".equals(vo.getIsPosition())){ + item.setIsPosition("0"); + } + //婚姻状态 + List maritalStatusList = sysDictService.queryDictItemsByCode("marital_status"); + Map maritalStatusMap = maritalStatusList.stream().collect(Collectors.toMap(DictModel::getText, DictModel::getValue)); + item.setMaritalStatus(maritalStatusMap.getOrDefault(vo.getMaritalStatus(),null)); + + driverService.addDriverWithUser(item); + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInfoServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInfoServiceImpl.java new file mode 100644 index 0000000..9c24dc8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInfoServiceImpl.java @@ -0,0 +1,250 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.ValidateUtil; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.msg.enums.SenderTypeEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.entity.TbAccidentInsuranceInfo; +import com.gci.boot.modules.vehicles.entity.TbAccidentProgress; +import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord; +import com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper; +import com.gci.boot.modules.vehicles.query.AccidentInfoQuery; +import com.gci.boot.modules.vehicles.service.ITbAccidentInfoService; +import com.gci.boot.modules.vehicles.service.ITbAccidentInsuranceInfoService; +import com.gci.boot.modules.vehicles.service.ITbAccidentProgressService; +import com.gci.boot.modules.vehicles.service.ITbInsuranceRecordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 事故信息基础表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@Service +public class TbAccidentInfoServiceImpl extends ServiceImpl implements ITbAccidentInfoService { + + @Autowired + private TbAccidentInfoMapper accidentInfoMapper; + @Autowired + private ITbAccidentInsuranceInfoService accidentInsuranceInfoService; + @Autowired + private ITbAccidentProgressService accidentProgressService; + @Autowired + private ITbInsuranceRecordService insuranceRecordService; + @Autowired + private ITbVehicleService vehicleService; + @Autowired + private MsgPushService msgPushService; + @Autowired + private IProjectsService projectsService; + + @Override + public IPage pageBuild(Page page, AccidentInfoQuery query) { + List accidentTime = query.getAccidentTime(); + List closingTime = query.getClosingTime(); + if (ObjectUtil.isNotEmpty(accidentTime)) { + if (accidentTime.size() != 2) { + throw new GciBootException("事故发生时间必须包含起止时间!"); + } + } + if (ObjectUtil.isNotEmpty(closingTime)) { + if (closingTime.size() != 2) { + throw new GciBootException("结案时间必须包含起止时间!"); + } + } + QueryWrapper accidentInfoQueryWrapper = new QueryWrapper<>(); + accidentInfoQueryWrapper.eq(StrUtil.isNotBlank(query.getProjectId()), "tai.project_id", query.getProjectId()) + .in(StrUtil.isNotBlank(query.getPlateNumber()), "tai.plate_number", StrUtil.split(query.getPlateNumber(),StrUtil.COMMA)) + .eq(StrUtil.isNotBlank(query.getLiabilityConfirm()), "taii.liability_confirm", query.getLiabilityConfirm()) + .eq(StrUtil.isNotBlank(query.getNatureConfirm()), "taii.nature_confirm", query.getNatureConfirm()); + if (ObjectUtil.isNotEmpty(accidentTime)) { + accidentInfoQueryWrapper.between(ObjectUtil.isNotEmpty(accidentTime), "tai.accident_time", accidentTime.get(0), accidentTime.get(1)); + } + if (ObjectUtil.isNotEmpty(closingTime)) { + accidentInfoQueryWrapper.between(ObjectUtil.isNotEmpty(closingTime), "tap.closing_time", closingTime.get(0), closingTime.get(1)); + } + if (ObjectUtil.isNotEmpty(query.getCaseClosed())) { + if ("1".equals(query.getCaseClosed())) { + accidentInfoQueryWrapper.eq("tap.case_closed",query.getCaseClosed()); + } else { + accidentInfoQueryWrapper.and(i->i.eq("tap.case_closed",query.getCaseClosed()) + .or().isNull("tap.case_closed")); + } + } + if (ObjectUtil.isNotEmpty(query.getIsRecord())) { + accidentInfoQueryWrapper.eq("taii.is_record",query.getIsRecord()); + } + IPage pagebuild = accidentInfoMapper.pageBuild(page, accidentInfoQueryWrapper); + if (ObjectUtil.isNotEmpty(pagebuild.getRecords())) { + for (TbAccidentInfo record : pagebuild.getRecords()) { + if (StrUtil.isNotBlank(record.getAccidentLossType())) { + List split = StrUtil.split(record.getAccidentLossType(), StrUtil.COMMA); + record.setAccidentLossTypeList(split); + } + } + } + return pagebuild; + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void saveItem(TbAccidentInfo tbAccidentInfo) { + if (ObjectUtil.isEmpty(tbAccidentInfo.getAccidentLossTypeList())) { + tbAccidentInfo.setAccidentLossType(""); + } else { + tbAccidentInfo.setAccidentLossType(StrUtil.join(StrUtil.COMMA,tbAccidentInfo.getAccidentLossTypeList())); + } + save(tbAccidentInfo); + TbAccidentInsuranceInfo accidentInsuranceInfo = tbAccidentInfo.getAccidentInsuranceInfo(); + TbAccidentProgress accidentProgress = tbAccidentInfo.getAccidentProgress(); + if (BeanUtil.isNotEmpty(accidentInsuranceInfo)) { + accidentInsuranceInfo.setInfoId(tbAccidentInfo.getId()); + if (accidentInsuranceInfo.getIsRecord().equals(CommonConstant.YES)) { + extracted(tbAccidentInfo, accidentInsuranceInfo, accidentProgress); + } + accidentInsuranceInfoService.save(accidentInsuranceInfo); + } + if (BeanUtil.isNotEmpty(accidentProgress)) { + accidentProgress.setInfoId(tbAccidentInfo.getId()); + accidentProgressService.save(accidentProgress); + } + //微信消息推送 -- 案件进度为空或者没结案 + if(!(BeanUtil.isNotEmpty(accidentProgress) && CommonConstant.YES.equals(accidentProgress.getCaseClosed()))){ + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(tbAccidentInfo.getProjectId()); + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType() +","+SenderTypeEnum.CUSTOMER.getSendType(),tbAccidentInfo.getId(), + tbAccidentInfo.getProjectId(), WorkOrderType.ACCIDENT.getType(),"未结案", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "新增事故,请及时查看")); + }); + } + } + + private void extracted(TbAccidentInfo tbAccidentInfo, TbAccidentInsuranceInfo accidentInsuranceInfo, TbAccidentProgress accidentProgress) { + TbInsuranceRecord tbInsuranceRecord = new TbInsuranceRecord(); + BeanUtil.copyProperties(accidentInsuranceInfo,tbInsuranceRecord); + TbInsuranceRecord r = insuranceRecordService.getOne(new LambdaQueryWrapper().eq(TbInsuranceRecord::getInfoId, tbAccidentInfo.getId()).or().eq(TbInsuranceRecord::getInsuranceNo,tbAccidentInfo.getReportNumber())); + if (BeanUtil.isNotEmpty(r)) { + tbInsuranceRecord.setId(r.getId()); + } else { + tbInsuranceRecord.setId(null); + } + + TbVehicle one = vehicleService.getOne(new LambdaQueryWrapper().eq(TbVehicle::getPlateNumber, tbAccidentInfo.getPlateNumber())); + if (BeanUtil.isEmpty(one)) { + throw new GciBootException("车牌号错误!"); + } else { + tbInsuranceRecord.setVehicleId(one.getId()); + tbInsuranceRecord.setVehicleType(one.getVehicleType()); + tbInsuranceRecord.setProjectId(one.getProjectId()); + } + tbInsuranceRecord.setHandleUser(tbAccidentInfo.getProcessedPerson()); + tbInsuranceRecord.setHandleStatus(CommonConstant.YES); + tbInsuranceRecord.setInsuranceNo(tbAccidentInfo.getReportNumber()); + tbInsuranceRecord.setInsurancePrice(accidentInsuranceInfo.getTotalAmountActuallyIncurred()); + + if (StrUtil.isNotBlank(accidentInsuranceInfo.getDocumentImage())) { + tbInsuranceRecord.setCompensateUrl(accidentInsuranceInfo.getDocumentImage()); + } + if (BeanUtil.isNotEmpty(accidentProgress)) { + if (StrUtil.isNotBlank(accidentProgress.getAccidentCertificatePhoto())) { + tbInsuranceRecord.setAccidentUrl(accidentProgress.getAccidentCertificatePhoto()); + } + if (StrUtil.isNotBlank(accidentProgress.getCompensationAgreementPhoto())) { + tbInsuranceRecord.setCompensateAgreementUrl(accidentProgress.getAccidentCertificatePhoto()); + } + if (StrUtil.isNotBlank(accidentProgress.getLossAssessmentPhoto())) { + tbInsuranceRecord.setLossAssessmentUrl(accidentProgress.getLossAssessmentPhoto()); + } + if (StrUtil.isNotBlank(accidentProgress.getOtherPhoto())) { + tbInsuranceRecord.setOtherUrl(accidentProgress.getOtherPhoto()); + } + } + String valid = ValidateUtil.valid(tbInsuranceRecord, SaveValidated.class); + if (StrUtil.isNotBlank(valid)) { + throw new GciBootException(valid); + } + if (StrUtil.isBlank(tbInsuranceRecord.getId())) { + insuranceRecordService.save(tbInsuranceRecord); + } else { + insuranceRecordService.updateById(tbInsuranceRecord); + } + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void updateItem(TbAccidentInfo tbAccidentInfo) { + if (ObjectUtil.isEmpty(tbAccidentInfo.getAccidentLossTypeList())) { + tbAccidentInfo.setAccidentLossType(""); + } else { + tbAccidentInfo.setAccidentLossType(StrUtil.join(StrUtil.COMMA,tbAccidentInfo.getAccidentLossTypeList())); + } + updateById(tbAccidentInfo); + TbAccidentInsuranceInfo accidentInsuranceInfo = tbAccidentInfo.getAccidentInsuranceInfo(); + TbAccidentProgress accidentProgress = tbAccidentInfo.getAccidentProgress(); + if (BeanUtil.isNotEmpty(accidentInsuranceInfo)) { + accidentInsuranceInfo.setInfoId(tbAccidentInfo.getId()); + if (StrUtil.isNotBlank(accidentInsuranceInfo.getId())) { + TbAccidentInsuranceInfo byId = accidentInsuranceInfoService.getById(accidentInsuranceInfo.getId()); + if (accidentInsuranceInfo.getIsRecord().equals(CommonConstant.YES) || byId.getIsRecord().equals(CommonConstant.YES)) { + accidentInsuranceInfo.setIsRecord(CommonConstant.YES); + extracted(tbAccidentInfo, accidentInsuranceInfo, accidentProgress); + } + accidentInsuranceInfoService.updateById(accidentInsuranceInfo); + } else { + if (accidentInsuranceInfo.getIsRecord().equals(CommonConstant.YES)) { + extracted(tbAccidentInfo, accidentInsuranceInfo, accidentProgress); + } + accidentInsuranceInfoService.save(accidentInsuranceInfo); + } + } + if (BeanUtil.isNotEmpty(accidentProgress)) { + accidentProgress.setInfoId(tbAccidentInfo.getId()); + if (StrUtil.isNotBlank(accidentProgress.getId())) { + accidentProgressService.updateById(accidentProgress); + } else { + accidentProgressService.save(accidentProgress); + } + } + } + + @Override + public void removeItem(String id) { + removeById(id); + accidentInsuranceInfoService.remove(new LambdaQueryWrapper().eq(TbAccidentInsuranceInfo::getInfoId,id)); + accidentProgressService.remove(new LambdaQueryWrapper().eq(TbAccidentProgress::getInfoId,id)); + } + + @Override + public TbAccidentInfo getItemById(String id) { + return accidentInfoMapper.getItemById(id); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInsuranceInfoServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInsuranceInfoServiceImpl.java new file mode 100644 index 0000000..9c2bf33 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentInsuranceInfoServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.gci.boot.modules.vehicles.entity.TbAccidentInsuranceInfo; +import com.gci.boot.modules.vehicles.mapper.TbAccidentInsuranceInfoMapper; +import com.gci.boot.modules.vehicles.service.ITbAccidentInsuranceInfoService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 事故保险信息 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@Service +public class TbAccidentInsuranceInfoServiceImpl extends ServiceImpl implements ITbAccidentInsuranceInfoService { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentProgressServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentProgressServiceImpl.java new file mode 100644 index 0000000..da23429 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAccidentProgressServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.gci.boot.modules.vehicles.entity.TbAccidentProgress; +import com.gci.boot.modules.vehicles.mapper.TbAccidentProgressMapper; +import com.gci.boot.modules.vehicles.service.ITbAccidentProgressService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 事件进度信息 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-13 + */ +@Service +public class TbAccidentProgressServiceImpl extends ServiceImpl implements ITbAccidentProgressService { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionInfoServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionInfoServiceImpl.java new file mode 100644 index 0000000..95d099b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionInfoServiceImpl.java @@ -0,0 +1,309 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.annotation.importHandler.ExcelTypeHandler; +import com.gci.boot.annotation.importHandler.MyExcelVerifyHandler; +import com.gci.boot.common.validated.ImportValidated; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.mapper.ProjectsMapper; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionRemind; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionInfoMapper; +import com.gci.boot.modules.vehicles.query.AnnualInspectionInfoQuery; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionInfoService; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionRemindService; +import com.gci.boot.modules.vehicles.service.ITbViolationRecordService; + +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ImportParams; +import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.text.StrBuilder; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; + +/** + *

+ * 年检信息表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-20 + */ +@Service +public class TbAnnualInspectionInfoServiceImpl extends ServiceImpl + implements ITbAnnualInspectionInfoService { + + @Autowired + private TbAnnualInspectionInfoMapper annualInspectionInfoMapper; + @Autowired + private ITbVehicleService vehicleService; + @Resource + private ITbViolationRecordService violationRecordService; + @Resource + private TbAccidentInfoMapper accidentInfoMapper; + @Autowired + private ITbAnnualInspectionRemindService annualInspectionRemindService; + @Autowired + private ProjectsMapper projectsMapper; + @Autowired + private MyExcelVerifyHandler myExcelVerifyHandler; + + @Value("${failExcel}") + private String failExcel; + + @Override + public IPage pageBuild(Page page, AnnualInspectionInfoQuery query) { + checkTime(query); + return annualInspectionInfoMapper.pageBuild(page, query); + } + + private void checkTime(AnnualInspectionInfoQuery query) { + List time = query.getTime(); + if (ObjectUtil.isNotEmpty(time)) { + if (time.size() != 2) { + throw new GciBootException("年审有效期必须包括起止时间!"); + } + if (DateUtil.between(time.get(0), time.get(1), DateUnit.MS, false) < 0) { + throw new GciBootException("开始时间不能大于结束时间!"); + } + } + } + + @Override + public IPage remindList(Page page, + AnnualInspectionInfoQuery query) { + checkTime(query); + IPage tbAnnualInspectionInfoIPage = annualInspectionInfoMapper.remindList(page, query); + for (TbAnnualInspectionInfo record : tbAnnualInspectionInfoIPage.getRecords()) { + Integer days = record.getDays(); + if (days > 0) { + record.setDaysToOverdue(days); + } else { + record.setOverdueDays(-days); + } + int violationCount = violationRecordService.count(new LambdaQueryWrapper() + .eq(TbViolationRecord::getPlateNumber, record.getPlateNumber()) + .eq(TbViolationRecord::getHandleResult, 0)); + record.setViolationCount(violationCount); + Integer integer = accidentInfoMapper.countAccidentNotClose( + new QueryWrapper().eq("tai.plate_number", record.getPlateNumber()) + .and(i -> i.eq("tap.case_closed", CommonConstant.NO).or().isNull("tap.case_closed"))); + record.setAccidentCount(integer); + } + return tbAnnualInspectionInfoIPage; + } + + @Override + public void init() { + List list = vehicleService.list(); + + ArrayList annualInspectionInfoArrayList = new ArrayList<>(); + ArrayList strings = new ArrayList<>(); + for (TbVehicle vehicle : list) { + TbAnnualInspectionInfo annualInspectionInfo = new TbAnnualInspectionInfo(); + annualInspectionInfo.setPlateNumber(vehicle.getPlateNumber()); + if (StrUtil.isBlank(vehicle.getProjectId())) { + strings.add(vehicle.getPlateNumber()); + continue; + } + annualInspectionInfo.setProjectId(vehicle.getProjectId()); + annualInspectionInfo.setProcessedPerson("系统"); + annualInspectionInfo.setHandlingDate(vehicle.getDeliveryTime()); + annualInspectionInfo + .setValidityPeriod(DateUtil.offset(vehicle.getDeliveryTime(), DateField.DAY_OF_YEAR, 365)); + annualInspectionInfo.setServiceFee(BigDecimal.ZERO); + annualInspectionInfo.setMiscellaneousFee(BigDecimal.ZERO); + annualInspectionInfo.setTestingFee(BigDecimal.ZERO); + annualInspectionInfo.setTotalFee(BigDecimal.ZERO); + annualInspectionInfoArrayList.add(annualInspectionInfo); + } + if (ObjectUtil.isNotEmpty(strings)) { + log.warn("无项目车辆" + strings.toString()); + } + saveBatch(annualInspectionInfoArrayList); + } + + @Override + public TbAnnualInspectionInfo getLastYear(String plateNumber) { + TbAnnualInspectionInfo one = getOne( + new LambdaQueryWrapper().eq(TbAnnualInspectionInfo::getPlateNumber, plateNumber) + .orderByDesc(TbAnnualInspectionInfo::getValidityPeriod).last("limit 1")); + if (BeanUtil.isEmpty(one)) { + one = new TbAnnualInspectionInfo(); + one.setServiceFee(BigDecimal.ZERO); + one.setTestingFee(BigDecimal.ZERO); + one.setTotalFee(BigDecimal.ZERO); + one.setMiscellaneousFee(BigDecimal.ZERO); + } + return one; + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void saveItem(TbAnnualInspectionInfo tbAnnualInspectionInfo) { + save(tbAnnualInspectionInfo); + TbAnnualInspectionRemind annualInspectionRemind = + annualInspectionRemindService.buildRemind(tbAnnualInspectionInfo); + annualInspectionRemindService.save(annualInspectionRemind); + annualInspectionRemindService.recalculate(tbAnnualInspectionInfo.getPlateNumber()); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void updateItem(TbAnnualInspectionInfo tbAnnualInspectionInfo) { + updateById(tbAnnualInspectionInfo); + TbAnnualInspectionRemind accidentInsuranceRemind = + annualInspectionRemindService.findRemind(tbAnnualInspectionInfo); + if (accidentInsuranceRemind != null) { + annualInspectionRemindService.updateById(accidentInsuranceRemind); + annualInspectionRemindService.recalculate(tbAnnualInspectionInfo.getPlateNumber()); + } else { + TbAnnualInspectionRemind annualInspectionRemind = + annualInspectionRemindService.buildRemind(tbAnnualInspectionInfo); + annualInspectionRemindService.save(annualInspectionRemind); + annualInspectionRemindService.recalculate(tbAnnualInspectionInfo.getPlateNumber()); + } + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void removeItem(String id) { + TbAnnualInspectionInfo byId = getById(id); + if (BeanUtil.isEmpty(byId)) { + throw new GciBootException("id错误!"); + } + removeById(id); + annualInspectionRemindService + .remove(new LambdaQueryWrapper().eq(TbAnnualInspectionRemind::getInfoId, id)); + annualInspectionRemindService.recalculate(byId.getPlateNumber()); + } + + @Override + public Result listImport(MultipartFile file) throws IOException { + LoginUser loginUser = (LoginUser)SecurityUtils.getSubject().getPrincipal(); + String realname = loginUser.getRealname(); + + String name = "车辆年检导出错误"+System.currentTimeMillis()+".xlsx"; + + JSONObject entries = new JSONObject(); + + // 有权限项目 + List list = projectsMapper.getAllProjects(); + // 有权限的车辆 + List tbVehicles = new ArrayList<>(); + if (!list.isEmpty()) { + tbVehicles = vehicleService.list(new LambdaQueryWrapper().in(TbVehicle::getProjectId, + list.stream().map(Projects::getId).collect(Collectors.toList()))); + } + Map plateNumberProjectId = + tbVehicles.stream().collect(Collectors.toMap(TbVehicle::getPlateNumber, TbVehicle::getProjectId)); + + List annualInspectionInfoList = this.list(); + + ImportParams importParams = new ImportParams(); + importParams.setNeedVerify(true); + importParams.setVerifyGroup(new Class[] {ImportValidated.class}); + importParams.setVerifyHandler(myExcelVerifyHandler); + + ArrayList excelTypeHandlers = new ArrayList<>(); + + List v = new ArrayList<>(); + v.add("plateNumber"); + v.add("validityPeriod"); + ExcelTypeHandler excelTypeHandler1 = new ExcelTypeHandler(v, true, annualInspectionInfoList, "车牌号,有效期重复!"); + excelTypeHandlers.add(excelTypeHandler1); + + List p = new ArrayList<>(); + p.add("plateNumber"); + List collect = tbVehicles.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList()); + ExcelTypeHandler excelTypeHandler2 = new ExcelTypeHandler(p, collect, "无对应车辆权限或车辆不存在系统内!"); + excelTypeHandlers.add(excelTypeHandler2); + myExcelVerifyHandler.setList(excelTypeHandlers); + + InputStream inputStream = file.getInputStream(); + try { + ExcelImportResult result = + ExcelImportUtil.importExcelMore(inputStream, TbAnnualInspectionInfo.class, importParams); + + List failList = result.getFailList(); + List successList = result.getList(); + // 成功的数据处理 + if (!successList.isEmpty()) { + for (TbAnnualInspectionInfo annualInspectionInfo : successList) { + if (StrUtil.isBlank(annualInspectionInfo.getProcessedPerson())) { + annualInspectionInfo.setProcessedPerson(realname); + } + BigDecimal total = NumberUtil.add(annualInspectionInfo.getServiceFee(), + annualInspectionInfo.getMiscellaneousFee(), annualInspectionInfo.getTestingFee()); + annualInspectionInfo.setTotalFee(total); + annualInspectionInfo.setProjectId(plateNumberProjectId.get(annualInspectionInfo.getPlateNumber())); + } + saveBatch(successList); + annualInspectionRemindService.init(); + } + + if (!failList.isEmpty()) { + Workbook failWorkbook = result.getFailWorkbook(); + String fullPath = failExcel + name; + FileOutputStream fileOutputStream = new FileOutputStream(fullPath); + failWorkbook.write(fileOutputStream); + fileOutputStream.close(); + String errorMsg = StrUtil.format("已导入{}条;失败{}条;具体失败详情见失败导出信息表;", successList.size(), failList.size()); + entries.set("msg", errorMsg); + entries.set("path", name); + return Result.ok(entries); + } + + } catch (Exception e) { + e.printStackTrace(); + throw new GciBootException("导入失败请联系管理员!"); + } finally { + inputStream.close(); + ThreadLocal> threadLocal = myExcelVerifyHandler.getThreadLocal(); + if (threadLocal != null) { + threadLocal.remove(); + } + } + return Result.ok(); + } + + private HashSet getValues(String key) { + return new HashSet(); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionRemindServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionRemindServiceImpl.java new file mode 100644 index 0000000..bba3cb2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbAnnualInspectionRemindServiceImpl.java @@ -0,0 +1,240 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionRemind; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.mapper.TbAccidentInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbAnnualInspectionRemindMapper; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionInfoService; +import com.gci.boot.modules.vehicles.service.ITbAnnualInspectionRemindService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.service.ITbViolationRecordService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 年检提醒 服务实现类 + *

+ * + * @author 2464 + * @since 2023-11-16 + */ +@Service +public class TbAnnualInspectionRemindServiceImpl extends ServiceImpl implements ITbAnnualInspectionRemindService { + + @Resource + private TbAnnualInspectionRemindMapper annualInspectionRemindMapper; + @Resource + private ITbViolationRecordService violationRecordService; + @Resource + private TbAccidentInfoMapper accidentInfoMapper; + @Autowired + @Lazy + private ITbAnnualInspectionInfoService annualInspectionInfoService; + + @Override + public void recalculate(String plateNumber) { + LambdaQueryWrapper eq = new LambdaQueryWrapper().eq(TbAnnualInspectionRemind::getPlateNumber, plateNumber); + List list = list(eq); + + List needUpdate = new ArrayList<>(); + if (list.size() > 0) { + //有效期倒序 + list.sort(Comparator.comparing(TbAnnualInspectionRemind::getValidityPeriod).reversed()); + boolean target = false; + DateTime dateTime = DateUtil.beginOfDay(new DateTime()); + if (list.size() == 0) { + return; + } + for (int i = 0; i < list.size(); i++) { + TbAnnualInspectionRemind annualInspectionRemind = list.get(i); + int between = Convert.toInt(DateUtil.between(annualInspectionRemind.getValidityPeriod(), dateTime, DateUnit.DAY, false)); + String remindStatus = annualInspectionRemind.getRemindStatus(); + String overdueType = annualInspectionRemind.getOverdueType(); + + + if (i == 0) { + //已过期 + if ("0".equals(remindStatus)) { + //改为提醒中 + annualInspectionRemind.setRemindStatus("1"); + } + if (between > 0) { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(between); + annualInspectionRemind.setOverdueType("2"); + annualInspectionRemind.setRemindStatus("1"); + } else if (between < 0) { + annualInspectionRemind.setDaysToOverdue(-between); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } else { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } + target = true; + needUpdate.add(annualInspectionRemind); + } else { + if (target) { + //其他数据提醒中改为已过期 + if ("1".equals(remindStatus)) { + annualInspectionRemind.setRemindStatus("0"); + needUpdate.add(annualInspectionRemind); + } + } + } + } + if (needUpdate.size() > 0) { + updateBatchById(needUpdate); + } + } + } + + @Override + public IPage pageBuild(Page page, LambdaQueryWrapper lambdaQueryWrapper) { + lambdaQueryWrapper.eq(TbAnnualInspectionRemind::getDelFlag,CommonConstant.DEL_FLAG_0) + .le(TbAnnualInspectionRemind::getDaysToOverdue,60); + IPage annualInspectionRemindIPage = annualInspectionRemindMapper.pageBuild(page,lambdaQueryWrapper); + for (TbAnnualInspectionRemind record : annualInspectionRemindIPage.getRecords()) { + int violationCount = violationRecordService.count(new LambdaQueryWrapper().eq(TbViolationRecord::getPlateNumber, record.getPlateNumber()).eq(TbViolationRecord::getHandleResult, 0)); + record.setViolationCount(violationCount); + Integer integer = accidentInfoMapper.countAccidentNotClose(new QueryWrapper().eq("tai.plate_number", record.getPlateNumber()).and(i -> i.eq("tap.case_closed", CommonConstant.NO) + .or().isNull("tap.case_closed"))); + record.setAccidentCount(integer); + } + return annualInspectionRemindIPage; + } + + @Override + public void updateDate() { + DateTime dateTime = DateUtil.beginOfDay(new DateTime()); + LambdaQueryWrapper eq = new LambdaQueryWrapper().eq(TbAnnualInspectionRemind::getRemindStatus, '1'); + List list = list(eq); + for (TbAnnualInspectionRemind annualInspectionRemind : list) { + int between = Convert.toInt(DateUtil.between(annualInspectionRemind.getValidityPeriod(), dateTime, DateUnit.DAY, false)); + if (between > 0) { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(between); + annualInspectionRemind.setOverdueType("2"); + annualInspectionRemind.setRemindStatus("1"); + } else if (between < 0) { + annualInspectionRemind.setDaysToOverdue(-between); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } else { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } + } + updateBatchById(list); + } + + @Override + public void init() { + List list = annualInspectionInfoService.list(); + + List inspectionReminds = list(); + List collect = inspectionReminds.stream().map(TbAnnualInspectionRemind::getInfoId).collect(Collectors.toList()); + List needAdd = new ArrayList(); + + List annualInspectionInfoList = list.stream().filter(i -> !collect.contains(i.getId())).collect(Collectors.toList()); + + for (TbAnnualInspectionInfo annualInspectionInfo : annualInspectionInfoList) { + TbAnnualInspectionRemind annualInspectionRemind = buildRemind(annualInspectionInfo); + needAdd.add(annualInspectionRemind); + } + saveBatch(needAdd); + List collect1 = needAdd.stream().map(TbAnnualInspectionRemind::getPlateNumber).distinct().collect(Collectors.toList()); + for (String s : collect1) { + recalculate(s); + } + + } + + + @Override + public TbAnnualInspectionRemind buildRemind(TbAnnualInspectionInfo tbAnnualInspectionInfo) { + DateTime dateTime = DateUtil.beginOfDay(new DateTime()); + long between = DateUtil.between(tbAnnualInspectionInfo.getValidityPeriod(), dateTime, DateUnit.DAY,false); + + TbAnnualInspectionRemind annualInspectionRemind = new TbAnnualInspectionRemind(); + BeanUtil.copyProperties(tbAnnualInspectionInfo,annualInspectionRemind); + annualInspectionRemind.setInfoId(annualInspectionRemind.getId()); + annualInspectionRemind.setId(null); + if (between > 0) { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(Convert.toInt(between)); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } else if (between < 0) { + annualInspectionRemind.setDaysToOverdue(Convert.toInt(-between)); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("2"); + annualInspectionRemind.setRemindStatus("1"); + } else { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } + return annualInspectionRemind; + + } + + @Override + public TbAnnualInspectionRemind findRemind(TbAnnualInspectionInfo tbAnnualInspectionInfo) { + LambdaQueryWrapper eq = new LambdaQueryWrapper().eq(TbAnnualInspectionRemind::getInfoId, tbAnnualInspectionInfo.getId()).last("limit 1"); + TbAnnualInspectionRemind annualInspectionRemind = getOne(eq); + if (BeanUtil.isNotEmpty(annualInspectionRemind)) { + annualInspectionRemind.setPlateNumber(tbAnnualInspectionInfo.getPlateNumber()); + annualInspectionRemind.setValidityPeriod(tbAnnualInspectionInfo.getValidityPeriod()); + DateTime dateTime = DateUtil.beginOfDay(new DateTime()); + long between = DateUtil.between(tbAnnualInspectionInfo.getValidityPeriod(), dateTime, DateUnit.DAY,false); + if (between > 0) { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(Convert.toInt(between)); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } else if (between < 0) { + annualInspectionRemind.setDaysToOverdue(Convert.toInt(-between)); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("2"); + annualInspectionRemind.setRemindStatus("1"); + } else { + annualInspectionRemind.setDaysToOverdue(0); + annualInspectionRemind.setOverdueDays(0); + annualInspectionRemind.setOverdueType("1"); + annualInspectionRemind.setRemindStatus("1"); + } + return annualInspectionRemind; + } else { + return null; + } + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateOutPartServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateOutPartServiceImpl.java new file mode 100644 index 0000000..c61624a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateOutPartServiceImpl.java @@ -0,0 +1,11 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplateOutPart; +import com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplateOutPartMapper; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplateOutPartService; +import org.springframework.stereotype.Service; + +@Service +public class TbConsumablesTemplateOutPartServiceImpl extends ServiceImpl implements ITbConsumablesTemplateOutPartService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplatePartServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplatePartServiceImpl.java new file mode 100644 index 0000000..32b51cb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplatePartServiceImpl.java @@ -0,0 +1,270 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplate; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplateOutPart; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplatePart; +import com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplateOutPartMapper; +import com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplatePartMapper; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplateOutPartService; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplatePartService; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplateService; + +import cn.hutool.core.text.StrBuilder; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; + +/** + *

+ * 耗材详情 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Service +public class TbConsumablesTemplatePartServiceImpl + extends ServiceImpl + implements ITbConsumablesTemplatePartService { + + @Autowired + @Lazy + private ITbConsumablesTemplateService templateService; + @Autowired + private ITbConsumablesTemplateOutPartService outPartService; + @Autowired + private TbConsumablesTemplateOutPartMapper outPartMapper; + + @Override + @Transactional(rollbackFor = {Exception.class}) + public void init() { + List list = templateService.list(); + List list1 = list(); + for (TbConsumablesTemplatePart part : list1) { + part.setRemainingQuantity(part.getQuantity()); + for (TbConsumablesTemplate tbConsumablesTemplate : list) { + if (StrUtil.isNotBlank(part.getTemplateId())) { + if (part.getTemplateId().equals(tbConsumablesTemplate.getId())) { + part.setProjectId(tbConsumablesTemplate.getProjectId()); + } + } + } + } + updateBatchById(list1); + } + + @Override + public IPage pageBuild(Page page, + LambdaQueryWrapper lambdaQueryWrapper, boolean onlyHadQuantity) { + if (onlyHadQuantity) { + lambdaQueryWrapper.ge(TbConsumablesTemplatePart::getRemainingQuantity, 0) + .orderByAsc(TbConsumablesTemplatePart::getStorageTime); + } + Page partPage = page(page, lambdaQueryWrapper); + List records = partPage.getRecords(); + + // 查找对应出库记录 + List collect = records.stream().map(TbConsumablesTemplatePart::getId).collect(Collectors.toList()); + List outPartList = new ArrayList<>(); + if (!collect.isEmpty()) { + outPartList = outPartService.list(new LambdaQueryWrapper() + .in(TbConsumablesTemplateOutPart::getPartId, collect) + .orderByDesc(TbConsumablesTemplateOutPart::getOutStorageTime)); + } + + Map> collect1 = + outPartList.stream().collect(Collectors.groupingBy(TbConsumablesTemplateOutPart::getPartId)); + for (TbConsumablesTemplatePart record : records) { + List tbConsumablesTemplateOutParts = collect1.get(record.getId()); + Integer count = 0; + if (ObjectUtil.isNotEmpty(tbConsumablesTemplateOutParts)) { + // 赋值补充参数 + for (TbConsumablesTemplateOutPart tbConsumablesTemplateOutPart : tbConsumablesTemplateOutParts) { + tbConsumablesTemplateOutPart.setName(record.getName()); + tbConsumablesTemplateOutPart.setUnits(record.getUnits()); + tbConsumablesTemplateOutPart.setSpecification(record.getSpecification()); + tbConsumablesTemplateOutPart.setProjectId(record.getProjectId()); + if (tbConsumablesTemplateOutPart.getOutQuantity() != null) { + count = count + tbConsumablesTemplateOutPart.getOutQuantity(); + } + } + record.setOutQuantityCount(count); + record.setOutPartList(tbConsumablesTemplateOutParts); + } + } + return partPage; + } + + @Override + public void inStorage(List partList) { + + List list = + list(new LambdaQueryWrapper().in(TbConsumablesTemplatePart::getProjectId, + partList.stream().map(TbConsumablesTemplatePart::getProjectId).collect(Collectors.toList()))); + for (TbConsumablesTemplatePart part : partList) { + for (TbConsumablesTemplatePart t : list) { + if (part.getProjectId().equals(t.getProjectId()) && part.getName().equals(t.getName()) + && part.getStorageTime().equals(t.getStorageTime()) + && part.getSpecification().equals(t.getSpecification()) + && part.getSupplier().equals(t.getSupplier())) { + throw new GciBootException("同一项目内相同耗材出库日期不能重复!"); + } + } + } + + List copyPartList = new ArrayList<>(); + StrBuilder strBuilder = new StrBuilder(); + for (int i = 0; i < partList.size(); i++) { + TbConsumablesTemplatePart part = partList.get(i); + String s = part.getName() + part.getStorageTime(); + if (copyPartList.contains(s)) { + strBuilder.append(String.valueOf(i + 1)).append("行与列表内数据重复!"); + } + copyPartList.add(s); + part.setRemainingQuantity(part.getQuantity()); + } + if (!strBuilder.isEmpty()) { + throw new GciBootException(strBuilder.toString()); + } else { + saveBatch(partList); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void outStorage(List partList) { + Map> collect = + partList.stream().collect(Collectors.groupingBy(TbConsumablesTemplateOutPart::getPartId)); + Set strings = collect.keySet(); + // 需要先和测试环境数据进行重复校验 + List list1 = + outPartService.list(new LambdaQueryWrapper() + .in(TbConsumablesTemplateOutPart::getPartId, strings)); + list1.addAll(partList); + Map collect1 = list1.stream() + .collect(Collectors.groupingBy(p -> p.getName() + "_" + p.getPartId() + "_" + p.getOutStorageTime() + + "_" + p.getSupplier() + "_" + p.getSupplier(), Collectors.counting())) + .entrySet().stream().filter(e -> e.getValue() > 1) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + if (!collect1.isEmpty()) { + throw new GciBootException("同一项目内相同耗材出库日期不能重复!"); + } + List list = + list(new LambdaQueryWrapper().in(TbConsumablesTemplatePart::getId, strings)); + if (list.size() != strings.size()) { + throw new GciBootException("存在非法id!"); + } + for (TbConsumablesTemplatePart inPart : list) { + List tbConsumablesTemplateOutParts = collect.get(inPart.getId()); + if (ObjectUtil.isNotEmpty(tbConsumablesTemplateOutParts)) { + for (TbConsumablesTemplateOutPart tbConsumablesTemplateOutPart : tbConsumablesTemplateOutParts) { + if (tbConsumablesTemplateOutPart.getOutStorageTime().before(inPart.getStorageTime())) { + throw new GciBootException("出库时间不能大于入库时间!"); + } + } + } + } + ArrayList needUpdate = new ArrayList<>(); + ArrayList needOutAdd = new ArrayList<>(); + ArrayList needOutUpdate = new ArrayList<>(); + checkAndBuild(collect, list, needUpdate, needOutAdd, needOutUpdate); + updateBatchById(needUpdate); + outPartService.saveBatch(needOutAdd); + } + + private void checkAndBuild(Map> collect, + List list, ArrayList needUpdate, + ArrayList needOutAdd, ArrayList needOutUpdate) { + for (Map.Entry> stringListEntry : collect.entrySet()) { + String key = stringListEntry.getKey(); + List value = stringListEntry.getValue(); + TbConsumablesTemplatePart part = list.stream().filter(l -> l.getId().equals(key)).findFirst().get(); + // 名字和日期校验 + Map collect1 = value.stream() + .collect(Collectors.groupingBy(p -> p.getName() + "_" + p.getPartId() + "_" + p.getOutStorageTime() + + "_" + p.getSupplier() + "_" + p.getSupplier(), Collectors.counting())) + .entrySet().stream().filter(e -> e.getValue() > 1) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + if (!collect1.isEmpty()) { + throw new GciBootException("同一项目内相同耗材出库日期不能重复!"); + } + + // 数量校验 + Integer totalOut = value.stream().mapToInt(TbConsumablesTemplateOutPart::getOutQuantity).sum(); + int residue = part.getRemainingQuantity() - totalOut; + part.setRemainingQuantity(residue); + if (residue < 0) { + throw new GciBootException(part.getName() + "剩余库存不足!"); + } else { + part.setRemainingQuantity(residue); + needUpdate.add(part); + for (TbConsumablesTemplateOutPart tbConsumablesTemplateOutPart : value) { + if (StrUtil.isBlank(tbConsumablesTemplateOutPart.getId())) { + needOutAdd.add(tbConsumablesTemplateOutPart); + } else { + needOutUpdate.add(tbConsumablesTemplateOutPart); + } + } + } + + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void inAndOutStorage(TbConsumablesTemplatePart part) { + // 因为页面上既可以编辑入库信息又可以编辑出库信息 + // 所有只需要以前端数据为主进行校验 + // 前端传过来的数据 + List outPartList = part.getOutPartList(); + + Map> collect = + outPartList.stream().collect(Collectors.groupingBy(TbConsumablesTemplateOutPart::getPartId)); + Set strings = collect.keySet(); + List list = + list(new LambdaQueryWrapper().in(TbConsumablesTemplatePart::getId, strings)); + if (list.size() != strings.size() || list.size() > 1) { + throw new GciBootException("存在非法id!"); + } + // 以前端数据为主 + list.clear(); + list.add(part); + for (TbConsumablesTemplatePart inPart : list) { + List tbConsumablesTemplateOutParts = collect.get(inPart.getId()); + if (ObjectUtil.isNotEmpty(tbConsumablesTemplateOutParts)) { + for (TbConsumablesTemplateOutPart tbConsumablesTemplateOutPart : tbConsumablesTemplateOutParts) { + if (tbConsumablesTemplateOutPart.getOutStorageTime().before(inPart.getStorageTime())) { + throw new GciBootException("出库时间不能大于入库时间!"); + } + } + } + } + part.setRemainingQuantity(part.getQuantity()); + ArrayList needUpdate = new ArrayList<>(); + ArrayList needOutAdd = new ArrayList<>(); + ArrayList needOutUpdate = new ArrayList<>(); + checkAndBuild(collect, list, needUpdate, needOutAdd, needOutUpdate); + updateBatchById(needUpdate); + outPartService.updateBatchById(needOutUpdate); + outPartService.saveBatch(needOutAdd); + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateServiceImpl.java new file mode 100644 index 0000000..8ad9deb --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbConsumablesTemplateServiceImpl.java @@ -0,0 +1,132 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplate; +import com.gci.boot.modules.vehicles.entity.TbConsumablesTemplatePart; +import com.gci.boot.modules.vehicles.mapper.TbConsumablesTemplateMapper; +import com.gci.boot.modules.vehicles.query.ConsumablesTemplateQuery; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplatePartService; +import com.gci.boot.modules.vehicles.service.ITbConsumablesTemplateService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.vo.ConsumablesTemplateVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 耗材模板 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Service +public class TbConsumablesTemplateServiceImpl extends ServiceImpl implements ITbConsumablesTemplateService { + + @Autowired + private ITbConsumablesTemplatePartService consumablesTemplatePartService; + + @Autowired + private IProjectsService projectsService; + + @Resource + private TbConsumablesTemplateMapper consumablesTemplateMapper; + + @Override + public IPage pageBuild(Page page, ConsumablesTemplateQuery query) { + IPage list = consumablesTemplateMapper.listVo(page,query); + return list; + } + + @Override + public void saveItem(TbConsumablesTemplate tbConsumablesTemplate) { + check(tbConsumablesTemplate); + save(tbConsumablesTemplate); + List projectList = tbConsumablesTemplate.getPartList(); + projectList.forEach(p->p.setTemplateId(tbConsumablesTemplate.getId())); + consumablesTemplatePartService.saveBatch(projectList); + } + + private void check(TbConsumablesTemplate tbConsumablesTemplate) { + Projects byId = projectsService.getById(tbConsumablesTemplate.getProjectId()); + if ("0".equals(byId.getStatus())) { + throw new GciBootException("该项目已禁用,请重新选择!"); + } + List partList = tbConsumablesTemplate.getPartList(); + long count = partList.stream().map(TbConsumablesTemplatePart::getName).distinct().count(); + if (count list = consumablesTemplatePartService.list(new LambdaQueryWrapper().eq(TbConsumablesTemplatePart::getTemplateId, tbConsumablesTemplate.getId())); + List collect = null; + if (ObjectUtil.isNotEmpty(list)) { + collect = list.stream().map(TbConsumablesTemplatePart::getId).collect(Collectors.toList()); + } + List partList = tbConsumablesTemplate.getPartList(); + ArrayList needAdd = new ArrayList<>(); + ArrayList needEdit = new ArrayList<>(); + for (TbConsumablesTemplatePart tbConsumablesTemplatePart : partList) { + if (StrUtil.isBlank(tbConsumablesTemplatePart.getId())) { + tbConsumablesTemplatePart.setTemplateId(tbConsumablesTemplate.getId()); + needAdd.add(tbConsumablesTemplatePart); + } else { + if (ObjectUtil.isNotEmpty(collect)) { + if (collect.contains(tbConsumablesTemplatePart.getId())) { + tbConsumablesTemplatePart.setTemplateId(tbConsumablesTemplate.getId()); + needEdit.add(tbConsumablesTemplatePart); + collect.remove(tbConsumablesTemplatePart.getId()); + } + } + } + } + if (ObjectUtil.isNotEmpty(needAdd)) { + consumablesTemplatePartService.saveBatch(needAdd); + } + if (ObjectUtil.isNotEmpty(needEdit)) { + consumablesTemplatePartService.updateBatchById(needEdit); + } + if (ObjectUtil.isNotEmpty(collect)) { + consumablesTemplatePartService.removeByIds(collect); + } + } + + @Override + public TbConsumablesTemplate getByProjectIdAndVehicleType(String projectId, String vehicleType) { + TbConsumablesTemplate byId = getOne(new LambdaQueryWrapper().eq(TbConsumablesTemplate::getProjectId,projectId).eq(TbConsumablesTemplate::getVehicleType,vehicleType).last("limit 1")); + if (BeanUtil.isEmpty(byId)) { + throw new GciBootException("项目id错误或车辆类型错误!"); + } + List list = consumablesTemplatePartService.list(new LambdaQueryWrapper().eq(TbConsumablesTemplatePart::getTemplateId, byId.getId()).orderByAsc(TbConsumablesTemplatePart::getSort)); + byId.setPartList(list); + return byId; + } + + @Override + public void removeItem(String projectId, String vehicleType) { + TbConsumablesTemplate one = getOne(new LambdaQueryWrapper().eq(TbConsumablesTemplate::getProjectId, projectId).eq(TbConsumablesTemplate::getVehicleType,vehicleType)); + if (ObjectUtil.isNotEmpty(one)) { + String id = one.getId(); + removeById(id); + consumablesTemplatePartService.remove(new LambdaQueryWrapper().eq(TbConsumablesTemplatePart::getTemplateId,id)); + } + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplatePartServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplatePartServiceImpl.java new file mode 100644 index 0000000..f1343cf --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplatePartServiceImpl.java @@ -0,0 +1,20 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplatePart; +import com.gci.boot.modules.vehicles.mapper.TbCustomizedTemplatePartMapper; +import com.gci.boot.modules.vehicles.service.ITbCustomizedTemplatePartService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 定制件详情表 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Service +public class TbCustomizedTemplatePartServiceImpl extends ServiceImpl implements ITbCustomizedTemplatePartService { + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplateServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplateServiceImpl.java new file mode 100644 index 0000000..f481a21 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbCustomizedTemplateServiceImpl.java @@ -0,0 +1,134 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplate; +import com.gci.boot.modules.vehicles.entity.TbCustomizedTemplatePart; +import com.gci.boot.modules.vehicles.mapper.TbCustomizedTemplateMapper; +import com.gci.boot.modules.vehicles.query.CustomizedTemplateQuery; +import com.gci.boot.modules.vehicles.service.ITbCustomizedTemplatePartService; +import com.gci.boot.modules.vehicles.service.ITbCustomizedTemplateService; +import com.gci.boot.modules.vehicles.vo.CustomizedTemplateVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.CheckForNull; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 定制件模板 服务实现类 + *

+ * + * @author 2464 + * @since 2023-09-12 + */ +@Service +public class TbCustomizedTemplateServiceImpl extends ServiceImpl implements ITbCustomizedTemplateService { + + @Autowired + private IProjectsService projectsService; + + @Autowired + private ITbCustomizedTemplatePartService customizedTemplatePartService; + + @Resource + private TbCustomizedTemplateMapper customizedTemplateMapper; + + + @Override + public IPage pageBuild(Page page, CustomizedTemplateQuery query) { + IPage list = customizedTemplateMapper.listVo(page, query); + return list; + } + + @Override + public void saveItem(TbCustomizedTemplate tbCustomizedTemplate) { + check(tbCustomizedTemplate); + save(tbCustomizedTemplate); + List projectList = tbCustomizedTemplate.getPartList(); + projectList.forEach(p -> p.setTemplateId(tbCustomizedTemplate.getId())); + customizedTemplatePartService.saveBatch(projectList); + } + + private void check(TbCustomizedTemplate tbCustomizedTemplate) { + Projects byId = projectsService.getById(tbCustomizedTemplate.getProjectId()); + if ("0".equals(byId.getStatus())) { + throw new GciBootException("该项目已禁用,请重新选择!"); + } + List partList = tbCustomizedTemplate.getPartList(); + long count = partList.stream().map(TbCustomizedTemplatePart::getName).distinct().count(); + if (count list = customizedTemplatePartService.list(new LambdaQueryWrapper().eq(TbCustomizedTemplatePart::getTemplateId, tbCustomizedTemplate.getId())); + List collect = null; + if (ObjectUtil.isNotEmpty(list)) { + collect = list.stream().map(TbCustomizedTemplatePart::getId).collect(Collectors.toList()); + } + List partList = tbCustomizedTemplate.getPartList(); + ArrayList needAdd = new ArrayList<>(); + ArrayList needEdit = new ArrayList<>(); + for (TbCustomizedTemplatePart tbCustomizedTemplatePart : partList) { + if (StrUtil.isBlank(tbCustomizedTemplatePart.getId())) { + tbCustomizedTemplatePart.setTemplateId(tbCustomizedTemplate.getId()); + needAdd.add(tbCustomizedTemplatePart); + } else { + if (ObjectUtil.isNotEmpty(collect)) { + if (collect.contains(tbCustomizedTemplatePart.getId())) { + tbCustomizedTemplatePart.setTemplateId(tbCustomizedTemplate.getId()); + needEdit.add(tbCustomizedTemplatePart); + collect.remove(tbCustomizedTemplatePart.getId()); + } + } + } + } + if (ObjectUtil.isNotEmpty(needAdd)) { + customizedTemplatePartService.saveBatch(needAdd); + } + if (ObjectUtil.isNotEmpty(needEdit)) { + customizedTemplatePartService.updateBatchById(needEdit); + } + if (ObjectUtil.isNotEmpty(collect)) { + customizedTemplatePartService.removeByIds(collect); + } + } + + @Override + public TbCustomizedTemplate getByProjectIdAndVehicleType(String projectId, String vehicleType) { + TbCustomizedTemplate byId = getOne(new LambdaQueryWrapper().eq(TbCustomizedTemplate::getProjectId, projectId).eq(TbCustomizedTemplate::getVehicleType,vehicleType).last("limit 1")); + if (BeanUtil.isEmpty(byId)) { + throw new GciBootException("项目id错误或车辆类型错误!"); + } + List list = customizedTemplatePartService.list(new LambdaQueryWrapper().eq(TbCustomizedTemplatePart::getTemplateId, byId.getId()).orderByAsc(TbCustomizedTemplatePart::getSort)); + byId.setPartList(list); + return byId; + } + + @Override + public void removeItem(String projectId, String vehicleType) { + TbCustomizedTemplate byId = getOne(new LambdaQueryWrapper().eq(TbCustomizedTemplate::getProjectId, projectId).eq(TbCustomizedTemplate::getVehicleType,vehicleType).last("limit 1")); + if (ObjectUtil.isNotEmpty(byId)) { + String id = byId.getId(); + removeById(id); + customizedTemplatePartService.remove(new LambdaQueryWrapper().eq(TbCustomizedTemplatePart::getTemplateId, id)); + } + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRecordServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRecordServiceImpl.java new file mode 100644 index 0000000..b783c16 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRecordServiceImpl.java @@ -0,0 +1,107 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.vehicles.entity.TbAccidentInsuranceInfo; +import com.gci.boot.modules.vehicles.entity.TbAccidentProgress; +import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper; +import com.gci.boot.modules.vehicles.service.ITbAccidentInfoService; +import com.gci.boot.modules.vehicles.service.ITbAccidentInsuranceInfoService; +import com.gci.boot.modules.vehicles.service.ITbAccidentProgressService; +import com.gci.boot.modules.vehicles.service.ITbInsuranceRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 出险管理 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-22 + */ +@Service +@Slf4j +public class TbInsuranceRecordServiceImpl extends ServiceImpl implements ITbInsuranceRecordService { + + @Autowired + @Lazy + private ITbAccidentInfoService accidentInfoService; + @Autowired + private ITbAccidentInsuranceInfoService accidentInsuranceInfoService; + @Autowired + private ITbAccidentProgressService accidentProgressService; + @Autowired + private ITbVehicleService vehicleService; + + @Override + public void saveItem(TbInsuranceRecord item) { + save(item); + } + + @Override + @Transactional(rollbackFor = RuntimeException.class) + public void updateItem(TbInsuranceRecord item) { + TbVehicle v = vehicleService.getById(item.getVehicleId()); + item.setVehicleType(v.getVehicleType()); + updateById(item); + if (StrUtil.isNotBlank(item.getInfoId())) { + TbAccidentInfo accidentInfo = accidentInfoService.getItemById(item.getInfoId()); + if (BeanUtil.isEmpty(accidentInfo)) { + log.warn("出险已有事故id但是无法查询对应数据!infoId:{}",item.getInfoId()); + } else { + TbAccidentInsuranceInfo accidentInsuranceInfo = accidentInfo.getAccidentInsuranceInfo(); + if (BeanUtil.isEmpty(accidentInsuranceInfo)) { + log.warn("出险已有事故id但是无法查询对应事故保险数据!infoId:{}",item.getInfoId()); + } else { + if (BeanUtil.isEmpty(v)) { + throw new GciBootException("车辆信息错误!"); + } + accidentInfo.setPlateNumber(v.getPlateNumber()); + accidentInfo.setProjectId(v.getProjectId()); + accidentInfo.setProcessedPerson(item.getHandleUser()); + accidentInfo.setReportNumber(item.getInsuranceNo()); + + String accidentInsuranceInfoId = accidentInsuranceInfo.getId(); + BeanUtil.copyProperties(item,accidentInsuranceInfo); + accidentInsuranceInfo.setId(accidentInsuranceInfoId); + accidentInsuranceInfo.setDocumentImage(item.getCompensateUrl()); + accidentInsuranceInfo.setTotalAmountActuallyIncurred(item.getInsurancePrice()); + + TbAccidentProgress accidentProgress = accidentInfo.getAccidentProgress(); + if (BeanUtil.isEmpty(accidentProgress)) { + accidentProgress = new TbAccidentProgress(); + accidentProgress.setInfoId(accidentInfo.getId()); + accidentProgress.setAccidentCertificatePhoto(item.getAccidentUrl()); + accidentProgress.setLossAssessmentPhoto(item.getLossAssessmentUrl()); + accidentProgress.setCompensationAgreementPhoto(item.getCompensateAgreementUrl()); + accidentProgress.setOtherPhoto(item.getOtherUrl()); + } else { + accidentProgress.setInfoId(accidentInfo.getId()); + accidentProgress.setAccidentCertificatePhoto(item.getAccidentUrl()); + accidentProgress.setLossAssessmentPhoto(item.getLossAssessmentUrl()); + accidentProgress.setCompensationAgreementPhoto(item.getCompensateAgreementUrl()); + accidentProgress.setOtherPhoto(item.getOtherUrl()); + } + accidentInfoService.updateById(accidentInfo); + accidentInsuranceInfoService.updateById(accidentInsuranceInfo); + if (StrUtil.isBlank(accidentProgress.getId())) { + accidentProgressService.save(accidentProgress); + } else { + accidentProgressService.updateById(accidentProgress); + } + } + } + } + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRemindServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRemindServiceImpl.java new file mode 100644 index 0000000..790a17e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceRemindServiceImpl.java @@ -0,0 +1,216 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import cn.hutool.core.util.ObjectUtil; +import com.gci.boot.modules.vehicles.entity.TbInsuranceRecord; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceRecordMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.annotation.Query.handle.QueryGenerator; +import com.gci.boot.common.util.BeanUtilsCopy; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.Lock; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.entity.TbInsuranceRemind; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceRemindMapper; +import com.gci.boot.modules.vehicles.service.ITbInsuranceRemindService; +import com.gci.boot.modules.vehicles.service.ITbInsuranceService; + +import lombok.extern.slf4j.Slf4j; + +/** + *

+ * 保险提醒 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-11-07 + */ +@Slf4j +@Service +public class TbInsuranceRemindServiceImpl extends ServiceImpl implements ITbInsuranceRemindService { + + @Autowired + private TbInsuranceMapper tbInsuranceMapper; + @Autowired + private TbInsuranceRecordMapper tbInsuranceRecordMapper; + @Autowired + private Lock lock; + + @Override + public void createRemind() { + Map remindMap = getInsurance(); + List list = list(); + Map map = new HashMap<>(); + for (TbInsuranceRemind tbInsurance : list) { + map.put(tbInsurance.getInsuranceId(), tbInsurance); + } + List rlist = new ArrayList<>(); + Date nextMonthEnd = DateUtils.getLastDayForNextMonth(new Date(),2,2); + log.info(DateUtils.formatDate(nextMonthEnd)+"---------保险提醒更新创建开始----------"+map.size()); + for (TbInsurance tbInsurance : remindMap.values()) { + //下两个月保险跳过 + if(tbInsurance.getCompulsoryValidTime().after(nextMonthEnd)) { + continue; + } + if(!map.containsKey(tbInsurance.getId())) { + TbInsuranceRemind remind = new TbInsuranceRemind(); + BeanUtilsCopy.copyBeanProp(remind, tbInsurance); + remind.setInsuranceId(tbInsurance.getId()); + rlist.add(remind); + } + } + saveBatch(rlist); + log.info(DateUtils.formatDate(nextMonthEnd)+"---------保险提醒更新创建结束----------"+rlist.size()); + } + + + //获取最新保险 + public Map getInsurance() { + Map remindMap = new HashMap<>(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + //queryWrapper.lt(TbInsurance::getCompulsoryValidTime, nextMonthEnd); + queryWrapper.orderByAsc(TbInsurance::getCompulsoryValidTime); + List list = tbInsuranceMapper.selectList(queryWrapper); + for (TbInsurance tbInsurance : list) { + remindMap.put(tbInsurance.getVehicleId(), tbInsurance); + } + return remindMap; + } + + + @Override + public void updateRemind() { + Map remindMap = getInsurance(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbInsuranceRemind::getStatus, "1"); + List list = list(queryWrapper); + List rlist = new ArrayList<>(); + log.info("---------保险提醒更新状态开始----------"+list.size()); + for (TbInsuranceRemind remind : list) { + if(!remindMap.containsKey(remind.getVehicleId())) { + continue; + } + TbInsurance in = remindMap.get(remind.getVehicleId()); + if(in.getCompulsoryValidTime().after(remind.getCompulsoryValidTime())) { + remind.setStatus("0"); + //remind.setCompulsoryValidTime(in.getCompulsoryValidTime()); + rlist.add(remind); + } + } + updateBatchById(rlist); + log.info("---------保险提醒更新状态结束----------"+rlist.size()); + } + + //每天1点执行 + @Scheduled(cron = "0 0 1 * * ?") + public void insuranceRemindTask() { + log.info("---------保险提醒更新开始----------"); + String key = CommonConstant.INSURANCE_REMIND_TASK_LOCK; + String value = lock.getUniqueNum(); + int n = 0 ; + try { + n = lock.getLock(key, value); + if(n > 0){ + createRemind(); + + updateRemind(); + log.info("---------保险提醒更新结束----------"); + } + }catch (Exception ex){ + log.error("保险提醒更新出错, {}", ex); + }finally { + //释放锁 + if(n > 0){ + lock.delLock(key, value); + } + } + } + + @Scheduled(cron = "0 */11 * * * ?") + public void updateRemindTask() { + + log.info("---------保险提醒更新状态任务开始----------"); + String key = CommonConstant.INSURANCE_REMIND_TASK_LOCK; + String value = lock.getUniqueNum(); + int n = 0 ; + try { + n = lock.getLock(key, value); + if(n > 0){ + updateRemind(); + log.info("---------保险提醒更新状态任务结束----------"); + } + }catch (Exception ex){ + log.error("保险提醒更新状态任务出错, {}", ex); + }finally { + //释放锁 + if(n > 0){ + lock.delLock(key, value); + } + } + } + + //逾期提醒 + @Override + public IPage getRemindPage(TbInsuranceRemind item,IPage pageList) { + LambdaQueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(TbInsuranceRemind.class, item); + queryWrapper.ge(item.getCompulsoryValidTimeStart()!=null,TbInsuranceRemind::getCompulsoryValidTime, item.getCompulsoryValidTimeStart()); + queryWrapper.le(item.getCompulsoryValidTimeEnd()!=null,TbInsuranceRemind::getCompulsoryValidTime, item.getCompulsoryValidTimeEnd()); + Date today = DateUtils.getToday(); + //1将逾期,2已逾期(<=今天) + if("1".equals(item.getIsOverTime())) { + queryWrapper.gt(TbInsuranceRemind::getCompulsoryValidTime, today); + } else if("2".equals(item.getIsOverTime())) { + queryWrapper.le(TbInsuranceRemind::getCompulsoryValidTime, today); + } + queryWrapper.orderByDesc(TbInsuranceRemind::getCreateTime); + IPage list = page(pageList,queryWrapper); + + for (TbInsuranceRemind vo : list.getRecords()) { + Integer count1 = null; + if(vo.getCompulsoryValidTime()!=null) { + count1 = DateUtils.differentDays(today,vo.getCompulsoryValidTime()); + } + if(count1!=null) { + if(count1<=0) { + vo.setCompulsoryOverDay(-count1+""); + }else{ + vo.setCompulsorySurplusDay(count1+""); + } + } + if(ObjectUtil.isNotEmpty(vo.getInsuranceId())){ + TbInsurance insurance = tbInsuranceMapper.selectById(vo.getInsuranceId()); + if(ObjectUtil.isNotEmpty(insurance)){ + LambdaQueryWrapper countQuery = new LambdaQueryWrapper(); + countQuery.eq(TbInsuranceRecord::getVehicleId,insurance.getVehicleId()); + countQuery.between(TbInsuranceRecord::getInsuranceDate,insurance.getCompulsoryStartTime(),insurance.getCompulsoryValidTime()); + + Integer occurrenceNum = tbInsuranceRecordMapper.selectCount(countQuery); + //出险次数 + vo.setOccurrenceNum(String.valueOf(occurrenceNum)); + + Double currentPremium = insurance.getCommercialPrice()+insurance.getCompulsoryPrice()+insurance.getVehicleVesselTax(); + //本期保费 + vo.setCurrentPremium(String.valueOf(currentPremium)); + } + // TODO: 2024/2/26 下期保费,不明确规则,默认为""; + vo.setNextPremium(""); + } + } + + return list; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceServiceImpl.java new file mode 100644 index 0000000..c7daaec --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbInsuranceServiceImpl.java @@ -0,0 +1,324 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONObject; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.basedata.entity.TbInsuranceCompanyArchives; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.mapper.TbInsuranceCompanyArchivesMapper; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.driver.vo.DriverImportVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.entity.TbContract; +import com.gci.boot.modules.projects.mapper.TbContractMapper; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.projects.service.ITbContractService; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.service.ITbInsuranceRemindService; +import com.gci.boot.modules.vehicles.vo.InsuranceImportVO; +import com.gci.boot.modules.vehicles.vo.RepairImportVO; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.MinioUtils; +import com.gci.boot.enums.FileExtension; +import com.gci.boot.exception.GciBootException; +import com.gci.boot.modules.statis.vo.InsuranceStatisVo; +import com.gci.boot.modules.statis.vo.StatisParamVO; +import com.gci.boot.modules.vehicles.controller.TbInsuranceController; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.mapper.TbInsuranceMapper; +import com.gci.boot.modules.vehicles.service.ITbInsuranceService; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * 保险信息 服务实现类 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Slf4j +@Service +public class TbInsuranceServiceImpl extends ServiceImpl implements ITbInsuranceService { + + @Autowired + private MinioUtils minioUtils; + + @Autowired + private IProjectsService projectsService; + + @Value("${failExcel}") + private String failExcel; + + @Autowired + private ITbVehicleService vehicleService; + + @Autowired + private TbContractMapper tbContractMapper; + + @Autowired + private TbInsuranceCompanyArchivesMapper tbInsuranceCompanyArchivesMapper; + + @Autowired + private ITbInsuranceRemindService insuranceRemindService; + + //保险业务量报表 + @Override + public List page(Page page, StatisParamVO vo) { + if("1".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM-DD"); + }else if("2".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY-MM"); + }else if("3".equals(vo.getStatisType())){ + vo.setStatisTime("YYYY"); + }else{ + vo.setStatisTime("YYYY-MM-DD"); + } + return baseMapper.findStatisInsuranceByDayMonthYear(page, vo); + } + + @Override + public Map getLastInsurance(List vids) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbInsurance::getVehicleId, vids); + queryWrapper.orderByAsc(TbInsurance::getCompulsoryValidTime); + List list = list(queryWrapper); + Map map = new HashMap<>(); + for (TbInsurance tbInsurance : list) { + map.put(tbInsurance.getVehicleId(), tbInsurance); + } + return map; + } + + @Override + public String checkItem(TbInsurance item) { + String error = ""; + List list = getByVehicleId(item); + for (TbInsurance tbInsurance : list) { + if(DateUtils.compareTo(item.getCompulsoryValidTime(), tbInsurance.getCompulsoryValidTime())<1 + &&DateUtils.compareTo(item.getCompulsoryValidTime(), tbInsurance.getCompulsoryStartTime())>-1) { + return "有效日期不能与已有保险交叉!"; + } + if(DateUtils.compareTo(item.getCompulsoryStartTime(), tbInsurance.getCompulsoryValidTime())<1 + &&DateUtils.compareTo(item.getCompulsoryStartTime(), tbInsurance.getCompulsoryStartTime())>-1) { + return "起保日期不能与已有保险交叉!"; + } + } + if(StringUtils.hasLength(item.getCompulsoryUrl())) { + if(item.getCompulsoryUrl().split(",").length>10) { + throw new GciBootException("上传交强险附件不能超过10个!"); + } + } + if(StringUtils.hasLength(item.getCommercialUrl())) { + if(item.getCommercialUrl().split(",").length>10) { + throw new GciBootException("上传商业保险附件不能超过10个!"); + } + } + return error; + } + + public List getByVehicleId(TbInsurance item) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbInsurance::getVehicleId, item.getVehicleId()); + queryWrapper.ne(StringUtils.hasLength(item.getId()),TbInsurance::getId, item.getId()); + List list = list(queryWrapper); + return list; + } + + public Map getInsuranceByFrameNumber() { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.orderByAsc(TbInsurance::getCompulsoryValidTime); + List list = list(queryWrapper); + Map map = new HashMap<>(); + for (TbInsurance tbInsurance : list) { + map.put(tbInsurance.getFrameNumber().toUpperCase(), tbInsurance); + } + return map; + } + + //保险附件批量上传 + @Override + public int uploadFiles(Map fileMap,String hasCompulsoryInsurance) { + int count = 0; + List update = new ArrayList<>(); + Map imap = getInsuranceByFrameNumber(); + for(String key:imap.keySet()) { + if(count==fileMap.size()) { + break; + } + String urls = ""; + TbInsurance item = imap.get(key); + for(String fkey:fileMap.keySet()) { + File file = fileMap.get(fkey); + if(file!=null&&fkey.contains(key)) { + String url = uploadFile(file); + if(StringUtils.hasLength(url)) { + count++; + if(StringUtils.hasLength(urls)) { + urls += ","+url; + }else { + urls = url; + } + fileMap.put(fkey, null); + } + } + } + if(!StringUtils.hasLength(urls)) { + continue; + } + if("1".equals(hasCompulsoryInsurance)) { + String comurl = item.getCompulsoryUrl(); + if(StringUtils.hasLength(comurl)) { + comurl += ","+urls; + }else { + comurl = urls; + } + item.setCompulsoryUrl(comurl); + if(item.getCompulsoryUrl().split(",").length>10) { + throw new GciBootException(item.getFrameNumber()+"上传交强险附件不能超过10个!"); + } + update.add(item); + }else { + String comurl = item.getCommercialUrl(); + if(StringUtils.hasLength(comurl)) { + comurl += ","+urls; + }else { + comurl = urls; + } + item.setCommercialUrl(comurl); + if(item.getCommercialUrl().split(",").length>10) { + throw new GciBootException(item.getFrameNumber()+"上传商业保险附件不能超过10个!"); + } + update.add(item); + } + } + updateBatchById(update); + return count; + } + + @Override + public Result listImport(List list) throws IOException { + + LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //查用户所有权限车牌 + List vehicles = projectsService.queryAllVehicleListOfUser(); + Map> repeatMap = ValidatorUtil.findDuplicates(list, "plateNumber"); + + Map> partitionedLists = + list.stream().map(i->{ + i.validate(); + if(ObjectUtil.isEmpty(i.getHasCompulsoryInsurance())&&ObjectUtil.isEmpty(i.getHasCommercialInsurance())){ + i.putErrorMsg("交强险跟商业险不能同时无数据"); + } + if(Objects.nonNull(repeatMap)&&repeatMap.containsKey(i.getPlateNumber())){ + i.putErrorMsg("存在重复的'车牌号'"); + } + TbVehicle vehicle = vehicles.stream() + .filter(v-> v.getPlateNumber().equals(i.getPlateNumber())).findFirst() + .orElse(null); + if(ObjectUtil.isEmpty(vehicle)){ + i.putErrorMsg("当前用户没有该车牌号权限或车辆不存在"); + }else{ + i.setVehicleId(vehicle.getId()); + i.setProjectId(vehicle.getProjectId()); + i.setVehicleModel(vehicle.getVehicleModel()); + i.setVehicleType(vehicle.getVehicleType()); + i.setFrameNumber(vehicle.getFrameNumber()); + } + LambdaQueryWrapper companyArchivesWrapper = new LambdaQueryWrapper<>(); + companyArchivesWrapper.and(wrapper-> wrapper.eq(TbInsuranceCompanyArchives::getName,i.getCompulsoryCompany()) + .or().eq(TbInsuranceCompanyArchives::getShortened,i.getCompulsoryCompany()) + ); + TbInsuranceCompanyArchives companyArchives = this.tbInsuranceCompanyArchivesMapper.selectOne(companyArchivesWrapper); + if(ObjectUtil.isEmpty(companyArchives)){ + i.putErrorMsg("系统不存在对应的保险公司"); + }else{ + i.setCompulsoryCompanyId(companyArchives.getId()); + } + LambdaQueryWrapper contractLambdaQueryWrapper = new LambdaQueryWrapper<>(); + contractLambdaQueryWrapper.eq(TbContract::getContractNo,i.getContractName()); + TbContract contract = this.tbContractMapper.selectOne(contractLambdaQueryWrapper); + if(ObjectUtil.isEmpty(contract)){ + i.putErrorMsg("系统不存在对应的保险合同"); + }else{ + i.setContractId(contract.getId()); + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbInsurance::getPlateNumber, i.getPlateNumber()); + List insurances = list(queryWrapper); + for (TbInsurance insurance : insurances) { + if(DateUtils.compareTo(DateUtil.parseDate(i.getCompulsoryValidTime()), insurance.getCompulsoryValidTime())<1 + &&DateUtils.compareTo(DateUtil.parseDate(i.getCompulsoryValidTime()), insurance.getCompulsoryStartTime())>-1) { + i.putErrorMsg("有效日期不能与已有保险交叉!"); + break; + } + if(DateUtils.compareTo(DateUtil.parseDate(i.getCompulsoryStartTime()), insurance.getCompulsoryValidTime())<1 + &&DateUtils.compareTo(DateUtil.parseDate(i.getCompulsoryStartTime()), insurance.getCompulsoryStartTime())>-1) { + i.putErrorMsg("起保日期不能与已有保险交叉!"); + break; + } + } + i.setSysOrgCode(loginUser.getOrgCode()); + i.setCreateBy(loginUser.getUsername()); + return i; + }).collect(Collectors.groupingBy(i->CollectionUtil.isEmpty(i.getValidationErrors()))); + + List failList = partitionedLists.get(false); + List successList = partitionedLists.get(true); + + if(CollectionUtil.isNotEmpty(successList)){ + List insurances = successList.stream().map(TbInsurance::buildByImportVo).collect(Collectors.toList()); + + System.out.println(insurances); + this.saveBatch(insurances); + insuranceRemindService.updateRemind(); + } + + if (CollectionUtil.isNotEmpty(failList)) { + JSONObject entries = new JSONObject(); + String failName = System.currentTimeMillis() + "_" +CommonConstant.INSURANCE_IMPORT_FAIL_EXCEL_NAME; + //导出失败数据 + EasyExcel.write(failExcel + failName, InsuranceImportVO.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("导入异常数据").doWrite(failList); + String errorMsg = "已导入"+ (list.size()-failList.size()) + "条;失败"+ failList.size() +"条;具体失败详情见失败导出信息表"; + entries.set("msg",errorMsg); + entries.set("path",failName); + return Result.ok(entries); + }else{ + return Result.ok(); + } + } + + public String uploadFile(File file) { + String url = null; + try { + url = minioUtils.uploadFileValid(file, FileExtension.getCommonFileTypes()); + } catch (Exception e) { + log.error("保险附件上传失败", e); + } + return url; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRefuelChargeRecordServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRefuelChargeRecordServiceImpl.java new file mode 100644 index 0000000..f76a8b8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRefuelChargeRecordServiceImpl.java @@ -0,0 +1,186 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.BeanUtilsCopy; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.basedata.entity.TbCustomerArchives; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbCustomerArchivesService; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.impl.SysDictServiceImpl; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.entity.TbRefuelChargeRecord; +import com.gci.boot.modules.vehicles.mapper.TbRefuelChargeRecordMapper; +import com.gci.boot.modules.vehicles.service.ITbRefuelChargeRecordService; +import com.gci.boot.modules.vehicles.vo.TbRefuelChargeRecordImportVo; +import com.gci.boot.modules.vehicles.vo.TbRefuelChargeRecordVo; +import com.gci.boot.modules.vehicles.vo.UpkeepImportVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.math.BigDecimal; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + *

+ * 加油充电记录 服务实现类 + *

+ * + * @author admin + * @since 2023-11-30 + */ +@Service +public class TbRefuelChargeRecordServiceImpl extends ServiceImpl implements ITbRefuelChargeRecordService { + + @Autowired + private ITbVehicleService vehicleService; + @Autowired + private ITbCustomerArchivesService customerArchivesService; + @Autowired + private IProjectsService projectsService; + @Autowired + private SysDictServiceImpl sysDictService; + @Value("${failExcel}") + private String failExcel; + + @Override + public void saveItem(TbRefuelChargeRecord item) { + initImte(item); + saveOrUpdate(item); + } + + public int getByOilCard(String oilCard) { + if(!StringUtils.hasLength(oilCard)) { + return 0; + } + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(TbVehicle::getOilCard, oilCard); + return vehicleService.count(query); + } + + public void initImte(TbRefuelChargeRecord item) { + int has = getByOilCard(item.getOilCard()); + if(has>0) { + item.setRefuelType("1"); + }else { + item.setRefuelType("2"); + } + if(!StringUtils.hasLength(item.getOrderNo())) { + item.setOrderNo("RC"+DateUtils.formatDate(new Date(), DateUtils.HYPHENS_DATETIME4)); + } + item.setPrice(null); + if(item.getTotalPrice()!=null&&item.getAmount()!=null&&!item.getAmount().equals(BigDecimal.ZERO)) { + item.setPrice(item.getTotalPrice().divide(item.getAmount(),2,BigDecimal.ROUND_HALF_UP)); + } + TbCustomerArchives com = customerArchivesService.getByProjectId(item.getProjectId()); + if(com!=null) { + item.setSysOrgCode(com.getSysOrgCode()); + } + //开始结束时间年月日处理 + Calendar recordDateCalendar = Calendar.getInstance(); + recordDateCalendar.setTime(item.getRecordDate()); + if(Objects.nonNull(item.getStartTime())){ + Calendar startTimeCalendar = Calendar.getInstance(); + startTimeCalendar.setTime(item.getStartTime()); + startTimeCalendar.set(Calendar.YEAR, recordDateCalendar.get(Calendar.YEAR)); + startTimeCalendar.set(Calendar.MONTH, recordDateCalendar.get(Calendar.MONTH)); + startTimeCalendar.set(Calendar.DAY_OF_MONTH, recordDateCalendar.get(Calendar.DAY_OF_MONTH)); + item.setStartTime(startTimeCalendar.getTime()); + } + if(Objects.nonNull(item.getEndTime())){ + Calendar endTimeCalendar = Calendar.getInstance(); + endTimeCalendar.setTime(item.getEndTime()); + endTimeCalendar.set(Calendar.YEAR, recordDateCalendar.get(Calendar.YEAR)); + endTimeCalendar.set(Calendar.MONTH, recordDateCalendar.get(Calendar.MONTH)); + endTimeCalendar.set(Calendar.DAY_OF_MONTH, recordDateCalendar.get(Calendar.DAY_OF_MONTH)); + item.setEndTime(endTimeCalendar.getTime()); + } + + } + + @Override + public Result saveItemBatch(List list) { + List vlist = vehicleService.list(); + Map vmap = vlist.stream().collect(Collectors.toMap(TbVehicle::getPlateNumber,Function.identity())); + //查用户所有权限车牌 + List plateNumbers = projectsService.queryAllPlateNumberListOfUser(); + //记录失败的数据 + List failList = new ArrayList<>(); + //油品规格/充电类型 + List oilTypeList = sysDictService.queryDictItemsByCode("oil_type"); + Map oilTypeMap = oilTypeList.stream().collect(Collectors.toMap(DictModel::getText, DictModel::getValue)); + for(int i = 0; i< list.size(); i++){ + int flag = 0; + list.get(i).validate(); + if(CollectionUtil.isNotEmpty(list.get(i).getValidationErrors())){ + flag += 1; + } + if(!plateNumbers.contains(list.get(i).getPlateNumber())){ + flag += 1; + list.get(i).putErrorMsg("当前用户没有该车牌号权限或车辆不存在"); + } + if(StrUtil.isNotBlank(list.get(i).getStartTime()) || StrUtil.isNotBlank(list.get(i).getEndTime())){ + if(StrUtil.isBlank(list.get(i).getStartTime()) || StrUtil.isBlank(list.get(i).getEndTime())){ + flag += 1; + list.get(i).putErrorMsg("开始时间、结束时间必须同时存在"); + } + } + if(flag == 0){ + try { + //保存数据 + TbRefuelChargeRecord item = new TbRefuelChargeRecord(); + BeanUtil.copyProperties(list.get(i),item); + item.setOilType(oilTypeMap.getOrDefault(item.getOilType(),null)); + + TbVehicle ve = vmap.get(item.getPlateNumber()); + item.setVehicleId(ve.getId()); + item.setFrameNumber(ve.getFrameNumber()); + item.setVehicleModel(ve.getVehicleModel()); + item.setVehicleType(ve.getVehicleType()); + item.setFuelType(ve.getFuelType()); + item.setProjectId(ve.getProjectId()); + item.setSysOrgCode(ve.getSysOrgCode()); + item.setSourceType("3"); + this.saveItem(item); + }catch (Exception e){ + e.printStackTrace(); + list.get(i).putErrorMsg(e.getMessage()); + failList.add(list.get(i)); + } + }else{ + failList.add(list.get(i)); + } + } + //处理返回数据 + if (CollectionUtil.isNotEmpty(failList)) { + JSONObject entries = new JSONObject(); + String fielName = System.currentTimeMillis() + CommonConstant.REFUEL_CHARGE_RECORD_FAIL_EXCEL_NAME; + //导出失败数据 + EasyExcel.write(failExcel + fielName, TbRefuelChargeRecordImportVo.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("导入异常数据").doWrite(failList); + String errorMsg = "已导入"+ (list.size()-failList.size()) + "条;失败"+ failList.size() +"条;具体失败详情见失败导出信息表"; + + entries.set("msg",errorMsg); + entries.set("path",fielName); + return Result.ok(entries); + }else{ + return Result.ok(); + } + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairAssignServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairAssignServiceImpl.java new file mode 100644 index 0000000..065248b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairAssignServiceImpl.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; +import com.gci.boot.modules.vehicles.mapper.TbRepairAssignMapper; +import com.gci.boot.modules.vehicles.mapper.TbRepairCheckMapper; +import com.gci.boot.modules.vehicles.service.ITbRepairAssignService; +import com.gci.boot.modules.vehicles.service.ITbRepairCheckService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbRepairAssignServiceImpl extends ServiceImpl implements ITbRepairAssignService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairCheckServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairCheckServiceImpl.java new file mode 100644 index 0000000..82d6fe2 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairCheckServiceImpl.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.mapper.TbRepairCheckMapper; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.service.ITbRepairCheckService; +import com.gci.boot.modules.vehicles.service.ITbRepairInfoService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbRepairCheckServiceImpl extends ServiceImpl implements ITbRepairCheckService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairInfoServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairInfoServiceImpl.java new file mode 100644 index 0000000..9d65a12 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairInfoServiceImpl.java @@ -0,0 +1,596 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.msg.enums.RepairSenderEnum; +import com.gci.boot.modules.msg.enums.SenderTypeEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.entity.*; +import com.gci.boot.modules.system.service.*; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; +import com.gci.boot.modules.vehicles.enums.*; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.service.*; +import com.gci.boot.modules.vehicles.vo.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class TbRepairInfoServiceImpl extends ServiceImpl implements ITbRepairInfoService { + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private ITbRepairAssignService repairAssignService; + @Autowired + private ITbRepairCheckService repairCheckService; + @Autowired + private ITbRepairOfferService repairOfferService; + @Autowired + private IProjectsService projectsService; + @Autowired + private CommonService commonService; + @Autowired + private ISysDictService sysDictService; + @Autowired + private MsgPushService msgPushService; + + @Override + public Page getRepairInfoList(Page page, RepairInfoListVO vo) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); +// if(Objects.isNull(sysUser)){ +// return page; +// } + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + String authorityType = commonService.getAuthority(sysUser.getUsername()); + + if("2".equals(authorityType)){ + vo.setRepairParam("维修厂"); + //维修厂派单不可见 + } + + List list = new ArrayList<>(); + list = repairInfoMapper.findRepairInfoList(page,vo); + //todo 做按钮权限处理 + handlerButtonAndType(list, authorityType); + page.setRecords(list); + return page; + } + + @Override + public RepairObjectVO getRepairObjectById(String id) { + RepairObjectVO vo = new RepairObjectVO(); + //todo + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); +// if(Objects.isNull(sysUser)){ +// return vo; +// } + + TbRepairInfo tbRepairInfo = this.getById(id); + vo.setId(id); + vo.setFlowStatus(tbRepairInfo.getFlowStatus()); + vo.setRepairInfo(tbRepairInfo); + vo.setAddType(tbRepairInfo.getAddType()); + + //补充作废信息 + if(9 == tbRepairInfo.getFlowStatus()){ + CancelObjectVO cancelObjectVO = new CancelObjectVO(); + cancelObjectVO.setCancelIdea(tbRepairInfo.getCancelIdea()); + cancelObjectVO.setCancelPeople(tbRepairInfo.getCancelPeople()); + cancelObjectVO.setCancelTime(tbRepairInfo.getCancelTime()); + vo.setCancelObject(cancelObjectVO); + } + + LambdaQueryWrapper assignQueryWrapper = new LambdaQueryWrapper<>(); + assignQueryWrapper.eq(TbRepairAssign::getRepairId,id).last(" limit 1 "); + TbRepairAssign tbRepairAssign = repairAssignService.getOne(assignQueryWrapper); + vo.setRepairAssign(tbRepairAssign); + + //暂只做单一”司机、维修厂、维保员工、领导” 身份的处理。取最高身份 + String authorityType = commonService.getAuthority(sysUser.getUsername()); + if("3".equals(authorityType)){ + authorityType = "2"; + } + if("6".equals(authorityType)){ + authorityType = "5"; + } + vo.setUserType(authorityType); + //todo 把报价放进去 + if(! "1".equals(authorityType)){ + LambdaQueryWrapper offerQueryWrapper = new LambdaQueryWrapper<>(); + offerQueryWrapper.eq(TbRepairOffer::getRepairId,id).last(" limit 1 "); + TbRepairOffer tbRepairOffer = repairOfferService.getOne(offerQueryWrapper); + if(Objects.nonNull(tbRepairOffer)){ + if("".equals(tbRepairOffer.getInRepairImgUrl())){ + tbRepairOffer.setInRepairImgUrl(null); + } + } + if(Objects.nonNull(tbRepairOffer) && StrUtil.isNotBlank(tbRepairOffer.getRepairDetailJson())){ + tbRepairOffer.setRepairDetailList(JSONUtil.toList(tbRepairOffer.getRepairDetailJson(), RepairDetailVO.class)); + } + if(Objects.nonNull(tbRepairOffer) && StrUtil.isNotBlank(tbRepairOffer.getAttachmentJson())){ + tbRepairOffer.setAttachmentList(JSONUtil.toList(tbRepairOffer.getAttachmentJson(), AttachmentDetailVO.class)); + } + vo.setRepairOffer(tbRepairOffer); + } + + LambdaQueryWrapper checkQueryWrapper = new LambdaQueryWrapper<>(); + checkQueryWrapper.eq(TbRepairCheck::getRepairId,id).orderByDesc(TbRepairCheck::getCheckTime); + List tbRepairCheckList = repairCheckService.list(checkQueryWrapper); + vo.setRepairCheckList(tbRepairCheckList); + + return vo; + } + + @Transactional + @Override + public String addDataEntry(RepairDataEntryVO vo, String isGuarantee) { + String repairId = StrUtil.uuid().replace("-",""); + TbRepairInfo repairInfo = vo.getRepairInfo(); + TbRepairOffer repairOffer = vo.getRepairOffer(); + //校验报价 + String ver= verifyOffer(repairOffer,isGuarantee); + if(StrUtil.isNotBlank(ver)){ + return ver; + } + TbRepairAssign repairAssign = vo.getRepairAssign(); + Projects projects = projectsService.getById(repairInfo.getProjectId()); + if(Objects.nonNull(projects)){ + repairInfo.setProjectName(projects.getProjectName()); + } + repairInfo.setId(repairId); + //报修时间 + if(Objects.isNull(repairInfo.getRepairTime())){ + repairInfo.setRepairTime(new Date()); + } + //直接结束归档 + repairInfo.setFlowStatus(8); + repairInfo.setFlowNode(4); + repairInfo.setAddType(1); + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + repairInfo.setOrderNo(format); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String username = ""; + if(Objects.nonNull(sysUser)){ + username = sysUser.getUsername(); + } + repairInfo.setCreateBy(username); + //报价 + repairOffer.setRepairId(repairId); + repairOffer.setRepairShop(repairAssign.getRepairShop()); + if(Objects.nonNull(repairOffer.getRepairDetailList())){ + repairOffer.setRepairDetailJson(JSONUtil.toJsonPrettyStr(repairOffer.getRepairDetailList())); + } + if(Objects.nonNull(repairOffer.getAttachmentList())){ + repairOffer.setAttachmentJson(JSONUtil.toJsonPrettyStr(repairOffer.getAttachmentList())); + } + //指派 + repairAssign.setRepairId(repairId); + + this.save(repairInfo); + repairOfferService.save(repairOffer); + repairAssignService.save(repairAssign); + + return null; + } + + @Transactional + @Override + public String submitRepairObject(RepairObjectVO vo, HttpServletRequest request) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + TbRepairInfo repairInfo = this.getById(vo.getId()); +// if(!repairInfo.getFlowStatus().equals(vo.getFlowStatus())){ +// return "该报修单流程状态已被修改,请刷新后重试!"; +// } + //判断是否超过2K到领导层级 + if(vo.getFlowStatus()==10 && vo.getCheckFlag()==1){ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbRepairOffer::getRepairId,vo.getId()); + TbRepairOffer one = repairOfferService.getOne(queryWrapper); + if(Objects.nonNull(one) && one.getRepairCost() > 2000){ + vo.setCheckFlag(2000); + } + } + //判断是否质保期内的 + if(vo.getFlowStatus()==2 && vo.getCheckFlag()==1){ + TbRepairAssign repairAssign = vo.getRepairAssign(); + if(Objects.nonNull(repairAssign) && "1".equals(repairAssign.getIsGuarantee())){ + vo.setCheckFlag(-1); + } + } + RepairStatusChangeEvent event = RepairStatusChangeEvent.getEnum(vo.getFlowStatus(),vo.getCheckFlag()); + if(Objects.isNull(event)){ + return "流程配置为空"; + } + //补充指派信息 + if(event.getFlowStatus() == 2){ + TbRepairAssign repairAssign = vo.getRepairAssign(); + if(StrUtil.isBlank(repairAssign.getRepairShop())){ + return "请选择维修厂!"; + } + if("1".equals(repairAssign.getIsGuarantee())){ + //质保期内的,直接到维修中,默认创建一条 质保维修的明细记录 + TbRepairOffer tbRepairOffer = buildRepairOffer(vo.getId(), repairAssign.getRepairShop()); + repairOfferService.save(tbRepairOffer); + } + repairAssign.setRepairId(vo.getId()); + repairAssignService.save(repairAssign); + //补充节点操作人 + saveCheck(sysUser, vo.getId(), "5"); + } + //维修厂报价信息 + if(event.getFlowStatus() == 3){ + //补充指派维修厂 + LambdaQueryWrapper repairAssignQuery = new LambdaQueryWrapper<>(); + repairAssignQuery.eq(TbRepairAssign::getRepairId,vo.getId()).last("limit 1"); + TbRepairAssign tbRepairAssign = repairAssignService.getOne(repairAssignQuery); + TbRepairOffer repairOffer = vo.getRepairOffer(); + String ver= verifyOffer(repairOffer,"0"); + if(StrUtil.isNotBlank(ver)){ + return ver; + } + repairOffer.setRepairId(vo.getId()); + repairOffer.setRepairShop(tbRepairAssign.getRepairShop()); + if(Objects.nonNull(repairOffer.getRepairDetailList())){ + repairOffer.setRepairDetailJson(JSONUtil.toJsonPrettyStr(repairOffer.getRepairDetailList())); + } + if(Objects.nonNull(repairOffer.getAttachmentList())){ + repairOffer.setAttachmentJson(JSONUtil.toJsonPrettyStr(repairOffer.getAttachmentList())); + } + if("".equals(repairOffer.getInRepairImgUrl())){ + repairOffer.setInRepairImgUrl(null); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbRepairOffer::getRepairId,vo.getId()); + TbRepairOffer one = repairOfferService.getOne(queryWrapper); + if(StrUtil.isBlank(repairOffer.getId()) && Objects.nonNull(one)){ + repairOffer.setId(one.getId()); + repairOfferService.updateById(repairOffer); + }else{ + repairOfferService.save(repairOffer); + } + //补充节点操作人 + saveCheck(sysUser, vo.getId(), "6"); + } + //员工维修报价审核 + if(event.getFlowStatus() == 4){ + TbRepairCheck repairCheck = vo.getCurrentRepairCheck(); + if("2".equals(repairCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(repairCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString(repairCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(repairCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString2(repairCheck.getCheckIdea(),200)); + } + } + repairCheck.setRepairId(vo.getId()); + repairCheck.setCheckType("1"); + updateRepairCheck(repairCheck,request); + } + //审核审批--待复核 + if(event.getFlowStatus() == 10){ + TbRepairCheck repairCheck = vo.getCurrentRepairCheck(); + if("2".equals(repairCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(repairCheck.getCheckIdea(),200))){ + return ("复核意见 " + StringUtil.checkString(repairCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(repairCheck.getCheckIdea(),200))){ + return ("复核意见 " + StringUtil.checkString2(repairCheck.getCheckIdea(),200)); + } + } + repairCheck.setRepairId(vo.getId()); + repairCheck.setCheckType("5"); + updateRepairCheck(repairCheck,request); + } + //领导维修报价审核 + if(event.getFlowStatus() == 5){ + TbRepairCheck repairCheck = vo.getCurrentRepairCheck(); + if("2".equals(repairCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(repairCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString(repairCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(repairCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString2(repairCheck.getCheckIdea(),200)); + } + } + repairCheck.setRepairId(vo.getId()); + repairCheck.setCheckType("2"); + updateRepairCheck(repairCheck,request); + } + //维修厂报价信息补充 + if(event.getFlowStatus() == 6){ + //判断是否维修质保--维修单据附件做不做判断处理 + LambdaQueryWrapper repairAssignQuery = new LambdaQueryWrapper<>(); + repairAssignQuery.eq(TbRepairAssign::getRepairId,vo.getId()).last("limit 1"); + TbRepairAssign tbRepairAssign = repairAssignService.getOne(repairAssignQuery); + String guarantee = tbRepairAssign.getIsGuarantee(); + + TbRepairOffer repairOffer = vo.getRepairOffer(); + String ver= verifyOffer(repairOffer,guarantee); + if(StrUtil.isNotBlank(ver)){ + return ver; + } + repairOffer.setRepairId(vo.getId()); + if(Objects.nonNull(repairOffer.getAttachmentList())){ + repairOffer.setAttachmentJson(JSONUtil.toJsonPrettyStr(repairOffer.getAttachmentList())); + } + if(Objects.nonNull(repairOffer.getRepairDetailList())){ + repairOffer.setRepairDetailJson(JSONUtil.toJsonPrettyStr(repairOffer.getRepairDetailList())); + } + if("".equals(repairOffer.getInRepairImgUrl())){ + repairOffer.setInRepairImgUrl(null); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbRepairOffer::getRepairId,vo.getId()); + TbRepairOffer one = repairOfferService.getOne(queryWrapper); + if(StrUtil.isBlank(repairOffer.getId()) && Objects.nonNull(one)){ + repairOffer.setId(one.getId()); + } + repairOfferService.updateById(repairOffer); + //补充节点操作人 + saveCheck(sysUser, vo.getId(), "7"); + } + //维修结果 + if(event.getFlowStatus() == 7){ + TbRepairCheck repairCheck = vo.getCurrentRepairCheck(); + repairCheck.setRepairId(vo.getId()); + repairCheck.setCheckType("3"); + if(StrUtil.isNotBlank(StringUtil.checkString2(repairCheck.getCheckIdea(),200))){ + return ("维修确认意见 " + StringUtil.checkString2(repairCheck.getCheckIdea(),200)); + } + updateRepairCheck(repairCheck,request); + } + //更新维修单流程状态、流程节点 + repairInfo.setFlowStatus(event.getNextFlowStatus()); + repairInfo.setFlowNode(event.getNextNode()); + this.updateById(repairInfo); + //待推送消息状态 + List validFlowStatuses = Arrays.asList(2, 3, 4, 5, 6, 7); + if (validFlowStatuses.contains(repairInfo.getFlowStatus())) { + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(repairInfo.getProjectId()); + List flowStatusList = sysDictService.queryDictItemsByCode("repair_status"); + Map flowStatusMap = flowStatusList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + msgPushService.pushMsgToRedis(new MsgRedisVO( + RepairSenderEnum.getEnumByFlowStatus(repairInfo.getFlowStatus()).getSendType(),repairInfo.getId(), + repairInfo.getProjectId(), WorkOrderType.REPAIR.getType(),flowStatusMap.getOrDefault(repairInfo.getFlowStatus().toString(),""), + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + } + return null; + } + + public void updateRepairCheck(TbRepairCheck repairCheck,HttpServletRequest request){ + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + String realName = ""; + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + + if("3".equals(repairCheck.getCheckType())){ + if("1".equals(repairCheck.getCheckResult())){ + repairCheck.setCheckResult("3"); + }else{ + repairCheck.setCheckResult("4"); + } + }else{ + repairCheck.setCheckResult(repairCheck.getCheckResult()); + } + if("2".equals(repairCheck.getCheckType())){ + repairCheck.setCheckPeopleType("2"); + }else if("5".equals(repairCheck.getCheckType())){ + repairCheck.setCheckPeopleType("3"); + }else{ + repairCheck.setCheckPeopleType("1"); + } + if(StrUtil.isBlank(repairCheck.getCheckPeople())){ + repairCheck.setCheckPeople(realName); + } + repairCheck.setCheckTime(new Date()); + + repairCheckService.save(repairCheck); + + } + + //补充按钮权限 + public void handlerButtonAndType(List list, String authorityType){ + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + if("1".equals(authorityType)){ + list.stream().forEach(item->{ + RepairStatusEnumDriver statusEnum = RepairStatusEnumDriver.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType(authorityType); + } + }); + } + if("2".equals(authorityType)){ + list.stream().forEach(item->{ + RepairStatusEnumRepair statusEnum = RepairStatusEnumRepair.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType(authorityType); + } + }); + } + if("3".equals(authorityType)){ + list.stream().forEach(item->{ + RepairStatusEnumRepairAndDriver statusEnum = RepairStatusEnumRepairAndDriver.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType("2"); + } + }); + } + if("4".equals(authorityType)){ + list.stream().forEach(item->{ + RepairStatusEnumEmployee statusEnum = RepairStatusEnumEmployee.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType(authorityType); + } + }); + } + if("5".equals(authorityType)){ + list.stream().forEach(item->{ + RepairStatusEnumLeader statusEnum = RepairStatusEnumLeader.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType(authorityType); + } + }); + } + if("6".equals(authorityType)){ + list.stream().forEach(item->{ + RepairStatusEnumEmployeeAndLeader statusEnum = RepairStatusEnumEmployeeAndLeader.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType("5"); + } + }); + } + } + + public String verifyOffer(TbRepairOffer repairOffer, String isGuarantee){ + if(Objects.isNull(repairOffer.getRepairCost())){ + return "联维修报价不能为空!"; + }else{ + if(repairOffer.getRepairCost() <0 || repairOffer.getRepairCost()>99999999){ + return "联维修报价在[0,99999999]之间!"; + } + } + if(Objects.isNull(repairOffer.getTotalWorkHours())){ + return "总计工时不能为空!"; + }else{ + if(repairOffer.getTotalWorkHours() <0 || repairOffer.getTotalWorkHours()>99999999){ + return "总计工时在[0,99999999]之间!"; + } + } + if(Objects.isNull(repairOffer.getTotalWorkHoursCost())){ + return "工时费用总计不能为空!"; + }else{ + if(repairOffer.getTotalWorkHoursCost() <0 || repairOffer.getTotalWorkHoursCost()>99999999){ + return "工时费用总计在[0,99999999]之间!"; + } + } + if(Objects.isNull(repairOffer.getMaterialCost())){ + return "总计材料费不能为空!"; + }else{ + if(repairOffer.getMaterialCost() <0 || repairOffer.getMaterialCost()>99999999){ + return "总计材料费在[0,99999999]之间!"; + } + } + if("0".equals(isGuarantee)){ + if(Objects.isNull(repairOffer.getAttachmentList()) || repairOffer.getAttachmentList().size() == 0){ + return "单据附件不能为空!"; + }else{ + if(JSONUtil.toJsonPrettyStr(repairOffer.getAttachmentList()).length() >= 5000){ + return "单据附件长度不能超过5000!"; + } + } + } + if(Objects.isNull(repairOffer.getRepairDetailList()) || repairOffer.getRepairDetailList().size() == 0){ + return "维修明细不能为空!"; + }else{ + for (RepairDetailVO vo : repairOffer.getRepairDetailList()){ + if(vo.getQuantity() <0 || vo.getQuantity()>99999999){ + return "数量在[0,99999999]之间!"; + } + if(vo.getTotalCost() <0 || vo.getTotalCost()>99999999){ + return "费用在[0,99999999]之间!"; + } + if(vo.getUnitPrice() <0 || vo.getUnitPrice()>99999999){ + return "材料在[0,99999999]之间!"; + } + if(vo.getWorkHours() <0 || vo.getWorkHours()>99999999){ + return "工时在[0,99999999]之间!"; + } + if(vo.getWorkHoursCost() <0 || vo.getWorkHoursCost()>99999999){ + return "工时费在[0,99999999]之间!"; + } + if(StrUtil.isNotBlank(vo.getRepairContent())){ + String str = StringUtil.checkString2(vo.getRepairContent(),100); + if(StrUtil.isNotBlank(str)){ + return "维修内容" + str; + } + } + } + } + if(Objects.nonNull(repairOffer.getContent())){ + String str = StringUtil.checkString2(repairOffer.getContent(),100); + if(StrUtil.isNotBlank(str)){ + return "内容说明" + str; + } + } + return null; + } + + public TbRepairOffer buildRepairOffer(String repairId, String repairShop){ + TbRepairOffer repairOffer = new TbRepairOffer(); + repairOffer.setRepairId(repairId); + repairOffer.setRepairShop(repairShop); + repairOffer.setContent("质保维修"); + repairOffer.setTotalWorkHours(0.0); + repairOffer.setTotalWorkHoursCost(0.0); + repairOffer.setRepairCost(0.0); + repairOffer.setMaterialCost(0.0); + RepairDetailVO repairDetailVO = new RepairDetailVO(); + repairDetailVO.setRepairClass("6"); + repairDetailVO.setRepairContent("质保维修"); + repairDetailVO.setQuantity(0); + repairDetailVO.setTotalCost(0.0); + repairDetailVO.setUnitPrice(0.0); + repairDetailVO.setWorkHoursCost(0.0); + repairDetailVO.setWorkHours(0.0); + List repairDetailList = new ArrayList<>(); + repairDetailList.add(repairDetailVO); + repairOffer.setRepairDetailJson(JSONUtil.toJsonPrettyStr(repairDetailList)); + return repairOffer; + } + + public void saveCheck(LoginUser sysUser, String repairId, String checkPeopleType){ + TbRepairCheck repairCheck = new TbRepairCheck(); + repairCheck.setRepairId(repairId); + if(Objects.nonNull(sysUser)){ + repairCheck.setCheckPeople(sysUser.getRealname()); + } + repairCheck.setCheckTime(new Date()); + repairCheck.setCheckPeopleType(checkPeopleType); + repairCheckService.save(repairCheck); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairOfferServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairOfferServiceImpl.java new file mode 100644 index 0000000..e4d8782 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbRepairOfferServiceImpl.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; +import com.gci.boot.modules.vehicles.mapper.TbRepairOfferMapper; +import com.gci.boot.modules.vehicles.service.ITbRepairOfferService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbRepairOfferServiceImpl extends ServiceImpl implements ITbRepairOfferService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepAssignServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepAssignServiceImpl.java new file mode 100644 index 0000000..f9186d6 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepAssignServiceImpl.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbUpkeepAssign; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepAssignMapper; +import com.gci.boot.modules.vehicles.service.ITbUpkeepAssignService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbUpkeepAssignServiceImpl extends ServiceImpl implements ITbUpkeepAssignService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepBillServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepBillServiceImpl.java new file mode 100644 index 0000000..3aaf50e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepBillServiceImpl.java @@ -0,0 +1,604 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.gis.entity.TbGisRunningbus; +import com.gci.boot.modules.gis.service.ITbGisRunningbusService; +import com.gci.boot.modules.msg.enums.RepairSenderEnum; +import com.gci.boot.modules.msg.enums.UpkeepBillSenderEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.entity.SysRole; +import com.gci.boot.modules.system.entity.SysUser; +import com.gci.boot.modules.system.entity.SysUserRole; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.service.ISysRoleService; +import com.gci.boot.modules.system.service.ISysUserRoleService; +import com.gci.boot.modules.system.service.ISysUserService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.*; +import com.gci.boot.modules.vehicles.enums.*; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper; +import com.gci.boot.modules.vehicles.service.*; +import com.gci.boot.modules.vehicles.vo.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class TbUpkeepBillServiceImpl extends ServiceImpl implements ITbUpkeepBillService { + + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbUpkeepOfferService upkeepOfferService; + @Autowired + private ITbUpkeepAssignService upkeepAssignService; + @Autowired + private ITbUpkeepCheckService upkeepCheckService; + @Autowired + private TbUpkeepBillMapper upkeepBillMapper; + @Autowired + private ITbGisRunningbusService gisRunningbusService; + + @Autowired + private CommonService commonService; + @Autowired + private ISysDictService sysDictService; + @Autowired + private MsgPushService msgPushService; + + @Transactional + @Override + public String addDataEntry(UpkeepDataEntryVO vo, String isGuarantee) { + //校验 + String ver = verifyOffer(vo.getUpkeepOffer(),isGuarantee); + if(StrUtil.isNotBlank(ver)){ + return ver; + } + String ver2 = verifyBill(vo.getUpkeepBill()); + if(StrUtil.isNotBlank(ver2)){ + return ver2; + } + String upkeepBillId = StrUtil.uuid().replace("-",""); + TbUpkeepBill upkeepBill = vo.getUpkeepBill(); + TbUpkeepOffer upkeepOffer = vo.getUpkeepOffer(); + Projects projects = projectsService.getById(upkeepBill.getProjectId()); + if(Objects.nonNull(projects)){ + upkeepBill.setProjectName(projects.getProjectName()); + } + upkeepBill.setId(upkeepBillId); + //直接结束归档 + upkeepBill.setFlowStatus(8); + upkeepBill.setFlowNode(4); + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + upkeepBill.setOrderNo(format); + //数据录入 + upkeepBill.setAddType(1); + //台账附件 + if(Objects.nonNull(upkeepBill.getAttachmentList())){ + upkeepBill.setAttachmentJson(JSONUtil.toJsonPrettyStr(upkeepBill.getAttachmentList())); + } + //指派信息 + TbUpkeepAssign upkeepAssign = vo.getUpkeepAssign(); + upkeepAssign.setUpkeepBillId(upkeepBillId); + + //报价 + upkeepOffer.setUpkeepBillId(upkeepBillId); + upkeepOffer.setRepairShop(upkeepAssign.getRepairShop()); + if(Objects.nonNull(upkeepOffer.getRepairDetailList())){ + upkeepOffer.setUpkeepDetailJson(JSONUtil.toJsonPrettyStr(upkeepOffer.getRepairDetailList())); + } + //附件 + if(Objects.nonNull(upkeepOffer.getAttachmentUpkeepList())){ + upkeepOffer.setAttachmentJson(JSONUtil.toJsonPrettyStr(upkeepOffer.getAttachmentUpkeepList())); + } + + this.save(upkeepBill); + upkeepOfferService.save(upkeepOffer); + upkeepAssignService.save(upkeepAssign); + return null; + } + + @Override + public Page getUpkeepBillList(Page page, UpkeepInfoListVO vo) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + String authorityType = commonService.getAuthority(sysUser.getUsername()); + + if("2".equals(authorityType)){ + vo.setRepairParam("维修厂"); + //维修厂派单不可见 + } + List list = new ArrayList<>(); + list = upkeepBillMapper.findUpkeepBillList(page,vo); + //todo 做按钮权限处理 + handlerButtonAndType(list, authorityType); + page.setRecords(list); + + return page; + } + + @Override + public List getAllUpkeepBillList(UpkeepInfoListVO vo) { + List list = new ArrayList<>(); + list = upkeepBillMapper.findAllUpkeepBillList(vo); + return list; + } + + @Override + public UpkeepObjectVO getUpkeepObjectById(String id) { + UpkeepObjectVO vo = new UpkeepObjectVO(); + TbUpkeepBill tbUpkeepBill = this.getById(id); + vo.setId(id); + vo.setFlowStatus(tbUpkeepBill.getFlowStatus()); + if(StrUtil.isNotBlank(tbUpkeepBill.getAttachmentJson())){ + tbUpkeepBill.setAttachmentList(JSONUtil.toList(tbUpkeepBill.getAttachmentJson(), AttachmentDetailVO.class)); + } + vo.setUpkeepBill(tbUpkeepBill); + vo.setAddType(tbUpkeepBill.getAddType()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //暂只做单一”司机、维修厂、维保员工、领导” 身份的处理。取最高身份 + String authorityType = commonService.getAuthority(sysUser.getUsername()); + if("3".equals(authorityType)){ + authorityType = "2"; + } + if("6".equals(authorityType)){ + authorityType = "5"; + } + vo.setUserType(authorityType); + + //补充作废信息 + if(9 == tbUpkeepBill.getFlowStatus()){ + CancelObjectVO cancelObjectVO = new CancelObjectVO(); + cancelObjectVO.setCancelIdea(tbUpkeepBill.getCancelIdea()); + cancelObjectVO.setCancelPeople(tbUpkeepBill.getCancelPeople()); + cancelObjectVO.setCancelTime(tbUpkeepBill.getCancelTime()); + vo.setCancelObject(cancelObjectVO); + } + + LambdaQueryWrapper assignQueryWrapper = new LambdaQueryWrapper<>(); + assignQueryWrapper.eq(TbUpkeepAssign::getUpkeepBillId,id).last(" limit 1 "); + TbUpkeepAssign tbUpkeepAssign = upkeepAssignService.getOne(assignQueryWrapper); + vo.setUpkeepAssign(tbUpkeepAssign); + + LambdaQueryWrapper offerQueryWrapper = new LambdaQueryWrapper<>(); + offerQueryWrapper.eq(TbUpkeepOffer::getUpkeepBillId,id).last(" limit 1 "); + TbUpkeepOffer tbUpkeepOffer = upkeepOfferService.getOne(offerQueryWrapper); + if(Objects.nonNull(tbUpkeepOffer)){ + if("".equals(tbUpkeepOffer.getInUpkeepImgUrl())){ + tbUpkeepOffer.setInUpkeepImgUrl(null); + } + if("".equals(tbUpkeepOffer.getAfterUpkeepImgUrl())){ + tbUpkeepOffer.setAfterUpkeepImgUrl(null); + } + if("".equals(tbUpkeepOffer.getBeforeUpkeepImgUrl())){ + tbUpkeepOffer.setBeforeUpkeepImgUrl(null); + } + } + if(Objects.nonNull(tbUpkeepOffer) && StrUtil.isNotBlank(tbUpkeepOffer.getUpkeepDetailJson())){ + tbUpkeepOffer.setRepairDetailList(JSONUtil.toList(tbUpkeepOffer.getUpkeepDetailJson(), RepairDetailVO.class)); + } + if(Objects.nonNull(tbUpkeepOffer) && StrUtil.isNotBlank(tbUpkeepOffer.getAttachmentJson())){ + tbUpkeepOffer.setAttachmentUpkeepList(JSONUtil.toList(tbUpkeepOffer.getAttachmentJson(), AttachmentDetailVO.class)); + } + vo.setUpkeepOffer(tbUpkeepOffer); + + LambdaQueryWrapper checkQueryWrapper = new LambdaQueryWrapper<>(); + checkQueryWrapper.eq(TbUpkeepCheck::getUpkeepBillId,id).orderByDesc(TbUpkeepCheck::getCheckTime); + List tbRepairCheckList = upkeepCheckService.list(checkQueryWrapper); + vo.setUpkeepCheckList(tbRepairCheckList); + + return vo; + } + + @Transactional + @Override + public String submitUpkeepObject(UpkeepObjectVO vo, HttpServletRequest request) { + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + TbUpkeepBill upkeepBill = this.getById(vo.getId()); +// if(!upkeepBill.getFlowStatus().equals(vo.getFlowStatus())){ +// return "该保养台账单流程状态已被修改,请刷新后重试!"; +// } + + UpkeepStatusChangeEvent event = UpkeepStatusChangeEvent.getEnum(vo.getFlowStatus(),vo.getCheckFlag()); + if(Objects.isNull(event)){ + return "找不到配置流程!"; + } + // 2 3 4 6 7 8 9 10 + //流程状态: 待委派 待报价 待审核 保养中 待确认 结束 作废 待复核 + //补充指派信息 + if(event.getFlowStatus() == 2){ + TbUpkeepAssign upkeepAssign = vo.getUpkeepAssign(); + if(StrUtil.isBlank(upkeepAssign.getRepairShop())){ + return "请选择维修厂!"; + } + upkeepAssign.setUpkeepBillId(vo.getId()); + upkeepAssignService.save(upkeepAssign); + //补充节点操作人 + saveCheck(sysUser, vo.getId(), "5"); + } + //维修厂报价信息 + if(event.getFlowStatus() == 3){ + //补充指派维修厂 + LambdaQueryWrapper upkeepAssignQuery = new LambdaQueryWrapper<>(); + upkeepAssignQuery.eq(TbUpkeepAssign::getUpkeepBillId,vo.getId()).last("limit 1"); + TbUpkeepAssign tbUpkeepAssign = upkeepAssignService.getOne(upkeepAssignQuery); + + TbUpkeepOffer upkeepOffer = vo.getUpkeepOffer(); + //校验 + String ver = verifyOffer(vo.getUpkeepOffer(),"0"); + if(StrUtil.isNotBlank(ver)){ + return ver; + } + upkeepOffer.setUpkeepBillId(vo.getId()); + upkeepOffer.setRepairShop(tbUpkeepAssign.getRepairShop()); + if(Objects.nonNull(upkeepOffer.getRepairDetailList())){ + upkeepOffer.setUpkeepDetailJson(JSONUtil.toJsonPrettyStr(upkeepOffer.getRepairDetailList())); + } + if(Objects.nonNull(upkeepOffer.getAttachmentUpkeepList())){ + upkeepOffer.setAttachmentJson(JSONUtil.toJsonPrettyStr(upkeepOffer.getAttachmentUpkeepList())); + } + if("".equals(upkeepOffer.getInUpkeepImgUrl())){ + upkeepOffer.setInUpkeepImgUrl(null); + } + if("".equals(upkeepOffer.getAfterUpkeepImgUrl())){ + upkeepOffer.setAfterUpkeepImgUrl(null); + } + if("".equals(upkeepOffer.getBeforeUpkeepImgUrl())){ + upkeepOffer.setBeforeUpkeepImgUrl(null); + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbUpkeepOffer::getUpkeepBillId,vo.getId()); + TbUpkeepOffer one = upkeepOfferService.getOne(queryWrapper); + if(StrUtil.isBlank(upkeepOffer.getId()) && Objects.nonNull(one)){ + upkeepOffer.setId(one.getId()); + upkeepOfferService.updateById(upkeepOffer); + }else{ + upkeepOfferService.save(upkeepOffer); + } + //补充节点操作人 + saveCheck(sysUser, vo.getId(), "6"); + + } + //员工领导维修报价审核 + if(event.getFlowStatus() == 4){ + TbUpkeepCheck upkeepCheck = vo.getCurrentUpkeepCheck(); + if("2".equals(upkeepCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(upkeepCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString(upkeepCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(upkeepCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString2(upkeepCheck.getCheckIdea(),200)); + } + } + upkeepCheck.setUpkeepBillId(vo.getId()); + String realName = ""; + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + if(StrUtil.isBlank(upkeepCheck.getCheckPeople())){ + upkeepCheck.setCheckPeople(realName); + } + upkeepCheck.setCheckType("1"); + upkeepCheck.setCheckPeopleType("1"); + upkeepCheck.setCheckTime(new Date()); + upkeepCheckService.save(upkeepCheck); + } + //待复核 + if(event.getFlowStatus() == 10){ + TbUpkeepCheck upkeepCheck = vo.getCurrentUpkeepCheck(); + if("2".equals(upkeepCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(upkeepCheck.getCheckIdea(),200))){ + return ("复核意见 " + StringUtil.checkString(upkeepCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(upkeepCheck.getCheckIdea(),200))){ + return ("复核意见 " + StringUtil.checkString2(upkeepCheck.getCheckIdea(),200)); + } + } + upkeepCheck.setUpkeepBillId(vo.getId()); + String realName = ""; + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + if(StrUtil.isBlank(upkeepCheck.getCheckPeople())){ + upkeepCheck.setCheckPeople(realName); + } + upkeepCheck.setCheckType("5"); + upkeepCheck.setCheckPeopleType("3"); + upkeepCheck.setCheckTime(new Date()); + upkeepCheckService.save(upkeepCheck); + //更新实际保养开始时间 --- 审核通过才有 + if(1 == vo.getCheckFlag()){ + TbUpkeepBill tbUpkeepBill = this.getById(vo.getId()); + tbUpkeepBill.setStartTime(new Date()); + this.updateById(tbUpkeepBill); + } + } + //维修厂报价信息补充 + if(event.getFlowStatus() == 6){ + TbUpkeepOffer upkeepOffer = vo.getUpkeepOffer(); + //校验 + String ver = verifyOffer(vo.getUpkeepOffer(),"0"); + if(StrUtil.isNotBlank(ver)){ + return ver; + } + upkeepOffer.setUpkeepBillId(vo.getId()); + if(Objects.nonNull(upkeepOffer.getAttachmentUpkeepList())){ + upkeepOffer.setAttachmentJson(JSONUtil.toJsonPrettyStr(upkeepOffer.getAttachmentUpkeepList())); + } + if(Objects.nonNull(upkeepOffer.getRepairDetailList())){ + upkeepOffer.setUpkeepDetailJson(JSONUtil.toJsonPrettyStr(upkeepOffer.getRepairDetailList())); + } + if("".equals(upkeepOffer.getInUpkeepImgUrl())){ + upkeepOffer.setInUpkeepImgUrl(null); + } + if("".equals(upkeepOffer.getAfterUpkeepImgUrl())){ + upkeepOffer.setAfterUpkeepImgUrl(null); + } + if("".equals(upkeepOffer.getBeforeUpkeepImgUrl())){ + upkeepOffer.setBeforeUpkeepImgUrl(null); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbUpkeepOffer::getUpkeepBillId,vo.getId()); + TbUpkeepOffer one = upkeepOfferService.getOne(queryWrapper); + if(StrUtil.isBlank(upkeepOffer.getId()) && Objects.nonNull(one)){ + upkeepOffer.setId(one.getId()); + } + upkeepOfferService.updateById(upkeepOffer); + //补充节点操作人 + saveCheck(sysUser, vo.getId(), "8"); + } + //维修结果 + if(event.getFlowStatus() == 7){ + TbUpkeepCheck upkeepCheck = vo.getCurrentUpkeepCheck(); + upkeepCheck.setUpkeepBillId(vo.getId()); + //校验特殊字符 + if("2".equals(upkeepCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(upkeepCheck.getCheckIdea(),200))){ + return ("确认意见 " + StringUtil.checkString(upkeepCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(upkeepCheck.getCheckIdea(),200))){ + return ("确认意见 " + StringUtil.checkString2(upkeepCheck.getCheckIdea(),200)); + } + } + String realName = ""; + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + upkeepCheck.setUpkeepBillId(vo.getId()); + upkeepCheck.setCheckType("4"); + upkeepCheck.setCheckPeopleType("2"); + if("1".equals(upkeepCheck.getCheckResult())){ + upkeepCheck.setCheckResult("5"); + //todo 最终结果通过,更新计划表的状态为已归档--5 + upkeepBillMapper.updateFinshPlan(vo.getId(),5); + //更新维修完成时间、维修实际里程 + TbUpkeepBill tbUpkeepBill = this.getById(vo.getId()); + tbUpkeepBill.setEndTime(new Date()); + LambdaQueryWrapper busQuery = new LambdaQueryWrapper<>(); + busQuery.eq(TbGisRunningbus::getPlateNumber,tbUpkeepBill.getPlateNumber()).last(" limit 1 "); + TbGisRunningbus runningbus = gisRunningbusService.getOne(busQuery); + if(Objects.nonNull(runningbus)){ + if(Objects.nonNull(runningbus.getTotalMileage())){ + tbUpkeepBill.setRealMileage(runningbus.getTotalMileage().intValue()); + } + } + this.updateById(tbUpkeepBill); + }else{ + upkeepCheck.setCheckResult("6"); + } + if(StrUtil.isBlank(upkeepCheck.getCheckPeople())){ + upkeepCheck.setCheckPeople(realName); + } + upkeepCheck.setCheckTime(new Date()); + upkeepCheckService.save(upkeepCheck); + } + //更新维修单流程状态、流程节点 + upkeepBill.setFlowStatus(event.getNextFlowStatus()); + upkeepBill.setFlowNode(event.getNextNode()); + this.updateById(upkeepBill); + //待推送消息状态 + List validFlowStatuses = Arrays.asList(2, 3, 4, 6, 7); + if (validFlowStatuses.contains(upkeepBill.getFlowStatus())) { + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(upkeepBill.getProjectId()); + List flowStatusList = sysDictService.queryDictItemsByCode("upkeep_status"); + Map flowStatusMap = flowStatusList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + msgPushService.pushMsgToRedis(new MsgRedisVO( + UpkeepBillSenderEnum.getEnumByFlowStatus(upkeepBill.getFlowStatus()).getSendType(), upkeepBill.getId(), + upkeepBill.getProjectId(), WorkOrderType.UPKEEP_BILL.getType(),flowStatusMap.getOrDefault(upkeepBill.getFlowStatus().toString(),""), + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + } + return null; + } + + + + //补充按钮权限 + public void handlerButtonAndType(List list, String authorityType){ + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + if("2".equals(authorityType) || "3".equals(authorityType)){ + list.stream().forEach(item->{ + UpkeepStatusEnumRepair statusEnum = UpkeepStatusEnumRepair.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setUserType("2"); + } + }); + } + + if("6".equals(authorityType) || "5".equals(authorityType) || "4".equals(authorityType)){ + list.stream().forEach(item->{ + UpkeepStatusEnumEmployeeAndLeader statusEnum = UpkeepStatusEnumEmployeeAndLeader.getEnum(item.getFlowStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + if("6".equals(authorityType)){ + //返回最高身份 + item.setUserType("5"); + }else{ + item.setUserType(authorityType); + } + } + }); + } + } + + //校验 + public String verifyBill(TbUpkeepBill upkeepBill){ + if(StrUtil.isBlank(upkeepBill.getProjectId())){ + return "所属项目不能为空!"; + } + if(StrUtil.isBlank(upkeepBill.getPlateNumber())){ + return "车牌号不能为空!"; + } + if(Objects.isNull(upkeepBill.getLastTime())){ + return "上次保养时间不能为空!"; + } + if(Objects.isNull(upkeepBill.getLastMileage())){ + return "上次保养里程不能为空!"; + }else{ + if(upkeepBill.getLastMileage() <0 || upkeepBill.getLastMileage()>99999999){ + return "上次保养里程在[0,99999999]之间!"; + } + } + if(Objects.isNull(upkeepBill.getPredictTime())){ + return "预计保养时间不能为空!"; + } + if(Objects.isNull(upkeepBill.getPredictMileage())){ + return "预计保养里程不能为空!"; + }else{ + if(upkeepBill.getPredictMileage() <0 || upkeepBill.getPredictMileage()>99999999){ + return "预计保养里程在[0,99999999]之间!"; + } + } + if(StrUtil.isBlank(upkeepBill.getContent())){ + return "保养内容不能为空!"; + }else{ + String str = StringUtil.checkString2(upkeepBill.getContent(),200); + if(StrUtil.isNotBlank(str)){ + return "保养内容 " + str; + } + } + return null; + } + + public String verifyOffer(TbUpkeepOffer upkeepOffer,String isGuarantee){ + if(Objects.isNull(upkeepOffer.getTotaCost())){ + return "总计不能为空!"; + }else{ + if(upkeepOffer.getTotaCost() <0 || upkeepOffer.getTotaCost()>99999999){ + return "总计在[0,99999999]之间!"; + } + } + if(Objects.isNull(upkeepOffer.getTotalWorkHours())){ + return "总计工时不能为空!"; + }else{ + if(upkeepOffer.getTotalWorkHours() <0 || upkeepOffer.getTotalWorkHours()>99999999){ + return "总计工时在[0,99999999]之间!"; + } + } + if(Objects.isNull(upkeepOffer.getTotalWorkHoursCost())){ + return "工时费用总计不能为空!"; + }else{ + if(upkeepOffer.getTotalWorkHoursCost() <0 || upkeepOffer.getTotalWorkHoursCost()>99999999){ + return "工时费用总计在[0,99999999]之间!"; + } + } + if(Objects.isNull(upkeepOffer.getMaterialCost())){ + return "总计材料费不能为空!"; + }else{ + if(upkeepOffer.getMaterialCost() <0 || upkeepOffer.getMaterialCost()>99999999){ + return "总计材料费在[0,99999999]之间!"; + } + } + if("0".equals(isGuarantee)){ + if(Objects.isNull(upkeepOffer.getAttachmentUpkeepList()) || upkeepOffer.getAttachmentUpkeepList().size() == 0){ + return "单据附件不能为空!"; + }else{ + if(JSONUtil.toJsonPrettyStr(upkeepOffer.getAttachmentUpkeepList()).length() >= 5000){ + return "单据附件长度不能超过5000!"; + } + } + } + if(Objects.isNull(upkeepOffer.getRepairDetailList()) || upkeepOffer.getRepairDetailList().size() == 0){ + return "维修明细不能为空!"; + }else{ + for (RepairDetailVO vo : upkeepOffer.getRepairDetailList()){ + if(vo.getQuantity() <0 || vo.getQuantity()>99999999){ + return "数量在[0,99999999]之间!"; + } + if(vo.getTotalCost() <0 || vo.getTotalCost()>99999999){ + return "费用在[0,99999999]之间!"; + } + if(vo.getUnitPrice() <0 || vo.getUnitPrice()>99999999){ + return "材料在[0,99999999]之间!"; + } + if(vo.getWorkHours() <0 || vo.getWorkHours()>99999999){ + return "工时在[0,99999999]之间!"; + } + if(vo.getWorkHoursCost() <0 || vo.getWorkHoursCost()>99999999){ + return "工时费在[0,99999999]之间!"; + } + if(StrUtil.isNotBlank(vo.getRepairContent())){ + String str = StringUtil.checkString2(vo.getRepairContent(),100); + if(StrUtil.isNotBlank(str)){ + return "保养内容 " + str; + } + }else{ + return "保养内容不能为空!"; + } + } + } + if(StrUtil.isBlank(upkeepOffer.getOfferContent())){ + return "内容说明不能为空!"; + }else{ + String str = StringUtil.checkString2(upkeepOffer.getOfferContent(),100); + if(StrUtil.isNotBlank(str)){ + return "内容说明 " + str; + }else{ + return null; + } + } + } + + public void saveCheck(LoginUser sysUser, String billId, String checkPeopleType){ + //补充节点操作人 + TbUpkeepCheck upkeepCheck = new TbUpkeepCheck(); + if(Objects.nonNull(sysUser)){ + upkeepCheck.setCheckPeople(sysUser.getRealname()); + } + upkeepCheck.setUpkeepBillId(billId); + upkeepCheck.setCheckPeopleType(checkPeopleType); + upkeepCheck.setCheckTime(new Date()); + upkeepCheckService.save(upkeepCheck); + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepCheckServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepCheckServiceImpl.java new file mode 100644 index 0000000..06df113 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepCheckServiceImpl.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbUpkeepCheck; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepCheckMapper; +import com.gci.boot.modules.vehicles.service.ITbUpkeepCheckService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbUpkeepCheckServiceImpl extends ServiceImpl implements ITbUpkeepCheckService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepOfferServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepOfferServiceImpl.java new file mode 100644 index 0000000..2497954 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepOfferServiceImpl.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbUpkeepOffer; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepOfferMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepRuleMapper; +import com.gci.boot.modules.vehicles.service.ITbUpkeepOfferService; +import com.gci.boot.modules.vehicles.service.ITbUpkeepRuleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbUpkeepOfferServiceImpl extends ServiceImpl implements ITbUpkeepOfferService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanCheckServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanCheckServiceImpl.java new file mode 100644 index 0000000..02ecbb4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanCheckServiceImpl.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbUpkeepCheck; +import com.gci.boot.modules.vehicles.entity.TbUpkeepPlanCheck; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepCheckMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanCheckMapper; +import com.gci.boot.modules.vehicles.service.ITbUpkeepCheckService; +import com.gci.boot.modules.vehicles.service.ITbUpkeepPlanCheckService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbUpkeepPlanCheckServiceImpl extends ServiceImpl implements ITbUpkeepPlanCheckService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanServiceImpl.java new file mode 100644 index 0000000..417ea58 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepPlanServiceImpl.java @@ -0,0 +1,501 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.util.StringUtil; +import com.gci.boot.modules.msg.enums.SenderTypeEnum; +import com.gci.boot.modules.msg.enums.WorkOrderType; +import com.gci.boot.modules.msg.service.MsgPushService; +import com.gci.boot.modules.msg.vo.MsgRedisVO; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.*; +import com.gci.boot.modules.system.vo.LoginUser; +import com.gci.boot.modules.vehicles.entity.*; +import com.gci.boot.modules.vehicles.enums.UpkeepPlanStatusEnumEmployee; +import com.gci.boot.modules.vehicles.enums.UpkeepPlanStatusEnumLeader; +import com.gci.boot.modules.vehicles.mapper.TbRepairInfoMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepBillMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepPlanMapper; +import com.gci.boot.modules.vehicles.service.*; +import com.gci.boot.modules.vehicles.vo.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class TbUpkeepPlanServiceImpl extends ServiceImpl implements ITbUpkeepPlanService { + + @Autowired + private ITbUpkeepPlanCheckService upkeepPlanCheckService; + @Autowired + private ITbUpkeepRuleService upkeepRuleService; + @Autowired + private TbRepairInfoMapper repairInfoMapper; + @Autowired + private TbUpkeepPlanMapper upkeepPlanMapper; + @Autowired + private TbUpkeepBillMapper upkeepBillMapper; + @Autowired + private CommonService commonService; + @Autowired + private ISysUserService sysUserService; + @Autowired + private ISysUserRoleService sysUserRoleService; + @Autowired + private ISysRoleService sysRoleService; + @Autowired + private MsgPushService msgPushService; + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbUpkeepCheckService upkeepCheckService; + + @Transactional + @Override + public String submitUpkeepPlan(UpkeepPlanObjectVO vo) { + List planIds = Arrays.asList(vo.getId().split(",")); + //无需审核数据不给审核操作 + if(CollectionUtil.isNotEmpty(planIds)){ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(TbUpkeepPlan::getId,planIds).in(TbUpkeepPlan::getAuditStatus,"2","3","4","5"); + List list = this.list(queryWrapper); + if(CollectionUtil.isNotEmpty(list)){ + return ("存在已审核、作废或归档数据,请重新操作!"); + } + } + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //批量提交 + for(String planId : planIds){ + //更新维修单流程状态、流程节点 + TbUpkeepPlan upkeepPlan = this.getById(planId); + TbUpkeepPlanCheck upkeepPlanCheck = vo.getCurrentUpkeepCheck(); + if("2".equals(upkeepPlanCheck.getCheckResult())){ + if(StrUtil.isNotBlank(StringUtil.checkString(upkeepPlanCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString(upkeepPlanCheck.getCheckIdea(),200)); + } + }else{ + if(StrUtil.isNotBlank(StringUtil.checkString2(upkeepPlanCheck.getCheckIdea(),200))){ + return ("审核意见 " + StringUtil.checkString2(upkeepPlanCheck.getCheckIdea(),200)); + } + } + if(vo.getCheckFlag() == 1){ + //审核通过 + upkeepPlan.setAuditStatus("2"); + this.updateById(upkeepPlan); + //同步数据到台账 + TbUpkeepBill upkeepBill = new TbUpkeepBill(); + BeanUtil.copyProperties(upkeepPlan,upkeepBill); + upkeepBill.setFlowStatus(2); + upkeepBill.setFlowNode(1); + //走流程的 + upkeepBill.setAddType(2); + upkeepBillMapper.insert(upkeepBill); + //补充节点操作人 + TbUpkeepCheck upkeepCheck = new TbUpkeepCheck(); + if(Objects.nonNull(sysUser)){ + upkeepCheck.setCheckPeople(sysUser.getRealname()); + } + upkeepCheck.setUpkeepBillId(upkeepBill.getId()); + upkeepCheck.setCheckPeopleType("4"); + upkeepCheck.setCheckTime(new Date()); + upkeepCheckService.save(upkeepCheck); + + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(upkeepBill.getProjectId()); + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),upkeepBill.getId(), + upkeepBill.getProjectId(), WorkOrderType.UPKEEP_BILL.getType(),"待派单", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + } + if(vo.getCheckFlag() == 2){ + //审核未通过 + upkeepPlan.setAuditStatus("3"); + this.updateById(upkeepPlan); + } + + String realName = ""; + if(Objects.nonNull(sysUser)){ + realName = sysUser.getRealname(); + } + //审核信息 + if(StrUtil.isBlank(upkeepPlanCheck.getCheckPeople())){ + upkeepPlanCheck.setCheckPeople(realName); + } + upkeepPlanCheck.setCheckType("2"); + upkeepPlanCheck.setCheckPeopleType("2"); + upkeepPlanCheck.setCheckTime(new Date()); + upkeepPlanCheck.setUpkeepPlanId(planId); + upkeepPlanCheckService.save(upkeepPlanCheck); + } + return null; + } + + @Override + public UpkeepPlanObjectVO getUpkeepPlanObjectById(String id) { + UpkeepPlanObjectVO vo = new UpkeepPlanObjectVO(); + TbUpkeepPlan tbUpkeepPlan = this.getById(id); + vo.setId(id); + vo.setUpkeepPlan(tbUpkeepPlan); + if(StrUtil.isNotBlank(tbUpkeepPlan.getAttachmentJson())){ + tbUpkeepPlan.setAttachmentList(JSONUtil.toList(tbUpkeepPlan.getAttachmentJson(), AttachmentDetailVO.class)); + } + vo.setAuditStatus(tbUpkeepPlan.getAuditStatus()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //暂只做单一”司机、维修厂、维保员工、领导” 身份的处理。取最高身份 + String authorityType = commonService.getAuthority(sysUser.getUsername()); + if("6".equals(authorityType)){ + authorityType = "5"; + } + vo.setUserType(authorityType); + + //补充作废信息 + if("4".equals(tbUpkeepPlan.getAuditStatus())){ + CancelObjectVO cancelObjectVO = new CancelObjectVO(); + cancelObjectVO.setCancelIdea(tbUpkeepPlan.getCancelIdea()); + cancelObjectVO.setCancelPeople(tbUpkeepPlan.getCancelPeople()); + cancelObjectVO.setCancelTime(tbUpkeepPlan.getCancelTime()); + vo.setCancelObject(cancelObjectVO); + } + + LambdaQueryWrapper checkQueryWrapper = new LambdaQueryWrapper<>(); + checkQueryWrapper.eq(TbUpkeepPlanCheck::getUpkeepPlanId,id); + List tbRepairCheckList = upkeepPlanCheckService.list(checkQueryWrapper); + vo.setUpkeepCheckList(tbRepairCheckList); + + return vo; + } + + /** + * 一个“或”规则,多次触发。后续触发需要屏蔽掉。仅生成一次 + * 同一次定时多个规则圈中同一辆车只生成一份 + */ + @Override + public String ruleCreatePlan() { + //当前批次 + Integer createNo = upkeepPlanMapper.findMaxPlanCreateNo() + 1; + //1、查启用的规则 + LambdaQueryWrapper ruleQuery = new LambdaQueryWrapper<>(); + ruleQuery.eq(TbUpkeepRule::getRuleStatus,"1"); + List upkeepRuleList = upkeepRuleService.list(ruleQuery); + //按时间、里程、时间或里程 + List ruleTimes = upkeepRuleList.stream().filter(s->"1".equals(s.getRuleType())).collect(Collectors.toList()); + List ruleMiles = upkeepRuleList.stream().filter(s->"2".equals(s.getRuleType())).collect(Collectors.toList()); + List ruleTimeOrMiles = upkeepRuleList.stream().filter(s->"3".equals(s.getRuleType())).collect(Collectors.toList()); + //按时间生成保养单 规则设置的时间间隔-上次保养时间<=30 + int timeCount = ruleCreatePlanByTime(ruleTimes,createNo); + //按里程生成保养单 (当前车辆的总里程数+本月的累计里程数)>=设置的里程数*90%则生成保养计划 + int mileCount = ruleCreatePlanByMile(ruleMiles, createNo); + //按时间或里程生成保养计划单,同一规则车仅会存在一条 + int timeOrMileCount = ruleCreatePlanByTimeOrMiles(ruleTimeOrMiles,createNo); + + String str = "按时间生成保养单: " + timeCount + "条; " + + "按里程生成保养单: " + mileCount + "条; " + + "按时间或里程生成保养计划单: " + timeOrMileCount + "条。"; + log.info("保养规则生成计划 {},{}" ,DateUtil.formatDateTime(new Date()), str); + return str; + } + + @Override + public Page getUpkeepPlanList(Page page, TbUpkeepPlan upkeepPlan) { + List list = new ArrayList<>(); + list = upkeepPlanMapper.findUpkeepPlanList(page,upkeepPlan); + //todo 做按钮权限处理 + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + String authorityType = commonService.getAuthority(sysUser.getUsername()); + handlerButtonAndType(list, authorityType); + page.setRecords(list); + + return page; + } + + public Integer ruleCreatePlanByTime(List ruleTimes,Integer createNo) { + AtomicInteger saveCount = new AtomicInteger(); + ruleTimes.stream().forEach(rule->{ + //按时间规则查车,没有上次里程的车取交车时间 + List vehicleInfoVOList = repairInfoMapper.findVehicleInfoByTime(rule.getVehicleType(),rule.getVehicleModel(),rule.getVehicleBrand()); + if(Objects.nonNull(vehicleInfoVOList) && vehicleInfoVOList.size()>0){ + for(VehicleInfoVO vo : vehicleInfoVOList){ + //查有无进行中的计划或台账 + int unFinishcount = upkeepPlanMapper.findUnfinishCount(vo.getPlateNumber()); + if(unFinishcount>0){ + continue; + } + + //查有无已生成的当前批次计划 + LambdaQueryWrapper planQuery = new LambdaQueryWrapper<>(); + planQuery.eq(TbUpkeepPlan::getPlateNumber,vo.getPlateNumber()) + .eq(TbUpkeepPlan::getCreateNo,createNo); + int count = this.count(planQuery); + if(count > 0){ + continue; + }else{ + //规则设置的时间间隔-上次保养时间<=30 + log.info(DateUtil.formatDateTime(vo.getLastTime()) + "-----" + rule.getTime()); + log.info(DateUtil.formatDateTime(DateUtil.offsetDay(vo.getLastTime(),rule.getTime()))); + long days = DateUtil.between(DateUtil.offsetDay(vo.getLastTime(),rule.getTime()), new Date(), DateUnit.DAY,false); + if(days <= 30 && days >= 0){ + //生成该车保养计划 + TbUpkeepPlan plan = new TbUpkeepPlan(); + BeanUtil.copyProperties(vo,plan,"id"); + //未审核 + plan.setAuditStatus("1"); + //自动、规则id、批次号、生成日期 + plan.setSaveType(1); + plan.setRuleId(rule.getId()); + plan.setCreateNo(createNo); + plan.setPlanSaveTime(new Date()); + //预计保养里程、时间。。。时间为这次上次保养时间+时间间隔 + plan.setPredictMileage(rule.getMileage()); + if(Objects.nonNull(rule.getTime())){ + plan.setPredictTime(DateUtil.offsetDay(vo.getLastTime(),rule.getTime())); + } + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + plan.setOrderNo(format); + plan.setContent(rule.getName()); + this.save(plan); + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(plan.getProjectId()); + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),plan.getId(), + plan.getProjectId(), WorkOrderType.UPKEEP_PLAN.getType(),"未审批", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + saveCount.getAndIncrement(); + } + } + } + } + }); + + return saveCount.get(); + } + + public Integer ruleCreatePlanByMile(List ruleMiles,Integer createNo) { + AtomicInteger saveCount = new AtomicInteger(); + ruleMiles.stream().forEach(rule->{ + //按时间规则查车,没有上次里程的车取交车时间 + List vehicleInfoVOList = repairInfoMapper.findVehicleInfoByMile(rule.getVehicleType(),rule.getVehicleModel(),rule.getVehicleBrand()); + if(Objects.nonNull(vehicleInfoVOList) && vehicleInfoVOList.size()>0){ + for(VehicleInfoVO vo : vehicleInfoVOList){ + //查有无进行中的计划或台账 + int unFinishcount = upkeepPlanMapper.findUnfinishCount(vo.getPlateNumber()); + if(unFinishcount>0){ + continue; + } + //查有无已生成的当前批次计划 + LambdaQueryWrapper planQuery = new LambdaQueryWrapper<>(); + planQuery.eq(TbUpkeepPlan::getPlateNumber,vo.getPlateNumber()) + .eq(TbUpkeepPlan::getCreateNo,createNo); + int count = this.count(planQuery); + if(count > 0){ + continue; + }else{ + //按里程生成保养单 (当前车辆的总里程数+本月的累计里程数)>=(设置的里程数间隔 + 上次保养里程)*90%则生成保养计划 + if((vo.getTotalMileage() + vo.getMonthlyTotalMileage())>= ((rule.getMileage() + vo.getLastMileage())*0.9)){ + //生成该车保养计划 + TbUpkeepPlan plan = new TbUpkeepPlan(); + BeanUtil.copyProperties(vo,plan,"id"); + //未审核 + plan.setAuditStatus("1"); + //自动、规则id、批次号、生成日期 + plan.setSaveType(1); + plan.setRuleId(rule.getId()); + plan.setCreateNo(createNo); + plan.setPlanSaveTime(new Date()); + //预计保养里程、时间。。。时间为这次上次保养时间+时间间隔 + plan.setPredictMileage(rule.getMileage() + vo.getLastMileage()); + if(Objects.nonNull(rule.getTime())){ + plan.setPredictTime(DateUtil.offsetDay(vo.getLastTime(),rule.getTime())); + } + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + plan.setOrderNo(format); + plan.setContent(rule.getName()); + this.save(plan); + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(plan.getProjectId()); + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),plan.getId(), + plan.getProjectId(), WorkOrderType.UPKEEP_PLAN.getType(),"未审批", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + saveCount.getAndIncrement(); + } + } + } + } + }); + return saveCount.get(); + } + + public Integer ruleCreatePlanByTimeOrMiles(List ruleTimeOrMiles,Integer createNo) { + AtomicInteger saveCount = new AtomicInteger(); + //“或”工单仅有一条 + ruleTimeOrMiles.stream().forEach(rule->{ + //按时间规则查车,没有上次里程的车取交车时间 + List vehicleInfoVOList = repairInfoMapper.findVehicleInfoByMile(rule.getVehicleType(),rule.getVehicleModel(),rule.getVehicleBrand()); + if(Objects.nonNull(vehicleInfoVOList) && vehicleInfoVOList.size()>0) { + for (VehicleInfoVO vo : vehicleInfoVOList) { + //查有无进行中的计划或台账 + int unFinishcount = upkeepPlanMapper.findUnfinishCount(vo.getPlateNumber()); + if(unFinishcount>0){ + continue; + } + //查有无已生成的当前批次计划 + LambdaQueryWrapper curPlanQuery = new LambdaQueryWrapper<>(); + curPlanQuery.eq(TbUpkeepPlan::getPlateNumber,vo.getPlateNumber()) + .eq(TbUpkeepPlan::getCreateNo,createNo); + int curCount = this.count(curPlanQuery); + if(curCount > 0){ + continue; + } + //查有无已经有生成过一次的“或”工单 + LambdaQueryWrapper planQuery = new LambdaQueryWrapper<>(); + planQuery.eq(TbUpkeepPlan::getRuleId,rule.getId()).eq(TbUpkeepPlan::getPlateNumber,vo.getPlateNumber()); + int count = this.count(planQuery); + if(count > 0){ + continue; + }else{ + //时间或里程,满足其一即可 + long days = DateUtil.between(DateUtil.offsetDay(vo.getLastTime(),rule.getTime()), new Date(), DateUnit.DAY,false); + if(days <= 30 && days >= 0){ + //生成该车保养计划 + TbUpkeepPlan plan = new TbUpkeepPlan(); + BeanUtil.copyProperties(vo,plan,"id"); + //未审核 + plan.setAuditStatus("1"); + //自动、规则id、批次号、生成日期 + plan.setSaveType(1); + plan.setRuleId(rule.getId()); + plan.setCreateNo(createNo); + plan.setPlanSaveTime(new Date()); + //预计保养里程、时间。。。时间为这次上次保养时间+时间间隔 + plan.setPredictMileage(rule.getMileage()); + if(Objects.nonNull(rule.getTime())){ + plan.setPredictTime(DateUtil.offsetDay(vo.getLastTime(),rule.getTime())); + } + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + plan.setOrderNo(format); + plan.setContent(rule.getName()); + this.save(plan); + saveCount.getAndIncrement(); + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(plan.getProjectId()); + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),plan.getId(), + plan.getProjectId(), WorkOrderType.UPKEEP_PLAN.getType(),"未审批", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + continue; + } + + if((vo.getTotalMileage() + vo.getMonthlyTotalMileage())>= ((rule.getMileage() + vo.getLastMileage())*0.9)){ + //生成该车保养计划 + TbUpkeepPlan plan = new TbUpkeepPlan(); + BeanUtil.copyProperties(vo,plan,"id"); + //未审核 + plan.setAuditStatus("1"); + //自动、规则id、批次号、生成日期 + plan.setSaveType(1); + plan.setRuleId(rule.getId()); + plan.setCreateNo(createNo); + plan.setPlanSaveTime(new Date()); + //预计保养里程、时间。。。时间为这次上次保养时间+时间间隔 + plan.setPredictMileage(rule.getMileage() + vo.getLastMileage()); + if(Objects.nonNull(rule.getTime())){ + plan.setPredictTime(DateUtil.offsetDay(vo.getLastTime(),rule.getTime())); + } + //工单号 + String format = DateUtil.format(new Date(),"yyyyMMddHHmmssSSS"); + plan.setOrderNo(format); + plan.setContent(rule.getName()); + this.save(plan); + saveCount.getAndIncrement(); + //推送微信消息 + ThreadUtil.execAsync(()->{ + Projects projects = projectsService.getById(plan.getProjectId()); + msgPushService.pushMsgToRedis(new MsgRedisVO( + SenderTypeEnum.YYWB.getSendType(),plan.getId(), + plan.getProjectId(), WorkOrderType.UPKEEP_PLAN.getType(),"未审批", + DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),projects.getProjectName() + "工单更新,请及时查看")); + }); + continue; + } + } + } + } + }); + return saveCount.get(); + } + + //补充按钮权限 + public void handlerButtonAndType(List list, String authorityType){ + //1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + if("4".equals(authorityType)){ + list.stream().forEach(item->{ + UpkeepPlanStatusEnumEmployee statusEnum = UpkeepPlanStatusEnumEmployee.getEnum(item.getAuditStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setAuditButton(statusEnum.getAuditButton()); + //手动生成才有编辑 + if(2 == item.getSaveType()){ + item.setEditButton(statusEnum.getEditButton()); + } + //没编辑就补充查看按钮 + if(Objects.isNull(item.getEditButton()) || item.getEditButton()==2){ + item.setCheckButton(1); + } + item.setUserType(authorityType); + } + }); + } + + if("6".equals(authorityType) || "5".equals(authorityType)){ + list.stream().forEach(item->{ + UpkeepPlanStatusEnumLeader statusEnum = UpkeepPlanStatusEnumLeader.getEnum(item.getAuditStatus()); + if(Objects.nonNull(statusEnum)){ + item.setCheckButton(statusEnum.getCheckButton()); + item.setDeleteButton(statusEnum.getDeleteButton()); + item.setAuditButton(statusEnum.getAuditButton()); + //手动生成才有编辑 + if(2 == item.getSaveType()){ + item.setEditButton(statusEnum.getEditButton()); + } + //没编辑就补充查看按钮 + if(Objects.isNull(item.getEditButton()) || item.getEditButton()==2){ + item.setCheckButton(1); + } + item.setUserType("5"); + } + }); + } + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepRuleServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepRuleServiceImpl.java new file mode 100644 index 0000000..001321e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbUpkeepRuleServiceImpl.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; +import com.gci.boot.modules.vehicles.entity.TbUpkeepRule; +import com.gci.boot.modules.vehicles.mapper.TbRepairOfferMapper; +import com.gci.boot.modules.vehicles.mapper.TbUpkeepRuleMapper; +import com.gci.boot.modules.vehicles.service.ITbRepairOfferService; +import com.gci.boot.modules.vehicles.service.ITbUpkeepRuleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class TbUpkeepRuleServiceImpl extends ServiceImpl implements ITbUpkeepRuleService { +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbViolationRecordServiceImpl.java b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbViolationRecordServiceImpl.java new file mode 100644 index 0000000..1951ca4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/service/impl/TbViolationRecordServiceImpl.java @@ -0,0 +1,453 @@ +package com.gci.boot.modules.vehicles.service.impl; + +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gci.boot.common.vo.Result; +import com.gci.boot.constant.CommonConstant; +import com.gci.boot.modules.driver.service.ITbDriverSignInService; +import com.gci.boot.modules.projects.entity.Projects; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.entity.SysDict; +import com.gci.boot.modules.system.entity.SysDictItem; +import com.gci.boot.modules.system.service.ISysDictItemService; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.entity.TbAnnualInspectionInfo; +import com.gci.boot.modules.vehicles.entity.TbInsurance; +import com.gci.boot.modules.vehicles.entity.TbViolationRecord; +import com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper; +import com.gci.boot.modules.vehicles.service.ITbViolationRecordService; +import com.gci.boot.modules.vehicles.vo.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class TbViolationRecordServiceImpl extends ServiceImpl implements ITbViolationRecordService { + + @Autowired + private TbViolationRecordMapper violationRecordMapper; + @Autowired + private ISysDictService sysDictService; + @Autowired + private ISysDictItemService sysDictItemService; + @Autowired + private IProjectsService projectsService; + @Autowired + private ITbDriverSignInService driverSignInService; + @Value("${failExcel}") + private String failExcel; + + @Override + public List queryVehicleProject() { + return violationRecordMapper.queryVehicleProject(); + } + + @Override + public List queryAllVehicle() { + return violationRecordMapper.queryAllVehicle(); + } + + @Override + public List queryAllProject() { + return violationRecordMapper.queryProjects(0,0); + } + + @Override + public MessageVO analyzeMessage(String template) { + log.info("识别短信 {}", template); + //模板1: 【四川交警】您的小型新能源汽车川AAP0633于2023-08-19 09:10在成都市二环路西二段与战旗东路交叉路口,被交通技术监控设备记录了『不按导向车道行驶』的违法行为。请于收到本告知之日起30日内接受处理。 + //模板2: 【成都交警】川AAP8022于2023-10-30在瑞星路与琼楼路交叉路口实施机动车通过有灯控路口时,不按所需行进方向驶入导向车道的违法行为,请三十日内到交警部门接受处理。该车有18笔违法记录未处理,请及时处理。(更多请关注蓉E行) + MessageVO vo = new MessageVO(); + // 定义车牌号的正则表达式 + String regexPlateNumber = "[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]*"; + // 定义时间的正则表达式--模板1 + String regexTime = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}"; + // 定义地点的正则表达式--模板1 + String regexLocation = "(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})在(.+?),"; + //违章行为--模板1 + String regexViolationAct = "『([^』]+)』"; + + Pattern patternPlateNumber = Pattern.compile(regexPlateNumber); + Matcher matcherPlateNumber = patternPlateNumber.matcher(template); + if (matcherPlateNumber.find()) { + vo.setPlateNumber(matcherPlateNumber.group()); + } + + Pattern patternTime = Pattern.compile(regexTime); + Matcher matcherTime = patternTime.matcher(template); + if (matcherTime.find()) { + vo.setViolationTime(matcherTime.group()); + }else{ + //时间模板2处理 + Matcher matcherTime2 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}").matcher(template); + if (matcherTime2.find()) { + vo.setViolationTime(matcherTime2.group() + " 00:00"); + } + } + + Pattern patternAddress = Pattern.compile(regexLocation); + Matcher matcherAddress = patternAddress.matcher(template); + if (matcherAddress.find()) { + vo.setViolationAddress(matcherAddress.group(2)); + }else{ + //地点模板2处理 + Matcher matcherAddress2 = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})在(.+?)实施").matcher(template); + if (matcherAddress2.find()) { + vo.setViolationAddress(matcherAddress2.group(2)); + } + } + + Pattern pattern = Pattern.compile(regexViolationAct); + Matcher matcher = pattern.matcher(template); + if (matcher.find()) { + String violation = matcher.group(1); + log.info("违章行为 {}", violation); + //查字典是否存在,没有存在的话加到字典里面去 + //违章行为字典 + List violationList = sysDictService.queryDictItemsByCode("violation_behavior"); + Map violationMap = violationList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + String act = ""; + for (String key : violationMap.keySet()) { + String value = violationMap.getOrDefault(key,""); + if(StrUtil.isNotBlank(value) && violation.equals(value)){ + act = key; + break; + } + } + if(StrUtil.isNotBlank(act)){ + vo.setViolationAct(act); + }else{ + vo.setIsNewBehavior(true); + vo.setNewBehavior(violation); + } + }else{ + //违章行为模板2处理 + Matcher matcher2 = Pattern.compile("实施(.+?)的违法行为").matcher(template); + if (matcher2.find()) { + String violation = matcher2.group(1); + log.info("违章行为 {}", violation); + //查字典是否存在,没有存在的话加到字典里面去 + //违章行为字典 + List violationList = sysDictService.queryDictItemsByCode("violation_behavior"); + Map violationMap = violationList.stream().collect(Collectors.toMap(DictModel::getValue, DictModel::getText)); + String act = ""; + for (String key : violationMap.keySet()) { + String value = violationMap.getOrDefault(key,""); + if(StrUtil.isNotBlank(value) && violation.equals(value)){ + act = key; + break; + } + } + if(StrUtil.isNotBlank(act)){ + vo.setViolationAct(act); + }else{ + vo.setIsNewBehavior(true); + vo.setNewBehavior(violation); + } + }else{ + vo.setIsNewBehavior(null); + } + } + + return vo; + } + + @Override + public String addViolationBehavior(MessageVO vo) { + //违章行为字典 + List violationList = sysDictService.queryDictItemsByCode("violation_behavior"); + List distTexts = violationList.stream().map(DictModel::getText).collect(Collectors.toList()); + if(distTexts.contains(vo.getNewBehavior())){ + return "已存在该违章行为!"; + } + //保存到字典 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysDict::getDictCode,"violation_behavior").last(" limit 1 "); + SysDict sysDict = sysDictService.getOne(queryWrapper); + + SysDictItem dictItem = new SysDictItem(); + dictItem.setDictId(sysDict.getId()); + dictItem.setItemText(vo.getNewBehavior()); + dictItem.setItemValue(String.valueOf(getMaxValue(violationList))); + dictItem.setStatus(1); + sysDictItemService.save(dictItem); + return dictItem.getItemValue(); + } + + @Override + public List importViolationMessage(List msgTemplates) { + if(CollectionUtil.isEmpty(msgTemplates)){ + return null; + } + List failList = new ArrayList<>(); + //查用户所有权限车牌 + List plateNumbers = projectsService.queryAllPlateNumberListOfUser(); + //查项目车牌对应 + List projectCarList = this.queryVehicleProject(); + List carList = projectCarList.stream().map(VehicleProjectVO::getPlateNumber).collect(Collectors.toList()); + //查是否有重复 + Map> repeatMap = getRepeatIndex(msgTemplates); + //历史记录 + List historyList = this.list(); + for(int i = 0; i< msgTemplates.size(); i++){ + int flag = 0; + String failDetails = ""; + MsgImportFailVO failVO = new MsgImportFailVO(); + MessageVO vo = this.analyzeMessage(msgTemplates.get(i)); + if(StrUtil.isBlank(vo.getPlateNumber())){ + flag += 1; + failDetails += "'车牌号' 解析为空 "; + failVO.setFormatErrors("1"); + } + if(StrUtil.isBlank(vo.getViolationAddress())){ + flag += 1; + failDetails += "'违章地点' 解析为空 "; + failVO.setFormatErrors("1"); + } + if((StrUtil.isBlank(vo.getViolationAct()) && StrUtil.isBlank(vo.getNewBehavior()))){ + flag += 1; + failDetails += "'违章行为' 解析为空 "; + failVO.setFormatErrors("1"); + } + if(StrUtil.isBlank(vo.getViolationTime())){ + flag += 1; + failDetails += "'违章时间' 解析为空 "; + failVO.setFormatErrors("1"); + } + + if(!plateNumbers.contains(vo.getPlateNumber())){ + flag += 1; + failDetails += "当前用户没有该车牌号权限或车辆不存在 "; + failVO.setFormatErrors("1"); + } + if(Objects.nonNull(vo.getIsNewBehavior()) && vo.getIsNewBehavior()){ + flag += 1; + failDetails += "该违章行为缺少对应字典 "; + failVO.setFormatErrors("1"); + } + if(!carList.contains(vo.getPlateNumber())){ + flag += 1; + failDetails += "该车牌号没有对应项目 "; + failVO.setFormatErrors("1"); + } + if(Objects.nonNull(repeatMap) && repeatMap.containsKey(msgTemplates.get(i))){ + flag += 1; + failDetails += "存在重复的'违章短信' "; + failVO.setRepeatErrors("1"); + } + if(StrUtil.isNotBlank(vo.getPlateNumber()) && StrUtil.isNotBlank(vo.getViolationAct()) && StrUtil.isNotBlank(vo.getViolationTime())){ + //判断是否与历史数据重复 + List historys = historyList.stream().filter(h -> vo.getPlateNumber().equals(h.getPlateNumber()) + && vo.getViolationAct().equals(h.getViolationAct()) + && vo.getViolationTime().equals(DateUtil.format(h.getViolationTime(),"yyyy-MM-dd HH:mm"))).collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(historys)){ + flag += 1; + failDetails += "'车牌号'、'违章行为'、'违章时间'已存在重复历史记录 "; + failVO.setRepeatErrors("1"); + } + } + if(flag > 0){ + //记录失败数据及原因 + failVO.setMsg(msgTemplates.get(i)); + failVO.setFailDetails(failDetails); + failList.add(failVO); + }else{ + try { + //保存 + TbViolationRecord violationRecord = new TbViolationRecord(); + violationRecord.setPlateNumber(vo.getPlateNumber()); + //项目、负责人 + VehicleProjectVO projectCar = projectCarList.stream().filter(item -> item.getPlateNumber().equals(vo.getPlateNumber())).findFirst().orElse(null); + if(Objects.nonNull(projectCar)){ + violationRecord.setProjectId(projectCar.getProjectId()); + violationRecord.setDirector(projectCar.getProjectManager()); + } + Projects projects = projectsService.getById(violationRecord.getProjectId()); + if(Objects.nonNull(projects)){ + violationRecord.setProjectName(projects.getProjectName()); + } + //违章行为、地点、时间 + violationRecord.setViolationAct(vo.getViolationAct()); + violationRecord.setViolationAddress(vo.getViolationAddress()); + violationRecord.setViolationTime(DateUtil.parse(vo.getViolationTime(),"yyyy-MM-dd HH:mm")); + //司机 + violationRecord.setViolationDriver(driverSignInService.queryDriverByPlateNumberAndTime(vo.getPlateNumber(),vo.getViolationTime())); + this.save(violationRecord); + }catch (Exception e){ + e.printStackTrace(); + //记录保存异常数据 + MsgImportFailVO newFailVO = new MsgImportFailVO(); + newFailVO.setMsg(msgTemplates.get(i)); + newFailVO.setFailDetails(e.getMessage()); + newFailVO.setFormatErrors("1"); + failList.add(newFailVO); + } + } + } + return failList; + } + + //已导入xx条;第x、a、y行数据重复,第xx、aa行数据格式异常。 + @Override + public Result msgImport(MultipartFile file) throws IOException { + InputStream inputStream = file.getInputStream(); + int size = 0; + try { +// List dataList = this.readSingleColumnFromExcel(inputStream); + List dataList = new ArrayList<>(); + List list = EasyExcel.read(inputStream).head(MsgImportFailVO.class).sheet().doReadSync(); + if(CollectionUtils.isEmpty(list)){ + return Result.error("导入违章短信数据不能为空!请检查导入模板!"); + } + dataList = list.stream().filter(s->StrUtil.isNotBlank(s.getMsg())).map(MsgImportFailVO::getMsg).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(dataList)){ + return Result.error("导入违章短信数据不能为空!请检查导入模板!"); + } + size = dataList.size(); + List failList = this.importViolationMessage(dataList); + if (CollectionUtil.isNotEmpty(failList)) { + String fielName = System.currentTimeMillis() + CommonConstant.VIOLATE_IMPORT_FAIL_EXCEL_NAME; + EasyExcel.write(failExcel + fielName, MsgImportFailVO.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("导入异常数据").doWrite(failList); + JSONObject entries = new JSONObject(); + //格式异常行数 +// List indexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getFormatErrors())) { +// indexes.add(i+2); +// } +// } +// //数据重复 +// List repeatIndexes = new ArrayList<>(); +// for (int i = 0; i < failList.size(); i++) { +// if ("1".equals(failList.get(i).getRepeatErrors())) { +// repeatIndexes.add(i+2); +// } +// } + String errorMsg = "已导入"+ (size-failList.size()) + "条;失败"+ failList.size() +"条;具体失败详情见失败导出信息表"; +// if(CollectionUtil.isNotEmpty(repeatIndexes)){ +// errorMsg += "第"+ repeatIndexes + "行数据重复;"; +// } +// if(CollectionUtil.isNotEmpty(indexes)){ +// errorMsg += "第"+ indexes + "行数据格式异常"; +// } + entries.set("msg",errorMsg); + entries.set("path",fielName); + return Result.ok(entries); + } + } catch (Exception e) { + e.printStackTrace(); + return Result.error("导入异常,请联系管理员!"); + } finally { + inputStream.close(); + } + return Result.ok(); + } + + + public int getMaxValue(List violationList) { + int maxValue = Integer.MIN_VALUE; + for (DictModel dictModel : violationList) { + String valueStr = dictModel.getValue(); + int value = Integer.parseInt(valueStr); + if (value > maxValue) { + maxValue = value; + } + } + return maxValue + 1; + } + + /** + *读Excel + */ + public List readSingleColumnFromExcel(InputStream inputStream) throws IOException { + List dataList = new ArrayList<>(); + Workbook workbook = new XSSFWorkbook(inputStream); + Sheet sheet = workbook.getSheetAt(0); + int rowCount = sheet.getLastRowNum(); // 获取最后一行的索引 + for (int i = 1; i <= rowCount; i++) { // 从第二行开始读取数据 + Row row = sheet.getRow(i); + if(Objects.nonNull(row)){ + Cell cell = row.getCell(0); + if (cell != null) { + String cellValue = getCellValueAsString(cell); + if (!cellValue.isEmpty() && !cellValue.trim().isEmpty()) { // 校验单元格内容非空 + dataList.add(cellValue); + } + } + } + } + workbook.close(); + return dataList; + } + private String getCellValueAsString(Cell cell) { + switch (cell.getCellType()) { + case STRING: + return cell.getStringCellValue(); + case NUMERIC: + return String.valueOf(cell.getNumericCellValue()); + case BOOLEAN: + return String.valueOf(cell.getBooleanCellValue()); + case BLANK: + return ""; + default: + return ""; + } + } + + /** + * 获取重复的导入数据索引,按重复短信进行分组 + */ + public Map> getRepeatIndex(List msgTemplates) { + if(CollectionUtil.isEmpty(msgTemplates)){ + return null; + } + Map> indexMap = new HashMap<>(); + for (int i = 0; i < msgTemplates.size(); i++) { + String msg = msgTemplates.get(i); + if (indexMap.containsKey(msg)) { + indexMap.get(msg).add(i+1); + } else { + List indexes = new ArrayList<>(); + indexes.add(i+1); + indexMap.put(msg, indexes); + } + } + //删除不重复的记录 + List keysToRemove = new ArrayList<>(); + for (Map.Entry> entry : indexMap.entrySet()) { + if (entry.getValue().size() == 1) { + keysToRemove.add(entry.getKey()); + } + } + for (String key : keysToRemove) { + indexMap.remove(key); + } + return indexMap; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/AttachmentDetailVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/AttachmentDetailVO.java new file mode 100644 index 0000000..c7d62c4 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/AttachmentDetailVO.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.vehicles.vo; + +import lombok.Data; + +@Data +public class AttachmentDetailVO { + + private String fileName; + + private String fileUrl; + + private String fileType; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/BacklogStatisVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/BacklogStatisVO.java new file mode 100644 index 0000000..cc1dae8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/BacklogStatisVO.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.vehicles.vo; + +import lombok.Data; + +@Data +public class BacklogStatisVO { + + private String type; + + private String value; + + private Long statisCount; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/CancelObjectVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/CancelObjectVO.java new file mode 100644 index 0000000..6589273 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/CancelObjectVO.java @@ -0,0 +1,25 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +public class CancelObjectVO { + + @ApiModelProperty("作废意见") + private String cancelIdea; + + @ApiModelProperty("作废人") + private String cancelPeople; + + @ApiModelProperty("作废时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date cancelTime; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/CancelVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/CancelVO.java new file mode 100644 index 0000000..2bbe057 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/CancelVO.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.vehicles.vo; + +import lombok.Data; + +@Data +public class CancelVO { + + private String id; + + private String cancelIdea; + + private String realname; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/ConsumablesTemplateVo.java b/src/main/java/com/gci/boot/modules/vehicles/vo/ConsumablesTemplateVo.java new file mode 100644 index 0000000..b964600 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/ConsumablesTemplateVo.java @@ -0,0 +1,98 @@ +package com.gci.boot.modules.vehicles.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * 列表返回的实体类 + * @author 24642 + */ +@Data +public class ConsumablesTemplateVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 其实是耗材的id + */ + private String id; + + /** + * 耗材名称 + */ + @Excel(name = "耗材名称",orderNum = "0") + private String name; + + /** + * 规格 + */ + @Excel(name = "耗材规格",orderNum = "4") + private String specification; + + /** + * 数量 + */ + @Excel(name = "耗材数量",orderNum = "3") + private Integer quantity; + + /** + * 单位 + */ + @Dict(dicCode = "units") + private String units; + + /** + * 入库时间 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "入库时间不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "入库时间",format = "yyyy-MM-dd",orderNum = "5") + private Date storageTime; + + /** + * 经办人 + */ + @NotBlank(message = "经办人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "经办人",orderNum = "4") + private String responsiblePerson; + + /** + * 项目id + */ + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @Excel(name = "所属项目",dict = "tb_projects,project_name,id",needMerge = true,orderNum = "1") + private String projectId; + + /** + * 车辆种类 + */ + @Dict(dicCode = "vehicle_type") + @Excel(name = "车辆种类",dict = "vehicle_type",needMerge = true,orderNum = "2") + private String vehicleType; + + /** + * 更新时间 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** + * 更新人 + */ + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + private String updateBy; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/CustomizedTemplateVo.java b/src/main/java/com/gci/boot/modules/vehicles/vo/CustomizedTemplateVo.java new file mode 100644 index 0000000..187e77c --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/CustomizedTemplateVo.java @@ -0,0 +1,96 @@ +package com.gci.boot.modules.vehicles.vo; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * @author 24642 + */ +@Data +public class CustomizedTemplateVo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 其实是定制件的id + */ + private String id; + + /** + * 定制件名称 + */ + @Excel(name = "定制件名称",orderNum = "0") + private String name; + + /** + * 规格 + */ + @Excel(name = "定制件规格",orderNum = "4") + private String specification; + + /** + * 数量 + */ + @Excel(name = "定制件数量",orderNum = "3") + private Integer quantity; + + /** + * 单位 + */ + @Dict(dicCode = "units") + private String units; + + /** + * 入库时间 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @NotNull(message = "入库时间不能为空!",groups = {SaveValidated.class, UpdateValidated.class}) + @Excel(name = "入库时间",format = "yyyy-MM-dd",orderNum = "5") + private Date storageTime; + + /** + * 经办人 + */ + @NotBlank(message = "经办人不能为空!",groups = {SaveValidated.class,UpdateValidated.class}) + @Excel(name = "经办人",orderNum = "4") + private String responsiblePerson; + + /** + * 项目id + */ + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @Excel(name = "所属项目",dict = "tb_projects,project_name,id",needMerge = true,orderNum = "1") + private String projectId; + + /** + * 车辆种类 + */ + @Dict(dicCode = "vehicle_type") + @Excel(name = "车辆种类",dict = "vehicle_type",needMerge = true,orderNum = "2") + private String vehicleType; + + /** + * 更新时间 + */ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + /** + * 更新人 + */ + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + private String updateBy; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceImportVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceImportVO.java new file mode 100644 index 0000000..594a626 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceImportVO.java @@ -0,0 +1,176 @@ +package com.gci.boot.modules.vehicles.vo; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.util.DateUtils; +import com.gci.boot.common.util.ValidatorUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 保险信息 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Data +public class InsuranceImportVO implements Serializable { + + @ExcelProperty("车牌号") + @ValidatorUtil.NotEmpty(message = "车牌号不能为空") + private String plateNumber; + + @ExcelProperty(value = "所属保险合同编号") + @ValidatorUtil.NotEmpty(message = "所属保险合同编号不能为空") + private String contractName; + + @ExcelProperty(value = "保险公司") + @ValidatorUtil.NotEmpty(message = "保险公司不能为空") + private String compulsoryCompany; + + @ExcelProperty(value = "起保日期") + @ValidatorUtil.NotEmpty(message = "起保日期不能为空") + @ValidatorUtil.DateValue(format = "yyyy-MM-dd", message = "日期格式错误:格式为'yyyy-MM-dd'") + private String compulsoryStartTime; + + @ExcelProperty(value = "有效日期") + @ValidatorUtil.NotEmpty(message = "有效日期不能为空") + @ValidatorUtil.DateValue(format = "yyyy-MM-dd", message = "日期格式错误:格式为'yyyy-MM-dd'") + private String compulsoryValidTime; + + @ExcelProperty(value = "交强险") + @ValidatorUtil.CollectionStr(collectionStr="是,否",message = "取值范围为是或否") + private String hasCompulsoryInsurance; + + @ExcelProperty(value = "交强险保险单号") + @ValidatorUtil.NotEmptyByField(field = "hasCompulsoryInsurance",message = "交强险为'是',交强险保险单号不能为空") + private String compulsoryInsuranceNo; + + @ExcelProperty(value = "保险金额(元)") + @ValidatorUtil.NumericValue(minValue = 0,maxValue = 99999999,message = "超过取值范围,金额范围为[0,99999999]") + @ValidatorUtil.NotEmptyByField(field = "hasCompulsoryInsurance",message = "交强险为'是',保险金额不能为空") + private Double compulsoryPrice; + + @ExcelProperty(value = "车船税(元)") + @ValidatorUtil.NumericValue(minValue = 0,maxValue = 99999999,message = "超过取值范围,金额范围为[0,99999999]") + @ValidatorUtil.NotEmptyByField(field = "hasCompulsoryInsurance",message = "交强险为'是',车船税不能为空") + private Double vehicleVesselTax; + + @ExcelProperty(value = "商业险") + @ValidatorUtil.CollectionStr(collectionStr="是,否",message = "取值范围为是或否") + private String hasCommercialInsurance; + + @ExcelProperty(value = "商业险保险单号") + @ValidatorUtil.NotEmptyByField(field = "hasCommercialInsurance",message = "商业险为'是',商业险保单号不能为空") + private String commercialInsuranceNo; + + @ExcelProperty(value = "保险费(元)") + @ValidatorUtil.NumericValue(minValue = 0,maxValue = 99999999,message = "超过取值范围,金额范围为[0,99999999]") + @ValidatorUtil.NotEmptyByField(field = "hasCommercialInsurance",message = "商业险为'是',保险费不能为空") + private Double commercialPrice; + + @ExcelProperty("备注") + private String remark; + + /** + * 用于记录校验异常信息 + */ + @ExcelIgnore + private List validationErrors; + @ExcelProperty("异常信息") + private String validationErrorsStr; + + /** + * 合同id + */ + @ExcelIgnore + private String contractId; + + + /** + * 保险公司id + */ + @ExcelIgnore + private String compulsoryCompanyId; + + + /** + * 所属机构 + */ + @ExcelIgnore + private String sysOrgCode; + + + /** + * 创建人 + */ + @ExcelIgnore + private String createBy; + + /** + * 车辆id + */ + @ExcelIgnore + private String vehicleId; + /** + * 项目id + */ + @ExcelIgnore + private String projectId; + + /** + * 车辆型号 + */ + @ExcelIgnore + private String vehicleModel; + /** + * 车辆种类 + */ + @ExcelIgnore + private String vehicleType; + /** + * 车架号 + */ + @ExcelIgnore + private String frameNumber; + + + public void validate() { + ValidatorUtil.trimStringFields(this); + List validationErrors = ValidatorUtil.validate(this); + if(CollectionUtil.isNotEmpty(validationErrors)){ + this.validationErrors = validationErrors.stream().map(ValidatorUtil.ValidationError::getMessage).collect(Collectors.toList()); + this.validationErrorsStr = this.validationErrors + ""; + } + } + + public void putErrorMsg(String msg){ + if(CollectionUtil.isNotEmpty(this.validationErrors)){ + this.validationErrors.add(msg); + }else{ + this.validationErrors = CollectionUtil.newArrayList(msg); + } + this.validationErrorsStr = this.validationErrors + ""; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/InsurancePriceVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/InsurancePriceVO.java new file mode 100644 index 0000000..b470af9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/InsurancePriceVO.java @@ -0,0 +1,13 @@ +package com.gci.boot.modules.vehicles.vo; + +import lombok.Data; + +@Data +public class InsurancePriceVO { + + private String plateNumber; + + private String yearTime; + + private Double amount; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceRecordStatisVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceRecordStatisVO.java new file mode 100644 index 0000000..6c005d9 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/InsuranceRecordStatisVO.java @@ -0,0 +1,56 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import lombok.Data; + +@Data +public class InsuranceRecordStatisVO { + @ColumnWidth(value = 20) + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",converter = DictConverter.class) + private String projectId; + @ColumnWidth(value = 20) + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类",converter = DictConverter.class) + private String vehicleType; + @ColumnWidth(value = 20) + @Dict(dicCode = "vehicle_brand") + @ExcelProperty(value = "品牌",converter = DictConverter.class) + private String vehicleBrand; + @ColumnWidth(value = 20) + @ExcelProperty(value = "型号") + private String vehicleModel; + @ColumnWidth(value = 20) + @ExcelProperty(value = "车牌号") + private String plateNumber; + @ExcelIgnore + private String vehicleId; + @ColumnWidth(value = 20) + @ExcelProperty(value = "车架号") + private String frameNumber; + @ColumnWidth(value = 20) + @ExcelProperty(value = "统计期间") + private String statisTime; + @ColumnWidth(value = 20) + @ExcelProperty(value = "出险车次") + private Integer insuranceTimes; + @ColumnWidth(value = 20) + @ExcelProperty(value = "出险金额(元)") + private Double insuranceAmount; + @ColumnWidth(value = 20) + @ExcelProperty(value = "平均出险金额(元/车次)") + private Double avgAmount; + @ColumnWidth(value = 20) + @ExcelProperty(value = "车辆年度保费") + private Double annualPremium; + @ColumnWidth(value = 20) + @ExcelProperty(value = "保费变化") + private String premiumChange; + @ColumnWidth(value = 20) + @ExcelProperty(value = "次年保费预算") + private Double nextYearPremium; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/MessageVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/MessageVO.java new file mode 100644 index 0000000..c22e89e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/MessageVO.java @@ -0,0 +1,28 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class MessageVO { + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("违章时间") + private String violationTime; + + @ApiModelProperty("违章地点") + private String violationAddress; + + @Dict(dicCode = "violation_behavior") + @ApiModelProperty("违章行为") + private String violationAct; + + @ApiModelProperty("是否新的违章行为") + private Boolean isNewBehavior = false; + + @ApiModelProperty("新的违章行为描述") + private String newBehavior; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/MsgImportFailVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/MsgImportFailVO.java new file mode 100644 index 0000000..532041d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/MsgImportFailVO.java @@ -0,0 +1,21 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +@Data +public class MsgImportFailVO { + + @ExcelProperty("违章短信") + private String msg; + + @ExcelProperty("异常信息") + private String failDetails; + //格式异常的 + @ExcelIgnore + private String formatErrors; + //重复的 + @ExcelIgnore + private String repeatErrors; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/RegexTemplateVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/RegexTemplateVO.java new file mode 100644 index 0000000..dd0b71e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/RegexTemplateVO.java @@ -0,0 +1,9 @@ +package com.gci.boot.modules.vehicles.vo; + +import lombok.Data; + +@Data +public class RegexTemplateVO { + + private String template; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/RepairDataEntryVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairDataEntryVO.java new file mode 100644 index 0000000..c0b8bba --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairDataEntryVO.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; +import lombok.Data; + +@Data +public class RepairDataEntryVO { + + private TbRepairInfo repairInfo; + + private TbRepairOffer repairOffer; + + private TbRepairAssign repairAssign; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/RepairDetailVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairDetailVO.java new file mode 100644 index 0000000..b6f8c75 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairDetailVO.java @@ -0,0 +1,31 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.gci.boot.common.dict.annotation.Dict; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class RepairDetailVO { + + @ApiModelProperty("报修分类") + @Dict(dicCode = "repair_class") + private String repairClass; + + @ApiModelProperty("维修内容") + private String repairContent; + + @ApiModelProperty("数量") + private Integer quantity; + + @ApiModelProperty("材料单价") + private Double unitPrice; + + @ApiModelProperty("工时") + private Double workHours; + + @ApiModelProperty("工时费") + private Double workHoursCost; + + @ApiModelProperty("费用小计") + private Double totalCost; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/RepairImportVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairImportVO.java new file mode 100644 index 0000000..e834c4f --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairImportVO.java @@ -0,0 +1,122 @@ +package com.gci.boot.modules.vehicles.vo; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gci.boot.common.util.ValidatorUtil; +import lombok.Data; +import net.sf.jsqlparser.util.validation.ValidationError; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class RepairImportVO { + // 报修信息: 车牌号 报修人 联系电话 报修时间 报修分类 报修内容 是否质保 维修厂 + // 维修信息: 维修分类 维修内容 数量 材料单价 工时 工时单价 内容说明 + @ValidatorUtil.NotEmpty(message = "车牌号不能为空") + @ExcelProperty({"报修信息", "车牌号"}) + private String plateNumber; + @ValidatorUtil.NotEmpty(message = "报修人不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 32, message = "报修人长度不能超过32位", fieldNameCN = "报修人") + @ExcelProperty({"报修信息", "报修人"}) + private String repairPeople; + @ValidatorUtil.NotEmpty(message = "联系电话不能为空") + @ValidatorUtil.PhoneNumber(message = "联系电话格式错误") + @ExcelProperty({"报修信息", "联系电话"}) + private String phone; + @ValidatorUtil.NotEmpty(message = "报修时间不能为空") + @ValidatorUtil.DateValue(format = "yyyy-MM-dd", message = "报修时间格式错误:格式为'yyyy-MM-dd'") + @ExcelProperty({"报修信息", "报修时间"}) + private String repairTime; + @ValidatorUtil.NotEmpty(message = "报修分类不能为空") + @ExcelProperty({"报修信息", "报修分类"}) + private String repairClass; + @ValidatorUtil.NotEmpty(message = "报修内容不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 200, message = "报修内容长度不能超过200位", fieldNameCN = "报修内容") + @ExcelProperty({"报修信息", "报修内容"}) + private String repairContent; + @ValidatorUtil.NotEmpty(message = "是否质保不能为空") + @ValidatorUtil.CollectionStr(collectionStr = "是,否", message = "是否质保只能为'是'或'否'") + @ExcelProperty({"报修信息", "是否质保"}) + private String isGuarantee; + @ValidatorUtil.NotEmpty(message = "维修厂不能为空") + @ExcelProperty({"报修信息", "维修厂"}) + private String repairShop; + + @ValidatorUtil.NotEmpty(message = "维修分类不能为空") + @ExcelProperty({"维修信息", "维修分类"}) + private String repairClassV2; + @ValidatorUtil.NotEmpty(message = "维修内容不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 100, message = "维修内容长度不能超过100位", fieldNameCN = "维修内容") + @ExcelProperty({"维修信息", "维修内容"}) + private String repairContentV2; + @ValidatorUtil.NotEmpty(message = "数量不能为空") + @ValidatorUtil.IntValue(minValue= 0, maxValue = 99999999, message = "数量必须为整数:且范围在[0,99999999]") + @ExcelProperty({"维修信息", "数量"}) + private String quantity; + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 99999999, message = "材料单价必须为数字:且范围在[0,99999999]") + @ValidatorUtil.NotEmpty(message = "材料单价不能为空") + @ExcelProperty({"维修信息", "材料单价"}) + private String unitPrice; + @ValidatorUtil.NotEmpty(message = "工时不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 99999999, message = "工时必须为数字:且范围在[0,99999999]") + @ExcelProperty({"维修信息", "工时"}) + private String workHours; + @ValidatorUtil.NotEmpty(message = "工时单价不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 99999999, message = "工时单价必须为数字:且范围在[0,99999999]") + @ExcelProperty({"维修信息", "工时单价"}) + private String workHoursCost; + @ValidatorUtil.NotEmpty(message = "内容说明不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 100, message = "内容说明长度不能超过100位", fieldNameCN = "内容说明") + @ExcelProperty({"维修信息", "内容说明"}) + private String content; + + + // 用于记录校验异常信息 + @ExcelIgnore + private List validationErrors; + @ExcelProperty({"异常信息", "异常信息"}) + private String validationErrorsStr; + // 用于记录所在行数 + @ExcelIgnore + private Integer row; + //字典值 + @ExcelIgnore + private String repairClassValue; + @ExcelIgnore + private String repairClassV2Value; + //维修厂信息 + @ExcelIgnore + private String repairShopId; + @ExcelIgnore + private String contact; + @ExcelIgnore + private String contactPhone; + //格式异常的 + @ExcelIgnore + private String formatErrors; + //重复的 + @ExcelIgnore + private String repeatErrors; + + public void validate() { + ValidatorUtil.trimStringFields(this); + List validationErrors = ValidatorUtil.validate(this); + if(CollectionUtil.isNotEmpty(validationErrors)){ + this.validationErrors = validationErrors.stream().map(ValidatorUtil.ValidationError::getMessage).collect(Collectors.toList()); + this.validationErrorsStr = this.validationErrors + ""; + } + } + + public void putErrorMsg(String msg){ + if(CollectionUtil.isNotEmpty(this.validationErrors)){ + this.validationErrors.add(msg); + }else{ + this.validationErrors = CollectionUtil.newArrayList(msg); + } + this.validationErrorsStr = this.validationErrors + ""; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/RepairInfoListVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairInfoListVO.java new file mode 100644 index 0000000..abefaf3 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairInfoListVO.java @@ -0,0 +1,114 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import java.util.Date; +import java.util.List; + +@Data +public class RepairInfoListVO { + + @ApiModelProperty("主键id") + @ExcelIgnore + private String id; + + //1待提交 - 2待派单 - 3待报价 - 4待审核报价 - 5待审批报价 - 6维修中 - 7待确认结果 - 8已归档 -9作废 + @ApiModelProperty("流程状态") + @Dict(dicCode = "repair_status") + @ExcelProperty(value = "流程状态",index = 7,converter = DictConverter.class) + @ColumnWidth(value = 20) + private Integer flowStatus; + //1运营维保部 - 2维修厂 - 3领导审批 - 4结束 + @ApiModelProperty("流程节点") + @Dict(dicCode = "repair_node") + @ExcelProperty(value = "流程节点",index = 8,converter = DictConverter.class) + @ColumnWidth(value = 20) + private Integer flowNode; + + @ApiModelProperty("工单号") + @ColumnWidth(value = 20) + @ExcelProperty(value = "工单号",index = 0) + private String orderNo; + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + @ApiModelProperty("车牌号") + @ColumnWidth(value = 20) + @ExcelProperty(value = "车牌号",index = 1) + private String plateNumber; + + @ApiModelProperty("报修人") + @ColumnWidth(value = 20) + @ExcelProperty(value = "报修人",index = 3) + private String repairPeople; + + @ApiModelProperty("报修时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "报修时间",index = 6) + @ColumnWidth(value = 20) + private Date repairTime; + + @ApiModelProperty("维修厂") + @Dict(dicCode = "id",dictTable = "tb_repair_shop_archives",dicText = "name") + @ExcelProperty(value = "维修厂",index = 4,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String repairShop; + + @ApiModelProperty("维修报价金额(元)") + @ColumnWidth(value = 20) + @ExcelProperty(value = "维修报价金额(元)",index = 5) + private Double repairCost; + + //查看按钮(派单。。。。) + @ExcelIgnore + private String checkButton; + + // 1-有作废按钮 2-没有 + @ExcelIgnore + private Integer deleteButton; + + // 用户类型 1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + @ExcelIgnore + private String userType; + + //1-数据录入,,2-走流程的 + @ExcelIgnore + private String addType; + + //司机 + @ExcelIgnore + private String driverParam; + //维修厂 + @ExcelIgnore + private String repairParam; + + //维修厂id集合参数,无需展示 + @ExcelIgnore + private List listRepairShop; + + //项目列表集合参数,无需展示 + @ExcelIgnore + private List listProject; + + //状态集合参数,无需展示 + @ExcelIgnore + private List flowStatusList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/RepairObjectVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairObjectVO.java new file mode 100644 index 0000000..5959b32 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/RepairObjectVO.java @@ -0,0 +1,48 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.modules.vehicles.entity.TbRepairAssign; +import com.gci.boot.modules.vehicles.entity.TbRepairCheck; +import com.gci.boot.modules.vehicles.entity.TbRepairInfo; +import com.gci.boot.modules.vehicles.entity.TbRepairOffer; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class RepairObjectVO { + + private String id; + + @ApiModelProperty("1-数据录入,,2-走流程的") + @ExcelIgnore + private Integer addType; + // 用户类型 1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + @ExcelIgnore + private String userType; + + @Dict(dicCode = "repair_status") + private Integer flowStatus; + + /** + * 审核状态 1-》通过, 2-》不通过 + */ + private Integer checkFlag = 2; + + private TbRepairInfo repairInfo; + + private TbRepairAssign repairAssign; + + private TbRepairOffer repairOffer; + + private CancelObjectVO cancelObject; + + /** + * 当前审核信息 + */ + private TbRepairCheck currentRepairCheck; + + private List repairCheckList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/TbInsuranceRemindVo.java b/src/main/java/com/gci/boot/modules/vehicles/vo/TbInsuranceRemindVo.java new file mode 100644 index 0000000..6a0462d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/TbInsuranceRemindVo.java @@ -0,0 +1,214 @@ +package com.gci.boot.modules.vehicles.vo; + +import java.io.Serializable; +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.fileUrl.FileUrl; +import com.gci.boot.annotation.fileUrl.handle.FileUrlHandle; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 保险信息 + *

+ * + * @author xushuhan + * @since 2023-09-21 + */ +@Getter +@Setter +@TableName("tb_insurance") +@ApiModel(value = "TbInsurance对象", description = "保险信息") +@ColumnWidth(20) +public class TbInsuranceRemindVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("所属车辆") + @ExcelProperty(value = "车牌号", converter = DictConverter.class, index = 1) + @Dict(dictTable = "tb_vehicle", dicText = "plate_number", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleId; + + @ApiModelProperty("所属项目") + @ExcelProperty(value = "所属项目", converter = DictConverter.class, index = 0) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String projectId; + + @ApiModelProperty("是否购买交强险(0,1)") + @ExcelIgnore + private String hasCompulsoryInsurance; + + @ApiModelProperty("交强险保险单号") + @SelectQuery + @ExcelIgnore + private String compulsoryInsuranceNo; + + @ApiModelProperty("交强险办理日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date compulsoryCreateDate; + + @ApiModelProperty("交强险保险公司") + @Dict(dictTable = "tb_insurance_company_archives", dicText = "name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelIgnore + private String compulsoryCompanyId; + + @ApiModelProperty("交强险保险金额") + @ExcelIgnore + private Double compulsoryPrice; + + @ApiModelProperty("车船税") + @ExcelIgnore + private Double vehicleVesselTax; + + @ApiModelProperty("交强险起保日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date compulsoryStartTime; + + @ApiModelProperty("交强险有效日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "交强险有效日期", index = 3) + private Date compulsoryValidTime; + + @ApiModelProperty("交强险附件") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String compulsoryUrl; + + @ApiModelProperty("是否购买商业保险(0,1)") + @ExcelIgnore + private String hasCommercialInsurance; + + @ApiModelProperty("商业保险单号") + @SelectQuery + @ExcelIgnore + private String commercialInsuranceNo; + + @ApiModelProperty("商业保险办理日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date commercialCreateDate; + + @ApiModelProperty("商业保险公司") + @Dict(dictTable = "tb_insurance_company_archives", dicText = "name", dicCode = "id") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelIgnore + private String commercialCompanyId; + + @ApiModelProperty("商业保险费合计") + @ExcelIgnore + private Double commercialPrice; + + @ApiModelProperty("商业保险起保日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelIgnore + private Date commercialStartTime; + + @ApiModelProperty("商业保险有效日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "商业保险有效日期", index = 6) + private Date commercialValidTime; + + @ApiModelProperty("商业保险附件") + @ExcelIgnore + @JsonDeserialize(using = FileUrlHandle.class) + @FileUrl + private String commercialUrl; + + @ApiModelProperty("备注") + @ExcelIgnore + @TableField(updateStrategy = FieldStrategy.IGNORED) + private String remark; + + @ApiModelProperty("所属机构") + @ExcelIgnore + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + + @ApiModelProperty("车辆型号") + //@ExcelProperty(value = "车辆型号", index = 2) + @ExcelIgnore + @SelectQuery + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "车辆种类", converter = DictConverter.class, index = 2) + private String vehicleType; + + @TableField(exist = false) + @ExcelProperty(value = "交强险到期天数", index = 4) + public String compulsorySurplusDay = "-"; + + @TableField(exist = false) + @ExcelProperty(value = "交强险逾期天数", index = 5) + public String compulsoryOverDay = "-"; + + @TableField(exist = false) + @ExcelProperty(value = "商业保险到期天数", index = 7) + public String commercialSurplusDay = "-"; + + @TableField(exist = false) + @ExcelProperty(value = "商业保险逾期天数", index = 8) + public String commercialOverDay = "-"; + + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordImportVo.java b/src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordImportVo.java new file mode 100644 index 0000000..b73a8ec --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordImportVo.java @@ -0,0 +1,134 @@ +package com.gci.boot.modules.vehicles.vo; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.util.ValidatorUtil; +import com.gci.boot.common.validated.ImportValidated; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 加油充电登记 + *

+ * + * @author admin + * @since 2023-11-30 + */ +@Data +@ColumnWidth(20) +public class TbRefuelChargeRecordImportVo { + + @ValidatorUtil.NotEmpty(message = "日期不能为空") + @ValidatorUtil.DateValue(format = "yyyy-MM-dd", message = "日期格式错误:格式为'yyyy-MM-dd'") + @ExcelProperty("日期") + @DateTimeFormat("yyyy-MM-dd") + private String recordDate; + + @ValidatorUtil.StrMaxLength(strMaxLength = 64, message = "单号长度不能超过64位", fieldNameCN = "单号") + @ExcelProperty("单号") + private String orderNo; + + @ValidatorUtil.DateValue(format = "HH:mm:ss", message = "开始时间错误:格式为'HH:mm:ss'") + @ExcelProperty(value = "开始时间") + @DateTimeFormat("HH:mm:ss") + private String startTime; + + @ValidatorUtil.DateValue(format = "HH:mm:ss", message = "结束时间错误:格式为'HH:mm:ss'") + @ExcelProperty(value = "结束时间") + @DateTimeFormat("HH:mm:ss") + private String endTime; + + @ValidatorUtil.NotEmpty(message = "车牌号不能为空") + @ExcelProperty(value = "车牌号") + private String plateNumber; + + @ValidatorUtil.NotEmpty(message = "卡号不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 32, message = "卡号不能超过32位", fieldNameCN = "卡号") + @ExcelProperty(value = "卡号") + private String oilCard; + + @ValidatorUtil.NotEmpty(message = "油品规格不能为空") + @ValidatorUtil.CollectionStr(collectionStr = "0号 车用柴油(Ⅵ),92号 车用汽油(ⅥB),95号 车用汽油(ⅥB),充电", + message = "油品规格只能为'0号 车用柴油(Ⅵ)'、'92号 车用汽油(ⅥB)'、'95号 车用汽油(ⅥB)'、'充电'") + @ExcelProperty(value = "油品规格") + private String oilType; + + @ValidatorUtil.NotEmpty(message = "数量(升/度)不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 999999, message = "数量(升/度)必须为数字:且范围在[0,999999]") + @ExcelProperty(value = "数量(升/度)") + private String amount; + + @ValidatorUtil.NotEmpty(message = "金额(元)不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 999999, message = "金额(元)必须为数字:且范围在[0,999999]") + @ExcelProperty(value = "金额(元)") + private String totalPrice; + + @ValidatorUtil.NotEmpty(message = "加油(充电)时里程(km)不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 999999, message = "加油(充电)时里程(km)必须为数字:且范围在[0,999999]") + @ExcelProperty(value = "加油(充电)时里程(km)") + private String mileage; + + @ValidatorUtil.StrMaxLength(strMaxLength = 1000, message = "备注长度不能超过1000位", fieldNameCN = "备注") + @ExcelProperty(value = "备注") + private String remark; + + @ValidatorUtil.StrMaxLength(strMaxLength = 64, message = "驾驶员长度不能超过64位", fieldNameCN = "驾驶员") + @ExcelProperty(value = "驾驶员") + private String driver; + @ValidatorUtil.StrMaxLength(strMaxLength = 64, message = "加油站长度不能超过64位", fieldNameCN = "加油站") + @ExcelProperty(value = "加油站") + private String oilStation; + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 999999, message = "卡余额(元)必须为数字:且范围在[0,999999]") + @ExcelProperty(value = "卡余额(元)") + private BigDecimal oilCardBalance; + + @ExcelIgnore + @TableField(exist = false) + private List validationErrors; + @ExcelProperty("异常信息") + @TableField(exist = false) + private String validationErrorsStr; + public void validate() { + ValidatorUtil.trimStringFields(this); + List validationErrors = ValidatorUtil.validate(this); + if(CollectionUtil.isNotEmpty(validationErrors)){ + this.validationErrors = validationErrors.stream().map(ValidatorUtil.ValidationError::getMessage).collect(Collectors.toList()); + this.validationErrorsStr = this.validationErrors + ""; + } + } + public void putErrorMsg(String msg){ + if(CollectionUtil.isNotEmpty(this.validationErrors)){ + this.validationErrors.add(msg); + }else{ + this.validationErrors = CollectionUtil.newArrayList(msg); + } + this.validationErrorsStr = this.validationErrors + ""; + } + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordVo.java b/src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordVo.java new file mode 100644 index 0000000..9e5d8ae --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/TbRefuelChargeRecordVo.java @@ -0,0 +1,208 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.ImportValidated; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 加油充电登记 + *

+ * + * @author admin + * @since 2023-11-30 + */ +@Getter +@Setter +@TableName("tb_refuel_charge_record") +@ApiModel(value = "TbRefuelChargeRecord对象", description = "加油充电记录") +@ColumnWidth(20) +public class TbRefuelChargeRecordVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键id") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @ExcelIgnore + private String id; + + @ApiModelProperty("日期") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat("yyyy-MM-dd") + @org.springframework.format.annotation.DateTimeFormat(pattern="yyyy-MM-dd") + @ExcelProperty(value = "日期", index = 0) + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private Date recordDate; + + @ApiModelProperty("单号") + @ExcelProperty(value = "单号", index = 1) + private String orderNo; + + @ApiModelProperty("开始时间") + @JsonFormat(timezone = "GMT+8",pattern = "HH:mm:ss") + @DateTimeFormat("HH:mm:ss") + @org.springframework.format.annotation.DateTimeFormat(pattern="HH:mm:ss") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "开始时间", index = 2) + private Date startTime; + + @ApiModelProperty("结束时间") + @JsonFormat(timezone = "GMT+8",pattern = "HH:mm:ss") + @DateTimeFormat("HH:mm:ss") + @org.springframework.format.annotation.DateTimeFormat(pattern="HH:mm:ss") + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @ExcelProperty(value = "结束时间", index = 3) + private Date endTime; + + @ApiModelProperty("所属项目") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + @Dict(dictTable = "tb_projects", dicText = "project_name", dicCode = "id") + private String projectId; + + @ApiModelProperty("车辆id") + @ExcelIgnore + private String vehicleId; + + @ApiModelProperty("车架号") + @ExcelIgnore + + @SelectQuery() + private String frameNumber; + + @ApiModelProperty("车辆型号") + @ExcelIgnore + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String vehicleType; + + @ApiModelProperty("车牌号") + @ExcelProperty(value = "车牌号", index = 4) + @SelectQuery() + private String plateNumber; + + @ApiModelProperty("燃料类型") + @Dict(dicCode = "fuel_type") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String fuelType; + + @ApiModelProperty("油卡卡号") + @ExcelProperty(value = "卡号", index = 5) + @SelectQuery() + private String oilCard; + + @ApiModelProperty("油品规格1:0号 车用柴油(Ⅵ),2:92号 车用汽油(ⅥB),3:95号 车用汽油(ⅥB),4:充电") + @Dict(dicCode = "oil_type") + @ExcelProperty(value = "油品规格",converter = DictConverter.class, index = 6) + private String oilType; + + @ApiModelProperty("单价") + @ExcelIgnore + private BigDecimal price; + + @ApiModelProperty("数量") + @ExcelProperty(value = "数量(升/度)", index = 7) + private BigDecimal amount; + + @ApiModelProperty("金额") + @ExcelProperty(value = "金额(元)", index = 8) + private BigDecimal totalPrice; + + @ApiModelProperty("加油(充电)时里程km") + @ExcelProperty(value = "加油(充电)时里程(km)", index = 9) + private BigDecimal mileage; + + @ApiModelProperty("备注") + @ExcelProperty(value = "备注", index = 10) + private String remark; + + @ApiModelProperty("所属机构") + @Dict(dictTable = "sys_depart", dicCode = "org_code", dicText = "depart_name") + @ExcelIgnore + @SelectQuery(Type = SelectQuery.SelectType.EQ) + private String sysOrgCode; + + @ApiModelProperty("创建时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date createTime; + + @ApiModelProperty("更新时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelIgnore + private Date updateTime; + + @ApiModelProperty("创建人") + @ExcelIgnore + private String createBy; + + @ApiModelProperty("更新人") + @ExcelIgnore + @Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname") + private String updateBy; + + @ExcelIgnore + @ApiModelProperty("删除标志") + private Integer delFlag; + + @ApiModelProperty("记录类型(1加油,2充电)") + @ExcelIgnore + private String refuelType; + + @ApiModelProperty("来源(1后台,2小程序)") + @ExcelIgnore + private String sourceType; + + @TableField(exist = false) + @ExcelIgnore + private String departName; + + @TableField(exist = false) + @ExcelIgnore + private String recordMonth; + + @ApiModelProperty("驾驶员") + @Length(max = 64,message = "驾驶员不能超过64位!",groups = {SaveValidated.class, UpdateValidated.class}) + @ExcelProperty(value = "驾驶员", index = 11) + private String driver; + @ApiModelProperty("加油站") + @Length(max = 64,message = "加油站不能超过64位!",groups = {SaveValidated.class, UpdateValidated.class}) + @ExcelProperty(value = "加油站", index = 12) + private String oilStation; + @ApiModelProperty("卡余额(元)") + @Min(value = 0, message = "卡余额(元)最小值为0!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @Max(value = 999999, message = "卡余额(元)最大值为999999!", groups = {SaveValidated.class, UpdateValidated.class, ImportValidated.class}) + @ExcelProperty(value = "卡余额(元)", index = 13) + private BigDecimal oilCardBalance; + +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepDataEntryVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepDataEntryVO.java new file mode 100644 index 0000000..5696d43 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepDataEntryVO.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.gci.boot.modules.vehicles.entity.TbUpkeepAssign; +import com.gci.boot.modules.vehicles.entity.TbUpkeepBill; +import com.gci.boot.modules.vehicles.entity.TbUpkeepOffer; +import lombok.Data; + +@Data +public class UpkeepDataEntryVO { + + private TbUpkeepBill upkeepBill; + + private TbUpkeepOffer upkeepOffer; + + private TbUpkeepAssign upkeepAssign; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepImportVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepImportVO.java new file mode 100644 index 0000000..951bf10 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepImportVO.java @@ -0,0 +1,110 @@ +package com.gci.boot.modules.vehicles.vo; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.gci.boot.common.util.ValidatorUtil; +import lombok.Data; + +import java.util.List; +import java.util.stream.Collectors; + +@Data +public class UpkeepImportVO { + // 基本信息: 车牌号 实际保养开始时间 实际保养完成时间 实际保养里程 保养内容 + // 保养信息: 维修厂 保养分类 保养内容 数量 材料单价 工时 工时单价 内容说明 + @ValidatorUtil.NotEmpty(message = "车牌号不能为空") + @ExcelProperty({"基本信息", "车牌号"}) + private String plateNumber; + @ValidatorUtil.NotEmpty(message = "实际保养开始时间不能为空") + @ValidatorUtil.DateValue(format = "yyyy-MM-dd HH:mm:ss", message = "实际保养开始时间格式错误:格式为'yyyy-MM-dd HH:mm:ss'") + @ExcelProperty({"基本信息", "实际保养开始时间"}) + private String startTime; + @ValidatorUtil.NotEmpty(message = "实际保养完成时间不能为空") + @ValidatorUtil.DateValue(format = "yyyy-MM-dd HH:mm:ss", message = "实际保养完成时间格式错误:格式为'yyyy-MM-dd HH:mm:ss'") + @ExcelProperty({"基本信息", "实际保养完成时间"}) + private String endTime; + @ValidatorUtil.NotEmpty(message = "实际保养里程不能为空") + @ValidatorUtil.IntValue(minValue= 0, maxValue = 99999999, message = "实际保养里程必须为数字:且范围在[0,99999999]") + @ExcelProperty({"基本信息", "实际保养里程"}) + private String realMileage; + @ValidatorUtil.NotEmpty(message = "保养内容不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 200, message = "保养内容长度不能超过200位", fieldNameCN = "保养内容") + @ExcelProperty({"基本信息", "保养内容"}) + private String content; + + @ValidatorUtil.NotEmpty(message = "维修厂不能为空") + @ExcelProperty({"保养信息", "维修厂"}) + private String repairShop; + @ValidatorUtil.NotEmpty(message = "保养分类不能为空") + @ExcelProperty({"保养信息", "保养分类"}) + private String repairClass; + @ValidatorUtil.NotEmpty(message = "保养内容(保养明细)不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 100, message = "保养内容(保养明细)长度不能超过100位", fieldNameCN = "保养内容(保养明细)") + @ExcelProperty({"保养信息", "保养内容(保养明细)"}) + private String repairContent; + @ValidatorUtil.NotEmpty(message = "数量不能为空") + @ValidatorUtil.IntValue(minValue= 0, maxValue = 99999999, message = "数量必须为整数:且范围在[0,99999999]") + @ExcelProperty({"保养信息", "数量"}) + private String quantity; + @ValidatorUtil.NotEmpty(message = "材料单价不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 99999999, message = "材料单价必须为数字:且范围在[0,99999999]") + @ExcelProperty({"保养信息", "材料单价"}) + private String unitPrice; + @ValidatorUtil.NotEmpty(message = "工时不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 99999999, message = "工时必须为数字:且范围在[0,99999999]") + @ExcelProperty({"保养信息", "工时"}) + private String workHours; + @ValidatorUtil.NotEmpty(message = "工时单价不能为空") + @ValidatorUtil.NumericValue(minValue= 0, maxValue = 99999999, message = "工时单价必须为数字:且范围在[0,99999999]") + @ExcelProperty({"保养信息", "工时单价"}) + private String workHoursCost; + @ValidatorUtil.NotEmpty(message = "内容说明不能为空") + @ValidatorUtil.StrMaxLength(strMaxLength = 100, message = "内容说明长度不能超过100位", fieldNameCN = "内容说明") + @ExcelProperty({"保养信息", "内容说明"}) + private String offerContent; + + // 用于记录校验异常信息 + @ExcelIgnore + private List validationErrors; + @ExcelProperty({"异常信息", "异常信息"}) + private String validationErrorsStr; + // 用于记录所在行数 + @ExcelIgnore + private Integer row; + //字典值 + @ExcelIgnore + private String repairClassValue; + //维修厂信息 + @ExcelIgnore + private String repairShopId; + @ExcelIgnore + private String contact; + @ExcelIgnore + private String contactPhone; + //格式异常的 + @ExcelIgnore + private String formatErrors; + //重复的 + @ExcelIgnore + private String repeatErrors; + + public void validate() { + ValidatorUtil.trimStringFields(this); + List validationErrors = ValidatorUtil.validate(this); + if(CollectionUtil.isNotEmpty(validationErrors)){ + this.validationErrors = validationErrors.stream().map(ValidatorUtil.ValidationError::getMessage).collect(Collectors.toList()); + this.validationErrorsStr = this.validationErrors + ""; + } + } + + public void putErrorMsg(String msg){ + if(CollectionUtil.isNotEmpty(this.validationErrors)){ + this.validationErrors.add(msg); + }else{ + this.validationErrors = CollectionUtil.newArrayList(msg); + } + this.validationErrorsStr = this.validationErrors + ""; + } +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepInfoListVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepInfoListVO.java new file mode 100644 index 0000000..a878b6b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepInfoListVO.java @@ -0,0 +1,141 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class UpkeepInfoListVO { + + @ApiModelProperty("主键id") + @ExcelIgnore + private String id; + //2 3 4 6 7 8 9 + //待委派 待报价 待审核 保养中 待确认 结束 作废 + @ApiModelProperty("流程状态") + @Dict(dicCode = "upkeep_status") + @ExcelProperty(value = "流程状态",index = 12,converter = DictConverter.class) + @ColumnWidth(value = 15) + private Integer flowStatus; + //1运营维保部 - 2维修厂 /- 3领导审批/ - 4结束 + @ApiModelProperty("流程节点") + @Dict(dicCode = "repair_node") + @ExcelIgnore +// @ExcelProperty(value = "流程节点",index = 13,converter = DictConverter.class) +// @ColumnWidth(value = 20) + private Integer flowNode; + + @ApiModelProperty("工单号") + @ColumnWidth(value = 30) + @ExcelProperty(value = "工单号",index = 0) + private String orderNo; + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + @ExcelProperty(value = "所属项目",index = 2,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String projectId; + + @ApiModelProperty("车牌号") + @ColumnWidth(value = 20) + @ExcelProperty(value = "车牌号",index = 1) + private String plateNumber; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + @ExcelProperty(value = "车辆种类",index = 3,converter = DictConverter.class) + @ColumnWidth(value = 20) + private String vehicleType; + + @ApiModelProperty("上次保养时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "上次保养时间",index = 4) + @ColumnWidth(value = 20) + private Date lastTime; + + @ApiModelProperty("上次保养里程") + @ExcelProperty(value = "上次保养里程(KM)",index = 5) + @ColumnWidth(value = 20) + private Integer lastMileage; + + @ApiModelProperty("预计保养时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd") + @ExcelProperty(value = "预计保养时间",index = 6) + @ColumnWidth(value = 20) + private Date predictTime; + + @ApiModelProperty("预计保养里程") + @ExcelProperty(value = "预计保养里程(KM)",index = 7) + @ColumnWidth(value = 20) + private Integer predictMileage; + + @ApiModelProperty("保养单位") + @Dict(dicCode = "id",dictTable = "tb_repair_shop_archives",dicText = "name") + @ExcelProperty(value = "保养单位",index = 8,converter = DictConverter.class) + @ColumnWidth(value = 30) + private String repairShop; + + @ApiModelProperty("报价金额") + @ExcelProperty(value = "报价金额(元)",index = 9) + @ColumnWidth(value = 20) + private Double totaCost; + + /**实际保养开始*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "实际保养开始") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty(value = "实际保养开始",index = 10) + @ColumnWidth(value = 30) + private Date startTime; + + /**实际保养结束*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "实际保养结束") + @com.alibaba.excel.annotation.format.DateTimeFormat("yyyy-MM-dd HH:mm:ss") + @ExcelProperty(value = "实际保养结束",index = 11) + @ColumnWidth(value = 30) + private Date endTime; + + /**实际保养里程*/ + @ApiModelProperty("实际保养里程") + @ExcelProperty(value = "实际保养里程",index = 13) + private Integer realMileage; + + + //查看按钮(派单。。。。) + @ExcelIgnore + private String checkButton; + // 1-有作废按钮 2-没有 + @ExcelIgnore + private Integer deleteButton; + // 用户类型 1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + @ExcelIgnore + private String userType; + //维修厂 + @ExcelIgnore + private String repairParam; + //修车厂id集合入参(支持多个) + @ExcelIgnore + private List listRepairShop; + //项目列表集合参数,无需展示 + @ExcelIgnore + private List listProject; + //状态集合参数,无需展示 + @ExcelIgnore + private List flowStatusList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepObjectVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepObjectVO.java new file mode 100644 index 0000000..559c684 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepObjectVO.java @@ -0,0 +1,45 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.modules.vehicles.entity.*; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +public class UpkeepObjectVO { + + private String id; + + @Dict(dicCode = "upkeep_status") + private Integer flowStatus; + + @ApiModelProperty("1-数据录入,,2-走流程的") + @ExcelIgnore + private Integer addType; + // 用户类型 1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + @ExcelIgnore + private String userType; + + /** + * 审核状态 1-》通过, 2-》不通过 + */ + private Integer checkFlag = 2; + + private TbUpkeepBill upkeepBill; + + private TbUpkeepAssign upkeepAssign; + + private TbUpkeepOffer upkeepOffer; + + private CancelObjectVO cancelObject; + + /** + * 当前审核信息 + */ + private TbUpkeepCheck currentUpkeepCheck; + + private List upkeepCheckList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepPlanObjectVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepPlanObjectVO.java new file mode 100644 index 0000000..ca13476 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/UpkeepPlanObjectVO.java @@ -0,0 +1,38 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.modules.vehicles.entity.*; +import lombok.Data; + +import java.util.List; + +@Data +public class UpkeepPlanObjectVO { + + private String id; + + @Dict(dicCode = "upkeep_status") + private Integer flowStatus; + // 用户类型 1-司机,2-维修厂,3-司机&维修厂,4-维保管理员,5-维保领导,6-维保管理员&维保领导 + @ExcelIgnore + private String userType; + + private String auditStatus; + + /** + * 审核状态 1-》通过, 2-》不通过 + */ + private Integer checkFlag = 2; + + private TbUpkeepPlan upkeepPlan; + + private CancelObjectVO cancelObject; + + /** + * 当前审核信息 + */ + private TbUpkeepPlanCheck currentUpkeepCheck; + + private List upkeepCheckList; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/VehicleInfoVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/VehicleInfoVO.java new file mode 100644 index 0000000..5cefcf8 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/VehicleInfoVO.java @@ -0,0 +1,75 @@ +package com.gci.boot.modules.vehicles.vo; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.gci.boot.annotation.Query.SelectQuery; +import com.gci.boot.annotation.repeat.FieldRepeat; +import com.gci.boot.common.dict.annotation.Dict; +import com.gci.boot.common.dict.excel.DictConverter; +import com.gci.boot.common.validated.SaveValidated; +import com.gci.boot.common.validated.UpdateValidated; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import java.util.Date; + +@Data +public class VehicleInfoVO { + + + private String id; + + @ApiModelProperty("所属项目") + @Dict(dicCode = "id",dictTable = "tb_projects",dicText = "project_name") + private String projectId; + + @ApiModelProperty("车牌号") + private String plateNumber; + + @ApiModelProperty("交车时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date deliveryTime; + + @ApiModelProperty("车架号") + private String frameNumber; + + @ApiModelProperty("车辆品牌") + @Dict(dicCode = "vehicle_brand") + private String vehicleBrand; + + @ApiModelProperty("车辆型号") + private String vehicleModel; + + @ApiModelProperty("车辆种类") + @Dict(dicCode = "vehicle_type") + private String vehicleType; + + @ApiModelProperty("VIN码") + private String vinCode; + + @ApiModelProperty("发动机码") + private String engineNumber; + + @ApiModelProperty("上次保养时间") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + private Date lastTime; + + @ApiModelProperty("上次保养里程") + private Integer lastMileage; + + @ApiModelProperty("总里程") + private Double totalMileage; + + @ApiModelProperty("本月的累计里程数") + private Double monthlyTotalMileage; +} diff --git a/src/main/java/com/gci/boot/modules/vehicles/vo/VehicleProjectVO.java b/src/main/java/com/gci/boot/modules/vehicles/vo/VehicleProjectVO.java new file mode 100644 index 0000000..2dd057d --- /dev/null +++ b/src/main/java/com/gci/boot/modules/vehicles/vo/VehicleProjectVO.java @@ -0,0 +1,16 @@ +package com.gci.boot.modules.vehicles.vo; + +import lombok.Data; + +@Data +public class VehicleProjectVO { + + private String plateNumber; + + private String projectId; + + private String projectName; + + private String projectManager; + +} diff --git a/src/main/java/com/gci/boot/modules/video/controller/VideoController.java b/src/main/java/com/gci/boot/modules/video/controller/VideoController.java new file mode 100644 index 0000000..ae93123 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/controller/VideoController.java @@ -0,0 +1,195 @@ +package com.gci.boot.modules.video.controller; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gci.boot.annotation.permission.DataPermission; +import com.gci.boot.common.log.annotation.AddSysLog; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.vehicles.entity.TbAccidentInfo; +import com.gci.boot.modules.video.service.IVideoService; +import com.gci.boot.modules.video.vo.CutVideoListPageVO; +import com.gci.boot.modules.video.vo.CutVideoListVO; +import com.gci.boot.modules.video.vo.ResultDeviceVO; +import com.gci.boot.modules.video.vo.VideoPlayVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@Slf4j +@RestController +@RequestMapping("/video") +public class VideoController { + + @Value("${video.baseUrl}") + private String baseUrl; + @Value("${video.DownloadResourceUrlSuffix}") + private String DownloadResourceUrlSuffix; + + @Autowired + private IVideoService videoService; + /** + * 测试方法 + */ + @GetMapping(value = "/videoTest") + public Result videoTest(String projectId,String id,Integer layer) { + return Result.ok(videoService.getDeviceList(projectId,id,layer)); + } + + /** + * 获取视频设备树形层级 + */ + @AddSysLog(value = "视频-获取视频设备树形层级") + @DataPermission(item="tv.projectId", sqlIds = {"com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper.queryOtherVehicleProject"}) + @GetMapping(value = "/getDeviceList") + public Result getDeviceList(String projectId,String id,Integer layer) { + return Result.ok(videoService.getDeviceList(projectId,id,layer)); + } + + /** + * 根据车牌查视频车列表 + */ + @AddSysLog(value = "视频-根据车牌查视频车列表") + @DataPermission(item="tb_vehicle.projectId", sqlIds = {"com.gci.boot.modules.basedata.mapper.TbVehicleMapper.selectList"}) + @GetMapping(value = "/queryDeviceList") + public Result queryDeviceList(String plateNumber) { + return Result.ok(videoService.queryDeviceList(plateNumber)); + } + + /** + * 获取设备实时视频 + */ + @AddSysLog(value = "视频-获取设备实时视频") + @GetMapping(value = "/getRealPlay") + public Result getRealPlay(String simNo, Integer channelNo) { + try{ + VideoPlayVO vo = videoService.getRealPlay(simNo,channelNo); + return Result.ok(vo); + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } + + /** + * 获取设备历史回放 + */ + @AddSysLog(value = "视频-获取设备历史回放") + @GetMapping(value = "/getPlayBack") + public Result getPlayBack(String simNo, Integer channelNo,String startTime, String endTime) { + try{ + VideoPlayVO vo = videoService.getPlayBack(simNo,channelNo,startTime,endTime); + return Result.ok(vo); + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } + + + /** + * 视频云平台文件查询(同步返回) + */ + @AddSysLog(value = "视频-视频云平台文件查询(同步返回)") + @GetMapping(value = "/getFilesAsync") + public Result getFilesAsync(String simNo, Integer channelNo,String startTime, String endTime) { + try{ + Object obj = videoService.getFilesAsync(simNo,channelNo,startTime,endTime); + if(Objects.isNull(obj)){ + return Result.error(101,"车辆离线,暂无数据"); + }else{ + return Result.ok(obj); + } + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } + + /** + * 裁剪视频 + */ + @AddSysLog(value = "视频-裁剪视频") + @GetMapping(value = "/cutVideo") + public Result cutVideo(String sessionId,String startTime, String endTime) { + try{ + int status = videoService.cutVideo(sessionId,startTime,endTime); + return Result.ok(status); + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } + + /** + * 裁剪视频任务信息列表 + */ + @AddSysLog(value = "视频-裁剪视频任务信息列表") + @GetMapping(value = "/getCutVideoList") + public Result getCutVideoList(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + String startTime, String endTime) { + try{ + CutVideoListPageVO vo = videoService.getCutVideoList(pageNo,pageSize,startTime,endTime); + Page page = new Page(pageNo, pageSize); + page.setRecords(vo.getList()); + page.setTotal(vo.getCount()); + return Result.ok(page); + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } + + /** + * 媒体资源下载 + */ + @AddSysLog(value = "视频-媒体资源下载") + @GetMapping(value = "/downloadResource") + public Result downloadResource(String fileIndex, HttpServletResponse response) { + try{ + String token = videoService.getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败!"); + } + if(Objects.isNull(fileIndex)){ + throw new RuntimeException("fileIndex不能为空!"); + } + String url = baseUrl + DownloadResourceUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("fileIndex", fileIndex); + try { + HttpResponse execute = HttpRequest.get(url).header(headers).form(param).execute(); + if (execute.getStatus() != 200) { + log.warn("视频云平台媒体资源下载失败:" + execute.body()); + throw new RuntimeException("视频云平台媒体资源下载失败!"); + } else { + byte[] bodyBytes = execute.bodyBytes(); + OutputStream output = response.getOutputStream(); + output.write(bodyBytes); + return Result.ok(); + } + }catch (Exception e){ + log.warn("视频云平台媒体资源下载失败:" + e.getMessage()); + throw new RuntimeException("视频云平台媒体资源下载失败!"); + } + }catch (Exception e){ + return Result.error(101,e.getMessage()); + } + } +} diff --git a/src/main/java/com/gci/boot/modules/video/service/IVideoService.java b/src/main/java/com/gci/boot/modules/video/service/IVideoService.java new file mode 100644 index 0000000..8757902 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/service/IVideoService.java @@ -0,0 +1,70 @@ +package com.gci.boot.modules.video.service; + +import com.gci.boot.common.vo.Result; +import com.gci.boot.modules.video.vo.CutVideoListPageVO; +import com.gci.boot.modules.video.vo.ResultDeviceVO; +import com.gci.boot.modules.video.vo.VideoDeviceVO; +import com.gci.boot.modules.video.vo.VideoPlayVO; + +import java.util.List; + +public interface IVideoService { + + /** + * 获取视频云平台token + * @return + */ + String getVedioToken(); + + /** + * 获取视频云平台所有的车辆列表 + */ + List getVideoDeviceList(); + + /** + * 获取视频云平台设备 + */ + VideoDeviceVO getVideoDevice(String plateNo); + + /** + * 获取设备视频云平台实时播放视频 + */ + VideoPlayVO getRealPlay(String simNo, Integer channelNo); + + /** + * 获取设备视频云平台历史回放 + */ + VideoPlayVO getPlayBack(String simNo, Integer channelNo,String startTime, String endTime); + + /** + * 视频云平台文件查询(同步返回) + */ + Object getFilesAsync(String simNo, Integer channelNo,String startTime, String endTime); + + /** + * 获取设备列表--树形分层-每一层单独调用接口获取-->1项目-->2车辆品牌-->3车牌-->通道 + * @param projectId + * @param id + * @param layer + * @return + */ + List getDeviceList(String projectId,String id,Integer layer); + + /** + * 查询视频车列表-->3车牌 + * @param plateNumber + * @return + */ + List queryDeviceList(String plateNumber); + + /** + * 视频云平台视频剪辑 + */ + int cutVideo(String sessionId,String startTime, String endTime); + + /** + * 裁剪视频任务信息列表 + */ + CutVideoListPageVO getCutVideoList(int pageNo, int pageSize, String startTime, String endTime); + +} diff --git a/src/main/java/com/gci/boot/modules/video/service/Impl/VideoServiceImpl.java b/src/main/java/com/gci/boot/modules/video/service/Impl/VideoServiceImpl.java new file mode 100644 index 0000000..dc8c29b --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/service/Impl/VideoServiceImpl.java @@ -0,0 +1,510 @@ +package com.gci.boot.modules.video.service.Impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.modules.basedata.entity.TbVehicle; +import com.gci.boot.modules.basedata.service.ITbVehicleService; +import com.gci.boot.modules.projects.service.IProjectsService; +import com.gci.boot.modules.system.service.ISysDictService; +import com.gci.boot.modules.system.vo.DictModel; +import com.gci.boot.modules.vehicles.mapper.TbViolationRecordMapper; +import com.gci.boot.modules.vehicles.vo.MessageVO; +import com.gci.boot.modules.vehicles.vo.VehicleProjectVO; +import com.gci.boot.modules.video.service.IVideoService; +import com.gci.boot.modules.video.vo.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class VideoServiceImpl implements IVideoService { + + @Value("${video.baseUrl}") + private String baseUrl; + @Value("${video.clientId}") + private String clientId; + @Value("${video.clientSecret}") + private String clientSecret; + @Value("${video.getTokenUrlSuffix}") + private String getTokenUrlSuffix; + @Value("${video.getDeviceListUrlSuffix}") + private String getDeviceListUrlSuffix; + @Value("${video.getDeviceUrlSuffix}") + private String getDeviceUrlSuffix; + @Value("${video.realPlayUrlSuffix}") + private String realPlayUrlSuffix; + @Value("${video.playBackUrlSuffix}") + private String playBackUrlSuffix; + @Value("${video.queryFilesAsyncUrlSuffix}") + private String queryFilesAsyncUrlSuffix; + @Value("${video.CutVideoUrlSuffix}") + private String CutVideoUrlSuffix; + @Value("${video.getCutVideoListUrlSuffix}") + private String getCutVideoListUrlSuffix; + @Value("${video.DownloadResourceUrlSuffix}") + private String DownloadResourceUrlSuffix; + @Autowired + private ITbVehicleService vehicleService; + @Autowired + private TbViolationRecordMapper violationRecordMapper; + @Autowired + private ISysDictService sysDictService; + @Autowired + private IProjectsService projectsService; + //码流类型 1-主码流 2-子码流 + private static final Integer BITTYPE = 2; + + @Override + public String getVedioToken() { + String url = baseUrl + getTokenUrlSuffix; + Map param = new HashMap<>(); + param.put("grant_type", "client_credentials"); + param.put("scope", "video"); + param.put("client_id", clientId); + param.put("client_secret", clientSecret); + try { + String body = HttpRequest.get(url).form(param).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + return bodyMap.getOrDefault("access_token","").toString(); + }catch (Exception e){ + log.warn("获取视频云平台token失败:" + e.getMessage()); + throw new RuntimeException("获取视频云平台token失败!"); + } + } + + @Override + public List getVideoDeviceList() { + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败!"); + } + String url = baseUrl + getDeviceListUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("pageNo", 1); + param.put("pageSize", 1000); + try { + String body = HttpRequest.get(url).header(headers).form(param).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + List videoDeviceVOList = JsonUtil.json2List(JsonUtil.object2JsonAllPretty(bodyMap.get("data")),VideoDeviceVO.class); + return videoDeviceVOList; + } else { + log.warn("获取视频云平台所有的车辆列表失败:" + body); + throw new RuntimeException("获取视频云平台所有的车辆列表!"); + } + }catch (Exception e){ + log.warn("获取视频云平台所有的车辆列表失败:" + e.getMessage()); + throw new RuntimeException("获取视频云平台所有的车辆列表失败!"); + } + } + + @Override + public VideoDeviceVO getVideoDevice(String plateNo) { + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败!"); + } + String url = baseUrl + getDeviceUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("plateNo", plateNo); + try { + String body = HttpRequest.get(url).header(headers).form(param).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + VideoDeviceVO vo = JsonUtil.json2Object(JsonUtil.object2JsonAllPretty(bodyMap.get("data")),VideoDeviceVO.class); + return vo; + } else { + log.warn("获取视频云平台设备失败:" + body); + throw new RuntimeException("获取视频云平台设备失败!"); + } + }catch (Exception e){ + log.warn("获取视频云平台设备失败:" + e.getMessage()); + throw new RuntimeException("获取视频云平台设备失败!"); + } + } + + @Override + public VideoPlayVO getRealPlay(String simNo, Integer channelNo) { + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败!"); + } + String url = baseUrl + realPlayUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("simNo", simNo); + param.put("channel", channelNo); + param.put("bitType", BITTYPE); + try { + String reqBody = JsonUtil.object2JsonAllPretty(param); + String body = HttpRequest.post(url).header(headers).body(reqBody).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + VideoPlayVO result = new ObjectMapper().convertValue(bodyMap.get("data"), VideoPlayVO.class);; + return result; + } else { + log.warn("获取设备视频云平台实时播放视频失败:" + body); + throw new RuntimeException("获取设备视频云平台实时播放视频失败!"); + } + }catch (Exception e){ + log.warn("获取设备视频云平台实时播放视频失败:" + e.getMessage()); + throw new RuntimeException("获取设备视频云平台实时播放视频失败!"); + } + } + + @Override + public VideoPlayVO getPlayBack(String simNo, Integer channelNo, String startTime, String endTime) { + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败"); + } + String url = baseUrl + playBackUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("simNo", simNo); + param.put("channel", channelNo); + param.put("startTime", startTime); + param.put("endTime", endTime); + param.put("bitType", 1); + try { + String reqBody = JsonUtil.object2JsonAllPretty(param); + String body = HttpRequest.post(url).header(headers).body(reqBody).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + VideoPlayVO result = new ObjectMapper().convertValue(bodyMap.get("data"), VideoPlayVO.class);; + return result; + } else { + log.warn("获取设备视频云平台历史回放失败:" + body); + throw new RuntimeException("获取设备视频云平台历史回放失败!"); + } + }catch (Exception e){ + log.warn("获取设备视频云平台历史回放失败:" + e.getMessage()); + throw new RuntimeException("获取设备视频云平台历史回放失败!"); + } + } + + @Override + public Object getFilesAsync(String simNo, Integer channelNo, String startTime, String endTime) { + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败"); + } + String url = baseUrl + queryFilesAsyncUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("simNo", simNo); + param.put("channel", channelNo); + param.put("startTime", startTime); + param.put("endTime", endTime); + try { + String reqBody = JsonUtil.object2JsonAllPretty(param); + String body = HttpRequest.post(url).header(headers).body(reqBody).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + return bodyMap.get("data"); + } else { + log.warn("视频云平台文件查询(同步返回)失败:" + body); + return null; +// throw new RuntimeException("视频云平台文件查询(同步返回)失败!"); + } + }catch (Exception e){ + log.warn("视频云平台文件查询(同步返回)失败:" + e.getMessage()); + throw new RuntimeException("视频云平台文件查询(同步返回)失败!"); + } + } + + @Override + public List getDeviceList(String projectId,String id,Integer layer) { + if(Objects.isNull(layer)){ + return buildProjectDevice(); + } + if(layer == 1){ + return buildBrandDevice(id,layer); + } + if(layer == 2){ + return buildVehicleDevice(projectId,id,layer); + } + if(layer == 3){ + return buildChannelDevice(projectId,id,layer); + } + return null; + } + + @Override + public List queryDeviceList(String plateNumber) { + List result = new ArrayList<>(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicle::getCancelFlag,0).like(TbVehicle::getPlateNumber,plateNumber); + List vehicleList = vehicleService.list(queryWrapper); + List plateNumberList = vehicleList.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList()); + + List videoDeviceVOList = getVideoDeviceList(); + videoDeviceVOList = videoDeviceVOList.stream().filter(item->plateNumberList.contains(item.getPlateNo())).collect(Collectors.toList()); + + if(Objects.nonNull(videoDeviceVOList) && videoDeviceVOList.size()>0){ + videoDeviceVOList.stream().forEach(item->{ + ResultDeviceVO vo = new ResultDeviceVO(); + vo.setLayer(3); + vo.setIsLeaf(false); + vo.setId(item.getPlateNo()); + //项目 + List tempList = vehicleList.stream().filter(s->item.getPlateNo().equals(s.getPlateNumber())).collect(Collectors.toList()); + if(Objects.nonNull(tempList) && tempList.size()>0){ + if(StrUtil.isBlank(tempList.get(0).getProjectId())){ + vo.setProjectId("其它"); + }else{ + vo.setProjectId(tempList.get(0).getProjectId()); + } + } + vo.setTitle(item.getPlateNo()); + vo.setOnline(item.getOnline()); + vo.setSimNo(item.getSimNo()); + vo.setChannelList(item.getChannelList()); + result.add(vo); + }); + } + + List inCloundplateNumberList = videoDeviceVOList.stream().map(VideoDeviceVO::getPlateNo).collect(Collectors.toList()); + List noInVehicleList = vehicleList.stream().filter(item->!(inCloundplateNumberList.contains(item.getPlateNumber()))).collect(Collectors.toList()); + noInVehicleList.stream().forEach(item->{ + ResultDeviceVO vo = new ResultDeviceVO(); + vo.setLayer(3); + vo.setIsLeaf(false); + vo.setId(item.getPlateNumber()); + //项目 + List tempList = vehicleList.stream().filter(s->item.getPlateNumber().equals(s.getPlateNumber())).collect(Collectors.toList()); + if(Objects.nonNull(tempList) && tempList.size()>0){ + if(StrUtil.isBlank(tempList.get(0).getProjectId())){ + vo.setProjectId("其它"); + }else{ + vo.setProjectId(tempList.get(0).getProjectId()); + } + } + vo.setTitle(item.getPlateNumber()); + vo.setOnline(false); + vo.setSimNo(null); + vo.setChannelList(null); + result.add(vo); + }); + return result; + } + + @Override + public int cutVideo(String sessionId,String startTime, String endTime) { + //状态(-3离线 -7终端不存在 0正在执行 2加入等待队列) + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败!"); + } + if(StrUtil.isBlank(sessionId) || StrUtil.isBlank(startTime) || StrUtil.isBlank(endTime)){ + throw new RuntimeException("开始、结束时间及sessionId不能为空!"); + } + //计算时间秒 + Date startDate = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss"); + Date endDate = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss"); + long timeDifference = endDate.getTime() - startDate.getTime(); + int duration = (int) timeDifference / 1000; + + String url = baseUrl + CutVideoUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("duration", duration); + param.put("playSessionId", sessionId); + try { + String reqBody = JsonUtil.object2JsonAllPretty(param); + String body = HttpRequest.post(url).header(headers).body(reqBody).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + CutVideoResultVO result = new ObjectMapper().convertValue(bodyMap.get("data"), CutVideoResultVO.class);; + return result.getStatus(); + } else { + log.warn("视频云平台裁剪视频失败:" + body); + throw new RuntimeException("视频云平台裁剪视频失败!"); + } + }catch (Exception e){ + log.warn("视频云平台裁剪视频失败:" + e.getMessage()); + throw new RuntimeException("视频云平台裁剪视频失败!"); + } + } + + @Override + public CutVideoListPageVO getCutVideoList(int pageNo, int pageSize, String startTime, String endTime) { + String token = getVedioToken(); + if(StrUtil.isBlank(token)){ + throw new RuntimeException("获取视频云平台token失败!"); + } + String url = baseUrl + getCutVideoListUrlSuffix; + HttpHeaders headers = new HttpHeaders(); + headers.setBearerAuth(token); + Map param = new HashMap<>(); + param.put("pageNo", pageNo); + param.put("pageSize", pageSize); + param.put("startTime", startTime); + param.put("endTime", endTime); + try { + String body = HttpRequest.get(url).header(headers).form(param).execute().body(); + Map bodyMap = JsonUtil.json2Map(body); + if ("200".equals(bodyMap.get("code").toString())) { + CutVideoListPageVO vo = JsonUtil.json2Object(JsonUtil.object2JsonAllPretty(bodyMap.get("data")),CutVideoListPageVO.class); + return vo; + } else { + log.warn("视频云平台获取裁剪视频任务信息列表失败:" + body); + throw new RuntimeException("视频云平台获取裁剪视频任务信息列表失败!"); + } + }catch (Exception e){ + log.warn("视频云平台获取裁剪视频任务信息列表失败:" + e.getMessage()); + throw new RuntimeException("视频云平台获取裁剪视频任务信息列表失败!"); + } + } + + /** + * 获取视频项目列表 + * @return + */ + public List buildProjectDevice(){ + + List result = new ArrayList<>(); + List voList = violationRecordMapper.queryOtherVehicleProject(); + if(Objects.nonNull(voList) && voList.size()>0){ + voList.stream().forEach(item->{ + ResultDeviceVO vo = new ResultDeviceVO(); + vo.setLayer(1); + vo.setIsLeaf(false); + vo.setId(item.getProjectId()); + vo.setProjectId(item.getProjectId()); + vo.setTitle(item.getProjectName()); + result.add(vo); + }); + } + return result; + } + /** + * 获取视频项目-->车辆品牌列表 + * @return + */ + public List buildBrandDevice(String id, Integer layer){ + List result = new ArrayList<>(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicle::getCancelFlag,0); + if("其它".equals(id)){ + queryWrapper.and(wrapper -> wrapper.eq(TbVehicle::getProjectId,"") + .or().isNull(TbVehicle::getProjectId)); + }else { + queryWrapper.eq(TbVehicle::getProjectId,id); + } + List vehicleList = vehicleService.list(queryWrapper); + List brandDictList = vehicleList.stream().map(TbVehicle::getVehicleBrand).collect(Collectors.toList()); + + List dictModelList = sysDictService.queryDictItemsByCode("vehicle_brand"); + dictModelList = dictModelList.stream().filter(item->brandDictList.contains(item.getValue())).collect(Collectors.toList()); + if(Objects.nonNull(dictModelList) && dictModelList.size()>0){ + dictModelList.stream().forEach(item->{ + ResultDeviceVO vo = new ResultDeviceVO(); + vo.setLayer(layer+1); + vo.setIsLeaf(false); + vo.setId(item.getValue()); + vo.setProjectId(id); + vo.setTitle(item.getText()); + vo.setParentId(id); + result.add(vo); + }); + } + return result; + } + /** + * 获取视频项目-->车辆品牌-->车牌列表 + * @return + */ + public List buildVehicleDevice(String projectId, String id, Integer layer){ + List result = new ArrayList<>(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TbVehicle::getCancelFlag,0).eq(TbVehicle::getVehicleBrand,id); + if("其它".equals(projectId)){ + queryWrapper.and(wrapper -> wrapper.eq(TbVehicle::getProjectId,"") + .or().isNull(TbVehicle::getProjectId)); + }else { + queryWrapper.eq(TbVehicle::getProjectId,projectId); + } + List vehicleList = vehicleService.list(queryWrapper); + List plateNumberList = vehicleList.stream().map(TbVehicle::getPlateNumber).collect(Collectors.toList()); + + List videoDeviceVOList = getVideoDeviceList(); + videoDeviceVOList = videoDeviceVOList.stream().filter(item->plateNumberList.contains(item.getPlateNo())).collect(Collectors.toList()); + + if(Objects.nonNull(videoDeviceVOList) && videoDeviceVOList.size()>0){ + videoDeviceVOList.stream().forEach(item->{ + ResultDeviceVO vo = new ResultDeviceVO(); + vo.setLayer(layer+1); + vo.setIsLeaf(false); + vo.setId(item.getPlateNo()); + vo.setProjectId(projectId); + vo.setTitle(item.getPlateNo()); + vo.setParentId(id); + vo.setOnline(item.getOnline()); + vo.setSimNo(item.getSimNo()); + vo.setChannelList(item.getChannelList()); + result.add(vo); + }); + } + + List inCloundplateNumberList = videoDeviceVOList.stream().map(VideoDeviceVO::getPlateNo).collect(Collectors.toList()); + List noInVehicleList = vehicleList.stream().filter(item->!(inCloundplateNumberList.contains(item.getPlateNumber()))).collect(Collectors.toList()); + noInVehicleList.stream().forEach(item->{ + ResultDeviceVO vo = new ResultDeviceVO(); + vo.setLayer(layer+1); + vo.setIsLeaf(false); + vo.setId(item.getPlateNumber()); + vo.setProjectId(projectId); + vo.setTitle(item.getPlateNumber()); + vo.setParentId(id); + vo.setOnline(false); + vo.setSimNo(null); + vo.setChannelList(null); + result.add(vo); + }); + + return result; + } + /** + * 获取视频项目-->车辆品牌-->车牌-->视频通道列表 + * @return + */ + public List buildChannelDevice(String projectId, String id, Integer layer){ + List result = new ArrayList<>(); + VideoDeviceVO vo = getVideoDevice(id); + if(Objects.nonNull(vo)){ + for(ChannelVO channelVO : vo.getChannelList()){ + ResultDeviceVO one = new ResultDeviceVO(); + one.setLayer(layer+1); + one.setIsLeaf(true); + one.setId(channelVO.getChannelNo().toString()); + one.setProjectId(projectId); + one.setTitle(channelVO.getChannelName()); + one.setParentId(id); + one.setOnline(vo.getOnline()); + one.setSimNo(vo.getSimNo()); + one.setChannelNo(channelVO.getChannelNo()); + result.add(one); + } + } + return result; + } +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/ChannelVO.java b/src/main/java/com/gci/boot/modules/video/vo/ChannelVO.java new file mode 100644 index 0000000..d6aa661 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/ChannelVO.java @@ -0,0 +1,19 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +/** + * 设备视频通道信息对象 + */ +@Data +public class ChannelVO { + + /** + *通道号 + */ + private Integer channelNo; + /** + *通道名 + */ + private String channelName; +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/CutVideoListPageVO.java b/src/main/java/com/gci/boot/modules/video/vo/CutVideoListPageVO.java new file mode 100644 index 0000000..cf82c86 --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/CutVideoListPageVO.java @@ -0,0 +1,14 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class CutVideoListPageVO { + + private Integer count; + + private List list; + +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/CutVideoListVO.java b/src/main/java/com/gci/boot/modules/video/vo/CutVideoListVO.java new file mode 100644 index 0000000..059b12a --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/CutVideoListVO.java @@ -0,0 +1,37 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +@Data +public class CutVideoListVO { + + private String duration; + + private String sessionId; + + private String simNo; + + private String channel; + + private String bitType; + + private String status; + + private String plateNo; + + private String deviceNo; + + private String fileIndex; + + private String fileSize; + + private String appKey; + + private String callbackCode; + + private String callbackUrl; + + private String createTime; + + private String updateTime; +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/CutVideoResultVO.java b/src/main/java/com/gci/boot/modules/video/vo/CutVideoResultVO.java new file mode 100644 index 0000000..82978dc --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/CutVideoResultVO.java @@ -0,0 +1,11 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +@Data +public class CutVideoResultVO { + + private int status; + + private String sessionId; +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/ResultDeviceVO.java b/src/main/java/com/gci/boot/modules/video/vo/ResultDeviceVO.java new file mode 100644 index 0000000..b980ade --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/ResultDeviceVO.java @@ -0,0 +1,65 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 树接口返回资源对象 + */ +@Data +public class ResultDeviceVO { + + /** + * 项目id + */ + private String projectId; + /** + * id + */ + private String id; + /** + * 父级id + */ + private String parentId; + /** + * 父级名称 + */ + private String parentName; + /** + * 数据层级 1-项目,2-品牌,3-车牌 + */ + private Integer layer; + /** + * 是否叶子节点 + */ + private Boolean isLeaf; + /** + * 显示名称 + */ + private String title; + /** + * Sim卡号 + */ + private String simNo; + /** + * 是否在线 + */ + private Boolean online; + /** + * 设备总数 + */ + private Integer cameraTotal; + /** + * 在线设备总数 + */ + private Integer onlineTotal; + /** + *通道号 + */ + private Integer channelNo; + /** + * 设备视频通道信息对象 + */ + private List channelList; +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/VideoDeviceVO.java b/src/main/java/com/gci/boot/modules/video/vo/VideoDeviceVO.java new file mode 100644 index 0000000..d93112e --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/VideoDeviceVO.java @@ -0,0 +1,57 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 视频云平台列表数据 + */ +@Data +public class VideoDeviceVO { + /** + * 主键 + */ + private String id; + /** + * Sim卡号 + */ + private String simNo; + /** + * 设备号 + */ + private String deviceNo; + /** + * 设备名 + */ + private String deviceName; + /** + * 车牌号 + */ + private String plateNo; + /** + * 设备类型 + */ + private String deviceType; + /** + * 设备类型 + */ + private String deviceTypeName; + /** + * 公司 + */ + private String company; + /** + * 是否在线 + */ + private Boolean online = false; + /** + * 线路/场站 + */ + private String lineName; + /** + * 设备视频通道信息对象 + */ + private List channelList = new ArrayList<>(); +} diff --git a/src/main/java/com/gci/boot/modules/video/vo/VideoPlayVO.java b/src/main/java/com/gci/boot/modules/video/vo/VideoPlayVO.java new file mode 100644 index 0000000..18e7fde --- /dev/null +++ b/src/main/java/com/gci/boot/modules/video/vo/VideoPlayVO.java @@ -0,0 +1,21 @@ +package com.gci.boot.modules.video.vo; + +import lombok.Data; + +@Data +public class VideoPlayVO { + + private String playH5Url; + + private String playRtmpUrl; + + private String rtmpUrl; + + private String sessionId; + + private Integer status; + + private String websocketSSL; + + private String websocketUrl; +} diff --git a/src/main/java/com/gci/boot/properties/GciRedisCacheProperties.java b/src/main/java/com/gci/boot/properties/GciRedisCacheProperties.java new file mode 100644 index 0000000..d90bbc9 --- /dev/null +++ b/src/main/java/com/gci/boot/properties/GciRedisCacheProperties.java @@ -0,0 +1,35 @@ +package com.gci.boot.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author chenzw + * @date 2023/8/3 + */ +@ConfigurationProperties(prefix = "gci.cache.redis") +@Data +public class GciRedisCacheProperties { + + /** 全局过期时间,单位毫秒,<=0不过期 ,默认一个小时 */ + private long defaultTtl = 3600000; + /** 默认缓存前缀 */ + private String defaultKeyPrefix; + + private boolean cacheNullValues = true; + + /**每个key的单独配置*/ + private Map keys = new HashMap<>(); + + @Data + public class KeyConfig{ + private String prefix; + private long ttl = 3600000; + private boolean cacheNullValues = true; + } +} diff --git a/src/main/java/com/gci/boot/properties/GciSecurityProperties.java b/src/main/java/com/gci/boot/properties/GciSecurityProperties.java new file mode 100644 index 0000000..9867473 --- /dev/null +++ b/src/main/java/com/gci/boot/properties/GciSecurityProperties.java @@ -0,0 +1,39 @@ +package com.gci.boot.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "gci.security") +@Data +public class GciSecurityProperties { + + private boolean enablePhoneEncrypt = false; + private Shiro shiro = new Shiro(); + private Jwt jwt = new Jwt(); + + @Data + public class Shiro { + + /** + * 不做权限控制的url + */ + private String excludeUrls; + + /** + * 登录缓存时间 毫秒ms, 默认30min + */ + private long expireTime = 30 * 60 * 1000; + } + + @Data + public class Jwt{ + //是否使用非对称加密,默认否 + private boolean asymmetric = false; + //对称加密密钥 + private String secret; + //公钥 + private String publicKey; + //私钥 + private String privateKey; + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..50e8e28 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,103 @@ +server: + port: 8089 + servlet: + context-path: /cdenv +spring: + application: + name: cdenv + datasource: + url: jdbc:postgresql://10.91.123.4:5432/cdenv-manage + username: postgres + password: DATA123-4@ceshi + driver-class-name: org.postgresql.Driver + hikari: + connection-test-query: SELECT 1 + max-lifetime: 30000 + servlet: + multipart: + max-file-size: 500MB + max-request-size: 501MB + redis: + database: 2 + host: 10.91.123.4 + password: Gci@6579! + port: 6579 + lettuce: + pool: + #连接的最大等待阻塞的时间 + max-wait: 10000 + #最大空闲连接 + max-idle: 8 + #最小空闲连接 + min-idle: 0 + #最大连接数 + max-active: 100 + #连接超时的时间 + timeout: 10000 + #关闭时的超时时间 + shutdown-timeout: 0 + devtools: + restart: + enabled: true #设置开启热部署 +minio: + minioUrl: http://10.91.134.242:9000/ + minioName: GKHSLPMVGTRFJWEBAFSI + minioPass: XXTxxt/K7MDENG/bPxRfiCYEXAMPLEKEY + bucketName: highway + fileUrl: http://10.91.134.242:9000/ +mybatis-plus: + # 打印sql + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + mapper-locations: classpath*:com/gci/boot/modules/**/xml/*Mapper.xml + global-config: + # 关闭MP3.0自带的banner + banner: false + db-config: + #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; + id-type: ASSIGN_ID + # 默认数据库表下划线命名 + table-underline: true + logic-delete-field: delFlag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) +gci: + security: + shiro: + excludeUrls: /error,/sys/login,/sys/getEncryptedString,/sys/randomImage/*,/sys/getApiToken + #token过期时间 毫秒ms + expireTime: 3600000 + cache: + redis: + #redis缓存默认过期时间,ms + defaultTtl: 300000 +logging: + file: + path: D:\logs + level: + root: info + +#特殊字符英文的 '"{};<>!@#$%^&*|\ +string: + specialChar: "[\"'{};<>!@#$%^&*|\\\\]" + +# 视频云平台配置信息 +video: + baseUrl: http://10.94.2.23:8088 + clientId: gci1065361602729 + clientSecret: 0f08e5f0fe96459c963d625bae6be51f + getTokenUrlSuffix: /gci/api/token + getDeviceUrlSuffix: /gci/api/video/basic/getDevice + getDeviceListUrlSuffix: /gci/api/video/basic/getDeviceList + realPlayUrlSuffix: /gci/api/video/RealPlay + playBackUrlSuffix: /gci/api/video/PlayBack + queryFilesAsyncUrlSuffix: /gci/api/video/QueryFilesAsync + CutVideoUrlSuffix: /gci/api/video/CutVideo + getCutVideoListUrlSuffix: /gci/api/video/getCutVideoList + DownloadResourceUrlSuffix: /gci/api/video/DownloadResource +# gps相关配置 +gps: + # 无速度数据时 需要切割的时间间隔 + timeCut: 20 +#failExcel: D:\opt +failExcel: /home/jylm001/cdenv/import_file/ diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..658651b --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,101 @@ +server: + port: 8080 + tomcat: + connection-timeout: 60000 + max-connections: 5000 + max-swallow-size: -1 + servlet: + context-path: /cdenv +spring: + application: + name: cdenv + datasource: + url: jdbc:postgresql://10.105.148.3:5432/cdnev_mange + username: cdht + password: ?wXYz@0987! + driver-class-name: org.postgresql.Driver + hikari: + connection-test-query: SELECT 1 + max-lifetime: 30000 + servlet: + multipart: + max-file-size: 512MB + max-request-size: 512MB + redis: + database: 0 + host: 10.105.148.9 + password: $1$OnjQ2FpX$1CxaR3RM7Pcup4DHRDmk1 + port: 7980 + lettuce: + pool: + #连接的最大等待阻塞的时间 + max-wait: 10000 + #最大空闲连接 + max-idle: 8 + #最小空闲连接 + min-idle: 0 + #最大连接数 + max-active: 100 + #连接超时的时间 + timeout: 10000 + #关闭时的超时时间 + shutdown-timeout: 0 +mybatis-plus: + mapper-locations: classpath*:com/gci/boot/modules/**/xml/*Mapper.xml + global-config: + # 关闭MP3.0自带的banner + banner: false + db-config: + #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; + id-type: ASSIGN_ID + # 默认数据库表下划线命名 + table-underline: true + logic-delete-field: delFlag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) +gci: + security: + shiro: + excludeUrls: /error,/sys/login,/sys/getEncryptedString,/sys/randomImage/*,/sys/getApiToken + #token过期时间 毫秒ms + expireTime: 3600000 + cache: + redis: + #redis缓存默认过期时间,ms + defaultTtl: 300000 +logging: + file: + path: /opt/logs + level: + root: info + +minio: + minioUrl: http://10.105.148.6:9000/ + minioName: cdhtuser + minioPass: p6tEwWykAz34BvAGds3 + bucketName: htfile + fileUrl: https://zuche.cdenvironment.com:25000/ + +#特殊字符 +string: + specialChar: "[\"'{};<>!@#$%^&*|\\\\]" + +# 视频云平台配置信息 +video: + baseUrl: http://183.56.220.198:8088 + clientId: gci1065361602729 + clientSecret: 0f08e5f0fe96459c963d625bae6be51f + getTokenUrlSuffix: /gci/api/token + getDeviceUrlSuffix: /gci/api/video/basic/getDevice + getDeviceListUrlSuffix: /gci/api/video/basic/getDeviceList + realPlayUrlSuffix: /gci/api/video/RealPlay + playBackUrlSuffix: /gci/api/video/PlayBack + queryFilesAsyncUrlSuffix: /gci/api/video/QueryFilesAsync + CutVideoUrlSuffix: /gci/api/video/CutVideo + getCutVideoListUrlSuffix: /gci/api/video/getCutVideoList + DownloadResourceUrlSuffix: /gci/api/video/DownloadResource +# gps相关配置 +gps: + # 无速度数据时 需要切割的时间间隔 + timeCut: 20 +failExcel: /opt/cdExcel/ diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml new file mode 100644 index 0000000..01b5bc8 --- /dev/null +++ b/src/main/resources/application-test.yml @@ -0,0 +1,90 @@ +server: + port: 8089 + servlet: + context-path: /cdenv +spring: + application: + name: cdenv + datasource: + url: jdbc:postgresql://10.91.123.4:5432/cdenv-manage + username: postgres + password: DATA123-4@ceshi + driver-class-name: org.postgresql.Driver + hikari: + connection-test-query: SELECT 1 + max-lifetime: 30000 + + redis: + database: 2 + host: 10.91.123.4 + password: Gci@6579! + port: 6579 + lettuce: + pool: + #连接的最大等待阻塞的时间 + max-wait: 10000 + #最大空闲连接 + max-idle: 8 + #最小空闲连接 + min-idle: 0 + #最大连接数 + max-active: 100 + #连接超时的时间 + timeout: 10000 + #关闭时的超时时间 + shutdown-timeout: 0 +minio: + minioUrl: http://10.91.134.242:9000/ + minioName: GKHSLPMVGTRFJWEBAFSI + minioPass: XXTxxt/K7MDENG/bPxRfiCYEXAMPLEKEY + bucketName: highway + fileUrl: http://10.91.134.242:9000/ +mybatis-plus: + mapper-locations: classpath*:com/gci/boot/modules/**/xml/*Mapper.xml + global-config: + # 关闭MP3.0自带的banner + banner: false + db-config: + #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; + id-type: ASSIGN_ID + # 默认数据库表下划线命名 + table-underline: true + logic-delete-field: delFlag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) +gci: + security: + shiro: + excludeUrls: /error,/sys/login,/sys/getEncryptedString,/sys/randomImage/*,/sys/getApiToken + #token过期时间 毫秒ms + expireTime: 3600000 + cache: + redis: + #redis缓存默认过期时间,ms + defaultTtl: 300000 +logging: + file: + path: /home/jylm001/cdenv/logs + level: + root: info + +#特殊字符英文的 '"{};<>!@#$%^&*|\ +string: + specialChar: "[\"'{};<>!@#$%^&*|\\\\]" + +# 视频云平台配置信息 +video: + baseUrl: http://10.94.2.23:8088 + clientId: gci1065361602729 + clientSecret: 0f08e5f0fe96459c963d625bae6be51f + getTokenUrlSuffix: /gci/api/token + getDeviceUrlSuffix: /gci/api/video/basic/getDevice + getDeviceListUrlSuffix: /gci/api/video/basic/getDeviceList + realPlayUrlSuffix: /gci/api/video/RealPlay + playBackUrlSuffix: /gci/api/video/PlayBack + queryFilesAsyncUrlSuffix: /gci/api/video/QueryFilesAsync +# gps相关配置 +gps: + # 无速度数据时 需要切割的时间间隔 + timeCut: 20 +failExcel: /home/jylm001/cdenv/import_file/ \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..86cda37 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,5 @@ +spring: + main: + allow-bean-definition-overriding: true + profiles: + active: dev diff --git a/src/main/resources/excelTemplate/保养台账导入模板.xlsx b/src/main/resources/excelTemplate/保养台账导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c5fb53b8699b710647ae5653f41d53c2362bbc30 GIT binary patch literal 11641 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/保险导入模板.xlsx b/src/main/resources/excelTemplate/保险导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..915aae1f79e2ee8edb19829259c54ffe40c186ee GIT binary patch literal 11964 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/司机档案导入模板.xlsx b/src/main/resources/excelTemplate/司机档案导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..79e3bffb581d93f9df472599126d79fe7a6f7ef2 GIT binary patch literal 11795 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/年检导入模板.xlsx b/src/main/resources/excelTemplate/年检导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b8f9128415b30c314b549c0033ff9d8c82e2b711 GIT binary patch literal 12516 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

p9p_>X)5K-Wd7~?9hE;kgxj9N(sXQnOK9fj_( zu)ZIzrn0LHseH9B$2@lsrN7x4hJ(t2YRzrZo%C#2 z9tOt(*T}sa8q#k2T!(d9rF54m%YK_$P8;?=4I={h{bwZ_jAM2PN9NC(fPN)Bv`1$y&g6 z&k_PxvuZ}~eg&Drpxp3Vbs6|$WM=2VA1v~HF#Q(}GOeGibdVaP|=|m)(=w&eSs$X_insAuU z`5?8uo5oiU(yYTGu+QJfV2CkKH*d%^n?WwuTL|Jm*9AL-jm?-6Nb9IFV|BktNtleo z^-V7s+68~%&n3vpy}WnKzSUrjM&N)V=-De+5`v&PKh3{GTF%C5orTIL5^*sJqN81r zDMao7)##{y_4P~Xnf3IV5-F@ZXvZRI-k#FvWzjW9#iutga~G3Vjl^D;c8{z4E|=%~ zUf}XlpkU}fi-lhd*5}>>IuHaDgb4Wa74<**@|S`C9_F76{9>+&kpB+)e@^;5>_2Jz zn$+|!ou3Eie@*rj2Y-zx=Izt?8%g)i`JU5spM-zSNBMWPf01^dL-d?``dd2+_}Kq7 z>A#t%&()t(DSxYj0K@ce^}mRf|7+7gjem`&O{)Vrg1{L6zZCvNDU#xEN#XfIpJ$J! ziGHC}|97?j$R*G1JZCWew&V6|y?^i-|JUN5xOBh9({Aa30S36+zcK6n^zw6V-IM08 z^{YM8e8#kUzJcdu^>0H3BtMt%A4T?a3(xPHe_I&G`eos-+voqa|396#4+H_Y|9^L9 z|J?lZ{_O7=QGk5uztnzrYo9Oqd1?IHz#K5k0S)}!@BeGjPh_iK2=z&-p+`7i3# z)5`xjfIMa3U*k!44|qEN)ctop{&VloGxC##UyjG6`ezHz^7C^np7X(e8$AAx?ff?N z+{$z2%x^2Oz#hb(8~bVHCy(a;yOmoY(*I!PCp$x43KICtKQVT&L3SWPKz3-J{`x=B CczKQh literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/车辆作业导出模板.xlsx b/src/main/resources/excelTemplate/车辆作业导出模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..123cd4202ed254b4d3a4824d67bfddac24959f74 GIT binary patch literal 10012 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/车辆作业综合分析周报导出模板.xlsx b/src/main/resources/excelTemplate/车辆作业综合分析周报导出模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fa6b9cfe2e6f339aa703cbef9557aac9170033c9 GIT binary patch literal 10208 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/车辆作业综合分析月报导出模板.xlsx b/src/main/resources/excelTemplate/车辆作业综合分析月报导出模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..94a2875a093cefc8206bee44c42a532d0ce391b6 GIT binary patch literal 10204 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 Z|4w<4m4N)YS&^R;#-N_%T1Z~>{vW+i$rJzp literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/车辆维修导入模板.xlsx b/src/main/resources/excelTemplate/车辆维修导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..277d019f671ad0932eac23a8abcbd219b24dfcba GIT binary patch literal 11901 zcmaKSbzIxa@-`6M3dNzgQ{1I!arffx7ThWB?ob>G6k6Qfy%hH%#oZ|mZ#cd8_LSdw z&;F6*lg!NSKJ(p~$<8A$1%QMHdm6#As{&8&{~d6k4@N*kd3&I(1A{zB3?1|Z>|bI{ z9CKxi;9y{^5MW>^e;3oYwWW8pw#ta@kOVNHi(L9WqErG|=tvZqsr^EDU^JZYS%CBH z(l6t-MsMio9f_}CY|eqocZe)#qeb=hF1m*st!J=Vzz-j)SNv-!3ghiW;joRRtW~*M z)H0)@sNkq%s4Xpt3N>LJ>3?3j{wM)N<3faDP^>#fZkt3v)dYzK*;UIp((K`d+MT~P z`7HUGvtqXZ+~4YhaWEn~Y(aqidMkptMS9KE^7wdh6oVFh9X$lX`+cpF#BSI8dK%32 zvmZNa4}n!bc=!Qxi`wD`{ws9fG~~^A;cnP<`102^pto@y<|WJWJ7&N4jF0ZkL!GbQ zU!NRY(9{2*z1b;A?%I~$12F9X6!xK;{JK#iwL9~BaXZ~q#G}2zbc zWV~&CSgqfA$8mdYa{~1zy0pf#?r%WoYJ$*3{X4pbKzrjScq8KkrMekW0+0M2bJmwA z%&`(jodu2M=wVgSfyAkcbnNEhxr-MwX|+u?l>~20mePPrhy%$UQ^Hw#+KamoV*%N) z)n>*ebx`i5swYTc>02771yl0b0M2S!1_pcm6f?Rv^V2>TZ1q$z)rOtuW?L=#*gO@0 z9_^Q}xI@yWX%4$4Y$|@NW&ptp1GMy^GNlf=4t*<9L$*T_41_+sSU?1$W@OD4@CY^+ zI*Fd~S2-LB5=`Y%Ie0;_?-;>jD#a8Q?{Ty{Fzci}Zu~YPCTn%(qHChuLTm3q6+%8$ zsv`jEP*W3H#(Tq6b*F5`c5CLxXd3SN!4D&DEC_R0zEuHHVt73Ntc2wK!&Z$PX7U{p z3f6)d402i-9Ae=8cinrh>Wb{BiATY&;v&qVWwU-vj=H`u&?O3@Q-R z$RMcE{(#!a!4YWv1a^MxkVO|GipXW)ga4S$bXP24hqL&d&$tMJOch6EI=0n-xc$8R z&5?@u#JC8@fqi|~kMF6D7u?883T6|pQ^8jaSKtOz7KXf_GwawQd`+!L7fj?8jaJAI z)i&xlcJfr?M{BWq9bnCwZOffCNQ|xoBO*_0xdD*8U-J_LfF0>NDM)G1X6(Zht zn;K5R7Bal5KTZ<6eP{IfYVO;9ZQ;Pq<__iEx>Mf40%CLG7b>YBoR2Ds0)7L~6oM}W zUl~esRDX(hxcCM^TU<mpQfF~{?y_}C*lC0&eAcpLfs~VODpc07oM_AE-i|OC$ng9{x z9uP7WX91ybp(pvnG7jGw3YVAO+kZPiDzO@5qVQ#Vse(apoy^&-NB%`p!PsA{Ot<9b zkT_^Nmn4))rQ^+fCu9jM2QZ+snAT8)5)qavKnzto8b&=SfK&~0AP%<={_B^|A82=1 zEbwSUE!7glAq};oD!`+fh6W9k1%<>tKZ_|xenkXlO*lZ=3kpmHKbuHy4S9J#ug}{2 zEiV|nyZ+kpWi%(s)CmQdIipVJ0n+P$e)f12!#9o5?PIDcA}(I@-_p9gD6ykLa62Z- zAHP+i8B&hy9p?HGV+yN_Inmt7C170`43tg)twuw$$^k&WskMqIq)!K+KLz6`AEYtwH$*waCvn3| zm4f9q{~gKJ*O+iCxPmByQYVjP*<3f;tj5^e-ShxIE!q0R@a!^TyK(Zj?55H<6^-|D zmm2cQZE-xKCgs7>5kIL^ApCzu4eL9l(|-`1v76AIm*s-XNODuJibOWkA-6>6e80;z zyAiKoA&#dDMrNfh&^h?tHe2;WxRTo@7mY)j7ln+e%C;&Z-2uHClckO+3(V$Y_13y> zGttSG4yg^k^OvrwHt+lWyOqp769UwSe|cCDe?5yv_WCa7Hm1)LUoWcbo(Jf8p2G$M z!+R#_Y;7g{ON)sf^!XrlF?y99rG5F`?jy>z4xk&3ES#82Wd;=5idvKi<(9fpmbp`@ z*yn7$?<4V7l8On528ZZlVUrH7%ePD|v6GH&CEYU2Y67^)9bciyO>&`E>J+X|^aYRc zo>c#E>cE&JA=k_qxZMwK%1`W)E5SKVu$up{(~OQWlP9@JXQq~_fQ;ckCAsN$^1VL_ zuUg32U>Hsj=}mYoxO!TPvbSHtwnNTO2wT7Ql{KB*TaM6DMKVo@336b-s^%XNuD~vb$g<&q&p#G=f~`t=~fNuxie(B<@%)u&aJ* zt3*>rTmi36)>RTt6if}-iO$~8OGYA`?sau~vzm~zOP%i6(3BZ&K$T$~4Ea%1Qqx%> zI2|2L1iytm9x0~e7eoZyD#p?Jqp&(l^=K`Aq&TLGA1kF3-%_Kj#i-XCS!rwIMk*P} z(rof18mKpYh^t@iSPng)+(;6kg91F0Mm*{7zD)hQd z$huxb8CR4J+XfN=v;RGDQ%kc7$Eswh0yy-@ynw8;Xr=K8AJx!|-1PD?L0fi7bX2i! z2T>8{1A^nKocZ7jA?nC+-dn&(huuiDQ`C~tWVG#&C+8hI<_+H26^D3cyX2j;M{!jr{1fT_pNf!womm&4y`_Vhv9aUx^F8X}lmP(=2F47^ zN}wbDl$HJ_`gg6P1lJ_l*b)y~4!vY$>4T+A>d!7s4U+WBfw&z9B!~s)W~M z*@ywHK1gf9H8arFMwQ!RX`8Awy}(bZRn>XWp)bHW-FTI(<;~f7|0rCgJuN};DF!w@ zaf8R;r};g{1)mW2N~M_^?c{OU@VDqAu%`yWpG3$pMn)<+&G@Exjs-c-%td{BO!nvm zr&-Q>)0!_)``K1W$!k1+T2p&^i(yM(3}h?EOeM7QZoNRVg(9h|C;^WYNvCNfMd+MG z)b@~ncN*_J?&*(Ecy@BvbWt~Hd?u)dqrMha1ZCqGc%o<%26!9tn;J zjLg}=`C7Yt41X$ODJspM6|K}j^%2yM8>7tIz10g%dsvrgf3fcga0S4kfK$uUz5LkJ zz~kgBAG!l>H%;;(&RiMuZASwtWaB5??jDqiSMc}a)Dq@rHk4T1u0 z&g`9htE-$*pQ6J-8~?fsr>iQV!%r{D2V_%Ksf>E z?p7Xf97Y6=PTSxXN(+2#x`Na+mK3y#F>757>N5CQMnYsY$^#o*PJG*1=u@eB-|Fu> znAw`9w)Ol5qWV^)*VCmi&bLxY^U0&HaT4LxQtGn?+k_^#8fsXO zHlz53XO3zqC-b|ZT{Yy{VT-L4yA3KMdYonPt7zTdTpW3OU!TtKn=m^yP8Cf=!+ns{ z1%pdmdBhAy3N*r22Z)v0sC0hUHOX}?0<>+xAKFYzt=tP|PYJk)On-2glJyzr-NaW= zF;A=~Ta9`jgq}m{AowHyV`^GX90EC`3ett9wN+6`dqOOd>}Bw~XmSeHG~$ZEbC32N z9gnlef2kmz{x^f-hNGFWweho}R~kQQbO8zsj0oq~-;Mu?{U!WYWI0fm0pf9>v|w#} ztL?YM8tsuXlfcyStx`C@6qXEoRitf^jOx-rM9tHPF;F4kn`=HM<-6ogH4iQBqcg6% z#x9ZuagBg)|L(P7u0>xzF`a=f*D5@(}O4wh+krW-}Q-RmjQJ}rl^LF`BE7##d6Nn2-MMzWVijOC2 z2~WJ4E7jlOO~I!5y}J`9&d2pGj0o^(=|hHT=n9%>Hw{s_Aqt)?L8fkmWvNBcIiM;OyoO` zNZQt{bxq+@NilGFFtV;q3WU|Q@LN*o%5T-REyCcWHVQPPMghGrVDbWCWD>kwBgc?X z@@?9}11V@nF~Swf6WRC?5nI>tMAJc&5t*=@14eyqnZ&cGQe|bjcULz(EJqjNg@w_X zS$sDe=O=3uV*FdJv|WG%(SjeJkJ_$o7vx&nGQBQ$2j1B-tRzn@@X); zUtdh{XYzYp4{v!t9Cw2+ubEkOijj46HigPH^U(U%?6l8*JxOUx?V%Fwt`uOpa;`rd znuSG0h&|_)Z|EKZTxt}fu?~N?P`#CnomyG!IUW(=VKw2Hn*nJ9nNsq|+wPRm z{R(pqQHjk?WC`4~+2|g0Np!cmRL73!l$N)XF8u&Wj)Gf)4%NmHOuwe=bc%dq-%pe* zhy5FDU%%Yof7^l7FJUIyPtu_z<5g-t!&w?~?pt2#Zg4|Z?RG~yYql+z|Ddcc zx1AgQkipd_XJ%==A0$!Lk$tIm0sXGnd5E${Y`R>b!aulQ>hwZ>$Gs?@sOy|ix9{$} zn^yl^gl9re05P!PTB8uv6)Cv6ZDQ#bPqS!Q8{2w94@$gdi^X{jrS~Wf`{p-tc<&p|83uD!lfc1`s;x&$4JqS@-Ya#St8acOOthuQH&$QGf zbm`9!#m9C%R+Vl?D@1Ty_Mk{Aow zv1%oHrSW|UYk`pS@Qhz$(5anp6*dNb5Bk}w(){L+d2NYIjI9`!K|Z*|)VM!56_KV9 zi>G9UN@E>nXPrja6=PY19p+f*R1~x)N(`nE!`aJU4u!M1`A?B_kJ1k#XGvWauh(K} z)Y;2YH9xf{3mxbdQK@1u!S}(ycRNQV zCh@_;niUi5l5>4D`&!ro5g=uE*0Ew`GhYE-f!yB}t6 zxt2~PMSrRAwBAcwo_z%)7Ug8PTnPc!XxnG)#t(~Js``2Dp_OenlA{?g6sQ}N$-fI_ zyL+V42h%!*7lAs~UsPP9k;lC|SK3^&BP+T|g)QX;T!pr7AkdBLXILhzHr9?MAJ?40 z^P#HCKN5e}>aihtP3R}Qa z|JZZB&cTqy-(B+4;{p3F5ygVLF{p*jimOt4q;DVY#i=(|O;~+VeHPmf)#1FLwz`ER znXAtogyW^I>-1mal&ES4M0mk0)2zKwv*ZE8lhU>uZ?aqXSn?2{Y0}j>gHGLqWb-NZ zVGX`ub}$aYinivo&N9h7wN3Eu0TCX$xEqUq!x9>V=%n=Udd9 zZPUp#IZSbJ#cE|^8{u!*57+vnj#*DKB;)YFBeJ%iVRCj_tda1pMD@xy%txWg*|8!` zRoWU`o@HY}CLMjSB?;`~h(^wibJ8CSBrA<`#woeHTZ+wH#ZHRW+voZTCQ&hC{95DF zFaU43(*jSXi%~-|Z^{Cvv0%l|jl;^S39vWnXRZ#=EoGKm$KV{`FGXn52CQijmDwUP zHBJk@duxeP>#bGG|JD!;yrBm^NfkrD4h3 z;7C5*&7mE}@FI1#o`lVirR<{-O(T3}8IdXki&953#aGujxQTh~5yEzeT=ddKYBK|= zQfq7OX-1!cNZ`>y-cdV`fD%3fY%}UB#Qmkrt)H(rzlfrbapVRhim4e{4R!G8kda*u zy2rO8V7V24QkeBH(WC`n5?4`&;7Fv-B~dvvG@^WDR>vZyC^w0yQAA}cgH(@VlsnPT!E>Hb7=xJtb8|AHI^F3Hkc6bZRRKOL~c?4)9?1 zOA+mq(=s4!K`=q36vkf+o=9^qDVmvr?s&s+B>sXvB#7dp6quV#zx+B2@!Ob*0K^_Q zr&q4=+I?ZxiBdz-AKZ9ZBp^SSjIU3zb!qo_N~2-&o4seM3@)Y-Wi-KwJa^5F)4IzbQ9|vvv|l3m7H-F81Pu1e2g_ExSil%T^REma~uA zd%erChgiOJ4L)Rp;4a}h?j`Jmsj^8PPTMHymFR|e78Ku1CtF|Pkuov+Q7PcHj@|{J z8SXRmZpJ%hXz&zIQCOclS_t8BLRrzKB;cyGy0Xv4U`Xv_fU2LDoU&*P{u*Uc1=x4T zW;zQxY3bUwlE6;}K*&!;`8fj+QVcVA`hJ9Nq?~%8Mw2H6?M^IQ-^D{#0_=21IC1I% z)NRQ~wT55kHSCv1b$^w%GL{m6?^I9s$BMkp_aCYUkTO96c9B=w5OUG8&Jg-#BLco= z`@N+hW>qKBH!Vtp+3(Tj=z9IBTa!UI@Yd3jlDW8Y8qv5QB8W*8=2dqv6d>w_K~E55 zU{S6V4GCHeQKACM42gyBF?j_mfK;-SyeF1APk|y^(QgL}O#PThzhdp9#*G#lEf$7D z`34Pg2o;pVml&^i(3ogv@<}<0beP3elQjNpX6A(nG|aVBYdNtM?X5#!2`w}lg5Ffp zGBaPKDwYm#v81aMkiAuJNCyPtFMg*j{E~+!>V6$dYpvatf+vzUP8!;&a2>cF=Oh7x z3@^4J95=9NVeY`eV=I|vuSP7DW~b(m%)VAGp7fs=Mj?y67`y6mlUJAniKgi^O|WuF z>#0+&DdiMN!yV^iZ?N#gOayK3ZC%HVua6H$V$ho+`7?CV!^u7nQ4K^psc=C^agn?c4l=`&7hek!U5jGTdj;|A;rCkq3s=#)8y zT??n@b5#?RM@)W4vQ{tz_@rD2wJYRsvX2)=H~U-s#rK@K;8})d$9c>WxHUiNib!PI zZcfjSE=}5aGWon5f6h@Bwmk@iN+_-4sV!E<}r9&Mb#Oz7U9?ytST!5CW)QCtmTEd9`X@S*r>6RTc2o8T@Dp+)`EHzPo!*(fplRdO(+5KBUWts z-OkiNUP?f;P_bIq$kDflE7zNqyq$ZGD!H~WbGIXKU#NY>JXRF6qd=-|+le2o>tf3V;PY6s?7w?nP zxrvkj7h;udp`w023Ajoh$nY=p>$C#wKfPV^F&BJkBK(W&M{Qgw0bo$DA2+$@k&b}2 zkAkBz#jF)gX3cG}GeP7qPQ|R%X#q2#i+X}i5Cb2eu)1GRY3;Xu4+V?o;;Rn`r)ODg)HdH zZKvix)>}mSil=B7WB^!#5Sd<#d=PXw&CSl-!UmP^HR^BbecVN2XZ_-VtvskD6zzM2 zx7E=370lHfeYwZ%F5PVu)(ZVRGw*ve-WJL6S|{vgt{^elADSPooHZYIWDCu$j#4c0 zRracB8cn8Ni?&p07ws*6`&nx~IjM1JiZU|FV_!x(@CjlBz*RpG$Aq%hUCR-SNN@(kIxF>+pVnKLkvAqS8;jG_k$s#@yC!2x1Fnih5kj0}Z-|!=Lh5J{P1L z1g9pL=~c-?!c#!grG3ox&Fk`y)Xrv%633aM>cHjfLrgfoU`u2w6;EbFQs%0=Br+1k z&4S`rFL<42&_ZADDeT}SlGN0V(RG_c&L0a8QEwas5HncFP33PrkP z&yT4NJ#yM?DVgvGyv{^Flrp|gLz@YQF7bXbSeEPktmDn3VVLLuLfaaI_KV*)+y+3P zw zT$9ArO5eQH4N31tYt6O`Doas)KWf@7bEA*Xgyf99k&1%@1~8YCOD}q3*A^>>I%t;S zvFan(eG(zMZB;D^Hc+LGWLStyFKU zf#cwdS}_x?dm1(2EfVQ46+|`r zIVt!F0Q;R=6^=b!)fWB4zqCvN+>~uQA)9tj4Q>PcH{T@8)04$&dn%4H2lG(Jn~&`% z%L`=ju!$6M@f(u*v$xpD+YFwH_GS^t%e?7Xq6zV6g0|xfY`z8pi}${*@TTUy9btLB zt{j`;WEF!E;qRF@+lF!>0u9YIV(-K^bmSr#{H4T%4oO5SFhwcs`-WDV9c^l#mMmcy zdG_$Nz{JE>XGiRqX7!LbcK~_r-Xj@vU-x>F8y}mlxcw>JXP5tf=jT7Svi}6<#&It8 z0SLxM5S+N6cTfQOCHB<%`R~E_FS;Nu2x9M%e~bT^m)&?IlW2xcZ}v=y2bke&Z!-fJ zDb2LHto|JJY{z6R#H@g}Bg&zL#fGEF7ZetTjPgcYREYF9?32)~$VV?2vO}zoYs0~j zBE-vIA05>a&Z;L#O;!V_?cj{E^$B!pC}#A4)ZqZ=9c8AAB#{D*7t{FGk?!$ZBi#2F zKK4I~el7{j-%`p4+r_Luwiv3^ATQ_M9x@##!pcO-Z1ZysxRUjIS=M zVFdNb>NpgnoR?e;e>kD#>E!Z?bLS4%MC|#1SeOzuNp$+vjyl##iW>{N<;rg3udC~S zelGtLrT^9$`zKh<2_)2knTGQ3ls6RP2pKnsa4WU*k(?EF#kv!cz@r^iG^LL z1a$bQP3+nBL@4LQvx%SmEQ#D?YYDKzP){r*hhzU~~=n-tze+)Z$_xfi(D zGcr{jo+Cas9m+7KM19ejOA(yi+{!{I zLnsJAriq8LTz=OPmta46 z6bs~Mk`Z^qKfK8@mcq*B@m$VpY-F+X9ZNm@nl~^cx+!#}F~R)7-LTx74aW;CryMdw z)YN0~J}7;c{YM2l_~bjp>S9+z1ekeizE#n#VIu86w zG?z5!EF6V7gsb5sBAG0UQaP`BH>Xxn*CT(9=II z^r}VqkN*2*;GYl8Q!xKEp6E_~pcC=mL-XgP&x8Au&aX)e{-^WTVfnYoo}%5a@if`f z_#2b+&-tEnIiG}o%?H}!Z?*q0JD)@JoU8a-I}r4!|8LU&G8dn#Kj+{5RzC&>nceVeMF`nCbPJ8=p z$Kuy|{~*Er+v1;yO25X_ZhwLvFVJrPMqB#R%g>2RPny5hPXzO)<}(`8^9?+&)_)sv zB>KzH|Eb-dTX=r){o8^i#xD#1y9WQa{r~AaPEaii+W&u>u77U+dE52(jJkhU``v_n zzU1dc^KS#I#DC5EcfbGJqM!IDzs8f(CP9$`wCKNO#edU%%DTVClP)gBbKQRqC(pC+ xlZ9W7m;V1)c$Sl&WAU6K^V{H4E&Atnew&h)g8C}}VuE3UX@U|UBK4Er{{xnnTeJWG literal 0 HcmV?d00001 diff --git a/src/main/resources/excelTemplate/违章短信导入模板.xlsx b/src/main/resources/excelTemplate/违章短信导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..19138c8fd930ff17b2246e13e04c25284465fbf9 GIT binary patch literal 8980 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..5ac223a --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + ${log.path}/${spring.application.name}.log + + ${log.path}/%d{yyyy-MM}/${spring.application.name}.%d{yyyy-MM-dd}.%i.log.gz + 500MB + 30 + + + %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n + + + ${log.level} + + + + + + + + + diff --git a/src/test/java/com/gci/boot/test/PermissionTest.java b/src/test/java/com/gci/boot/test/PermissionTest.java new file mode 100644 index 0000000..3a5bcbb --- /dev/null +++ b/src/test/java/com/gci/boot/test/PermissionTest.java @@ -0,0 +1,101 @@ +package com.gci.boot.test; + +import com.gci.boot.common.util.JsonUtil; +import com.gci.boot.modules.system.entity.SysDepart; +import com.gci.boot.modules.system.entity.SysPermission; +import com.gci.boot.modules.system.util.JwtUtil; +import io.swagger.annotations.ApiModelProperty; +import org.springframework.core.annotation.AnnotationUtils; + +import javax.annotation.*; +import java.lang.annotation.*; +import java.lang.reflect.Field; + +public class PermissionTest { + + public static void main(String[] args) { + test3(); + } + + public static void test1() { + System.out.println(JsonUtil.object2JsonAllPretty(new SysDepart())); + + Field[] fields = SysPermission.class.getDeclaredFields(); + for (Field f : fields) { + if (f.isAnnotationPresent(ApiModelProperty.class)) { + ApiModelProperty annotation = f.getAnnotation(ApiModelProperty.class); + String value = annotation.value(); + System.out.println(f.getName() + "\t" + value + "\t" + f.getType().getSimpleName() + "\t是\t" + value); + } + } + } + + public static void test2() { + try { + String token = JwtUtil.sign("admin", "abcdef", 200); + Thread.sleep(1000L); + boolean verify = JwtUtil.verify(token, "admin", "abcdef"); + System.out.println(verify); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public static void test3(){ + System.out.println(TestAB.class.isAnnotationPresent(Aaa.class)); + System.out.println(TestAB.class.isAnnotationPresent(Bbb.class)); + Aaa annotation = AnnotationUtils.findAnnotation(TestAB.class, Aaa.class); + System.out.println(annotation.annotationType().toString()); + + Annotation[] annotations = TestAB.class.getAnnotations(); + for(Annotation a : annotations){ + System.out.println(a.toString()); + } + getAnnos(TestAB.class); + } + + @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) + @Retention(RetentionPolicy.RUNTIME) + public static @interface Aaa{ + + } + + @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) + @Retention(RetentionPolicy.RUNTIME) + @Aaa + public static @interface Bbb{ + + } + + @Bbb + public static class TestAB{ + + } + + public static void getAnnos(Class classz) { + Annotation[] annotations = classz.getAnnotations(); + for (Annotation annotation : annotations) { + if (annotation.annotationType() != Deprecated.class && + annotation.annotationType() != SuppressWarnings.class && + annotation.annotationType() != Override.class && + annotation.annotationType() != PostConstruct.class && + annotation.annotationType() != PreDestroy.class && + annotation.annotationType() != Resource.class && + annotation.annotationType() != Resources.class && + annotation.annotationType() != Generated.class && + annotation.annotationType() != Target.class && + annotation.annotationType() != Retention.class && + annotation.annotationType() != Documented.class && + annotation.annotationType() != Inherited.class + ) { + if (annotation.annotationType() == Aaa.class) { + System.out.println(" 存在注解 @Aaa "); + return; + } else { + getAnnos(annotation.annotationType()); + } + } + } + } + +} diff --git a/src/updateSql/update-230915.sql b/src/updateSql/update-230915.sql new file mode 100644 index 0000000..56ee974 --- /dev/null +++ b/src/updateSql/update-230915.sql @@ -0,0 +1,22 @@ +ALTER TABLE tb_projects ADD customer_id varchar(32) NULL; +COMMENT ON COLUMN tb_projects.customer_id IS '所属客户'; +ALTER TABLE tb_driver_sign_in ADD project_name varchar(256) NULL; +COMMENT ON COLUMN tb_driver_sign_in.project_name IS '项目名称'; +ALTER TABLE tb_driver_sign_in ADD sign_in_date timestamp NULL; +COMMENT ON COLUMN tb_driver_sign_in.sign_in_date IS '签到日期'; + +ALTER TABLE sys_user ALTER COLUMN del_flag SET DEFAULT 0; +ALTER TABLE sys_user ALTER COLUMN status SET DEFAULT 1; +COMMENT ON COLUMN tb_driver_sign_in.op_type IS '操作类型(1用户,2系统自动,3后台)'; +ALTER TABLE tb_driver_sign_in ALTER COLUMN driver_id TYPE varchar(32) USING driver_id::varchar; +ALTER TABLE tb_driver_sign_in ALTER COLUMN driver_name TYPE varchar(32) USING driver_name::varchar; +ALTER TABLE tb_driver_sign_in ADD sign_out_id varchar(32) NULL; +COMMENT ON COLUMN tb_driver_sign_in.sign_out_id IS '签退id'; + +ALTER TABLE tb_repair_info ALTER COLUMN order_no TYPE varchar(32) USING order_no::varchar; +ALTER TABLE tb_repair_info ALTER COLUMN repair_class TYPE varchar(32) USING repair_class::varchar; + +ALTER TABLE tb_upkeep_bill ALTER COLUMN flow_status TYPE int2 USING flow_status::int2; + +ALTER TABLE tb_vehicle_check_template_project ALTER COLUMN "content" TYPE varchar(128) USING "content"::varchar; +ALTER TABLE tb_vehicle_check_project ALTER COLUMN "content" TYPE varchar(128) USING "content"::varchar; diff --git a/src/updateSql/update-230919.sql b/src/updateSql/update-230919.sql new file mode 100644 index 0000000..aca353e --- /dev/null +++ b/src/updateSql/update-230919.sql @@ -0,0 +1,13 @@ +ALTER TABLE tb_accident_info ALTER COLUMN accident_loss_type TYPE varchar(16) USING accident_loss_type::varchar; + +ALTER TABLE public.tb_repair_info ADD cancel_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_info.cancel_time IS '作废时间'; + +ALTER TABLE public.tb_upkeep_plan ADD cancel_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_plan.cancel_time IS '作废时间'; + +ALTER TABLE public.tb_upkeep_bill ADD cancel_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_bill.cancel_time IS '作废时间'; + +ALTER TABLE public.tb_upkeep_offer ALTER COLUMN total_work_hours TYPE numeric(10, 2) USING total_work_hours::numeric; +ALTER TABLE public.tb_repair_offer ALTER COLUMN total_work_hours TYPE numeric(10, 2) USING total_work_hours::numeric; diff --git a/src/updateSql/update-230921.sql b/src/updateSql/update-230921.sql new file mode 100644 index 0000000..6f47768 --- /dev/null +++ b/src/updateSql/update-230921.sql @@ -0,0 +1,127 @@ +CREATE TABLE tb_insurance ( + id varchar(32) NOT NULL, + vehicle_id varchar(32) NULL, + project_id varchar(32) NULL, + has_compulsory_insurance varchar(2) NULL DEFAULT 0, + compulsory_insurance_no varchar(32) NULL, + compulsory_create_date timestamp NULL, + compulsory_company_id varchar(32) NULL, + compulsory_price float4 NOT NULL DEFAULT 0, + vehicle_vessel_tax float4 NOT NULL DEFAULT 0, + compulsory_start_time timestamp NULL, + compulsory_valid_time timestamp NULL, + compulsory_url text NULL, + has_commercial_insurance varchar(2) NULL DEFAULT 0, + commercial_insurance_no varchar(32) NULL, + commercial_create_date timestamp NULL, + commercial_company_id varchar(32) NULL, + commercial_price float4 NOT NULL DEFAULT 0, + commercial_start_time timestamp NULL, + commercial_valid_time timestamp NULL, + commercial_url text NULL, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0, + CONSTRAINT tb_insurance_pk PRIMARY KEY (id) +); +COMMENT ON TABLE tb_insurance IS '保险信息'; + +-- Column comments + +COMMENT ON COLUMN tb_insurance.vehicle_id IS '所属车辆'; +COMMENT ON COLUMN tb_insurance.project_id IS '所属项目'; +COMMENT ON COLUMN tb_insurance.has_compulsory_insurance IS '是否购买交强险(0,1)'; +COMMENT ON COLUMN tb_insurance.compulsory_insurance_no IS '交强险保险单号'; +COMMENT ON COLUMN tb_insurance.compulsory_create_date IS '交强险办理日期'; +COMMENT ON COLUMN tb_insurance.compulsory_company_id IS '交强险保险公司'; +COMMENT ON COLUMN tb_insurance.compulsory_price IS '交强险保险金额'; +COMMENT ON COLUMN tb_insurance.vehicle_vessel_tax IS '车船税'; +COMMENT ON COLUMN tb_insurance.compulsory_start_time IS '交强险起保日期'; +COMMENT ON COLUMN tb_insurance.compulsory_valid_time IS '交强险有效日期'; +COMMENT ON COLUMN tb_insurance.compulsory_url IS '交强险附件'; +COMMENT ON COLUMN tb_insurance.has_commercial_insurance IS '是否购买商业保险(0,1)'; +COMMENT ON COLUMN tb_insurance.commercial_insurance_no IS '商业保险单号'; +COMMENT ON COLUMN tb_insurance.commercial_create_date IS '商业保险办理日期'; +COMMENT ON COLUMN tb_insurance.commercial_company_id IS '商业保险公司'; +COMMENT ON COLUMN tb_insurance.commercial_price IS '商业保险金额'; +COMMENT ON COLUMN tb_insurance.commercial_start_time IS '商业保险起保日期'; +COMMENT ON COLUMN tb_insurance.commercial_valid_time IS '商业保险有效日期'; +COMMENT ON COLUMN tb_insurance.commercial_url IS '商业保险附件'; +COMMENT ON COLUMN tb_insurance.sys_org_code IS '所属机构'; +COMMENT ON COLUMN tb_insurance.create_time IS '创建时间'; +COMMENT ON COLUMN tb_insurance.update_time IS '更新时间'; +COMMENT ON COLUMN tb_insurance.create_by IS '创建人'; +COMMENT ON COLUMN tb_insurance.update_by IS '更新人'; +COMMENT ON COLUMN tb_insurance.del_flag IS '删除标志'; + +ALTER TABLE tb_insurance ADD vehicle_model varchar(32) NOT NULL; +COMMENT ON COLUMN tb_insurance.vehicle_model IS '车辆型号'; +ALTER TABLE tb_insurance ADD vehicle_type varchar(2) NOT NULL; +COMMENT ON COLUMN tb_insurance.vehicle_type IS '车辆种类'; + +ALTER TABLE tb_insurance ALTER COLUMN vehicle_vessel_tax DROP NOT NULL; +ALTER TABLE tb_insurance ALTER COLUMN compulsory_price DROP NOT NULL; +ALTER TABLE tb_insurance ALTER COLUMN commercial_price DROP NOT NULL; +ALTER TABLE tb_insurance ALTER COLUMN vehicle_model DROP NOT NULL; +ALTER TABLE tb_insurance ALTER COLUMN vehicle_type DROP NOT NULL; +ALTER TABLE tb_insurance ADD remark text NULL; +COMMENT ON COLUMN tb_insurance.remark IS '备注'; + +CREATE TABLE tb_insurance_record ( + id varchar(32) NOT NULL, + vehicle_id varchar(32) NULL, + project_id varchar(32) NULL, + vehicle_model varchar(32) NULL, + vehicle_type varchar(2) NULL, + insurance_date timestamp NULL, + company_id varchar(32) NULL, + insurance_no varchar(32) NULL, + insurance_price float4 NULL DEFAULT 0, + handle_user varchar(32) NULL, + handle_status varchar(2) NULL, + remark text NULL, + accident_url text NULL, + compensate_agreement_url text NULL, + loss_assessment_url text NULL, + compensate_url text NULL, + other_url text NULL, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0, + CONSTRAINT tb_insurance_record_pk PRIMARY KEY (id) +); +COMMENT ON TABLE tb_insurance_record IS '出险管理'; + +-- Column comments + +COMMENT ON COLUMN tb_insurance_record.vehicle_id IS '所属车辆'; +COMMENT ON COLUMN tb_insurance_record.project_id IS '所属项目'; +COMMENT ON COLUMN tb_insurance_record.vehicle_model IS '车辆型号'; +COMMENT ON COLUMN tb_insurance_record.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN tb_insurance_record.insurance_date IS '出险日期'; +COMMENT ON COLUMN tb_insurance_record.company_id IS '保险公司'; +COMMENT ON COLUMN tb_insurance_record.insurance_no IS '理赔案号'; +COMMENT ON COLUMN tb_insurance_record.insurance_price IS '理赔金额'; +COMMENT ON COLUMN tb_insurance_record.handle_user IS '处理人'; +COMMENT ON COLUMN tb_insurance_record.handle_status IS '处理结果'; +COMMENT ON COLUMN tb_insurance_record.remark IS '备注'; +COMMENT ON COLUMN tb_insurance_record.accident_url IS '事故认定书'; +COMMENT ON COLUMN tb_insurance_record.compensate_agreement_url IS '赔偿协议书'; +COMMENT ON COLUMN tb_insurance_record.loss_assessment_url IS '定损单'; +COMMENT ON COLUMN tb_insurance_record.compensate_url IS '赔偿单据'; +COMMENT ON COLUMN tb_insurance_record.other_url IS '其他'; +COMMENT ON COLUMN tb_insurance_record.sys_org_code IS '所属机构'; +COMMENT ON COLUMN tb_insurance_record.create_time IS '创建时间'; +COMMENT ON COLUMN tb_insurance_record.update_time IS '更新时间'; +COMMENT ON COLUMN tb_insurance_record.create_by IS '创建人'; +COMMENT ON COLUMN tb_insurance_record.update_by IS '更新人'; +COMMENT ON COLUMN tb_insurance_record.del_flag IS '删除标志'; + +ALTER TABLE tb_vehicle ADD price float4 NULL DEFAULT 0; +COMMENT ON COLUMN tb_vehicle.price IS '车辆价格'; diff --git a/src/updateSql/update-230925.sql b/src/updateSql/update-230925.sql new file mode 100644 index 0000000..c1c8c99 --- /dev/null +++ b/src/updateSql/update-230925.sql @@ -0,0 +1,129 @@ +-- public.tb_gis_road_mile_log definition + +-- Drop table + +-- DROP TABLE public.tb_gis_road_mile_log; + +CREATE TABLE public.tb_gis_road_mile_log ( + id varchar(32) NOT NULL, + number_plate varchar(32) NOT NULL, -- 车牌号 + project_id varchar(32) NOT NULL, -- 所属项目id + project_name varchar(32) NULL, -- 所属项目名称 + vehicle_brand varchar(2) null,--车辆品牌 + vehicle_model varchar(32) null,--车辆型号 + vehicle_type varchar(2) null,--车辆种类 + vin_code varchar(64) NOT NULL, -- VIN 码 + start_time timestamp NULL, -- 开始时间 + end_time timestamp NULL, -- 结束时间 + power_consume numeric(12, 2) NULL, -- 耗电量 kwh + road_mile numeric(12, 2) NULL, -- 行驶里程 km + energy_consume numeric(12,4),--能耗 kwh + create_time timestamp NOT NULL, -- 入库时间 + CONSTRAINT pk_tb_gis_road_mile_log PRIMARY KEY (id) +); +CREATE INDEX tb_gis_road_mile_log_number_plate_idx ON public.tb_gis_road_mile_log USING btree (number_plate); +COMMENT ON TABLE public.tb_gis_road_mile_log IS '车辆能耗记录表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_gis_road_mile_log.number_plate IS '车牌号'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.project_id IS '所属项目id'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.project_name IS '所属项目名称'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.vehicle_brand IS '车辆品牌'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.vehicle_model IS '车辆型号'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.vin_code IS 'VIN 码'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.start_time IS '开始时间'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.end_time IS '结束时间'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.power_consume IS '耗电量 耗电量 kwh'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.road_mile IS '行驶里程 km'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.energy_consume IS '能耗 kmh/km'; +COMMENT ON COLUMN public.tb_gis_road_mile_log.create_time IS '入库时间'; + +ALTER TABLE public.tb_gis_road_mile_log ADD own_date varchar(10) NULL; +COMMENT ON COLUMN public.tb_gis_road_mile_log.own_date IS '所属日期 例如:2023-06-05'; + +ALTER TABLE public.tb_gis_road_mile_log ALTER COLUMN power_consume SET DEFAULT 0; +ALTER TABLE public.tb_gis_road_mile_log ALTER COLUMN road_mile SET DEFAULT 0; + + +--维修保养表结构调整sql + +ALTER TABLE public.tb_repair_assign ADD sys_org_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_assign.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_repair_assign ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_assign.create_time IS '创建日期'; +ALTER TABLE public.tb_repair_assign ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_assign.update_time IS '更新日期'; +ALTER TABLE public.tb_repair_assign ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_assign.create_by IS '创建人'; +ALTER TABLE public.tb_repair_assign ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_assign.update_by IS '更新人'; + +ALTER TABLE public.tb_repair_check ADD sys_org_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_check.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_repair_check ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_check.create_time IS '创建日期'; +ALTER TABLE public.tb_repair_check ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_check.update_time IS '更新日期'; +ALTER TABLE public.tb_repair_check ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_check.create_by IS '创建人'; +ALTER TABLE public.tb_repair_check ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_check.update_by IS '更新人'; + +ALTER TABLE public.tb_repair_offer ADD sys_org_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_offer.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_repair_offer ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_offer.create_time IS '创建日期'; +ALTER TABLE public.tb_repair_offer ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_repair_offer.update_time IS '更新日期'; +ALTER TABLE public.tb_repair_offer ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_offer.create_by IS '创建人'; +ALTER TABLE public.tb_repair_offer ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_repair_offer.update_by IS '更新人'; + + + +ALTER TABLE public.tb_upkeep_assign ADD sys_org_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_assign.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_upkeep_assign ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_assign.create_time IS '创建日期'; +ALTER TABLE public.tb_upkeep_assign ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_assign.update_time IS '更新日期'; +ALTER TABLE public.tb_upkeep_assign ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_assign.create_by IS '创建人'; +ALTER TABLE public.tb_upkeep_assign ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_assign.update_by IS '更新人'; + +ALTER TABLE public.tb_upkeep_check ADD sys_org_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_check.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_upkeep_check ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_check.create_time IS '创建日期'; +ALTER TABLE public.tb_upkeep_check ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_check.update_time IS '更新日期'; +ALTER TABLE public.tb_upkeep_check ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_check.create_by IS '创建人'; +ALTER TABLE public.tb_upkeep_check ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_check.update_by IS '更新人'; + +ALTER TABLE public.tb_upkeep_plan_check ADD sys_org_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_plan_check.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_upkeep_plan_check ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_plan_check.create_time IS '创建日期'; +ALTER TABLE public.tb_upkeep_plan_check ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_upkeep_plan_check.update_time IS '更新日期'; +ALTER TABLE public.tb_upkeep_plan_check ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_plan_check.create_by IS '创建人'; +ALTER TABLE public.tb_upkeep_plan_check ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_upkeep_plan_check.update_by IS '更新人'; + + +ALTER TABLE public.tb_repair_offer ALTER COLUMN in_repair_img_url TYPE varchar(2048) USING in_repair_img_url::varchar; +ALTER TABLE public.tb_repair_offer ALTER COLUMN after_repair_img_url TYPE varchar(2048) USING after_repair_img_url::varchar; +ALTER TABLE public.tb_repair_offer ALTER COLUMN attachment_url TYPE varchar(2048) USING attachment_url::varchar; + +ALTER TABLE public.tb_upkeep_offer ALTER COLUMN before_upkeep_img_url TYPE varchar(2048) USING before_upkeep_img_url::varchar; +ALTER TABLE public.tb_upkeep_offer ALTER COLUMN in_upkeep_img_url TYPE varchar(2048) USING in_upkeep_img_url::varchar; +ALTER TABLE public.tb_upkeep_offer ALTER COLUMN after_upkeep_img_url TYPE varchar(2048) USING after_upkeep_img_url::varchar; + + diff --git a/src/updateSql/update-231007.sql b/src/updateSql/update-231007.sql new file mode 100644 index 0000000..b204c64 --- /dev/null +++ b/src/updateSql/update-231007.sql @@ -0,0 +1,29 @@ +ALTER TABLE public.tb_vehicle_check ADD sent_vehicle_user_id varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle_check.sent_vehicle_user_id IS '交车人id'; + +ALTER TABLE public.tb_projects DROP CONSTRAINT tb_projects_project_name_key; + +CREATE TABLE public.tb_project_vehicle_bind_log ( + id varchar(32) NOT NULL, -- id + project_id varchar(32) NOT NULL, -- 项目id + project_name varchar(128) NULL, -- 项目名称 + plate_number varchar(16) NOT NULL, -- 车牌号 + bind_type int2 NOT NULL, -- 绑定类型 1-绑定 2-解绑 + bind_source int2 NOT NULL, -- 操作来源 1-车辆操作 2-项目结束 3-项目操作 + create_time timestamp NOT NULL, -- 创建时间 + create_by varchar(32) NULL, -- 创建人 + CONSTRAINT tb_project_vehicle_bind_log_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_project_vehicle_bind_log IS '车辆绑定日志表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.id IS 'id'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.project_id IS '项目id'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.project_name IS '项目名称'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.plate_number IS '车牌号'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.bind_type IS '绑定类型 1-绑定 2-解绑'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.bind_source IS '操作来源 1-车辆操作 2-项目结束 3-项目操作'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_project_vehicle_bind_log.create_by IS '创建人'; + diff --git a/src/updateSql/update-231011.sql b/src/updateSql/update-231011.sql new file mode 100644 index 0000000..5b53355 --- /dev/null +++ b/src/updateSql/update-231011.sql @@ -0,0 +1,64 @@ +-- public.tb_customer_follow_template definition + +-- Drop table + +-- DROP TABLE public.tb_customer_follow_template; + +CREATE TABLE public.tb_customer_follow_template ( + id varchar(32) NOT NULL, -- 主键id + "name" varchar(64) NOT NULL, -- 模板名称 + remark text NULL, -- 备注 + sys_org_code varchar(16) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL, -- 更新人 + CONSTRAINT tb_customer_follow_template_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_customer_follow_template IS '客户回访模板'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_follow_template.id IS '主键id'; +COMMENT ON COLUMN public.tb_customer_follow_template."name" IS '模板名称'; +COMMENT ON COLUMN public.tb_customer_follow_template.remark IS '备注'; +COMMENT ON COLUMN public.tb_customer_follow_template.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_follow_template.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_follow_template.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_follow_template.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_follow_template.update_by IS '更新人'; + + +-- public.tb_customer_follow_template_part definition + +-- Drop table + +-- DROP TABLE public.tb_customer_follow_template_part; + +CREATE TABLE public.tb_customer_follow_template_part ( + id varchar(32) NOT NULL, -- 主键id + category_name varchar(64) NULL, -- 回访类别 + follow_name varchar(64) NULL, -- 回访题目 + sort int2 NOT NULL DEFAULT 1, -- 排序 + template_id varchar(32) NULL, -- 模板id + sys_org_code varchar(16) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL, -- 更新人 + CONSTRAINT tb_customer_follow_template_part_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_customer_follow_template_part IS '客户回放模板详情'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_follow_template_part.id IS '主键id'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.category_name IS '回访类别'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.follow_name IS '回访题目'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.sort IS '排序'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.template_id IS '模板id'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_follow_template_part.update_by IS '更新人'; \ No newline at end of file diff --git a/src/updateSql/update-231014.sql b/src/updateSql/update-231014.sql new file mode 100644 index 0000000..4c6d132 --- /dev/null +++ b/src/updateSql/update-231014.sql @@ -0,0 +1,160 @@ +CREATE TABLE public.tb_customer_follow ( + id varchar(32) NOT NULL, + project_id varchar(32) NULL, + template_part_id varchar(32) NULL, + review_type varchar(2) NULL DEFAULT 1, + review_time timestamp NULL, + remark text NULL, + file_url text NULL, + review_user_id text NULL, + result_status varchar(2) NULL DEFAULT 1, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0, + CONSTRAINT tb_customer_follow_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_customer_follow IS '客户回访台账'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_follow.id IS 'id'; +COMMENT ON COLUMN public.tb_customer_follow.project_id IS '所属项目'; +COMMENT ON COLUMN public.tb_customer_follow.template_part_id IS '回访模板'; +COMMENT ON COLUMN public.tb_customer_follow.review_type IS '回访类型(1上门回访,2电话回访)'; +COMMENT ON COLUMN public.tb_customer_follow.review_time IS '回访时间'; +COMMENT ON COLUMN public.tb_customer_follow.remark IS '备注'; +COMMENT ON COLUMN public.tb_customer_follow.file_url IS '附件'; +COMMENT ON COLUMN public.tb_customer_follow.review_user_id IS '回访人'; +COMMENT ON COLUMN public.tb_customer_follow.result_status IS '回访结果(0未开始,1未完成,2已完成)'; +COMMENT ON COLUMN public.tb_customer_follow.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_follow.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_follow.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_follow.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_follow.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_customer_follow.del_flag IS '删除标志'; + +CREATE TABLE public.tb_customer_follow_part ( + id varchar(32) NOT NULL, + category_name varchar(64) NULL, + follow_name varchar(64) NULL, + sort int2 NOT NULL DEFAULT 1, + template_part_id varchar(32) NULL, + follow_id varchar(32) NULL, + pleased_status varchar(2) NULL, + remark text NULL, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0, + CONSTRAINT tb_customer_follow_part_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_customer_follow_part IS '客户回访详情'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_follow_part.id IS '主键id'; +COMMENT ON COLUMN public.tb_customer_follow_part.category_name IS '回访类别'; +COMMENT ON COLUMN public.tb_customer_follow_part.follow_name IS '回访题目'; +COMMENT ON COLUMN public.tb_customer_follow_part.sort IS '排序'; +COMMENT ON COLUMN public.tb_customer_follow_part.template_part_id IS '回访模板详情id'; +COMMENT ON COLUMN public.tb_customer_follow_part.follow_id IS '回访台账id'; +COMMENT ON COLUMN public.tb_customer_follow_part.pleased_status IS '回访结果(1满意,2不满意)'; +COMMENT ON COLUMN public.tb_customer_follow_part.remark IS '备注'; +COMMENT ON COLUMN public.tb_customer_follow_part.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_follow_part.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_follow_part.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_follow_part.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_follow_part.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_customer_follow_part.del_flag IS '删除标志'; + +ALTER TABLE public.tb_customer_follow ADD follow_no varchar(32) NULL; +COMMENT ON COLUMN public.tb_customer_follow.follow_no IS '回访单号'; +ALTER TABLE public.tb_customer_follow ADD source_type varchar(2) NULL DEFAULT 1; +COMMENT ON COLUMN public.tb_customer_follow.source_type IS '来源(1用户,2计划)'; + +CREATE TABLE public.tb_customer_opinion ( + id varchar(32) NOT NULL, + project_id varchar(32) NULL, + register_time timestamp NULL, + name varchar(64) NULL, + opinion_type varchar(2) NULL DEFAULT 1, + propose_name varchar(32) NULL, + phone varchar(20) NULL, + registrant text NULL, + "content" text NULL, + handle_id varchar(32) NULL, + file_url text NULL, + follow_id varchar(32) NULL, + remark text NULL, + opinion_status varchar(2) NULL DEFAULT 1, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0 +); +COMMENT ON TABLE public.tb_customer_opinion IS '客户反馈意见'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_opinion.id IS 'id'; +COMMENT ON COLUMN public.tb_customer_opinion.project_id IS '所属项目'; +COMMENT ON COLUMN public.tb_customer_opinion.register_time IS '登记时间'; +COMMENT ON COLUMN public.tb_customer_opinion.name IS '意见标题'; +COMMENT ON COLUMN public.tb_customer_opinion.opinion_type IS '意见分类(1客户服务,2服务需求,3其他)'; +COMMENT ON COLUMN public.tb_customer_opinion.propose_name IS '提议人'; +COMMENT ON COLUMN public.tb_customer_opinion.phone IS '联系电话'; +COMMENT ON COLUMN public.tb_customer_opinion.registrant IS '登记人'; +COMMENT ON COLUMN public.tb_customer_opinion."content" IS '意见内容'; +COMMENT ON COLUMN public.tb_customer_opinion.handle_id IS '处理人'; +COMMENT ON COLUMN public.tb_customer_opinion.file_url IS '附件'; +COMMENT ON COLUMN public.tb_customer_opinion.follow_id IS '客户回访id'; +COMMENT ON COLUMN public.tb_customer_opinion.remark IS '备注'; +COMMENT ON COLUMN public.tb_customer_opinion.opinion_status IS '状态(1未完成,2已完成)'; +COMMENT ON COLUMN public.tb_customer_opinion.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_opinion.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_opinion.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_opinion.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_opinion.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_customer_opinion.del_flag IS '删除标志'; + +ALTER TABLE public.tb_customer_opinion ADD CONSTRAINT tb_customer_opinion_pk PRIMARY KEY (id); +CREATE TABLE public.tb_customer_opinion_handle ( + id varchar(32) NOT NULL, + opinion_id varchar(32) NULL, + "content" text NULL, + handle_time timestamp NULL, + pleased_status varchar(2) NULL, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0, + CONSTRAINT tb_customer_opinion_handle_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_customer_opinion_handle IS '客户反馈意见处理'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_opinion_handle.id IS 'id'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.opinion_id IS '客户意见id'; +COMMENT ON COLUMN public.tb_customer_opinion_handle."content" IS '处理方案'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.handle_time IS '处理时间'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.pleased_status IS '客户满意度(1满意,2不满意)'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_customer_opinion_handle.del_flag IS '删除标志'; + +ALTER TABLE public.tb_vehicle_check_project ALTER COLUMN sort DROP NOT NULL; +ALTER TABLE public.tb_vehicle_check_project ALTER COLUMN check_status DROP NOT NULL; + diff --git a/src/updateSql/update-231020.sql b/src/updateSql/update-231020.sql new file mode 100644 index 0000000..954bf0f --- /dev/null +++ b/src/updateSql/update-231020.sql @@ -0,0 +1,612 @@ + +CREATE TABLE public.tb_gis_gps_analysis ( + id varchar(32) NOT NULL, + project_id varchar(32) NOT NULL, -- 所属项目id + number_plate varchar(32) NOT NULL, -- 车牌号 + vehicle_brand varchar(2) NULL, -- 车辆品牌 + vehicle_model varchar(32) NULL, -- 车辆型号 + vehicle_type varchar(2) NULL, -- 车辆种类 + own_date date NOT NULL, -- 所属日期 例如:2023-06-05 + record_type int2 NOT NULL, -- 记录类型 1-行驶未作业 2-行驶作业 3-停靠作业 4-停靠未作业 + start_time timestamp NULL, -- 开始时间 + end_time timestamp NULL, -- 结束时间 + duration int8 NOT NULL DEFAULT 0, -- 时长 + start_mile numeric(12, 2) NULL DEFAULT 0, -- 开始里程 km + end_mile numeric(12, 2) NULL DEFAULT 0, -- 结束里程 km + mile numeric(12, 2) NULL DEFAULT 0, -- 里程 km + start_soc int2 NULL DEFAULT 0, -- 开始soc % + end_soc int2 NULL DEFAULT 0, -- 结束soc % + power_consume numeric(12, 2) NULL DEFAULT 0, -- 耗电量 kwh + create_time timestamp NOT NULL, -- 入库时间 + CONSTRAINT pk_tb_gis_gps_analysis PRIMARY KEY (id) +); +CREATE INDEX tb_gis_gps_analysis_number_plate_idx ON public.tb_gis_gps_analysis USING btree (number_plate, own_date); +COMMENT ON TABLE public.tb_gis_gps_analysis IS '车辆gps记录分析表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_gis_gps_analysis.project_id IS '所属项目id'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.number_plate IS '车牌号'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.vehicle_brand IS '车辆品牌'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.vehicle_model IS '车辆型号'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.own_date IS '所属日期 例如:2023-06-05'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.record_type IS '记录类型 1-行驶未作业 2-行驶作业 3-停靠作业 4-停靠未作业'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.start_time IS '开始时间'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.end_time IS '结束时间'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.duration IS '时长'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.start_mile IS '开始里程 km'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.end_mile IS '结束里程 km'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.mile IS '里程 km'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.start_soc IS '开始soc %'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.end_soc IS '结束soc %'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.power_consume IS '耗电量 kwh'; +COMMENT ON COLUMN public.tb_gis_gps_analysis.create_time IS '入库时间'; + + +ALTER TABLE public.tb_gis_gps_analysis ADD battery_capacity numeric(12, 2) NULL DEFAULT 0; +COMMENT ON COLUMN public.tb_gis_gps_analysis.battery_capacity IS '电池容量kwh'; + + + + +-- 增加gps表状态 +ALTER TABLE public.tb_gis_gps ADD is_work int2 NULL DEFAULT 0; + +-- 增加gps表状态 +ALTER TABLE public.tb_gis_runningbus ADD is_work int2 NULL DEFAULT -1; +COMMENT ON COLUMN public.tb_gis_runningbus.is_work IS '是否作业 0-否 1-是 -1无效'; + +-- 客户培训 +-- public.tb_customer_training definition + +-- Drop table + +-- DROP TABLE public.tb_customer_training; + +CREATE TABLE public.tb_customer_training ( + id varchar(32) NOT NULL, -- 主键id + sys_org_code varchar(16) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL, -- 更新人 + project_id varchar(32) NULL, -- 所属项目 + contract_no varchar(64) NULL, -- 合同编号 + expected_start_time timestamp NULL, -- 预计开始时间 + training_type varchar(64) NULL, -- 培训类型 + trainees varchar(64) NULL, -- 培训对象 + actual_start_time timestamp NULL, -- 实际开始时间 + actual_end_time timestamp NULL, -- 培训结束时间 + lecturer varchar(64) NULL, -- 授课人 + teaching_content varchar(1024) NULL, -- 授课内容 + attachment text NULL, -- 附件 + CONSTRAINT tb_customer_training_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_customer_training IS '客户培训'; + +-- Column comments + +COMMENT ON COLUMN public.tb_customer_training.id IS '主键id'; +COMMENT ON COLUMN public.tb_customer_training.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_customer_training.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_customer_training.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_customer_training.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_customer_training.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_customer_training.project_id IS '所属项目'; +COMMENT ON COLUMN public.tb_customer_training.contract_no IS '合同编号'; +COMMENT ON COLUMN public.tb_customer_training.expected_start_time IS '预计开始时间'; +COMMENT ON COLUMN public.tb_customer_training.training_type IS '培训类型'; +COMMENT ON COLUMN public.tb_customer_training.trainees IS '培训对象'; +COMMENT ON COLUMN public.tb_customer_training.actual_start_time IS '实际开始时间'; +COMMENT ON COLUMN public.tb_customer_training.actual_end_time IS '培训结束时间'; +COMMENT ON COLUMN public.tb_customer_training.lecturer IS '授课人'; +COMMENT ON COLUMN public.tb_customer_training.teaching_content IS '授课内容'; +COMMENT ON COLUMN public.tb_customer_training.attachment IS '附件'; + + +-- public.tb_inspection_task definition + +-- Drop table + +-- DROP TABLE public.tb_inspection_task; + +CREATE TABLE public.tb_inspection_task ( + id varchar(32) NOT NULL, -- 主键id + sys_org_code varchar(16) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL, -- 更新人 + inspection_time timestamp NULL, -- 巡检时间 + inspection_type varchar(2) NULL, -- 巡检类型 1-线上巡检 2-回访巡检 + inspection_template_id varchar(32) NULL, -- 巡检项目Id + handle_plan varchar(512) NULL, -- 处理方案 + handle_type varchar(2) NULL, -- 处理结果 + handle_time timestamp NULL, -- 处理时间 + source_type varchar(2) NULL DEFAULT 1, -- 来源(1用户,2计划) + inspection_result varchar(2) NULL, -- 巡检结果 + remark varchar(512) NULL, -- 备注 + attachment text NULL, -- 附件 + follow_id varchar(32) NULL, -- 回访台账id + inspection_user_id varchar(32) NULL, -- 处理人 + CONSTRAINT tb_inspection_records_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_inspection_task IS '巡检任务'; + +-- Column comments + +COMMENT ON COLUMN public.tb_inspection_task.id IS '主键id'; +COMMENT ON COLUMN public.tb_inspection_task.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_inspection_task.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_inspection_task.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_inspection_task.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_inspection_task.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_inspection_task.inspection_time IS '巡检时间'; +COMMENT ON COLUMN public.tb_inspection_task.inspection_type IS '巡检类型 1-线上巡检 2-回访巡检'; +COMMENT ON COLUMN public.tb_inspection_task.inspection_template_id IS '巡检项目Id'; +COMMENT ON COLUMN public.tb_inspection_task.handle_plan IS '处理方案'; +COMMENT ON COLUMN public.tb_inspection_task.handle_type IS '处理结果'; +COMMENT ON COLUMN public.tb_inspection_task.handle_time IS '处理时间'; +COMMENT ON COLUMN public.tb_inspection_task.source_type IS '来源(1用户,2计划)'; +COMMENT ON COLUMN public.tb_inspection_task.inspection_result IS '巡检结果'; +COMMENT ON COLUMN public.tb_inspection_task.remark IS '备注'; +COMMENT ON COLUMN public.tb_inspection_task.attachment IS '附件'; +COMMENT ON COLUMN public.tb_inspection_task.follow_id IS '回访台账id'; +COMMENT ON COLUMN public.tb_inspection_task.inspection_user_id IS '处理人'; + + +-- public.tb_inspection_task_part definition + +-- Drop table + +-- DROP TABLE public.tb_inspection_task_part; + +CREATE TABLE public.tb_inspection_task_part ( + id varchar(32) NOT NULL, -- 主键id + sys_org_code varchar(16) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL, -- 更新人 + "name" varchar(64) NULL, -- 巡检项目 + "content" varchar(64) NULL, -- 巡检内容 + sort int2 NOT NULL DEFAULT 1, -- 排序 + normal varchar(2) NULL DEFAULT 1, -- 是否正常 1-正常 0-不正常 + remark varchar(512) NULL, -- 备注 + task_id varchar(32) NULL, -- 巡检任务id + CONSTRAINT tb_inspection_task_part_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_inspection_task_part IS '巡检任务关联信息'; + +-- Column comments + +COMMENT ON COLUMN public.tb_inspection_task_part.id IS '主键id'; +COMMENT ON COLUMN public.tb_inspection_task_part.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_inspection_task_part.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_inspection_task_part.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_inspection_task_part.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_inspection_task_part.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_inspection_task_part."name" IS '巡检项目'; +COMMENT ON COLUMN public.tb_inspection_task_part."content" IS '巡检内容'; +COMMENT ON COLUMN public.tb_inspection_task_part.sort IS '排序'; +COMMENT ON COLUMN public.tb_inspection_task_part.normal IS '是否正常 1-正常 0-不正常'; +COMMENT ON COLUMN public.tb_inspection_task_part.remark IS '备注'; +COMMENT ON COLUMN public.tb_inspection_task_part.task_id IS '巡检任务id'; + + +-- public.tb_inspection_task_project definition + +-- Drop table + +-- DROP TABLE public.tb_inspection_task_project; + +CREATE TABLE public.tb_inspection_task_project ( + id varchar(32) NOT NULL, -- 主键id + inspection_task_id varchar(32) NULL, -- 巡检任务Id + project_id varchar(32) NULL, -- 项目Id + CONSTRAINT tb_inspection_task_project_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_inspection_task_project IS '巡检项目关联id'; + +-- Column comments + +COMMENT ON COLUMN public.tb_inspection_task_project.id IS '主键id'; +COMMENT ON COLUMN public.tb_inspection_task_project.inspection_task_id IS '巡检任务Id'; +COMMENT ON COLUMN public.tb_inspection_task_project.project_id IS '项目Id'; + + +-- public.tb_inspection_task_vehicle definition + +-- Drop table + +-- DROP TABLE public.tb_inspection_task_vehicle; + +CREATE TABLE public.tb_inspection_task_vehicle ( + id varchar(32) NOT NULL, -- 主键id + vehicle_id varchar(32) NULL, -- 车辆Id + inspection_task_id varchar(32) NULL, -- 巡检任务Id + CONSTRAINT tb_inspection_task_vehicle_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_inspection_task_vehicle IS '巡检任务关联车辆'; + +-- Column comments + +COMMENT ON COLUMN public.tb_inspection_task_vehicle.id IS '主键id'; +COMMENT ON COLUMN public.tb_inspection_task_vehicle.vehicle_id IS '车辆Id'; +COMMENT ON COLUMN public.tb_inspection_task_vehicle.inspection_task_id IS '巡检任务Id'; + +-- public.tb_scheduled_plan definition + +-- Drop table + +-- DROP TABLE public.tb_scheduled_plan; + +CREATE TABLE public.tb_scheduled_plan ( + id varchar(32) NOT NULL, -- id + sys_org_code varchar(32) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + create_by varchar(32) NULL, -- 创建人 + update_time timestamp NULL, -- 更新时间 + update_by varchar(32) NULL, -- 更新人 + cron_expression varchar(32) NULL, -- cron表达式 + frequency_type varchar(2) NULL, -- 频率类型标识 + project_id text NULL, -- 关联项目 + plan_type varchar(2) NULL, -- 定时任务类型 + CONSTRAINT tb_scheduled_plan_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_scheduled_plan IS '定时任务记录表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_scheduled_plan.id IS 'id'; +COMMENT ON COLUMN public.tb_scheduled_plan.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_scheduled_plan.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_scheduled_plan.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_scheduled_plan.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_scheduled_plan.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_scheduled_plan.cron_expression IS 'cron表达式'; +COMMENT ON COLUMN public.tb_scheduled_plan.frequency_type IS '频率类型标识'; +COMMENT ON COLUMN public.tb_scheduled_plan.project_id IS '关联项目'; +COMMENT ON COLUMN public.tb_scheduled_plan.plan_type IS '定时任务类型'; + + + +ALTER TABLE public.tb_contract ADD goods_name varchar(256) NULL; +COMMENT ON COLUMN public.tb_contract.goods_name IS '货物名称'; + +CREATE TABLE public.tb_contract_vehicle ( + id varchar(32) NULL, + contract_id varchar(32) NULL, + vehicle_brand varchar(32) NULL, + vehicle_model varchar(32) NULL, + vehicle_type varchar(32) NULL, + quantity int4 NULL, + total_price numeric(10, 2) NULL +); +COMMENT ON TABLE public.tb_contract_vehicle IS '合同车辆细项表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_contract_vehicle.id IS '主键id'; +COMMENT ON COLUMN public.tb_contract_vehicle.contract_id IS '合同id'; +COMMENT ON COLUMN public.tb_contract_vehicle.vehicle_brand IS '车辆品牌'; +COMMENT ON COLUMN public.tb_contract_vehicle.vehicle_model IS '车辆型号'; +COMMENT ON COLUMN public.tb_contract_vehicle.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_contract_vehicle.quantity IS '数量'; +COMMENT ON COLUMN public.tb_contract_vehicle.total_price IS '单价(万元含税)'; + + +ALTER TABLE public.tb_insurance_company_archives ADD "type" varchar(16) NULL; +COMMENT ON COLUMN public.tb_insurance_company_archives."type" IS '供应商类型'; +ALTER TABLE public.tb_insurance_company_archives ADD remark varchar(256) NULL; +COMMENT ON COLUMN public.tb_insurance_company_archives.remark IS '备注'; + +ALTER TABLE public.tb_repair_shop_archives ADD "type" varchar(16) NULL; +COMMENT ON COLUMN public.tb_repair_shop_archives."type" IS '供应商类型'; +ALTER TABLE public.tb_repair_shop_archives ADD remark varchar(256) NULL; +COMMENT ON COLUMN public.tb_repair_shop_archives.remark IS '备注'; + +ALTER TABLE public.tb_vehicle_supplier_archives ADD "type" varchar(16) NULL; +COMMENT ON COLUMN public.tb_vehicle_supplier_archives."type" IS '供应商类型'; +ALTER TABLE public.tb_vehicle_supplier_archives ADD remark varchar(256) NULL; + + +-- public.tb_vehicle_cost definition + +-- Drop table + +-- DROP TABLE public.tb_vehicle_cost; + +CREATE TABLE public.tb_vehicle_cost ( + id varchar(32) NULL, -- id + vehicle_type varchar(100) NULL, -- 车辆种类 + unit_price numeric(10, 4) NULL, -- 单价(万元) + purchase_tax numeric(10, 4) NULL, -- 上牌费用/购置税(万元) + insurance numeric(10, 4) NULL, -- 保险(万元/台/年) + repair numeric(10, 4) NULL, -- 维修及易损件(万元) + upkeep numeric(10, 4) NULL, -- 保养(万元) + annual_audit numeric(10, 4) NULL, -- 年审(万元) + one_year numeric(10, 4) NULL, -- 第一年 + two_year numeric(10, 4) NULL, -- 第二年 + three_year numeric(10, 4) NULL, -- 第三年 + four_year numeric(10, 4) NULL, -- 第四年 + five_year numeric(10, 4) NULL, -- 第五年 + six_year numeric(10, 4) NULL, -- 第六年 + seven_year numeric(10, 4) NULL, -- 第七年 + eight_year numeric(10, 4) NULL, -- 第八年 + sys_org_code varchar(32) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL -- 更新人 +); +COMMENT ON TABLE public.tb_vehicle_cost IS '车辆成本表对'; + +-- Column comments + +COMMENT ON COLUMN public.tb_vehicle_cost.id IS 'id'; +COMMENT ON COLUMN public.tb_vehicle_cost.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_vehicle_cost.unit_price IS '单价(万元)'; +COMMENT ON COLUMN public.tb_vehicle_cost.purchase_tax IS '上牌费用/购置税(万元)'; +COMMENT ON COLUMN public.tb_vehicle_cost.insurance IS '保险(万元/台/年)'; +COMMENT ON COLUMN public.tb_vehicle_cost.repair IS '维修及易损件(万元)'; +COMMENT ON COLUMN public.tb_vehicle_cost.upkeep IS '保养(万元)'; +COMMENT ON COLUMN public.tb_vehicle_cost.annual_audit IS '年审(万元)'; +COMMENT ON COLUMN public.tb_vehicle_cost.one_year IS '第一年'; +COMMENT ON COLUMN public.tb_vehicle_cost.two_year IS '第二年'; +COMMENT ON COLUMN public.tb_vehicle_cost.three_year IS '第三年'; +COMMENT ON COLUMN public.tb_vehicle_cost.four_year IS '第四年'; +COMMENT ON COLUMN public.tb_vehicle_cost.five_year IS '第五年'; +COMMENT ON COLUMN public.tb_vehicle_cost.six_year IS '第六年'; +COMMENT ON COLUMN public.tb_vehicle_cost.seven_year IS '第七年'; +COMMENT ON COLUMN public.tb_vehicle_cost.eight_year IS '第八年'; +COMMENT ON COLUMN public.tb_vehicle_cost.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_vehicle_cost.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_vehicle_cost.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_vehicle_cost.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_vehicle_cost.update_by IS '更新人'; + + +-- public.tb_finance_base definition + +-- Drop table + +-- DROP TABLE public.tb_finance_base; + +CREATE TABLE public.tb_finance_base ( + id varchar(32) NULL, -- id + project_id varchar(32) NULL, -- 项目id + year_limit int2 NULL, -- 租赁年限 + financing_ratio numeric(10, 4) NULL, -- 融资比例 + financing_rate numeric(10, 4) NULL, -- 融资利率(%) + overhead_sharing numeric(10, 4) NULL, -- 管理费用分担(%) + sys_org_code varchar(32) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL -- 更新人 +); +COMMENT ON TABLE public.tb_finance_base IS '财务测算基本表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_finance_base.id IS 'id'; +COMMENT ON COLUMN public.tb_finance_base.project_id IS '项目id'; +COMMENT ON COLUMN public.tb_finance_base.year_limit IS '租赁年限'; +COMMENT ON COLUMN public.tb_finance_base.financing_ratio IS '融资比例'; +COMMENT ON COLUMN public.tb_finance_base.financing_rate IS '融资利率(%)'; +COMMENT ON COLUMN public.tb_finance_base.overhead_sharing IS '管理费用分担(%)'; +COMMENT ON COLUMN public.tb_finance_base.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_finance_base.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_finance_base.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_finance_base.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_finance_base.update_by IS '更新人'; + + + +-- public.tb_finance_measure_result definition + +-- Drop table + +-- DROP TABLE public.tb_finance_measure_result; + +CREATE TABLE public.tb_finance_measure_result ( + id varchar(32) NULL, -- id + base_id varchar(32) NULL, -- 基础表id + car_cost_recovery numeric(10, 4) NULL, -- 购车成本回收期(年) + financing_cost numeric(10, 4) NULL, -- 融资成本(万元) + internal_rate numeric(10, 4) NULL, -- 内部收益率(%) + vat_and_additional numeric(10, 4) NULL, -- 实缴增值税及附加(万元) + income_tax numeric(10, 4) NULL, -- 所得税(万元) + net_profit numeric(10, 4) NULL, -- 净利润(万元) + salvage_value numeric(10, 4) NULL, -- 残值(万元) + rental_income_json text NULL, -- 租金收入(万元) + manage_cost_json text NULL, -- 管理、运维、保险费用(万元) + income_and_tax_json text NULL, -- 收入与税金表(万元) + cost_and_profit_json text NULL -- 成本与利润表(万元) +); +COMMENT ON TABLE public.tb_finance_measure_result IS '财务测算测算结果关联表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_finance_measure_result.id IS 'id'; +COMMENT ON COLUMN public.tb_finance_measure_result.base_id IS '基础表id'; +COMMENT ON COLUMN public.tb_finance_measure_result.car_cost_recovery IS '购车成本回收期(年)'; +COMMENT ON COLUMN public.tb_finance_measure_result.financing_cost IS '融资成本(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.internal_rate IS '内部收益率(%)'; +COMMENT ON COLUMN public.tb_finance_measure_result.vat_and_additional IS '实缴增值税及附加(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.income_tax IS '所得税(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.net_profit IS '净利润(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.salvage_value IS '残值(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.rental_income_json IS '租金收入(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.manage_cost_json IS '管理、运维、保险费用(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.income_and_tax_json IS '收入与税金表(万元)'; +COMMENT ON COLUMN public.tb_finance_measure_result.cost_and_profit_json IS '成本与利润表(万元)'; + + + +-- public.tb_finance_vehicle_cost definition + +-- Drop table + +-- DROP TABLE public.tb_finance_vehicle_cost; + +CREATE TABLE public.tb_finance_vehicle_cost ( + id varchar(32) NULL, -- id + base_id varchar(32) NULL, -- 基础表id + vehicle_type varchar(100) NULL, -- 车辆种类 + unit_price numeric(10, 4) NULL, -- 单价(万元) + purchase_tax numeric(10, 4) NULL, -- 上牌费用/购置税(万元) + insurance numeric(10, 4) NULL, -- 保险(万元/台/年) + repair numeric(10, 4) NULL, -- 维修及易损件(万元) + upkeep numeric(10, 4) NULL, -- 保养(万元) + annual_audit numeric(10, 4) NULL, -- 年审(万元) + quantity int4 NULL, -- 数量 + salvage_value numeric(10, 4) NULL, -- 残值(万元/台) + one_year numeric(10, 4) NULL, -- 第一年 + two_year numeric(10, 4) NULL, -- 第二年 + three_year numeric(10, 4) NULL, -- 第三年 + four_year numeric(10, 4) NULL, -- 第四年 + five_year numeric(10, 4) NULL, -- 第五年 + six_year numeric(10, 4) NULL, -- 第六年 + seven_year numeric(10, 4) NULL, -- 第七年 + eight_year numeric(10, 4) NULL -- 第八年 +); +COMMENT ON TABLE public.tb_finance_vehicle_cost IS '财务测算车辆费用关联表'; + +-- Column comments + +COMMENT ON COLUMN public.tb_finance_vehicle_cost.id IS 'id'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.base_id IS '基础表id'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.unit_price IS '单价(万元)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.purchase_tax IS '上牌费用/购置税(万元)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.insurance IS '保险(万元/台/年)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.repair IS '维修及易损件(万元)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.upkeep IS '保养(万元)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.annual_audit IS '年审(万元)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.quantity IS '数量'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.salvage_value IS '残值(万元/台)'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.one_year IS '第一年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.two_year IS '第二年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.three_year IS '第三年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.four_year IS '第四年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.five_year IS '第五年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.six_year IS '第六年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.seven_year IS '第七年'; +COMMENT ON COLUMN public.tb_finance_vehicle_cost.eight_year IS '第八年'; + + +CREATE TABLE public.tb_project_user_rel ( + id varchar(32) NOT NULL, + project_id varchar(32) NULL, -- 项目id + user_id varchar(32) NULL, -- 用户id + create_time timestamp(6) NULL, -- 创建时间 + create_by varchar(32) NULL, -- 创建人 + update_time timestamp(6) NULL, -- 更新时间 + update_by varchar(32) NULL, -- 更新人 + CONSTRAINT tb_project_user_pkey PRIMARY KEY (id) +); + +-- Column comments + +COMMENT ON COLUMN public.tb_project_user_rel.project_id IS '项目id'; +COMMENT ON COLUMN public.tb_project_user_rel.user_id IS '用户id'; +COMMENT ON COLUMN public.tb_project_user_rel.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_project_user_rel.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_project_user_rel.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_project_user_rel.update_by IS '更新人'; + + +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714833496767037441', '1702865172494635010', '保养', '', NULL, NULL, NULL, 2, 'UpkeepBill:repairing', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:39:00.351', 'adminLeader', '2023-10-19 10:39:00.351', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714833190222135298', '1702865172494635010', '审核', '', NULL, NULL, NULL, 2, 'UpkeepBill:checkOffer', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:37:47.265', 'adminLeader', '2023-10-19 10:37:47.265', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714833017202900993', '1702865172494635010', '报价', '', NULL, NULL, NULL, 2, 'UpkeepBill:offer', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:37:06.015', 'adminLeader', '2023-10-19 10:37:06.015', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714832922499710977', '1702865172494635010', '派单', '', NULL, NULL, NULL, 2, 'UpkeepBill:send', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:36:43.435', 'adminLeader', '2023-10-19 10:36:43.435', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714827702247981057', '1702611066496593922', '作废', '', NULL, NULL, NULL, 2, 'UpkeepPlan:cancel', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:15:58.830', 'adminLeader', '2023-10-19 10:15:58.830', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714827627677450242', '1702611066496593922', '编辑', '', NULL, NULL, NULL, 2, 'UpkeepPlan:edit', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:15:41.051', 'adminLeader', '2023-10-19 10:15:41.051', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714827144829173761', '1702611066496593922', '审批', '', NULL, NULL, NULL, 2, 'UpkeepPlan:leaderCheckOffer', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:13:45.930', 'yubowen', '2023-10-19 15:48:23.563', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714826902809444353', '1702611066496593922', '查看', '', NULL, NULL, NULL, 2, 'UpkeepPlan:view', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 10:12:48.227', 'adminLeader', '2023-10-19 10:14:16.975', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714814366764589057', '1701116944293138433', '作废', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:cancel', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:22:59.403', 'adminLeader', '2023-10-19 09:33:53.865', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714813971195584514', '1701116944293138433', '查看', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:view', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:21:25.091', 'adminLeader', '2023-10-19 09:34:11.531', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714813702047096834', '1701116944293138433', '确认', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:confirmResult', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:20:20.922', 'adminLeader', '2023-10-19 09:33:38.318', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714813480818532354', '1701116944293138433', '维修', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:repairing', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:19:28.174', 'adminLeader', '2023-10-19 09:30:13.278', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714813300861919233', '1701116944293138433', '审批', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:leaderCheckOffer', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:18:45.272', 'adminLeader', '2023-10-19 09:54:38.216', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714813137841905665', '1701116944293138433', '审核', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:checkOffer', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:18:06.406', 'adminLeader', '2023-10-19 09:30:01.648', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714812828595871746', '1701116944293138433', '报价', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:offer', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:16:52.675', 'adminLeader', '2023-10-19 09:54:23.853', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714812708307427330', '1701116944293138433', '派单', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:send', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:16:23.997', 'adminLeader', '2023-10-19 09:29:33.327', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1714812533069406209', '1701116944293138433', '提交', '', NULL, NULL, NULL, 2, 'VehiclesMaintain:submit', '1', 1.0, NULL, 1, NULL, '1', NULL, NULL, 'adminLeader', '2023-10-19 09:15:42.215', 'adminLeader', '2023-10-19 09:29:51.689', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1713743963266781186', '1712281696415252481', '车辆巡检', '/customerService/inspection', 'customerService/inspection/index', NULL, NULL, 1, NULL, NULL, 0.0, 'DocumentChecked', 0, NULL, NULL, NULL, NULL, 'chenyufeng', '2023-10-16 10:29:35.320', 'chenyufeng', '2023-10-16 10:29:35.320', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1713740570959912961', '1712281696415252481', '客户回访', '/customerService/follow', 'customerService/follow/index', NULL, NULL, 1, NULL, NULL, 0.0, 'Handbag', 1, NULL, NULL, NULL, NULL, 'chenyufeng', '2023-10-16 10:16:06.531', 'chenyufeng', '2023-10-16 10:16:06.531', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1712311358352785409', '1712281696415252481', '意见反馈', '/customerService/feedback', 'customerService/feedback/index', NULL, NULL, 1, NULL, NULL, 3.0, 'Warning', 0, NULL, NULL, NULL, NULL, 'chenyufeng', '2023-10-12 11:36:55.694', 'chenyufeng', '2023-10-12 11:37:07.981', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1712282149702074369', '1712281696415252481', '客户培训', '/customerService/training', 'customerService/training/index', NULL, NULL, 1, NULL, NULL, 0.0, 'Finished', 1, NULL, NULL, NULL, NULL, 'chenyufeng', '2023-10-12 09:40:51.809', 'chenyufeng', '2023-10-16 09:41:13.024', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1712281696415252481', '', '客户服务', '/customerService', NULL, NULL, NULL, 0, NULL, NULL, 4.0, 'Dessert', 0, NULL, NULL, NULL, NULL, 'chenyufeng', '2023-10-12 09:39:03.738', 'weibao_leader', '2023-10-18 15:19:28.807', 0, 0); +INSERT INTO public.sys_permission (id, parent_id, "name", url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1711946741130723329', '1699702223404421121', '客户回访模板', '/baseData/Template/CustomerFollowTemplate', 'baseData/Template/CustomerFollowTemplate/index', NULL, NULL, 1, NULL, NULL, 0.0, 'Tickets', 1, NULL, NULL, NULL, NULL, 'chenyufeng', '2023-10-11 11:28:04.173', 'chenyufeng', '2023-10-16 09:27:24.623', 0, 0); + + +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1714535024125841409', '频率类型', 'frequency_type', '每周1; +每月2; +每月两次3; +每半年4; +每年5;', 0, 'chenyufeng', '2023-10-18 14:52:58.928', 'chenyufeng', '2023-10-20 17:23:45.521', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1714197385170423810', '结果状态2', 'opinion_status', '1未完成,2已完成', 0, 'admin', '2023-10-17 16:31:19.528', 'admin', '2023-10-18 16:01:47.998', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1714153961331396609', '供应商类型', 'supplier_type', '', 0, 'adminLeader', '2023-10-17 13:38:46.478', 'adminLeader', '2023-10-17 13:38:46.478', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1714123765605765122', '巡检类型', 'inspection_type', '', 0, 'chenyufeng', '2023-10-17 11:38:47.256', 'chenyufeng', '2023-10-17 11:38:47.256', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1714121501826650113', '客户满意度', 'pleased_status', '1满意,2不满意', 0, 'admin', '2023-10-17 11:29:47.529', 'admin', '2023-10-17 11:29:47.529', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1714121063924535298', '意见分类', 'opinion_type', '1客户服务,2服务需求,3其他', 0, 'admin', '2023-10-17 11:28:03.125', 'admin', '2023-10-17 11:28:03.125', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1713892858458312705', '巡检结果', 'inspection_result', '', 0, 'chenyufeng', '2023-10-16 20:21:14.702', 'chenyufeng', '2023-10-16 20:21:14.702', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1713106236410273793', '回访方式', 'review_type', '', 0, 'admin', '2023-10-14 16:15:29.391', 'admin', '2023-10-14 16:15:29.391', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1713105899179843585', '结果状态', 'result_status', '0未开始,1未完成,2已完成', 0, 'admin', '2023-10-14 16:14:08.988', 'admin', '2023-10-17 11:31:09.387', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1712430019545661441', '事件分类', 'event_category', '', 0, 'weibao_1', '2023-10-12 19:28:26.727', 'weibao_1', '2023-10-12 19:28:26.727', 0); +INSERT INTO public.sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1710856749092507650', '项目状态', 'project_status', '', 0, 'weibao_leader', '2023-10-08 11:16:49.821', NULL, '2023-10-08 11:16:49.821', 0); + + +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1716369065439461377', '1698869263734734849', 'BB', '16', NULL, NULL, 1, 'weibao_leader', '2023-10-23 16:20:48.452', 'weibao_leader', '2023-10-23 16:20:48.452'); + +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714573090558410754', '1697444619626110978', '其它', '99', '', 99, 1, 'weibao_1', '2023-10-18 17:24:14.679', 'weibao_1', '2023-10-18 17:24:14.679'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714535530558689282', '1714535024125841409', '每年', '5', '', 5, 1, 'chenyufeng', '2023-10-18 14:54:59.671', 'chenyufeng', '2023-10-18 14:54:59.671'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714535487881646081', '1714535024125841409', '每半年', '4', '', 4, 1, 'chenyufeng', '2023-10-18 14:54:49.496', 'chenyufeng', '2023-10-18 14:54:49.496'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714535284147523586', '1714535024125841409', '每月两次', '3', '', 3, 1, 'chenyufeng', '2023-10-18 14:54:00.922', 'chenyufeng', '2023-10-18 14:54:00.922'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714535225548902401', '1714535024125841409', '每月', '2', '', 2, 1, 'chenyufeng', '2023-10-18 14:53:46.951', 'chenyufeng', '2023-10-18 14:53:46.951'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714535143369904130', '1714535024125841409', '每周', '1', '', 1, 1, 'chenyufeng', '2023-10-18 14:53:27.359', 'chenyufeng', '2023-10-18 14:53:27.359'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714534846773891073', '1714534762803924993', '巡检任务', '2', '', 2, 1, 'chenyufeng', '2023-10-18 14:52:16.645', 'chenyufeng', '2023-10-18 14:52:16.645'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714534804386254850', '1714534762803924993', '客户回访', '1', '', 1, 1, 'chenyufeng', '2023-10-18 14:52:06.538', 'chenyufeng', '2023-10-18 14:52:06.538'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714197479441600513', '1714197385170423810', '已完成', '2', '', 2, 1, 'admin', '2023-10-17 16:31:42.004', 'admin', '2023-10-17 16:31:42.004'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714197436600979458', '1714197385170423810', '未完成', '1', '', 1, 1, 'admin', '2023-10-17 16:31:31.790', 'admin', '2023-10-17 16:31:31.790'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714193559134703618', '1714153961331396609', '车辆供应商', '3', '', 3, 1, 'adminLeader', '2023-10-17 16:16:07.330', 'adminLeader', '2023-10-17 16:16:07.330'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714154125404180482', '1714153961331396609', '其它', '9', '', 9, 1, 'adminLeader', '2023-10-17 13:39:25.596', 'adminLeader', '2023-10-17 13:39:25.596'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714154064070873089', '1714153961331396609', '保险公司', '2', '', 2, 1, 'adminLeader', '2023-10-17 13:39:10.973', 'adminLeader', '2023-10-17 13:39:10.973'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714154010924847106', '1714153961331396609', '维修厂', '1', '', 1, 1, 'adminLeader', '2023-10-17 13:38:58.302', 'adminLeader', '2023-10-17 13:38:58.302'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714130273303302145', '1697501565750706177', '其它', '9', '', 9, 1, 'adminLeader', '2023-10-17 12:04:38.812', 'adminLeader', '2023-10-17 12:04:38.812'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714123867535740929', '1714123765605765122', '回访巡检', '2', '', 1, 1, 'chenyufeng', '2023-10-17 11:39:11.558', 'chenyufeng', '2023-10-17 11:39:11.558'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714123827140399105', '1714123765605765122', '线上巡检', '1', '', 1, 1, 'chenyufeng', '2023-10-17 11:39:01.927', 'chenyufeng', '2023-10-17 11:39:01.927'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714121592859824129', '1714121501826650113', '不满意', '2', '', 2, 1, 'admin', '2023-10-17 11:30:09.234', 'admin', '2023-10-17 11:30:09.234'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714121554154786818', '1714121501826650113', '满意', '1', '', 1, 1, 'admin', '2023-10-17 11:30:00.003', 'admin', '2023-10-17 11:30:00.003'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714121230249660418', '1714121063924535298', '其他', '3', '', 3, 1, 'admin', '2023-10-17 11:28:42.781', 'admin', '2023-10-17 11:28:42.781'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714121188667330561', '1714121063924535298', '服务需求', '2', '', 2, 1, 'admin', '2023-10-17 11:28:32.867', 'admin', '2023-10-17 11:28:32.867'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1714121139182931970', '1714121063924535298', '客户服务', '1', '', 1, 1, 'admin', '2023-10-17 11:28:21.069', 'admin', '2023-10-17 11:28:21.069'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713892959318740994', '1713892858458312705', '不合格', '0', '', 1, 1, 'chenyufeng', '2023-10-16 20:21:38.749', 'chenyufeng', '2023-10-16 20:21:38.749'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713892910576734209', '1713892858458312705', '合格', '1', '', 1, 1, 'chenyufeng', '2023-10-16 20:21:27.127', 'chenyufeng', '2023-10-16 20:21:27.127'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713793205385650177', '1713793008228196353', '已完成', '2', '', 2, 1, 'chenyufeng', '2023-10-16 13:45:15.558', 'chenyufeng', '2023-10-16 13:45:15.558'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713793166034690049', '1713793008228196353', '未完成', '1', '', 1, 1, 'chenyufeng', '2023-10-16 13:45:06.176', 'chenyufeng', '2023-10-16 13:45:06.176'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713793128587943938', '1713793008228196353', '未开始', '0', '', 1, 1, 'chenyufeng', '2023-10-16 13:44:57.248', 'chenyufeng', '2023-10-16 13:44:57.248'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713106325744754690', '1713106236410273793', '电话回访', '2', '', 2, 1, 'admin', '2023-10-14 16:15:50.690', 'admin', '2023-10-14 16:15:50.690'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713106285060005889', '1713106236410273793', '上门回访', '1', '', 1, 1, 'admin', '2023-10-14 16:15:40.990', 'admin', '2023-10-14 16:15:40.990'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713106135755366402', '1713105899179843585', '已完成', '2', '', 3, 1, 'admin', '2023-10-14 16:15:05.393', 'admin', '2023-10-14 16:15:05.393'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713106081929863170', '1713105899179843585', '未完成', '1', '', 2, 1, 'admin', '2023-10-14 16:14:52.561', 'admin', '2023-10-14 16:14:52.561'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1713106000287735809', '1713105899179843585', '未开始', '0', '', 1, 1, 'admin', '2023-10-14 16:14:33.094', 'admin', '2023-10-14 16:14:33.094'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1712430131571326978', '1712430019545661441', '其它', '10', '', 1, 1, 'weibao_1', '2023-10-12 19:28:53.436', 'weibao_1', '2023-10-12 19:28:53.436'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1712430083458465794', '1712430019545661441', '特情类', '2', '', 1, 1, 'weibao_1', '2023-10-12 19:28:41.965', 'weibao_1', '2023-10-12 19:28:41.965'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1712430058259087361', '1712430019545661441', '培训类', '1', '', 1, 1, 'weibao_1', '2023-10-12 19:28:35.958', 'weibao_1', '2023-10-12 19:28:35.958'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711359157749018625', '1698869263734734849', '你好你好', '15', NULL, NULL, 1, 'yubowen', '2023-10-09 20:33:13.380', NULL, '2023-10-09 20:33:13.380'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711356925850808322', '1698869263734734849', '测试行为', '14', NULL, NULL, 1, 'yubowen', '2023-10-09 20:24:21.254', NULL, '2023-10-09 20:24:21.254'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711356133899104258', '1698869263734734849', 'abc', '13', NULL, NULL, 1, 'yubowen', '2023-10-09 20:21:12.438', NULL, '2023-10-09 20:21:12.438'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711352434854326273', '1698869263734734849', '超速889', '12', NULL, NULL, 1, 'yubowen', '2023-10-09 20:06:30.516', NULL, '2023-10-09 20:06:30.516'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711351836578803713', '1698869263734734849', '超速88', '11', NULL, NULL, 1, 'yubowen', '2023-10-09 20:04:07.876', NULL, '2023-10-09 20:04:07.876'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711289316304297986', '1698869263734734849', 'hhjj', '10', NULL, NULL, 1, NULL, '2023-10-09 15:55:41.882', NULL, '2023-10-09 15:55:41.882'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1711285371527831554', '1698869263734734849', 'fghh', '9', NULL, NULL, 1, NULL, '2023-10-09 15:40:01.372', NULL, '2023-10-09 15:40:01.372'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1710927879753027586', '1698869263734734849', 'AQ', '8', NULL, NULL, 1, 'weibao_leader', '2023-10-08 15:59:28.692', NULL, '2023-10-08 15:59:28.692'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1710926757101424641', '1698869263734734849', 'AA', '7', NULL, NULL, 1, 'weibao_leader', '2023-10-08 15:55:01.031', NULL, '2023-10-08 15:55:01.031'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1710856827790233601', '1710856749092507650', '结束', '0', '', 1, 1, 'weibao_leader', '2023-10-08 11:17:08.584', NULL, '2023-10-08 11:17:08.584'); +INSERT INTO public.sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1710856797847097346', '1710856749092507650', '进行中', '1', '', 1, 1, 'weibao_leader', '2023-10-08 11:17:01.445', NULL, '2023-10-08 11:17:01.445'); + diff --git a/src/updateSql/update-231024.sql b/src/updateSql/update-231024.sql new file mode 100644 index 0000000..f7f662f --- /dev/null +++ b/src/updateSql/update-231024.sql @@ -0,0 +1,5 @@ +ALTER TABLE public.tb_insurance_record ADD source_type varchar(2) NULL DEFAULT 1; +COMMENT ON COLUMN public.tb_insurance_record.source_type IS '来源(1后台,2小程序)'; + +ALTER TABLE public.tb_vehicle_check ADD source_type varchar(2) NULL DEFAULT 1; +COMMENT ON COLUMN public.tb_vehicle_check.source_type IS '来源(1后台,2小程序)'; diff --git a/src/updateSql/update-231031.sql b/src/updateSql/update-231031.sql new file mode 100644 index 0000000..ceb4ff2 --- /dev/null +++ b/src/updateSql/update-231031.sql @@ -0,0 +1,141 @@ +ALTER TABLE public.tb_contract ADD vehicle_count int2 NULL DEFAULT 0; +COMMENT ON COLUMN public.tb_contract.vehicle_count IS '车辆数'; +ALTER TABLE public.tb_contract ADD signing_name varchar(64) NULL; +COMMENT ON COLUMN public.tb_contract.signing_name IS '签约方名称(客户档案(客户租赁合同)、维修厂档案(维修合同)、车辆供应商档案(车辆采购合同)、保险档案(保险合同),其填文本)'; +ALTER TABLE public.tb_contract ADD status varchar(2) NULL; +COMMENT ON COLUMN public.tb_contract.status IS '合同状态(0未交接,1已交接)'; + + +ALTER TABLE public.tb_contract_vehicle ADD CONSTRAINT tb_contract_vehicle_pk PRIMARY KEY (id); + + +COMMENT ON COLUMN public.tb_contract_vehicle.sys_org_code IS '所属机构'; +ALTER TABLE public.tb_contract_vehicle ADD create_time timestamp NULL; +COMMENT ON COLUMN public.tb_contract_vehicle.create_time IS '创建时间'; +ALTER TABLE public.tb_contract_vehicle ADD update_time timestamp NULL; +COMMENT ON COLUMN public.tb_contract_vehicle.update_time IS '更新时间'; +ALTER TABLE public.tb_contract_vehicle ADD create_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_contract_vehicle.create_by IS '创建人'; +ALTER TABLE public.tb_contract_vehicle ADD update_by varchar(32) NULL; +COMMENT ON COLUMN public.tb_contract_vehicle.update_by IS '更新人'; + +ALTER TABLE public.tb_vehicle_check_detail ADD vehicle_brand varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle_check_detail.vehicle_brand IS '车辆品牌'; +ALTER TABLE public.tb_vehicle_check_detail ADD vehicle_model varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle_check_detail.vehicle_model IS '车辆型号'; +ALTER TABLE public.tb_vehicle_check_detail ADD vehicle_type varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle_check_detail.vehicle_type IS '车辆种类'; +ALTER TABLE public.tb_vehicle_check_detail ADD plate_number varchar(10) NULL; +COMMENT ON COLUMN public.tb_vehicle_check_detail.plate_number IS '车牌号'; + +ALTER TABLE public.tb_insurance ALTER COLUMN compulsory_price TYPE numeric(11, 2) USING compulsory_price::numeric; +ALTER TABLE public.tb_insurance ALTER COLUMN commercial_price TYPE numeric(11, 2) USING commercial_price::numeric; +ALTER TABLE public.tb_insurance ALTER COLUMN vehicle_vessel_tax TYPE numeric(11, 2) USING vehicle_vessel_tax::numeric; + +ALTER TABLE public.tb_insurance_record ALTER COLUMN insurance_price TYPE numeric(11, 2) USING insurance_price::numeric; + +ALTER TABLE public.tb_contract ALTER COLUMN total_price TYPE numeric(11, 2) USING total_price::numeric; +ALTER TABLE public.tb_contract ALTER COLUMN total_price DROP NOT NULL; +ALTER TABLE public.tb_contract ALTER COLUMN total_price_no_tax TYPE numeric(11, 2) USING total_price_no_tax::numeric; +ALTER TABLE public.tb_contract ALTER COLUMN total_price_no_tax DROP NOT NULL; +ALTER TABLE public.tb_contract ALTER COLUMN added_tax_rate TYPE numeric(11, 2) USING added_tax_rate::numeric; +ALTER TABLE public.tb_contract ALTER COLUMN added_tax_rate DROP NOT NULL; +ALTER TABLE public.tb_contract ALTER COLUMN added_tax TYPE numeric(11, 2) USING added_tax::numeric; +ALTER TABLE public.tb_contract ALTER COLUMN added_tax DROP NOT NULL; + +update public.tb_contract set status ='0' where contract_type ='1' or contract_type ='4' + +ALTER TABLE public.tb_vehicle_check ADD registration_time timestamp NULL; +COMMENT ON COLUMN public.tb_vehicle_check.registration_time IS '初登日期'; + +ALTER TABLE public.tb_vehicle_check ADD parent_id varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle_check.parent_id IS '租赁交车id'; + +ALTER TABLE public.tb_vehicle_check ADD status varchar(2) NULL DEFAULT 0; +COMMENT ON COLUMN public.tb_vehicle_check.status IS '状态(0待提交,1已提交)'; +ALTER TABLE public.tb_vehicle_check ALTER COLUMN check_status DROP NOT NULL; +ALTER TABLE public.tb_vehicle_check ALTER COLUMN vehicle_type DROP NOT NULL; +ALTER TABLE public.tb_vehicle_check ALTER COLUMN check_type DROP NOT NULL; + +COMMENT ON COLUMN public.tb_vehicle_check.check_status IS '验收结果(0不合格,1合格)'; +ALTER TABLE public.tb_vehicle_check ADD receive_status varchar(2) NULL DEFAULT 0; +COMMENT ON COLUMN public.tb_vehicle_check.receive_status IS '收车状态(0未收车,1已收车)'; + +ALTER TABLE public.tb_insurance ADD contract_id varchar(32) NULL; +COMMENT ON COLUMN public.tb_insurance.contract_id IS '所属合同'; +ALTER TABLE public.tb_insurance ADD frame_number varchar(20) NULL; +COMMENT ON COLUMN public.tb_insurance.frame_number IS '车架号'; + +CREATE TABLE public.tb_insurance_remind ( + id varchar(32) NOT NULL, + vehicle_id varchar(32) NULL, + project_id varchar(32) NULL, + vehicle_model varchar(32) NULL, + vehicle_type varchar(2) NULL, + contract_id varchar(32) NULL, + frame_number varchar(20) NULL, + has_compulsory_insurance varchar(2) NULL DEFAULT 0, + compulsory_start_time timestamp NULL, + compulsory_valid_time timestamp NULL, + has_commercial_insurance varchar(2) NULL DEFAULT 0, + insurance_id varchar(32) NULL, + status varchar(2) NULL DEFAULT 1, + sys_org_code varchar(16) NULL, + create_time timestamp NULL, + update_time timestamp NULL, + create_by varchar(32) NULL, + update_by varchar(32) NULL, + del_flag int2 NULL DEFAULT 0, + CONSTRAINT tb_insurance_remind_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_insurance_remind IS '保险提醒'; + +-- Column comments + +COMMENT ON COLUMN public.tb_insurance_remind.vehicle_id IS '所属车辆'; +COMMENT ON COLUMN public.tb_insurance_remind.project_id IS '所属项目'; +COMMENT ON COLUMN public.tb_insurance_remind.vehicle_model IS '车辆型号'; +COMMENT ON COLUMN public.tb_insurance_remind.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_insurance_remind.contract_id IS '所属合同'; +COMMENT ON COLUMN public.tb_insurance_remind.frame_number IS '车架号'; +COMMENT ON COLUMN public.tb_insurance_remind.has_compulsory_insurance IS '是否购买交强险(0,1)'; +COMMENT ON COLUMN public.tb_insurance_remind.compulsory_start_time IS '起保日期'; +COMMENT ON COLUMN public.tb_insurance_remind.compulsory_valid_time IS '有效日期'; +COMMENT ON COLUMN public.tb_insurance_remind.has_commercial_insurance IS '是否购买商业保险(0,1)'; +COMMENT ON COLUMN public.tb_insurance_remind.insurance_id IS '提醒保险id'; +COMMENT ON COLUMN public.tb_insurance_remind.status IS '提醒状态(0已过期,1提醒中)'; +COMMENT ON COLUMN public.tb_insurance_remind.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_insurance_remind.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_insurance_remind.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_insurance_remind.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_insurance_remind.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_insurance_remind.del_flag IS '删除标志'; + +ALTER TABLE public.tb_vehicle ADD source_type varchar(2) NULL DEFAULT 1; +COMMENT ON COLUMN public.tb_vehicle.source_type IS '来源(1车辆档案,2采购交车)'; + +update tb_contract set signing_name = signing_id where contract_type > '4'; +update tb_contract set signing_name = t.name from tb_customer_archives t where tb_contract.contract_type = '1' and t.id = tb_contract.signing_id ; +update tb_contract set signing_name = t.name from tb_insurance_company_archives t where tb_contract.contract_type = '2' and t.id = tb_contract.signing_id ; +update tb_contract set signing_name = t.name from tb_repair_shop_archives t where tb_contract.contract_type = '3' and t.id = tb_contract.signing_id ; +update tb_contract set signing_name = t.name from tb_vehicle_supplier_archives t where tb_contract.contract_type = '4' and t.id = tb_contract.signing_id ; + +update tb_vehicle_check_detail set frame_number=v.frame_number , vehicle_brand=v.vehicle_brand ,vehicle_model=v.vehicle_model ,vehicle_type=v.vehicle_type,plate_number=v.plate_number from tb_vehicle v where tb_vehicle_check_detail.plate_number is null and v.id =vehicle_id; + +update tb_insurance set compulsory_valid_time = commercial_valid_time where compulsory_valid_time is null; +update tb_insurance set compulsory_start_time = commercial_start_time where compulsory_start_time is null; +ALTER TABLE public.tb_insurance_remind ADD compulsory_insurance_no varchar(32) NULL; +COMMENT ON COLUMN public.tb_insurance_remind.compulsory_insurance_no IS '交强险保险单号'; +ALTER TABLE public.tb_insurance_remind ADD commercial_insurance_no varchar(32) NULL; +COMMENT ON COLUMN public.tb_insurance_remind.commercial_insurance_no IS '商业保险单号'; + +ALTER TABLE public.tb_insurance ADD plate_number varchar(10) NULL; +COMMENT ON COLUMN public.tb_insurance.plate_number IS '车牌号'; +ALTER TABLE public.tb_insurance_remind ADD plate_number varchar(10) NULL; +COMMENT ON COLUMN public.tb_insurance_remind.plate_number IS '车牌号'; + +update tb_insurance set plate_number = t.plate_number from tb_vehicle t where t.id = tb_insurance.vehicle_id and tb_insurance.plate_number is null; +update tb_insurance_remind set plate_number= t.plate_number from tb_vehicle t where t.id = tb_insurance_remind.vehicle_id and tb_insurance_remind.plate_number is null; + +ALTER TABLE public.tb_annual_inspection_info ADD source_type varchar(2) NULL DEFAULT 1; +COMMENT ON COLUMN public.tb_annual_inspection_info.source_type IS '来源(1车辆档案,2采购交车)'; diff --git a/src/updateSql/update-231106.sql b/src/updateSql/update-231106.sql new file mode 100644 index 0000000..7f71dee --- /dev/null +++ b/src/updateSql/update-231106.sql @@ -0,0 +1,36 @@ +ALTER TABLE public.tb_scheduled_plan ADD template_id varchar(32) NULL; +COMMENT ON COLUMN public.tb_scheduled_plan.template_id IS '关联模板id'; + + +ALTER TABLE public.tb_inspection_template ALTER COLUMN vehicle_type DROP NOT NULL; + +ALTER TABLE public.tb_inspection_task_vehicle ADD is_normal varchar(2) NULL; +COMMENT ON COLUMN public.tb_inspection_task_vehicle.is_normal IS '是否正常'; + +ALTER TABLE public.tb_inspection_task_vehicle ADD abnormal_msg varchar(512) NULL; +COMMENT ON COLUMN public.tb_inspection_task_vehicle.abnormal_msg IS '异常信息'; + +ALTER TABLE public.tb_accident_info ALTER COLUMN driver DROP NOT NULL; +ALTER TABLE public.tb_accident_info ALTER COLUMN driver_license_number DROP NOT NULL; +ALTER TABLE public.tb_accident_info ALTER COLUMN driver_phone_number DROP NOT NULL; + +--客户档案表联系人支持多选 +ALTER TABLE public.tb_customer_archives ALTER COLUMN contact TYPE varchar(500) USING contact::varchar; +ALTER TABLE public.tb_customer_archives ALTER COLUMN phone TYPE varchar(1000) USING phone::varchar; + +UPDATE tb_customer_archives +SET contact = ( + SELECT TO_JSONB(JSONB_BUILD_ARRAY(contact))::TEXT + FROM tb_customer_archives AS t + WHERE tb_customer_archives.id = t.id + and t.contact is not null +); + +UPDATE tb_customer_archives +SET phone = ( + SELECT TO_JSONB(JSONB_BUILD_ARRAY(phone))::TEXT + FROM tb_customer_archives AS t + WHERE tb_customer_archives.id = t.id + and t.phone is not null +); +-- \ No newline at end of file diff --git a/src/updateSql/update-231108.sql b/src/updateSql/update-231108.sql new file mode 100644 index 0000000..0ff6de5 --- /dev/null +++ b/src/updateSql/update-231108.sql @@ -0,0 +1,20 @@ +alter table tb_vehicle drop constraint tb_vehicle_un_vin_code +ALTER TABLE public.tb_vehicle ALTER COLUMN vin_code DROP NOT NULL; +ALTER TABLE public.tb_vehicle ALTER COLUMN engine_number DROP NOT NULL; + + +ALTER TABLE public.tb_gis_vehicle_fault_alarm ADD close_type varchar(2) NULL DEFAULT 1; +COMMENT ON COLUMN public.tb_gis_vehicle_fault_alarm.close_type IS '关闭类型 1-自动 2-用户手动操作'; +ALTER TABLE public.tb_gis_vehicle_fault_alarm ADD remark varchar(512) NULL; +COMMENT ON COLUMN public.tb_gis_vehicle_fault_alarm.remark IS '备注'; + + +ALTER TABLE public.tb_vehicle ADD key_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.key_code IS '钥匙编码'; + + +ALTER TABLE public.tb_gis_gps_statistics ADD support_video varchar(2) NULL; +COMMENT ON COLUMN public.tb_gis_gps_statistics.support_video IS '是否有视频'; + +ALTER TABLE public.tb_gis_gps_statistics ADD support_terminal varchar(2) NULL; +COMMENT ON COLUMN public.tb_gis_gps_statistics.support_terminal IS '是否终端直连'; \ No newline at end of file diff --git a/src/updateSql/update-231109.sql b/src/updateSql/update-231109.sql new file mode 100644 index 0000000..9a65f69 --- /dev/null +++ b/src/updateSql/update-231109.sql @@ -0,0 +1,44 @@ +ALTER TABLE public.tb_insurance_record ALTER COLUMN insurance_price TYPE numeric(12,2) USING insurance_price::numeric; + + +COMMENT ON COLUMN public.tb_accident_insurance_info.case_receipt_number IS '保险单号'; + + +ALTER TABLE public.tb_insurance_record ADD vehicle_loss_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.vehicle_loss_amount IS '标的车损失金额'; +ALTER TABLE public.tb_insurance_record ADD vehicle_personal_injury_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.vehicle_personal_injury_amount IS '标的车人伤金额'; +ALTER TABLE public.tb_insurance_record ADD third_property_damage_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.third_property_damage_amount IS '第三方物损金额'; +ALTER TABLE public.tb_insurance_record ADD third_personal_injury_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.third_personal_injury_amount IS '第三方人伤金额'; +ALTER TABLE public.tb_insurance_record ADD estimated_total_loss_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.estimated_total_loss_amount IS '预估损失总金额'; +ALTER TABLE public.tb_insurance_record ADD claim_to_company_account_date timestamp NULL; +COMMENT ON COLUMN public.tb_insurance_record.claim_to_company_account_date IS '理赔至公司账户日期'; +ALTER TABLE public.tb_insurance_record ADD claim_to_company_account_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.claim_to_company_account_amount IS '理赔至公司账户金额'; +ALTER TABLE public.tb_insurance_record ADD claim_to_third_account_date timestamp NULL; +COMMENT ON COLUMN public.tb_insurance_record.claim_to_third_account_date IS '理赔至第三方账户日期'; +ALTER TABLE public.tb_insurance_record ADD claim_to_third_account_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.claim_to_third_account_amount IS '理赔至第三方账户金额'; +ALTER TABLE public.tb_insurance_record ADD total_compensation_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.total_compensation_amount IS '出险赔偿总金额'; +ALTER TABLE public.tb_insurance_record ADD uncompensated_amount numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_insurance_record.uncompensated_amount IS '出险未赔偿金额'; +COMMENT ON COLUMN public.tb_insurance_record.insurance_price IS '理赔金额(案件实际发生总金额)'; + +ALTER TABLE public.tb_accident_insurance_info ADD is_record varchar(2) NULL DEFAULT 0; +COMMENT ON COLUMN public.tb_accident_insurance_info.is_record IS '是否同步出险'; +ALTER TABLE public.tb_accident_insurance_info ADD company_id varchar(32) NULL; +COMMENT ON COLUMN public.tb_accident_insurance_info.company_id IS '保险公司'; +ALTER TABLE public.tb_accident_insurance_info ADD insurance_date timestamp NULL; +COMMENT ON COLUMN public.tb_accident_insurance_info.insurance_date IS '出险日期'; + +ALTER TABLE public.tb_insurance_record ADD info_id varchar(32) NULL; +COMMENT ON COLUMN public.tb_insurance_record.info_id IS '事故id'; + +ALTER TABLE public.tb_accident_progress ALTER COLUMN accident_certificate_photo TYPE text USING accident_certificate_photo::text; +ALTER TABLE public.tb_accident_progress ALTER COLUMN compensation_agreement_photo TYPE text USING compensation_agreement_photo::text; +ALTER TABLE public.tb_accident_progress ALTER COLUMN loss_assessment_photo TYPE text USING loss_assessment_photo::text; +ALTER TABLE public.tb_accident_progress ALTER COLUMN other_photo TYPE text USING other_photo::text; \ No newline at end of file diff --git a/src/updateSql/update-231117-2.sql b/src/updateSql/update-231117-2.sql new file mode 100644 index 0000000..bc2ceaf --- /dev/null +++ b/src/updateSql/update-231117-2.sql @@ -0,0 +1,51 @@ +ALTER TABLE public.tb_annual_inspection_info ADD del_flag int2 NULL DEFAULT 0; +COMMENT ON COLUMN public.tb_annual_inspection_info.del_flag IS '删除标志'; + + + +-- public.tb_annual_inspection_remind definition + +-- Drop table + +-- DROP TABLE public.tb_annual_inspection_remind; + +CREATE TABLE public.tb_annual_inspection_remind ( + id varchar(32) NOT NULL, -- id + sys_org_code varchar(32) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + create_by varchar(32) NULL, -- 创建人 + update_time timestamp NULL, -- 更新时间 + update_by varchar(32) NULL, -- 更新人 + plate_number varchar(32) NOT NULL, -- 车牌号 + validity_period timestamp NULL, -- 年审有效期 + overdue_type varchar(2) NULL, -- 逾期类型 + days_to_overdue int2 NULL, -- 将要逾期天数 + overdue_days int2 NULL, -- 逾期天数 + remind_status varchar(2) NULL, -- 提醒状态 1-提醒中 0-已过期 + info_id varchar(32) NULL, -- 年检台账id + del_flag int2 NULL DEFAULT 0, -- 删除标志 + CONSTRAINT tb_accident_insurance_remind_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_annual_inspection_remind IS '年检提醒'; + +-- Column comments + +COMMENT ON COLUMN public.tb_annual_inspection_remind.id IS 'id'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.plate_number IS '车牌号'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.validity_period IS '年审有效期'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.overdue_type IS '逾期类型'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.days_to_overdue IS '将要逾期天数'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.overdue_days IS '逾期天数'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.remind_status IS '提醒状态 1-提醒中 0-已过期'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.info_id IS '年检台账id'; +COMMENT ON COLUMN public.tb_annual_inspection_remind.del_flag IS '删除标志'; +ALTER TABLE public.tb_annual_inspection_remind ADD CONSTRAINT tb_accident_insurance_remind_pk PRIMARY KEY (id); + +ALTER TABLE public.tb_customer_training ADD training_name varchar(64) NULL; +COMMENT ON COLUMN public.tb_customer_training.training_name IS '培训名称'; +ALTER TABLE public.tb_gis_fence_vehicle ALTER COLUMN gps_no DROP NOT NULL; \ No newline at end of file diff --git a/src/updateSql/update-231117.sql b/src/updateSql/update-231117.sql new file mode 100644 index 0000000..0c77b55 --- /dev/null +++ b/src/updateSql/update-231117.sql @@ -0,0 +1,4 @@ +ALTER TABLE public.tb_vehicle ADD battery_code varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.battery_code IS '电池编码'; +ALTER TABLE public.tb_vehicle ADD manufacturer varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.manufacturer IS '制造商'; \ No newline at end of file diff --git a/src/updateSql/update-240220.sql b/src/updateSql/update-240220.sql new file mode 100644 index 0000000..0853fcb --- /dev/null +++ b/src/updateSql/update-240220.sql @@ -0,0 +1,189 @@ +ALTER TABLE tb_accident_info ADD accident_scene_video varchar(5000) NULL; +COMMENT ON COLUMN tb_accident_info.accident_scene_video IS '事故现场视频'; + + +ALTER TABLE public.tb_vehicle ADD battery_brand_and_model varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.battery_brand_and_model IS '电池品牌及型号'; +ALTER TABLE public.tb_vehicle ADD electronic_control_brand_and_model varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.electronic_control_brand_and_model IS '电控品牌及型号'; +ALTER TABLE public.tb_vehicle ADD curb_weight numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_vehicle.curb_weight IS '整备质量'; + + +ALTER TABLE public.tb_vehicle_check_detail ADD curb_weight numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_vehicle_check_detail.curb_weight IS '整备质量'; + +ALTER TABLE public.tb_contract_vehicle ADD curb_weight numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_contract_vehicle.curb_weight IS '整备质量'; + +-- public.tb_gis_stopping_alarm definition + +-- Drop table + +-- DROP TABLE tb_gis_stopping_alarm; + +CREATE TABLE tb_gis_stopping_alarm ( + id varchar(32) NOT NULL, -- id + plate_number varchar(32) NOT NULL, -- 车牌号 + start_time timestamp NOT NULL, -- 告警开始时间 + end_time timestamp NULL, -- 告警结束时间 + project_id varchar(32) NOT NULL, -- 所属项目id + start_lon numeric(12, 6) NULL, -- 开始经度(高德) + start_lat numeric(12, 6) NULL, -- 开始纬度(高德) + end_lon numeric(12, 6) NULL, -- 结束经度(高德) + end_lat numeric(12, 6) NULL, -- 结束纬度(高德) + stop_time int4 NULL, -- 停车时长(秒) + sys_org_code varchar(32) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + project_name varchar(64) NULL, -- 项目名称 + CONSTRAINT tb_gis_speeding_alarm_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_gis_stopping_alarm IS '停车超时记录'; + +-- Column comments + +COMMENT ON COLUMN public.tb_gis_stopping_alarm.id IS 'id'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.plate_number IS '车牌号'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.start_time IS '告警开始时间'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.end_time IS '告警结束时间'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.project_id IS '所属项目id'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.start_lon IS '开始经度(高德)'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.start_lat IS '开始纬度(高德)'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.end_lon IS '结束经度(高德)'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.end_lat IS '结束纬度(高德)'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.stop_time IS '停车时长(秒)'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_gis_stopping_alarm.project_name IS '项目名称'; + + + +ALTER TABLE public.tb_driver ADD company varchar(64) NULL; +COMMENT ON COLUMN public.tb_driver.company IS '所属公司'; +ALTER TABLE public.tb_driver ALTER COLUMN customer_id TYPE varchar(32) USING customer_id::varchar; +ALTER TABLE public.tb_driver ADD employee_type varchar(64) NULL; +COMMENT ON COLUMN public.tb_driver.employee_type IS '员工类别'; +ALTER TABLE public.tb_driver ADD is_position varchar(2) NULL; +COMMENT ON COLUMN public.tb_driver.is_position IS '是否定位 0-否,1-是'; +ALTER TABLE public.tb_driver ADD age int2 NULL; +COMMENT ON COLUMN public.tb_driver.age IS '年龄'; +ALTER TABLE public.tb_driver ADD marital_status varchar(2) NULL; +COMMENT ON COLUMN public.tb_driver.marital_status IS '婚姻状况'; +ALTER TABLE public.tb_driver ADD childrens int2 NULL; +COMMENT ON COLUMN public.tb_driver.childrens IS '子女数'; +ALTER TABLE public.tb_driver ADD file_number varchar(64) NULL; +COMMENT ON COLUMN public.tb_driver.file_number IS '档案号'; + + +ALTER TABLE public.tb_vehicle ADD oil_card varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.oil_card IS '油卡卡号'; + + +-- public.tb_refuel_charge_record definition + +-- Drop table + +-- DROP TABLE public.tb_refuel_charge_record; + +CREATE TABLE public.tb_refuel_charge_record ( + id varchar(32) NOT NULL, -- 主键id + record_date timestamp NULL, -- 日期 + order_no varchar(64) NULL, -- 单号 + start_time timestamp NULL, -- 开始时间 + end_time timestamp NULL, -- 结束时间 + project_id varchar(32) NULL, -- 所属项目 + vehicle_id varchar(32) NULL, -- 车辆id + frame_number varchar(32) NULL, -- 车架号 + vehicle_model varchar(32) NULL, -- 车辆型号 + vehicle_type varchar(32) NULL, -- 车辆种类 + plate_number varchar(10) NULL, -- 车牌号 + fuel_type varchar(2) NULL, -- 燃料类型 + oil_card varchar(32) NULL, -- 油卡卡号 + oil_type varchar(32) NULL, -- 油品规格 + price numeric(11, 2) NULL, -- 单价 + amount numeric(11, 2) NULL, -- 数量 + total_price numeric(11, 2) NULL, -- 金额 + mileage numeric(11, 2) NULL, -- 加油充电时里程 + remark text NULL, -- 备注 + sys_org_code varchar(16) NULL, -- 所属机构 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + create_by varchar(32) NULL, -- 创建人 + update_by varchar(32) NULL, -- 更新人 + del_flag int2 NULL DEFAULT 0, -- 删除标志 + refuel_type varchar(2) NULL DEFAULT 1, -- 记录类型(1加油,2充电) + source_type varchar(2) NULL DEFAULT 1, -- 来源(1后台,2小程序,3后台导入) + driver varchar(64) NULL, -- 驾驶员 + oil_station varchar(64) NULL, -- 加油站 + oil_card_balance numeric(11, 2) NULL, -- 油卡余额 + attachment_url text NULL, -- 附件url + CONSTRAINT tb_refuel_charge_record_pk PRIMARY KEY (id) +); +COMMENT ON TABLE public.tb_refuel_charge_record IS '加油充电登记'; + +-- Column comments + +COMMENT ON COLUMN public.tb_refuel_charge_record.id IS '主键id'; +COMMENT ON COLUMN public.tb_refuel_charge_record.record_date IS '日期'; +COMMENT ON COLUMN public.tb_refuel_charge_record.order_no IS '单号'; +COMMENT ON COLUMN public.tb_refuel_charge_record.start_time IS '开始时间'; +COMMENT ON COLUMN public.tb_refuel_charge_record.end_time IS '结束时间'; +COMMENT ON COLUMN public.tb_refuel_charge_record.project_id IS '所属项目'; +COMMENT ON COLUMN public.tb_refuel_charge_record.vehicle_id IS '车辆id'; +COMMENT ON COLUMN public.tb_refuel_charge_record.frame_number IS '车架号'; +COMMENT ON COLUMN public.tb_refuel_charge_record.vehicle_model IS '车辆型号'; +COMMENT ON COLUMN public.tb_refuel_charge_record.vehicle_type IS '车辆种类'; +COMMENT ON COLUMN public.tb_refuel_charge_record.plate_number IS '车牌号'; +COMMENT ON COLUMN public.tb_refuel_charge_record.fuel_type IS '燃料类型'; +COMMENT ON COLUMN public.tb_refuel_charge_record.oil_card IS '油卡卡号'; +COMMENT ON COLUMN public.tb_refuel_charge_record.oil_type IS '油品规格'; +COMMENT ON COLUMN public.tb_refuel_charge_record.price IS '单价'; +COMMENT ON COLUMN public.tb_refuel_charge_record.amount IS '数量'; +COMMENT ON COLUMN public.tb_refuel_charge_record.total_price IS '金额'; +COMMENT ON COLUMN public.tb_refuel_charge_record.mileage IS '加油充电时里程'; +COMMENT ON COLUMN public.tb_refuel_charge_record.remark IS '备注'; +COMMENT ON COLUMN public.tb_refuel_charge_record.sys_org_code IS '所属机构'; +COMMENT ON COLUMN public.tb_refuel_charge_record.create_time IS '创建时间'; +COMMENT ON COLUMN public.tb_refuel_charge_record.update_time IS '更新时间'; +COMMENT ON COLUMN public.tb_refuel_charge_record.create_by IS '创建人'; +COMMENT ON COLUMN public.tb_refuel_charge_record.update_by IS '更新人'; +COMMENT ON COLUMN public.tb_refuel_charge_record.del_flag IS '删除标志'; +COMMENT ON COLUMN public.tb_refuel_charge_record.refuel_type IS '记录类型(1加油,2充电)'; +COMMENT ON COLUMN public.tb_refuel_charge_record.source_type IS '来源(1后台,2小程序,3后台导入)'; +COMMENT ON COLUMN public.tb_refuel_charge_record.driver IS '驾驶员'; +COMMENT ON COLUMN public.tb_refuel_charge_record.oil_station IS '加油站'; +COMMENT ON COLUMN public.tb_refuel_charge_record.oil_card_balance IS '油卡余额'; +COMMENT ON COLUMN public.tb_refuel_charge_record.attachment_url IS '附件url'; + + + +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1764537969428758530', '1762354981077078018', '查看', '', NULL, NULL, NULL, 2, 'refuelingCharging:view', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-04 14:26:50.097', 'yubowen', '2024-03-04 14:26:50.097', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1764537885496541186', '1762354981077078018', '删除', '', NULL, NULL, NULL, 2, 'refuelingCharging:del', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-04 14:26:30.087', 'yubowen', '2024-03-04 14:27:46.955', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1764537715715309570', '1762354981077078018', '编辑', '', NULL, NULL, NULL, 2, 'refuelingCharging:update', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-04 14:25:49.609', 'yubowen', '2024-03-04 14:28:40.789', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1764530522987266050', '1762354981077078018', '导入', '', NULL, NULL, NULL, 2, 'refuelingCharging:import', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-04 13:57:14.728', 'yubowen', '2024-03-04 13:57:14.728', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1764530409388736513', '1762354981077078018', '导出', '', NULL, NULL, NULL, 2, 'refuelingCharging:export', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-04 13:56:47.644', 'yubowen', '2024-03-04 13:56:47.644', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1764530109475028994', '1762354981077078018', '新增', '', NULL, NULL, NULL, 2, 'refuelingCharging:add', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-04 13:55:36.137', 'yubowen', '2024-03-04 13:55:36.137', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1762354981077078018', '1697180778124619778', '加油充电登记', '/chauffeurManage/RefuelingCharging', 'chauffeurManage/RefuelingCharging/index', NULL, NULL, 1, NULL, NULL, 8.0, NULL, 0, NULL, NULL, 0, NULL, 'yubowen', '2024-02-27 13:52:25.116', 'test90', '2024-02-28 13:38:44.730', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1762011654396944385', '1761924131223064577', '导出', '', NULL, NULL, NULL, 2, 'InsuranceStatement:export', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-02-26 15:08:09.661', 'yubowen', '2024-02-26 15:08:09.661', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1761946877456502786', '1761931206124720130', '导出', '', NULL, NULL, NULL, 2, 'ParkingTimeout:export', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-02-26 10:50:45.624', 'yubowen', '2024-02-26 10:50:45.624', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1761931206124720130', '1697455362346319874', '停车超时', '/vehicleMonitoring/ParkingTimeout', 'vehicleMonitoring/ParkingTimeout/ParkingTimeout', NULL, NULL, 1, NULL, NULL, 12.0, NULL, 0, NULL, NULL, 0, NULL, 'weibao_leader', '2024-02-26 09:48:29.295', 'weibao_leader', '2024-02-26 09:48:29.295', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1761924131223064577', '1710545411476578306', '保险年度报表', '/statementCenter/InsuranceStatement', 'statementCenter/InsuranceStatement/InsuranceStatement', NULL, NULL, 1, NULL, NULL, 7.0, NULL, 0, NULL, NULL, 0, NULL, 'weibao_leader', '2024-02-26 09:20:22.506', 'yubowen', '2024-02-26 14:02:16.024', 0, 0); + +INSERT INTO sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1762299892803129346', '油品规格', 'oil_type', '1:0号 车用柴油(Ⅵ),2:92号 车用汽油(ⅥB),3:95号 车用汽油(ⅥB),4:充电', 0, 'test90', '2024-02-27 10:13:31.048', 'test90', '2024-02-27 10:13:31.048', 0); +INSERT INTO sys_dict (id, dict_name, dict_code, description, del_flag, create_by, create_time, update_by, update_time, "type") VALUES('1761933064054591489', '婚姻状况', 'marital_status', '婚姻状况', 0, 'adminLeader', '2024-02-26 09:55:52.260', 'adminLeader', '2024-02-26 09:55:52.260', 0); + + +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1762300145342173185', '1762299892803129346', '充电', '4', '', 4, 1, 'test90', '2024-02-27 10:14:31.259', 'test90', '2024-02-27 10:14:31.259'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1762300098156253186', '1762299892803129346', '95号 车用汽油(ⅥB)', '3', '', 3, 1, 'test90', '2024-02-27 10:14:20.009', 'test90', '2024-02-27 10:14:20.009'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1762300053604356098', '1762299892803129346', '92号 车用汽油(ⅥB)', '2', '', 2, 1, 'test90', '2024-02-27 10:14:09.387', 'test90', '2024-02-27 10:14:09.387'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1762299995764903937', '1762299892803129346', '0号 车用柴油(Ⅵ)', '1', '', 1, 1, 'test90', '2024-02-27 10:13:55.597', 'test90', '2024-02-27 10:13:55.597'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1761934714072813569', '1761933064054591489', '丧偶', '4', '', 4, 1, 'adminLeader', '2024-02-26 10:02:25.656', 'adminLeader', '2024-02-26 10:02:25.656'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1761934673845243905', '1761933064054591489', '离婚', '3', '', 3, 1, 'adminLeader', '2024-02-26 10:02:16.065', 'adminLeader', '2024-02-26 10:02:16.065'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1761934629880549377', '1761933064054591489', '已婚', '2', '', 2, 1, 'adminLeader', '2024-02-26 10:02:05.582', 'adminLeader', '2024-02-26 10:02:05.582'); +INSERT INTO sys_dict_item (id, dict_id, item_text, item_value, description, sort_order, status, create_by, create_time, update_by, update_time) VALUES('1761933874528342018', '1761933064054591489', '未婚', '1', '', 1, 1, 'adminLeader', '2024-02-26 09:59:05.492', 'adminLeader', '2024-02-26 09:59:21.326'); + + + + diff --git a/src/updateSql/update-240307.sql b/src/updateSql/update-240307.sql new file mode 100644 index 0000000..fa77c6a --- /dev/null +++ b/src/updateSql/update-240307.sql @@ -0,0 +1,21 @@ +ALTER TABLE public.tb_gis_charge_log ADD estimated_cost numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_gis_charge_log.estimated_cost IS '预估费用'; + + +ALTER TABLE public.tb_vehicle ADD third_organization varchar(32) NULL; +COMMENT ON COLUMN public.tb_vehicle.third_organization IS '机构名称'; +ALTER TABLE public.tb_vehicle ADD acceptance_fee numeric(12, 2) NULL; +COMMENT ON COLUMN public.tb_vehicle.acceptance_fee IS '验收费用'; + +ALTER TABLE public.tb_annual_inspection_info ADD personnel varchar(32) NULL; +COMMENT ON COLUMN public.tb_annual_inspection_info.personnel IS '年检人员'; +ALTER TABLE public.tb_annual_inspection_info ADD items varchar(32) NULL; +COMMENT ON COLUMN public.tb_annual_inspection_info.items IS '年检项目'; + +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1767089200969932802', '1767088814921998338', '导出', '', NULL, NULL, NULL, 2, 'VehicleRental:export', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-11 15:24:31.095', 'yubowen', '2024-03-11 15:24:31.095', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1767088814921998338', '1710546036633395201', '车辆租金收入', '/statementCenter/VehicleRental', 'statementCenter/VehicleRental/VehicleRental', NULL, NULL, 1, NULL, NULL, 10.0, NULL, 0, NULL, NULL, 0, NULL, 'yubowen', '2024-03-11 15:22:59.056', 'yubowen', '2024-03-11 15:27:29.734', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1765981587901374465', '1765981455420088321', '导出', '', NULL, NULL, NULL, 2, 'Weighbridge:export', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-08 14:03:15.563', 'yubowen', '2024-03-08 14:03:15.563', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1765981455420088321', '1710545411476578306', '地磅数据', '/statementCenter/Weighbridge', 'statementCenter/Weighbridge/Weighbridge', NULL, NULL, 1, NULL, NULL, 8.0, NULL, 0, NULL, NULL, 0, NULL, 'yubowen', '2024-03-08 14:02:43.977', 'yubowen', '2024-03-08 14:02:43.977', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1765911770565566465', '1765911618543017985', '导出', '', NULL, NULL, NULL, 2, 'FuelConsumption:export', '1', 1.0, NULL, 1, NULL, '1', 0, NULL, 'yubowen', '2024-03-08 09:25:49.814', 'yubowen', '2024-03-08 09:25:49.814', 0, 0); +INSERT INTO sys_permission (id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, icon, is_leaf, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external, hidden) VALUES('1765911618543017985', '1697455362346319874', '油耗异常', '/vehicleMonitoring/FuelConsumption', 'vehicleMonitoring/FuelConsumption/FuelConsumption', NULL, NULL, 1, NULL, NULL, 13.0, NULL, 0, NULL, NULL, 0, NULL, 'yubowen', '2024-03-08 09:25:13.566', 'yubowen', '2024-03-08 09:25:13.566', 0, 0); +