diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java index d89f6f3..02a20d1 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/areaSub/service/impl/AreaSubServiceImpl.java @@ -3,7 +3,6 @@ package com.ruoyi.bst.areaSub.service.impl; import java.util.Collections; import java.util.List; -import com.ruoyi.common.utils.ServiceUtil; import org.locationtech.jts.geom.Geometry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -19,6 +18,7 @@ import com.ruoyi.bst.areaSub.service.AreaSubService; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.collection.CollectionUtils; import com.ruoyi.common.utils.map.GeoUtils; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/domain/DeviceVO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/domain/DeviceVO.java index 3038847..30e2c61 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/domain/DeviceVO.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/domain/DeviceVO.java @@ -29,6 +29,8 @@ public class DeviceVO extends Device { private BigDecimal modelLowVoltage; @ApiModelProperty("车型续航") private BigDecimal modelFullEndurance; + @ApiModelProperty("车型是否允许用户打开坐垫锁") + private Boolean modelEnableSeat; // 运营区 @ApiModelProperty("运营区名称") diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml index 55df5ef..58cc941 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/mapper/DeviceMapper.xml @@ -51,6 +51,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" bm.full_voltage as model_full_voltage, bm.low_voltage as model_low_voltage, bm.full_endurance as model_full_endurance, + bm.enable_seat as model_enable_seat, ba.name as area_name, ba.user_id as area_user_id, ba.undercharge as area_undercharge, @@ -132,6 +133,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and bd.last_time >= #{query.lastTimeStart} and bd.location_type = #{query.locationType} and bd.order_device_id = #{query.orderDeviceId} + and bm.enable_seat = #{query.modelEnableSeat} and ( bd.sn like concat('%', #{query.keyword}, '%') diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java index 57b9db9..650cc70 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java @@ -205,4 +205,14 @@ public class DeviceUtil { device.setOnlineStatus(DeviceOnlineStatus.ONLINE.getStatus()); device.setLastOnlineTime(at); } + + /** + * 判断设备是否离线 + * + * @param device 设备 + * @return 是否离线 + */ + public static boolean isOffline(DeviceVO device) { + return device != null && device.getOnlineStatus() != null && DeviceOnlineStatus.OFFLINE.getStatus().equals(device.getOnlineStatus()); + } } \ No newline at end of file diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/model/domain/Model.java b/ruoyi-service/src/main/java/com/ruoyi/bst/model/domain/Model.java index 243748a..3917ffd 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/model/domain/Model.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/model/domain/Model.java @@ -71,6 +71,10 @@ public class Model extends BaseEntity implements LogBizParam @Min(value = 0, message = "骑行低电量提醒不能小于0") private Integer lowBatteryReminder; + @Excel(name = "是否允许用户打开坐垫锁") + @ApiModelProperty("是否允许用户打开坐垫锁") + private Boolean enableSeat; + @Override public Object logBizId() { return id; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/model/mapper/ModelMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/model/mapper/ModelMapper.xml index 23ec1dd..c4c8510 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/model/mapper/ModelMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/model/mapper/ModelMapper.xml @@ -19,6 +19,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" bm.deleted, bm.low_battery_reminder_switch, bm.low_battery_reminder, + bm.enable_seat, su.nick_name as user_name from @@ -36,6 +37,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and bm.deleted = false and bm.low_battery_reminder_switch = #{query.lowBatteryReminderSwitch} and su.nick_name like concat('%', #{query.userName}, '%') + and bm.enable_seat = #{query.enableSeat} and bm.id in @@ -86,6 +88,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" remark, low_battery_reminder_switch, low_battery_reminder, + enable_seat, #{areaId}, @@ -98,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{remark}, #{lowBatteryReminderSwitch}, #{lowBatteryReminder}, + #{enableSeat}, @@ -119,6 +123,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" remark = #{data.remark}, low_battery_reminder_switch = #{data.lowBatteryReminderSwitch}, low_battery_reminder = #{data.lowBatteryReminder}, + enable_seat = #{data.enableSeat}, diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderSeatDTO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderSeatDTO.java new file mode 100644 index 0000000..efe7824 --- /dev/null +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderSeatDTO.java @@ -0,0 +1,23 @@ +package com.ruoyi.bst.order.domain.dto; + +import java.math.BigDecimal; + +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class OrderSeatDTO { + + @ApiModelProperty("订单ID") + @NotNull(message = "订单ID不能为空") + private Long orderId; + + @ApiModelProperty("手机经度") + private BigDecimal lon; + + @ApiModelProperty("手机纬度") + private BigDecimal lat; + +} diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java index 82e3c3c..d0f5d6a 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java @@ -14,6 +14,7 @@ import com.ruoyi.bst.order.domain.dto.OrderCreateDTO; import com.ruoyi.bst.order.domain.dto.OrderEndDTO; import com.ruoyi.bst.order.domain.dto.OrderOpenDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDTO; +import com.ruoyi.bst.order.domain.dto.OrderSeatDTO; import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO; import com.ruoyi.bst.order.domain.vo.OrderEndVO; import com.ruoyi.bst.order.domain.vo.OrderFeeVO; @@ -209,4 +210,12 @@ public interface OrderService { * @param distance 距离 */ public int updateDisatance(Long id, BigDecimal distance); + + /** + * 打开坐垫锁 + * + * @param dto 参数 + * @return 结果 + */ + public boolean seat(OrderSeatDTO dto); } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderValidator.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderValidator.java index e8afc76..2fea2d9 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderValidator.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderValidator.java @@ -101,4 +101,9 @@ public interface OrderValidator { * 是否是用户 */ boolean isUser(Long orderId, Long userId); + + /** + * 是否是用户 + */ + boolean isUser(OrderVO order, Long userId); } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java index e32ee77..2928464 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java @@ -5,7 +5,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import com.ruoyi.bst.device.service.DeviceAssembler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -21,6 +20,7 @@ import com.ruoyi.bst.areaSub.service.AreaSubService; import com.ruoyi.bst.channel.domain.ChannelVO; import com.ruoyi.bst.channel.service.ChannelService; import com.ruoyi.bst.device.domain.DeviceVO; +import com.ruoyi.bst.device.service.DeviceAssembler; import com.ruoyi.bst.device.service.DeviceIotService; import com.ruoyi.bst.device.service.DeviceService; import com.ruoyi.bst.locationLog.domain.vo.LocationLogPositionVO; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java index 2c23da9..22b62a1 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import com.ruoyi.bst.device.service.DeviceAssembler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.support.TransactionTemplate; @@ -27,6 +26,7 @@ import com.ruoyi.bst.device.domain.DeviceVO; import com.ruoyi.bst.device.domain.enums.DeviceLocationType; import com.ruoyi.bst.device.domain.enums.DeviceUnLockType; import com.ruoyi.bst.device.domain.vo.DeviceIotVO; +import com.ruoyi.bst.device.service.DeviceAssembler; import com.ruoyi.bst.device.service.DeviceIotService; import com.ruoyi.bst.device.service.DeviceService; import com.ruoyi.bst.device.utils.DeviceUtil; @@ -49,6 +49,7 @@ import com.ruoyi.bst.order.domain.dto.OrderCreateDTO; import com.ruoyi.bst.order.domain.dto.OrderEndDTO; import com.ruoyi.bst.order.domain.dto.OrderOpenDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDTO; +import com.ruoyi.bst.order.domain.dto.OrderSeatDTO; import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO; import com.ruoyi.bst.order.domain.enums.OrderReturnType; import com.ruoyi.bst.order.domain.enums.OrderStatus; @@ -83,6 +84,7 @@ import com.ruoyi.common.utils.MathUtils; import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.SnowFlakeUtil; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.collection.CollectionUtils; import com.ruoyi.system.user.service.UserService; @@ -498,18 +500,14 @@ public class OrderServiceImpl implements OrderService { private void handleDeviceLocationAsync(DeviceVO device, BigDecimal lon, BigDecimal lat) { if (device != null && device.getId() != null && StringUtils.isNotBlank(device.getMac()) && DeviceUtil.validLocation(lon, lat)) { scheduledExecutorService.execute(() -> { - device.setLongitude(lon); - device.setLatitude(lat); - device.setLocationType(DeviceLocationType.PHONE.getCode()); - device.setLastLocationTime(LocalDateTime.now()); - // 若卫星信号弱,则更新设备定位 - if (DeviceUtil.isLowSatelliteSignal(device)) { + // 若卫星信号弱或者离线,则更新设备定位 + if (DeviceUtil.isLowSatelliteSignal(device) || DeviceUtil.isOffline(device)) { Device data = new Device(); data.setMac(device.getMac()); - data.setLongitude(device.getLongitude()); - data.setLatitude(device.getLatitude()); - data.setLocationType(device.getLocationType()); + data.setLongitude(lon); + data.setLatitude(lat); + data.setLocationType(DeviceLocationType.PHONE.getCode()); data.setLastLocationTime(LocalDateTime.now()); int rows = deviceIotService.updateIot(data); if (rows != 1) { @@ -517,12 +515,19 @@ public class OrderServiceImpl implements OrderService { } } - // 直接保存定位日志 - LocationLog locationLog = locationLogConverter.toPo(device); + // 直接保存手机定位日志 + DeviceVO vo = new DeviceVO(); + BeanUtils.copyProperties(device, vo); + vo.setLongitude(lon); + vo.setLatitude(lat); + vo.setLocationType(DeviceLocationType.PHONE.getCode()); + vo.setLastLocationTime(LocalDateTime.now()); + LocationLog locationLog = locationLogConverter.toPo(vo); if (locationLog == null) { log.error("通过手机定位转换定位日志失败: {}", device.getMac()); return; } + // 暂存到Redis缓存 redisCache.rightPush(CacheConstants.LOCATION_LOG_QUEUE, locationLog); @@ -890,4 +895,26 @@ public class OrderServiceImpl implements OrderService { return orderMapper.updateOrder(data); } + @Override + public boolean seat(OrderSeatDTO dto) { + OrderVO order = this.selectOrderById(dto.getOrderId()); + ServiceUtil.assertion(order == null, "ID为%s的订单不存在", dto.getOrderId()); + ServiceUtil.assertion(!OrderStatus.inUse().contains(order.getStatus()), "ID为%s的订单当前状态不允许打开坐垫锁", dto.getOrderId()); + + // 查询设备 + DeviceVO device = deviceService.selectDeviceById(order.getDeviceId()); + ServiceUtil.assertion(device == null, "ID为%s的设备不存在", order.getDeviceId()); + boolean enableSeat = device.getModelEnableSeat() != null && device.getModelEnableSeat(); + ServiceUtil.assertion(!enableSeat, "ID为%s的设备不允许用户打开坐垫锁", order.getDeviceId()); + deviceAssembler.assembleIot(device); + + // 设置日志参数 + this.setLogParam(device); + + // 异步使用手机定位更新设备定位 + this.handleDeviceLocationAsync(device, dto.getLon(), dto.getLat()); + + return deviceIotService.unlockSeat(device, "订单打开坐垫锁:" + order.getNo(), false); + } + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java index 8a3239e..199d8a9 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java @@ -7,8 +7,6 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; -import com.ruoyi.bst.device.utils.DeviceUtil; -import com.ruoyi.bst.orderDevice.domain.enums.OrderDeviceStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -21,6 +19,7 @@ import com.ruoyi.bst.device.domain.DeviceQuery; import com.ruoyi.bst.device.domain.DeviceVO; import com.ruoyi.bst.device.domain.enums.DeviceStatus; import com.ruoyi.bst.device.service.DeviceService; +import com.ruoyi.bst.device.utils.DeviceUtil; import com.ruoyi.bst.model.domain.ModelVO; import com.ruoyi.bst.order.domain.OrderQuery; import com.ruoyi.bst.order.domain.OrderVO; @@ -121,7 +120,8 @@ public class OrderValidatorImpl implements OrderValidator{ } // 是否是下单用户 - private boolean isUser(OrderVO order, Long userId) { + @Override + public boolean isUser(OrderVO order, Long userId) { return order != null && userId != null && Objects.equals(order.getUserId(), userId); } @@ -244,4 +244,5 @@ public class OrderValidatorImpl implements OrderValidator{ OrderVO order = orderMapper.selectOrderById(orderId); return isUser(order, userId); } + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java index 6f19b62..0b6c3d1 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java @@ -141,7 +141,7 @@ public class OrderUtil { vo.setMobileAreaSub(mobileAreaSub); // 是否在停车点 boolean inParking = deviceAreaSub != null || mobileAreaSub != null; - vo.setInParking(inParking); + vo.setInParking(inParking); // 实际停车点 if (deviceAreaSub != null) { diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/domain/OrderDeviceVO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/domain/OrderDeviceVO.java index d7366f9..8b7378d 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/domain/OrderDeviceVO.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/domain/OrderDeviceVO.java @@ -46,6 +46,8 @@ public class OrderDeviceVO extends OrderDevice{ // 车型 @ApiModelProperty("车型") private String deviceModelName; + @ApiModelProperty("车型是否允许用户打开坐垫锁") + private Boolean deviceModelEnableSeat; // 设备剩余续航(公里) public BigDecimal getDeviceRemainEndurance() { diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/mapper/OrderDeviceMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/mapper/OrderDeviceMapper.xml index ce54822..e6ad75c 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/mapper/OrderDeviceMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/orderDevice/mapper/OrderDeviceMapper.xml @@ -44,7 +44,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" bd.latitude as device_latitude, su.nick_name as order_user_name, mch.nick_name as device_mch_name, - bm.name as device_model_name + bm.name as device_model_name, + bm.enable_seat as device_model_eanble_seat from bst_order_device bod left join bst_order bo on bo.id = bod.order_id left join bst_device bd on bd.id = bod.device_id @@ -75,6 +76,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and bod.end_area_sub_name like concat('%', #{query.endAreaSubName}, '%') and bod.return_mode = #{query.returnMode} and bm.name like concat('%', #{query.deviceModelName}, '%') + and bm.enable_seat = #{query.deviceModelEnableSeat} and bod.status in diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java b/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java index bee5b60..8eab379 100644 --- a/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java +++ b/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java @@ -21,6 +21,7 @@ import com.ruoyi.bst.order.domain.dto.OrderCloseDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderCreateDTO; import com.ruoyi.bst.order.domain.dto.OrderEndDTO; import com.ruoyi.bst.order.domain.dto.OrderOpenDeviceDTO; +import com.ruoyi.bst.order.domain.dto.OrderSeatDTO; import com.ruoyi.bst.order.domain.enums.OrderReturnType; import com.ruoyi.bst.order.domain.enums.OrderStatus; import com.ruoyi.bst.order.domain.vo.OrderEndVO; @@ -214,4 +215,17 @@ public class AppOrderController extends BaseController { return toAjax(orderService.changeDevice(dto)); } + @ApiOperation("打开坐垫锁") + @PutMapping("/seat") + @Log(title = "打开坐垫锁", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.ORDER) + public AjaxResult seat(@RequestBody @Validated OrderSeatDTO dto) { + // 设置日志参数 + LogParamHolder.set(LogParamHolder.PARAM_LON, dto.getLon()); + LogParamHolder.set(LogParamHolder.PARAM_LAT, dto.getLat()); + + OrderVO order = orderService.selectOrderById(dto.getOrderId()); + ServiceUtil.assertion(!orderValidator.isUser(order, getUserId()), "您无权操作ID为%s的订单打开坐垫锁", order.getId()); + return success(orderService.seat(dto)); + } + }