localizer
ljw 2025-09-29 17:25:23 +08:00
commit 262d04c023
14 changed files with 385 additions and 128 deletions

View File

@ -27,7 +27,7 @@ public class JT808MessageHandler extends ChannelInboundHandlerAdapter {
if (msg instanceof JT808Message) {
JT808Message message = (JT808Message) msg;
int messageId = message.getMessageId();
log.info("收到消息, 设备号: {}消息ID: 0x{}, 流水号: {}", message.getTerminalPhone(), Integer.toHexString(messageId), message.getFlowId());
// log.info("收到消息, 设备号: {}消息ID: 0x{}, 流水号: {}", message.getTerminalPhone(), Integer.toHexString(messageId), message.getFlowId());
if (messageId == 0x0100) {
JT808.register(message.getTerminalPhone(), ctx.channel());
}

View File

@ -38,7 +38,7 @@ public class TuqiangListeners {
public void onLocationReport(TerminalMessageBody message) {
ByteBuf byteBuf = message.getBody();
LocationReportMessage locationReportMsg = new LocationReportMessage(byteBuf);
log.info("终端位置信息汇报消息: {}", locationReportMsg);
// log.info("终端位置信息汇报消息: {}", locationReportMsg);
String terminalId = message.getTerminalId();
RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
@ -76,7 +76,7 @@ public class TuqiangListeners {
String terminalId = message.getTerminalId();
ByteBuf body = message.getBody();
SearchLocationResponseMessage searchLocationResponseMsg = new SearchLocationResponseMessage(body);
log.info("查询位置响应消息: {}", searchLocationResponseMsg);
// log.info("查询位置响应消息: {}", searchLocationResponseMsg);
LocationReportMessage locationReportMsg = searchLocationResponseMsg.getLocationReportMessage();
RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
@ -90,7 +90,7 @@ public class TuqiangListeners {
@TuqiangListener(messageId = TxtReport)
public void onTerminalTxtReport(TerminalMessageBody message) {
TerminalTxtMessage terminalTxtReportMsg = new TerminalTxtMessage(message.getBody());
log.info("终端文本信息汇报消息: {}", terminalTxtReportMsg);
// log.info("终端文本信息汇报消息: {}", terminalTxtReportMsg);
String txt = terminalTxtReportMsg.getTxt();
SearchDeviceInfoMessage deviceInfo = SearchDeviceInfoMessage.parse(txt);
if (deviceInfo != null) {

View File

@ -1,5 +1,6 @@
package com.njzscloud.common.mqtt.support;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.core.jackson.Jackson;
import com.njzscloud.common.mqtt.config.MqttProperties;
@ -21,7 +22,7 @@ public class MqttCliWrapper implements BeanPostProcessor {
public MqttCliWrapper(MqttProperties mqttProperties) {
String broker = mqttProperties.getBroker();
String clientId = mqttProperties.getClientId();
String clientId = mqttProperties.getClientId() + "-" + IdUtil.nanoId(5);
String username = mqttProperties.getUsername();
String password = mqttProperties.getPassword();
try {
@ -80,7 +81,7 @@ public class MqttCliWrapper implements BeanPostProcessor {
String jsonStr = null;
try {
jsonStr = Jackson.toJsonStr(msg);
log.info("mqtt 发布消息:{} {} {}", topic, qos, jsonStr);
// log.info("mqtt 发布消息:{} {} {}", topic, qos, jsonStr);
MqttMessage message = new MqttMessage(jsonStr.getBytes());
message.setQos(qos);
client.publish(topic, message);

View File

@ -17,6 +17,7 @@ import java.util.List;
*
*/
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/truck_location_track")
@RequiredArgsConstructor
@ -72,9 +73,24 @@ public class TruckLocationTrackController {
*/
@GetMapping("/history")
public SseEmitter history(@RequestParam("orderId") Long orderId,
@RequestParam("startTime") LocalDateTime startTime,
@RequestParam("endTime") LocalDateTime endTime) {
return truckLocationTrackService.history(orderId, startTime, endTime);
@RequestParam(value = "startTime", required = false) LocalDateTime startTime,
@RequestParam(value = "endTime", required = false) LocalDateTime endTime,
@RequestParam(value = "speed", defaultValue = "1") Integer speed
) {
if (speed <= 0) {
speed = 1;
} else if (speed > 60) {
speed = 60;
}
return truckLocationTrackService.history(orderId, startTime, endTime, speed);
}
/**
*
*/
@GetMapping("/realtime")
public SseEmitter realtime(@RequestParam("orderId") Long orderId) {
return truckLocationTrackService.realtime(orderId);
}

View File

@ -1,6 +1,8 @@
package com.njzscloud.supervisory.biz.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -19,11 +21,14 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
*
@ -32,19 +37,34 @@ import java.util.concurrent.TimeUnit;
@Service
public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMapper, TruckLocationTrackEntity> implements IService<TruckLocationTrackEntity> {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(200, 200, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1));
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1));
HashMap<Long, List<TruckLocationTrackEntity>> LOCATION_CACHE = new HashMap<>();
ReentrantLock lock = new ReentrantLock();
public static void send(SseEmitter emitter, TruckLocationTrackEntity data) {
public static void send(SseEmitter emitter, String eventName, TruckLocationTrackEntity data) {
try {
emitter.send(SseEmitter.event()
.id(String.valueOf(System.currentTimeMillis()))
.name("historyData")
.id(data.getId().toString())
.name(eventName)
.data(data));
} catch (IOException e) {
log.error("发送定位器历史记录失败", e);
}
}
public static void complete(SseEmitter emitter, String eventName) {
try {
emitter.send(SseEmitter.event()
.id(IdUtil.simpleUUID())
.name(eventName)
.data("complete"));
emitter.complete();
} catch (IOException e) {
log.error("发送定位器历史记录失败", e);
}
}
/**
*
*/
@ -81,7 +101,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
return PageResult.of(this.page(pageParam.toPage(), Wrappers.<TruckLocationTrackEntity>query(truckLocationTrackEntity)));
}
public SseEmitter history(Long orderId, LocalDateTime startTime, LocalDateTime endTime) {
/* public SseEmitter history(Long orderId, LocalDateTime startTime, LocalDateTime endTime, Integer speed) {
SseEmitter emitter = new SseEmitter(0L);
// 提交异步任务
@ -95,7 +115,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
// 检查是否被取消
if (Thread.currentThread().isInterrupted()) {
log.info("任务被取消");
emitter.complete();
complete(emitter);
return;
}
@ -110,7 +130,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
List<TruckLocationTrackEntity> records = resultPage.getRecords();
if (records.isEmpty()) {
// 没有更多数据,推送完成信息
emitter.complete();
complete(emitter);
break;
}
@ -118,7 +138,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
for (TruckLocationTrackEntity record : records) {
if (Thread.currentThread().isInterrupted()) {
log.info("任务被取消");
emitter.complete();
complete(emitter);
return;
}
@ -133,7 +153,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
}
// 推送当前数据
send(emitter, record);
send(emitter, "historyData", record);
// 更新上一条数据的时间
lastRecordTime = currentTime;
@ -141,7 +161,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
// 判断是否为最后一页
if (currentPage >= resultPage.getPages()) {
emitter.complete();
complete(emitter);
break;
}
@ -150,7 +170,7 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
}
// 所有数据推送完成,关闭连接
emitter.complete();
complete(emitter);
} catch (Exception e) {
// 其他异常
@ -159,11 +179,191 @@ public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMap
}, threadPoolExecutor);
// 注册连接关闭回调,中断任务
emitter.onCompletion(() -> future.cancel(true));
emitter.onTimeout(() -> future.cancel(true));
emitter.onError((e) -> future.cancel(true));
emitter.onCompletion(() -> {
log.info("连接关闭,取消任务");
future.cancel(true);
});
emitter.onTimeout(() -> {
log.info("连接超时,取消任务");
future.cancel(true);
});
emitter.onError((e) -> {
log.info("连接错误,取消任务");
future.cancel(true);
});
return emitter;
} */
public SseEmitter history(Long orderId, LocalDateTime startTime, LocalDateTime endTime, Integer speed) {
SseEmitter emitter = new SseEmitter(0L);
// 提交异步任务
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
int currentPage = 1;
// 分页查询每次500条
while (true) {
// 检查是否被取消
if (Thread.currentThread().isInterrupted()) {
log.info("任务被取消");
complete(emitter, "historyData");
return;
}
Page<TruckLocationTrackEntity> page = new Page<>(currentPage, 500);
page.addOrder(OrderItem.asc("location_time"));
// 分页查询当前页数据
IPage<TruckLocationTrackEntity> resultPage = this.page(page, Wrappers.lambdaQuery(TruckLocationTrackEntity.class)
.eq(TruckLocationTrackEntity::getOrderId, orderId)
.ge(startTime != null, TruckLocationTrackEntity::getLocationTime, startTime)
.le(endTime != null, TruckLocationTrackEntity::getLocationTime, endTime));
List<TruckLocationTrackEntity> records = resultPage.getRecords();
if (records.isEmpty()) {
// 没有更多数据,推送完成信息
complete(emitter, "historyData");
return;
}
// 处理当前页数据,按时间间隔推送
for (TruckLocationTrackEntity record : records) {
if (Thread.currentThread().isInterrupted()) {
log.info("任务被取消");
complete(emitter, "historyData");
return;
}
if (!ThreadUtil.sleep(speed * 1000)) {
log.info("任务被取消");
complete(emitter, "historyData");
return;
}
send(emitter, "historyData", record);
}
// 判断是否为最后一页
if (currentPage >= resultPage.getPages()) {
complete(emitter, "historyData");
return;
}
// 继续查询下一页
currentPage++;
}
} catch (Exception e) {
// 其他异常
emitter.completeWithError(e);
}
}, threadPoolExecutor);
// 注册连接关闭回调,中断任务
emitter.onCompletion(() -> {
log.info("连接关闭,取消任务");
future.cancel(true);
});
emitter.onTimeout(() -> {
log.info("连接超时,取消任务");
future.cancel(true);
});
emitter.onError((e) -> {
log.info("连接错误,取消任务");
future.cancel(true);
});
return emitter;
}
public void cache(TruckLocationTrackEntity truckLocationTrackEntity) {
Long orderId = truckLocationTrackEntity.getOrderId();
lock.lock();
try {
List<TruckLocationTrackEntity> value = LOCATION_CACHE.computeIfAbsent(orderId, k -> new LinkedList<>());
if (value.size() >= 10) {
value.remove(0);
}
value.add(truckLocationTrackEntity);
} finally {
lock.unlock();
}
}
public SseEmitter realtime(Long orderId) {
SseEmitter emitter = new SseEmitter(0L);
// 提交异步任务
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
// 记录上一条数据的时间,用于计算间隔
LocalDateTime lastRecordTime = null;
while (true) {
// 检查是否被取消
if (Thread.currentThread().isInterrupted()) {
log.info("任务被取消");
complete(emitter, "realtimeData");
return;
}
lock.lock();
List<TruckLocationTrackEntity> records = LOCATION_CACHE.get(orderId);
LOCATION_CACHE.remove(orderId);
lock.unlock();
if (CollUtil.isEmpty(records)) {
if (ThreadUtil.sleep(1000)) {
log.info("任务被取消");
complete(emitter, "realtimeData");
return;
}
continue;
}
// 处理当前页数据,按时间间隔推送
for (TruckLocationTrackEntity record : records) {
if (Thread.currentThread().isInterrupted()) {
log.info("任务被取消");
complete(emitter, "realtimeData");
return;
}
LocalDateTime currentTime = record.getLocationTime();
// 计算与上一条数据的时间间隔
if (lastRecordTime != null && currentTime != null) {
long interval = Duration.between(lastRecordTime, currentTime).toMillis();
if (interval > 0) {
// 按实际间隔等待
ThreadUtil.sleep(interval);
}
}
// 推送当前数据
send(emitter, "realtimeData", record);
// 更新上一条数据的时间
lastRecordTime = currentTime;
}
}
} catch (Exception e) {
// 其他异常
emitter.completeWithError(e);
}
}, threadPoolExecutor);
// 注册连接关闭回调,中断任务
// 注册连接关闭回调,中断任务
emitter.onCompletion(() -> {
log.info("连接关闭,取消任务");
future.cancel(true);
});
emitter.onTimeout(() -> {
log.info("连接超时,取消任务");
future.cancel(true);
});
emitter.onError((e) -> {
log.info("连接错误,取消任务");
future.cancel(true);
});
return emitter;
}
}

View File

@ -26,7 +26,6 @@ public class StatisticsController {
public R<?> obtainData() throws Exception {
long l = System.currentTimeMillis();
Map<String, Object> data = statisticsService.obtainData();
System.out.println("耗时: " + (System.currentTimeMillis() - l));
return R.success(data);
}
@ -39,7 +38,6 @@ public class StatisticsController {
public R<?> obtainData1() {
long l = System.currentTimeMillis();
Map<String, Object> data = supervisionStatisticsService.obtainData();
System.out.println("耗时: " + (System.currentTimeMillis() - l));
return R.success(data);
}

View File

@ -11,6 +11,7 @@ import lombok.experimental.Accessors;
@Accessors(chain = true)
public class Order {
private Long orderId;
private String orderNo;
private String realname;
private String mobile;
@ -28,4 +29,5 @@ public class Order {
private Integer finish;
private Integer carStatus;
private Integer status;
private String gps;
}

View File

@ -13,6 +13,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private int inOutGap = 300;
private DefaultPlace defaultPlace;
@Getter

View File

@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.mqtt.util.Mqtt;
import com.njzscloud.supervisory.device.contant.DeviceCode;
import com.njzscloud.supervisory.device.mapper.DeviceInfoMapper;
import com.njzscloud.supervisory.device.pojo.entity.DeviceInfoEntity;
@ -323,17 +324,17 @@ public class DeviceInfoService extends ServiceImpl<DeviceInfoMapper, DeviceInfoE
private void open(String sn) {
log.info("开门: {}", sn);
/* MqttUtil.publish("zsy/1/barrier", MapUtil.builder()
Mqtt.publish("zsy/1/barrier", MapUtil.builder()
.put("deviceNo", sn)
.build()); */
.build());
}
private void playVoice(String sn, String content, Object... params) {
String format = StrUtil.format(content, params);
log.info("播语音: {} {}", sn, format);
/* MqttUtil.publish("zsy/1/voice", MapUtil.builder()
Mqtt.publish("zsy/1/voice", MapUtil.builder()
.put("deviceNo", sn)
.put("text", format)
.build()); */
.build());
}
}

View File

@ -176,9 +176,15 @@ public class OrderInfoController {
return R.success();
}
@GetMapping("/t1")
public R<?> t1() {
orderInfoService.t1();
@GetMapping("/start_track")
public R<?> startTrack(@RequestParam("orderId") String orderId) {
orderInfoService.startTuqiangTrack(orderId);
return R.success();
}
@GetMapping("/stop_track")
public R<?> stopTrack(@RequestParam("orderId") String orderId) {
orderInfoService.stopTrack(orderId);
return R.success();
}

View File

@ -98,12 +98,20 @@ public class OrderCarInOutService extends ServiceImpl<OrderCarInOutMapper, Order
Integer roughWeight = null;
Integer tareWeight = null;
Integer settleWeight = null;
Integer roughWeight__ = orderCarInOutEntity.getRoughWeight();
if (roughWeight__ == null) {
BizTruckEntity bizTruckEntity = bizTruckService.getById(truckId);
Integer truckTareWeight = bizTruckEntity.getTareWeight();
Assert.notNull(truckTareWeight, () -> Exceptions.exception("车辆未配置皮重"));
orderCarInOutEntity.setRoughWeight(truckTareWeight);
roughWeight__ = truckTareWeight;
}
if (orderCategory == OrderCategory.DuanBoChu) {
roughWeight = truckLeavingOrderParam.getWeight();
settleWeight = roughWeight - orderCarInOutEntity.getRoughWeight();
settleWeight = roughWeight - roughWeight__;
} else {
tareWeight = truckLeavingOrderParam.getWeight();
settleWeight = orderCarInOutEntity.getRoughWeight() - tareWeight;
settleWeight = roughWeight__ - tareWeight;
}
Integer roughWeight_ = roughWeight;
Integer tareWeight_ = tareWeight;

View File

@ -29,6 +29,7 @@ import com.njzscloud.supervisory.biz.pojo.entity.TruckLocationTrackEntity;
import com.njzscloud.supervisory.biz.service.BizAuditConfigService;
import com.njzscloud.supervisory.biz.service.BizWarnService;
import com.njzscloud.supervisory.biz.service.TruckLocationTrackService;
import com.njzscloud.supervisory.config.AppProperties;
import com.njzscloud.supervisory.constant.Constant;
import com.njzscloud.supervisory.expense.contant.ExpenseItemCategory;
import com.njzscloud.supervisory.expense.contant.Scope;
@ -40,10 +41,7 @@ import com.njzscloud.supervisory.order.contant.OrderCategory;
import com.njzscloud.supervisory.order.contant.OrderStatus;
import com.njzscloud.supervisory.order.contant.OrderViewType;
import com.njzscloud.supervisory.order.mapper.OrderInfoMapper;
import com.njzscloud.supervisory.order.pojo.entity.OrderCargoPlaceEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderExpenseItemsEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderGoodsEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderInfoEntity;
import com.njzscloud.supervisory.order.pojo.entity.*;
import com.njzscloud.supervisory.order.pojo.param.*;
import com.njzscloud.supervisory.order.pojo.result.*;
import com.njzscloud.supervisory.sys.auth.pojo.result.MyResult;
@ -54,6 +52,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
@ -80,6 +79,22 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
private final ExpenseItemsConfigService expenseItemsConfigService;
private final TruckLocationTrackService truckLocationTrackService;
private final BizWarnService bizWarnService;
private final AppProperties appProperties;
private static void stopTuqiangTrack(String gpsId) {
CompletableFuture.runAsync(() -> {
Assert.notEmpty(gpsId, () -> Exceptions.clierr("车辆未绑定GPS"));
Mqtt.publish("location/track", MapUtil.builder()
.put("terminalId", gpsId)
.put("interval", 0)
.build());
Mqtt.unsubscribe(gpsId + "/track_location");
}).whenComplete((aVoid, throwable) -> {
if (throwable != null) {
log.error("关闭GPS失败", throwable);
}
});
}
/**
*
@ -625,6 +640,10 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
String gpsId = truckInfo.getGps();
String licensePlate = truckInfo.getLicensePlate();
startTuqiangTrack(gpsId, licensePlate, orderInfoId, truckId);
}
private void startTuqiangTrack(String gpsId, String licensePlate, Long orderInfoId, Long truckId) {
CompletableFuture.runAsync(() -> {
Assert.notEmpty(gpsId, () -> Exceptions.clierr("车辆未绑定GPS"));
Mqtt.subscribe(gpsId + "/track_location", (msg) -> {
@ -640,7 +659,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
);
}
log.info("mqtt 收到消息:{} {}", gpsId + "/track_location", realtimeLocationResult);
truckLocationTrackService.save(new TruckLocationTrackEntity()
TruckLocationTrackEntity entity = new TruckLocationTrackEntity()
.setOrderId(orderInfoId)
.setTruckId(truckId)
.setTerminalId(gpsId)
@ -651,12 +670,13 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
.setLocationTime(LocalDateTime.now())
.setDirection(realtimeLocationResult.getDirection())
.setOverspeed(realtimeLocationResult.isOverspeed())
.setCompensate(realtimeLocationResult.getType() == 1)
);
.setCompensate(realtimeLocationResult.getType() == 1);
truckLocationTrackService.save(entity);
truckLocationTrackService.cache(entity);
});
Mqtt.publish("location/track", MapUtil.builder()
.put("terminalId", gpsId)
.put("interval", 1)
.put("interval", 3)
.build());
}).whenComplete((aVoid, throwable) -> {
if (throwable != null) {
@ -665,43 +685,28 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
});
}
public void t1() {
CompletableFuture.runAsync(() -> {
String gpsId = "61000602070";
long orderInfoId = 1L;
long truckId = 1L;
Mqtt.subscribe(gpsId + "/track_location", (msg) -> {
RealtimeLocationResult realtimeLocationResult = msg.getMsg(RealtimeLocationResult.class);
if (realtimeLocationResult == null) {
return;
}
if (realtimeLocationResult.isOverspeed()) {
bizWarnService.save(new BizWarnEntity()
.setWarnCategory(WarnCategory.SPEED.getVal())
.setWarnContent(StrUtil.format("{} 已超速,当前时速 {}km/h", "京AAAAAA", realtimeLocationResult.getSpeed()))
.setOrderId(orderInfoId)
);
}
log.info("mqtt 收到消息:{} {}", gpsId + "/track_location", realtimeLocationResult);
truckLocationTrackService.save(new TruckLocationTrackEntity()
.setOrderId(orderInfoId)
.setTruckId(truckId)
.setTerminalId(gpsId)
.setLatitude(realtimeLocationResult.getLatitude())
.setLongitude(realtimeLocationResult.getLongitude())
.setAltitude(realtimeLocationResult.getAltitude())
.setSpeed(realtimeLocationResult.getSpeed())
.setLocationTime(LocalDateTime.now())
.setDirection(realtimeLocationResult.getDirection())
.setOverspeed(realtimeLocationResult.isOverspeed())
.setCompensate(realtimeLocationResult.getType() == 1)
);
});
}).whenComplete((aVoid, throwable) -> {
if (throwable != null) {
log.error("开启GPS失败", throwable);
}
});
public void startTuqiangTrack(String orderId) {
OrderInfoEntity orderInfo = this.getOne(Wrappers.lambdaQuery(OrderInfoEntity.class)
.eq(OrderInfoEntity::getSn, orderId)
.or().eq(OrderInfoEntity::getId, orderId)
);
Long orderInfoId = orderInfo.getId();
Long truckId = orderInfo.getTruckId();
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String gpsId = truckInfo.getGps();
String licensePlate = truckInfo.getLicensePlate();
startTuqiangTrack(gpsId, licensePlate, orderInfoId, truckId);
}
public void stopTrack(String orderId) {
OrderInfoEntity orderInfo = this.getOne(Wrappers.lambdaQuery(OrderInfoEntity.class)
.eq(OrderInfoEntity::getSn, orderId)
.or().eq(OrderInfoEntity::getId, orderId)
);
Long truckId = orderInfo.getTruckId();
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String gpsId = truckInfo.getGps();
stopTuqiangTrack(gpsId);
}
public void cancel(Long orderId) {
@ -720,18 +725,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
Long truckId = orderInfo.getTruckId();
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String gpsId = truckInfo.getGps();
CompletableFuture.runAsync(() -> {
if (StrUtil.isEmpty(gpsId)) return;
Mqtt.publish("location/track", MapUtil.builder()
.put("terminalId", gpsId)
.put("interval", 0)
.build());
Mqtt.unsubscribe(gpsId + "/track_location");
}).whenComplete((aVoid, throwable) -> {
if (throwable != null) {
log.error("关闭GPS失败", throwable);
}
});
stopTuqiangTrack(gpsId);
}
@Transactional(rollbackFor = Exception.class)
@ -771,6 +765,37 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
OrderInfoEntity orderInfoEntity = this.getById(truckComingOrderParam.getOrderId());
Assert.notNull(orderInfoEntity, () -> Exceptions.clierr("订单不存在"));
OrderStatus orderStatus = orderInfoEntity.getOrderStatus();
if (orderStatus == OrderStatus.YiJinChang) {
Long carInOutId = orderInfoEntity.getCarInOutId();
if (carInOutId == null) {
log.warn("订单{}不存在关联的车辆进场记录", orderInfoEntity.getId());
return;
}
OrderCarInOutEntity orderCarInOutEntity = orderCarInOutService.getById(carInOutId);
if (orderCarInOutEntity == null) {
log.warn("订单{}不存在关联的车辆进场记录", orderInfoEntity.getId());
return;
}
LocalDateTime inTime = orderCarInOutEntity.getInTime();
long interval = Duration.between(inTime, LocalDateTime.now()).toMillis() / 1000;
int inOutGap = appProperties.getInOutGap();
if (inOutGap <= 0) {
inOutGap = 300;
}
if (interval <= inOutGap) {
log.warn("车辆进场时间间隔不能小于{}秒,订单{}", inOutGap, orderInfoEntity.getSn());
return;
}
log.info("进道闸转出道闸,订单{}", orderInfoEntity.getSn());
truckLeaving(new TruckLeavingOrderParam()
.setOrderId(orderInfoEntity.getId())
.setWeight(truckComingOrderParam.getWeight())
.setFrontPhoto(truckComingOrderParam.getFrontPhoto())
.setBodyPhoto(truckComingOrderParam.getBodyPhoto()),
0);
return;
}
Assert.isTrue(orderStatus == OrderStatus.QingYunZhong, () -> Exceptions.clierr("当前订单状态,无法进场"));
OrderCategory orderCategory = orderInfoEntity.getOrderCategory();
@ -792,41 +817,33 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
@Transactional(rollbackFor = Exception.class)
public void truckLeaving(TruckLeavingOrderParam truckLeavingOrderParam, int i) {
OrderInfoEntity orderInfoEntity = this.getById(truckLeavingOrderParam.getOrderId());
Assert.notNull(orderInfoEntity, () -> Exceptions.clierr("订单不存在"));
OrderStatus orderStatus = orderInfoEntity.getOrderStatus();
Assert.isTrue(orderStatus == OrderStatus.YiJinChang, () -> Exceptions.clierr("当前订单状态,无法出场"));
baseMapper.busyDriver(orderInfoEntity.getDriverId(), Boolean.FALSE);
baseMapper.busyTruck(orderInfoEntity.getTruckId(), Boolean.FALSE);
this.updateById(new OrderInfoEntity()
.setAutoOrder(3 ^ (i << 1))
.setId(orderInfoEntity.getId())
.setOrderStatus(OrderStatus.YiChuChang)
);
OrderCategory orderCategory = orderInfoEntity.getOrderCategory();
Long truckId = orderInfoEntity.getTruckId();
// 计算本单净重(或结算重量),作为结算时的数量依据
Integer settleWeight = orderCarInOutService.truckOut(orderInfoEntity.getCarInOutId(), truckLeavingOrderParam, orderCategory, truckId);
try {
Assert.notNull(orderInfoEntity, () -> Exceptions.clierr("订单不存在"));
OrderStatus orderStatus = orderInfoEntity.getOrderStatus();
Assert.isTrue(orderStatus == OrderStatus.YiJinChang, () -> Exceptions.clierr("当前订单状态,无法出场"));
baseMapper.busyDriver(orderInfoEntity.getDriverId(), Boolean.FALSE);
baseMapper.busyTruck(orderInfoEntity.getTruckId(), Boolean.FALSE);
this.updateById(new OrderInfoEntity()
.setAutoOrder(3 ^ (i << 1))
.setId(orderInfoEntity.getId())
.setOrderStatus(OrderStatus.YiChuChang)
);
OrderCategory orderCategory = orderInfoEntity.getOrderCategory();
// 计算本单净重(或结算重量),作为结算时的数量依据
Integer settleWeight = orderCarInOutService.truckOut(orderInfoEntity.getCarInOutId(), truckLeavingOrderParam, orderCategory, truckId);
// 结算(目前仅针对清运公司):
// 1) 复制“产品”到 order_expense_items
// 2) 从 expense_items_config 读取可用付费项并按 scope 过滤all / customer_type=QiYe|GeTi / customer 包含 trans_company_id
// 3) 合并集合,计算 total_money 与 settle_money并批量落库。
settleForTransCompany(orderInfoEntity, settleWeight);
// TODO 关闭 GPS
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String gpsId = truckInfo.getGps();
CompletableFuture.runAsync(() -> {
Assert.notEmpty(gpsId, () -> Exceptions.clierr("车辆未绑定GPS"));
Mqtt.publish("location/track", MapUtil.builder()
.put("terminalId", gpsId)
.put("interval", 0)
.build());
Mqtt.unsubscribe(gpsId + "/track_location");
}).whenComplete((aVoid, throwable) -> {
if (throwable != null) {
log.error("关闭GPS失败", throwable);
}
});
// 结算(目前仅针对清运公司):
// 1) 复制“产品”到 order_expense_items
// 2) 从 expense_items_config 读取可用付费项并按 scope 过滤all / customer_type=QiYe|GeTi / customer 包含 trans_company_id
// 3) 合并集合,计算 total_money 与 settle_money并批量落库。
settleForTransCompany(orderInfoEntity, settleWeight);
} finally {
// TODO 关闭 GPS
BizTruckEntity truckInfo = baseMapper.getTruckInfo(truckId);
String gpsId = truckInfo.getGps();
stopTuqiangTrack(gpsId);
}
}
/**
@ -899,12 +916,12 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
for (OrderExpenseItemsEntity item : extraItems) {
// total_money = quantity * unit_price 如果计费策略是按吨总金额计算时数量需要÷1000
BigDecimal quantity = new BigDecimal(item.getQuantity() == null ? 0 : item.getQuantity());
// 如果计费策略是按吨数量需要除以1000
if (MoneyStrategy.Dun.getVal().equals(item.getMoneyStrategy())) {
quantity = quantity.divide(new BigDecimal("1000"), 6, BigDecimal.ROUND_HALF_UP);
}
BigDecimal totalMoney = item.getUnitPrice().multiply(quantity);
// settle_money = total_money + discount_money + revise_moneydiscount、revise 可为正负)
BigDecimal discount = item.getDiscountMoney() == null ? BigDecimal.ZERO : item.getDiscountMoney();

View File

@ -128,6 +128,10 @@ public class UserService extends ServiceImpl<UserMapper, UserEntity> implements
String username = userQueryParam.getUsername();
Boolean disabled = userQueryParam.getDisabled();
QueryWrapper<UserDetailResult> ew = Wrappers.<UserDetailResult>query()
.and(it ->
it.eq("a.biz_obj", BizObj.SiBang)
.or().isNull("a.biz_obj")
)
.like(StrUtil.isNotBlank(nickname), "a.nickname", nickname)
.eq(gender != null, "a.gender", gender)
.like(StrUtil.isNotBlank(email), "a.email", email)

View File

@ -89,7 +89,8 @@
</select>
<select id="getOrders" resultType="com.njzscloud.supervisory.bs.pojo.result.Order">
SELECT a.sn order_no,
SELECT a.id order_id,
a.sn order_no,
d.nickname realname,
d.phone mobile,
i.category_name goods_category_name,
@ -112,7 +113,8 @@
h.address,
h.lng lon,
h.lat,
IF(a.order_status = 'YiWanCheng', 1, 0) finish
IF(a.order_status = 'YiWanCheng', 1, 0) finish,
g.gps
FROM order_info a
LEFT JOIN (SELECT a.id, a.company_name, b.nickname
FROM biz_company a