ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TAppUserPositioningController.java
New file @@ -0,0 +1,99 @@ package com.ruoyi.web.controller.api; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.system.model.TAppUser; import com.ruoyi.system.model.TAppUserPositioning; import com.ruoyi.system.query.PositioningDetailQuery; import com.ruoyi.system.service.TAppUserPositioningService; import com.ruoyi.system.service.TAppUserService; import com.ruoyi.system.vo.PositioningDetailVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Objects; /** * <p> * 用户每日定位存储 前端控制器 * </p> * * @author xiaochen * @since 2025-10-21 */ @Api(tags = "人员分布") @RestController @RequestMapping("/t-app-user-positioning") public class TAppUserPositioningController { private final TAppUserPositioningService appUserPositioningService; private final TAppUserService appUserService; private final RedisCache redisCache; @Autowired public TAppUserPositioningController(TAppUserPositioningService appUserPositioningService, TAppUserService appUserService, RedisCache redisCache) { this.appUserPositioningService = appUserPositioningService; this.appUserService = appUserService; this.redisCache = redisCache; } /** * 用户实时获取 */ @ApiOperation(value = "人员分布-队伍实时点位") @PostMapping(value = "/api/t-app-user-positioning/queryPositioning") public R<List<TAppUser>> queryPositioning() { List<TAppUser> list = appUserService.list(Wrappers.lambdaQuery(TAppUser.class) .eq(TAppUser::getStatus, 1) .eq(TAppUser::getState, 1)); for (TAppUser appUser : list) { String location = redisCache.getCacheObject(Constants.LOCATION + appUser.getId()); if(StringUtils.hasLength(location)){ String[] split = location.split(","); appUser.setLon(split[0]); appUser.setLat(split[1]); } } return R.ok(list); } /** * 用户实时获取 */ @ApiOperation(value = "人员分布-队伍实时点位") @PostMapping(value = "/api/t-app-user-positioning/queryPositioningDetail") public R<PositioningDetailVO> queryPositioningDetail(@RequestBody String param) { PositioningDetailQuery positioningDetailQuery = JSON.parseObject(param,PositioningDetailQuery.class); TAppUser appUser = appUserService.getById(positioningDetailQuery.getAppUserId()); if(appUser == null){ return R.fail("用户不存在"); } PositioningDetailVO positioningDetailVO = new PositioningDetailVO(); BeanUtils.copyProperties(appUser,positioningDetailVO); TAppUserPositioning appUserPositioning = appUserPositioningService.getOne(Wrappers.lambdaQuery(TAppUserPositioning.class) .eq(TAppUserPositioning::getAppUserId,appUser.getId()) .like(TAppUserPositioning::getCreateTime, positioningDetailQuery.getStartTime()) .last("LIMIT 1")); if(Objects.nonNull(appUserPositioning)){ positioningDetailVO.setRealTimePositioning(appUserPositioning.getUserLocation()); } return R.ok(positioningDetailVO); } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSecretConfigController.java
New file @@ -0,0 +1,39 @@ package com.ruoyi.web.controller.api; import com.ruoyi.common.core.domain.R; import com.ruoyi.system.model.TSecretConfig; import com.ruoyi.system.service.TSecretConfigService; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * 密钥 前端控制器 * </p> * * @author xiaochen * @since 2025-10-13 */ @RestController @RequestMapping("") public class TSecretConfigController { private final TSecretConfigService secretConfigService; @Autowired public TSecretConfigController(TSecretConfigService secretConfigService) { this.secretConfigService = secretConfigService; } @ApiOperation(value = "密钥", response = TSecretConfig.class) @PostMapping(value = "/api/system/getEncryptionKey") public R<TSecretConfig> pageList() { return R.ok(secretConfigService.getById(12879)); } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
@@ -1,83 +1,69 @@ //package com.ruoyi.web.controller.task; // // //import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; //import com.ruoyi.common.utils.SmsUtil; //import com.ruoyi.system.mapper.TBillMapper; //import com.ruoyi.system.model.TBill; //import com.ruoyi.system.model.TContract; //import com.ruoyi.system.model.TContractRentType; //import com.ruoyi.system.service.TBillService; //import com.ruoyi.system.service.TContractRentTypeService; //import com.ruoyi.system.service.TContractService; //import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.scheduling.annotation.Scheduled; //import org.springframework.stereotype.Component; // //import javax.annotation.Resource; //import java.math.BigDecimal; //import java.time.LocalDate; //import java.time.LocalDateTime; //import java.time.LocalTime; //import java.time.ZoneId; //import java.time.temporal.ChronoUnit; //import java.time.temporal.TemporalAdjusters; //import java.util.ArrayList; //import java.util.Date; //import java.util.List; //import java.util.Random; //import java.util.stream.Collectors; // ///** // * @author zhibing.pu // * @date 2023/7/11 8:39 // */ //@Component //public class TaskUtil { // @Autowired // private TContractService contractService; // @Autowired // private TBillMapper billMapper; // // 用于更新违约金账单 // // 每分钟执行一次的定时任务 // // @Scheduled(cron = "0 * * * * ?") // public void dayOfProportionBill() { // try { // // 查询所有未缴费账单 // List<TBill> list = billMapper.selectList(new LambdaQueryWrapper<TBill>().eq(TBill::getPayFeesStatus, 1) // .le(TBill::getPayableFeesTime,LocalDate.now())); // for (TBill tBill : list) { // tBill.setPayFeesStatus("4"); // TContract contract = contractService.getById(tBill.getContractId()); // LocalDate payableFeesTime = tBill.getPayableFeesTime(); // // 将LocalDate转化为LocalDateTime // LocalDateTime payableFeesTime1 = LocalDateTime.of(payableFeesTime, LocalTime.of(0, 0, 0)); // LocalDateTime now = LocalDateTime.now(); // // 计算两个时间相差多少个小时 // long hours = ChronoUnit.HOURS.between(payableFeesTime1, now); // long l = hours / 24; // if (l>=3){ // // 违约金比例 // BigDecimal proportion = contract.getProportion(); // // 按每天 待缴费金额 * XX% 增加违约金费用 // if (tBill.getOutstandingMoney().compareTo(new BigDecimal("0"))==0){ // tBill.setPayFeesStatus("3"); // billMapper.updateById(tBill); // continue; // } // BigDecimal money = tBill.getOutstandingMoney().multiply(new BigDecimal(100).add(proportion)).divide(new BigDecimal(100),2, BigDecimal.ROUND_DOWN); // tBill.setOverDays((int) l); // tBill.setPayableFeesPenalty((tBill.getPayableFeesPenalty()!=null?tBill.getPayableFeesPenalty():BigDecimal.ZERO).add(money)); // tBill.setOutstandingMoney(money); // billMapper.updateById(tBill); // // } // } // } catch (Exception e) { // e.printStackTrace(); // } // } // // //} package com.ruoyi.web.controller.task; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.system.model.TAppUser; import com.ruoyi.system.model.TAppUserPositioning; import com.ruoyi.system.service.TAppUserPositioningService; import com.ruoyi.system.service.TAppUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; /** * @author xiaochen * @date 2025/10/11 8:39 */ @Component public class TaskUtil { @Autowired private RedisCache redisCache; @Autowired private TAppUserService appUserService; @Autowired private TAppUserPositioningService appUserPositioningService; //每天0点30分执行 @Scheduled(cron = "0 30 0 * * ?") public void dayOfSavePositioning() { try { // 获取前一天时间 LocalDate localDate = LocalDate.now().minusDays(1); // 查询所有的用户 List<TAppUser> appUserList = appUserService.list(Wrappers.lambdaQuery(TAppUser.class) .eq(TAppUser::getState, 1) .eq(TAppUser::getState, 1)); List<TAppUserPositioning> appUserPositioningList = new ArrayList<>(); for (TAppUser appUser : appUserList) { TAppUserPositioning appUserPositioning = new TAppUserPositioning(); // 获取定位 String location = redisCache.getCacheObject(Constants.LOCATION + appUser.getId() + ":" + localDate); if(StringUtils.hasLength(location)){ appUserPositioning.setAppUserId(appUser.getId()); appUserPositioning.setUserLocation(location); appUserPositioning.setCreateTime(localDate.atStartOfDay()); appUserPositioningList.add(appUserPositioning); } } if(!CollectionUtils.isEmpty(appUserPositioningList)){ appUserPositioningService.saveBatch(appUserPositioningList); } } catch (Exception e) { e.printStackTrace(); } } } ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TAppUserController.java
@@ -3,7 +3,9 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.dto.UpdateDetailTeamDto; import com.ruoyi.system.model.TAppUser; @@ -16,7 +18,10 @@ import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; /** * <p> @@ -36,13 +41,15 @@ private final PasswordEncoder passwordEncoder; private final TAppUserEquipmentService appUserEquipmentService; private final TAppUserLocationService appUserLocationService; private final RedisCache redisCache; @Autowired public TAppUserController(TAppUserService appUserService, TokenService tokenService, PasswordEncoder passwordEncoder, TAppUserEquipmentService appUserEquipmentService, TAppUserLocationService appUserLocationService) { public TAppUserController(TAppUserService appUserService, TokenService tokenService, PasswordEncoder passwordEncoder, TAppUserEquipmentService appUserEquipmentService, TAppUserLocationService appUserLocationService, RedisCache redisCache) { this.appUserService = appUserService; this.tokenService = tokenService; this.passwordEncoder = passwordEncoder; this.appUserEquipmentService = appUserEquipmentService; this.appUserLocationService = appUserLocationService; this.redisCache = redisCache; } /** @@ -91,7 +98,7 @@ * 查看人员管理详情--修改队伍情况 */ @ApiOperation(value = "查看人员管理详情--修改队伍情况",response = UpdateDetailTeamDto.class) @PostMapping(value = "/open/t-app-user/updateDetailTeam") @PostMapping(value = "/api/t-app-user/updateDetailTeam") public R<?> updateDetailTeam(@RequestBody String param) { String userId = tokenService.getLoginUserApplet().getUserId(); UpdateDetailTeamDto dto = JSON.parseObject(param, UpdateDetailTeamDto.class); @@ -108,7 +115,7 @@ * 用户打点 */ @ApiOperation(value = "用户打点",response = TAppUserLocation.class) @PostMapping(value = "/open/t-app-user/appUserLocation") @PostMapping(value = "/api/t-app-user/appUserLocation") public R<?> appUserLocation(@RequestBody String param) { TAppUserLocation location = JSON.parseObject(param,TAppUserLocation.class); String userId = tokenService.getLoginUserApplet().getUserId(); @@ -117,5 +124,24 @@ return R.ok(); } /** * 用户实时定位上传 */ @ApiOperation(value = "用户实时定位上传") @PostMapping(value = "/open/t-app-user/positioningUpload") public R<String> positioningUpload(@RequestParam(value = "lon") String lon , @RequestParam(value = "lat") String lat ) { String userId = tokenService.getLoginUserApplet().getUserId(); String location = redisCache.getCacheObject(Constants.LOCATION + userId + ":" + LocalDate.now()); if(StringUtils.hasLength(location)){ redisCache.setCacheObject(Constants.LOCATION + userId + ":" + LocalDate.now(), location + ";" +lon + "," + lat); }else { redisCache.setCacheObject(Constants.LOCATION + userId + ":" + LocalDate.now(), lon + "," + lat); } // 实时定位点 redisCache.setCacheObject(Constants.LOCATION + userId, lon + "," + lat); return R.ok(); } } ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -162,4 +162,8 @@ * 用户类型 */ public static final String USER_TYPE = "用户类型"; /** * 用户实时上传定位 */ public static final String LOCATION = "location:"; } ruoyi-system/src/main/java/com/ruoyi/system/mapper/TAppUserPositioningMapper.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.TAppUserPositioning; /** * <p> * 用户每日定位存储 Mapper 接口 * </p> * * @author xiaochen * @since 2025-10-21 */ public interface TAppUserPositioningMapper extends BaseMapper<TAppUserPositioning> { } ruoyi-system/src/main/java/com/ruoyi/system/mapper/TSecretConfigMapper.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.system.model.TSecretConfig; /** * <p> * 密钥 Mapper 接口 * </p> * * @author xiaochen * @since 2025-10-13 */ public interface TSecretConfigMapper extends BaseMapper<TSecretConfig> { } ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUser.java
@@ -73,5 +73,11 @@ @TableField("level") private String level; @ApiModelProperty(value = "经度") @TableField(exist = false) private String lon; @ApiModelProperty(value = "纬度") @TableField(exist = false) private String lat; } ruoyi-system/src/main/java/com/ruoyi/system/model/TAppUserPositioning.java
New file @@ -0,0 +1,49 @@ package com.ruoyi.system.model; 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 io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; import java.time.LocalDateTime; /** * <p> * 用户每日定位存储 * </p> * * @author xiaochen * @since 2025-10-21 */ @Data @EqualsAndHashCode(callSuper = false) @TableName("t_app_user_positioning") @ApiModel(value="TAppUserPositioning对象", description="用户每日定位存储") public class TAppUserPositioning implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.ASSIGN_ID) private String id; @ApiModelProperty(value = "用户id") @TableField("app_user_id") private String appUserId; @ApiModelProperty(value = "用户定位") @TableField("user_location") private String userLocation; @ApiModelProperty(value = "添加时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @TableField("create_time") private LocalDateTime createTime; } ruoyi-system/src/main/java/com/ruoyi/system/model/TSecretConfig.java
New file @@ -0,0 +1,38 @@ package com.ruoyi.system.model; 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 io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; /** * <p> * 密钥 * </p> * * @author xiaochen * @since 2025-10-13 */ @Data @EqualsAndHashCode(callSuper = false) @TableName("t_secret_config") @ApiModel(value="TSecretConfig对象", description="密钥") public class TSecretConfig implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value = "密钥") @TableField("secret_key") private String secretKey; } ruoyi-system/src/main/java/com/ruoyi/system/query/PositioningDetailQuery.java
New file @@ -0,0 +1,23 @@ package com.ruoyi.system.query; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import java.io.Serializable; @Data @ApiModel(value = "人员分布队伍实时点位查询参数PositioningDetailQuery") public class PositioningDetailQuery implements Serializable { @NotBlank(message = "用户id不能为空") @ApiModelProperty(value = "用户id") private String appUserId; @NotBlank(message = "查询时间不能为空") @ApiModelProperty(value = "查询时间 yyyy-MM-dd") private String startTime; } ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserPositioningService.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.model.TAppUserPositioning; /** * <p> * 用户每日定位存储 服务类 * </p> * * @author xiaochen * @since 2025-10-21 */ public interface TAppUserPositioningService extends IService<TAppUserPositioning> { } ruoyi-system/src/main/java/com/ruoyi/system/service/TSecretConfigService.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.system.model.TSecretConfig; /** * <p> * 密钥 服务类 * </p> * * @author xiaochen * @since 2025-10-13 */ public interface TSecretConfigService extends IService<TSecretConfig> { } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserPositioningServiceImpl.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.TAppUserPositioningMapper; import com.ruoyi.system.model.TAppUserPositioning; import com.ruoyi.system.service.TAppUserPositioningService; import org.springframework.stereotype.Service; /** * <p> * 用户每日定位存储 服务实现类 * </p> * * @author xiaochen * @since 2025-10-21 */ @Service public class TAppUserPositioningServiceImpl extends ServiceImpl<TAppUserPositioningMapper, TAppUserPositioning> implements TAppUserPositioningService { } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TSecretConfigServiceImpl.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.TSecretConfigMapper; import com.ruoyi.system.model.TSecretConfig; import com.ruoyi.system.service.TSecretConfigService; import org.springframework.stereotype.Service; /** * <p> * 密钥 服务实现类 * </p> * * @author xiaochen * @since 2025-10-13 */ @Service public class TSecretConfigServiceImpl extends ServiceImpl<TSecretConfigMapper, TSecretConfig> implements TSecretConfigService { } ruoyi-system/src/main/java/com/ruoyi/system/vo/PositioningDetailVO.java
New file @@ -0,0 +1,15 @@ package com.ruoyi.system.vo; import com.ruoyi.system.model.TAppUser; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel(value = "人员分布轨迹详情PositioningDetailVO") public class PositioningDetailVO extends TAppUser { @ApiModelProperty(value = "轨迹") private String realTimePositioning; } ruoyi-system/src/main/resources/mapper/system/TAppUserPositioningMapper.xml
New file @@ -0,0 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.system.mapper.TAppUserPositioningMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TAppUserPositioning"> <id column="id" property="id" /> <result column="app_user_id" property="appUserId" /> <result column="user_location" property="userLocation" /> <result column="create_time" property="createTime" /> </resultMap> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> id, app_user_id, user_location, create_time </sql> </mapper>