opt:西门子优化
This commit is contained in:
@@ -94,7 +94,13 @@ public class NDCAgvServiceImpl implements NDCAgvService {
|
|||||||
//如果起始点在PS15起始点位区间、终点也在PS15终点区间,则使用PS15,type=2其他情况,type =1
|
//如果起始点在PS15起始点位区间、终点也在PS15终点区间,则使用PS15,type=2其他情况,type =1
|
||||||
StorageCell startStorageCell = storageCellService.getByCode(inst.getStart_point_code());
|
StorageCell startStorageCell = storageCellService.getByCode(inst.getStart_point_code());
|
||||||
StorageCell endStorageCell = storageCellService.getByCode(inst.getNext_point_code());
|
StorageCell endStorageCell = storageCellService.getByCode(inst.getNext_point_code());
|
||||||
if ((null != startStorageCell && null != endStorageCell)
|
if(null != startStorageCell && null != endStorageCell
|
||||||
|
&& "small".equals(inst.getCar_type())){
|
||||||
|
inst.setCar_type("1");
|
||||||
|
startAddress = deviceService.queryEndAddressBydeviceCode(inst.getStart_point_code());
|
||||||
|
nextAddress = deviceService.queryAddressBydeviceCode(inst.getNext_point_code());
|
||||||
|
}
|
||||||
|
else if ((null != startStorageCell && null != endStorageCell)
|
||||||
&& (("start".equals(inst.getCar_type()) && "2".equals(startStorageCell.getCar_type()))
|
&& (("start".equals(inst.getCar_type()) && "2".equals(startStorageCell.getCar_type()))
|
||||||
|| "end".equals(inst.getCar_type()) && "2".equals(endStorageCell.getCar_type())
|
|| "end".equals(inst.getCar_type()) && "2".equals(endStorageCell.getCar_type())
|
||||||
|| "new_car".equals(startStorageCell.getRemark())
|
|| "new_car".equals(startStorageCell.getRemark())
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ public interface AcsAgvUsageRecordMapper extends BaseMapper<AcsAgvUsageRecord> {
|
|||||||
|
|
||||||
AcsAgvUsageRecord selectActiveByDeviceCode(@Param("deviceCode") String deviceCode);
|
AcsAgvUsageRecord selectActiveByDeviceCode(@Param("deviceCode") String deviceCode);
|
||||||
|
|
||||||
|
AcsAgvUsageRecord selectActiveByInstructionCode(@Param("instructionCode") String instructionCode);
|
||||||
|
|
||||||
List<AcsAgvUsageRecord> selectByDeviceCodeAndDate(@Param("deviceCode") String deviceCode, @Param("workDate") Date workDate);
|
List<AcsAgvUsageRecord> selectByDeviceCodeAndDate(@Param("deviceCode") String deviceCode, @Param("workDate") Date workDate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,15 @@
|
|||||||
LIMIT 1
|
LIMIT 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectActiveByInstructionCode" resultMap="BaseResultMap">
|
||||||
|
SELECT * FROM acs_agv_usage_record
|
||||||
|
WHERE instruction_code = #{instructionCode}
|
||||||
|
AND status = '0'
|
||||||
|
AND is_active = '1'
|
||||||
|
ORDER BY start_time DESC
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectByDeviceCodeAndDate" resultMap="BaseResultMap">
|
<select id="selectByDeviceCodeAndDate" resultMap="BaseResultMap">
|
||||||
SELECT * FROM acs_agv_usage_record
|
SELECT * FROM acs_agv_usage_record
|
||||||
WHERE device_code = #{deviceCode}
|
WHERE device_code = #{deviceCode}
|
||||||
|
|||||||
@@ -83,4 +83,12 @@ public class AgvUsageController {
|
|||||||
agvUsageService.endWork(deviceCode, taskCode, instructionCode);
|
agvUsageService.endWork(deviceCode, taskCode, instructionCode);
|
||||||
return new ResponseEntity<>("success", HttpStatus.OK);
|
return new ResponseEntity<>("success", HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/monthly")
|
||||||
|
@Log("获取月度AGV使用率统计")
|
||||||
|
@ApiOperation("获取月度AGV使用率统计")
|
||||||
|
public ResponseEntity<Object> getMonthlyStatistics() {
|
||||||
|
List<Map<String, Object>> result = agvUsageService.getMonthlyAgvUsageRate();
|
||||||
|
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,4 +22,6 @@ public interface AcsAgvUsageService {
|
|||||||
List<Map<String, Object>> getAgvUsageRate(Date startDate, Date endDate);
|
List<Map<String, Object>> getAgvUsageRate(Date startDate, Date endDate);
|
||||||
|
|
||||||
Map<String, Object> getAgvRealtimeStatus();
|
Map<String, Object> getAgvRealtimeStatus();
|
||||||
|
|
||||||
|
List<Map<String, Object>> getMonthlyAgvUsageRate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cn.hutool.core.util.IdUtil;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.nl.acs.agv_usage.domain.AcsAgvDailyStatistics;
|
import org.nl.acs.agv_usage.domain.AcsAgvDailyStatistics;
|
||||||
import org.nl.acs.agv_usage.domain.AcsAgvUsageRecord;
|
import org.nl.acs.agv_usage.domain.AcsAgvUsageRecord;
|
||||||
import org.nl.acs.agv_usage.mapper.AcsAgvDailyStatisticsMapper;
|
import org.nl.acs.agv_usage.mapper.AcsAgvDailyStatisticsMapper;
|
||||||
@@ -37,36 +38,58 @@ public class AcsAgvUsageServiceImpl implements AcsAgvUsageService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void startWork(String deviceCode, String deviceName, String taskCode, String instructionCode) {
|
public void startWork(String deviceCode, String deviceName, String taskCode, String instructionCode) {
|
||||||
AcsAgvUsageRecord existingRecord = usageRecordMapper.selectActiveByDeviceCode(deviceCode);
|
if(StringUtils.isBlank(instructionCode)) {
|
||||||
if (existingRecord != null) {
|
log.warn("指令号为空,无法开始工作记录");
|
||||||
log.warn("AGV {} 已有工作中的记录,先结束上一条记录", deviceCode);
|
return;
|
||||||
endWork(deviceCode, existingRecord.getTask_code(), existingRecord.getInstruction_code());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AcsAgvUsageRecord record = new AcsAgvUsageRecord();
|
AcsAgvUsageRecord existingRecord = usageRecordMapper.selectActiveByInstructionCode(instructionCode);
|
||||||
record.setId(IdUtil.simpleUUID());
|
if (existingRecord != null) {
|
||||||
record.setDevice_code(deviceCode);
|
// 如果记录已存在,更新车号和设备名称
|
||||||
record.setDevice_name(deviceName);
|
if (StringUtils.isNotBlank(deviceCode)) {
|
||||||
record.setTask_code(taskCode);
|
existingRecord.setDevice_code(deviceCode);
|
||||||
record.setInstruction_code(instructionCode);
|
existingRecord.setDevice_name(deviceName);
|
||||||
record.setStart_time(new Date());
|
existingRecord.setUpdate_time(new Date());
|
||||||
record.setWork_date(new Date());
|
usageRecordMapper.updateById(existingRecord);
|
||||||
record.setStatus("0");
|
log.info("AGV {} 工作记录已更新,任务号: {}, 指令号: {}", deviceCode, taskCode, instructionCode);
|
||||||
record.setWork_duration(0L);
|
}
|
||||||
record.setIs_active("1");
|
} else {
|
||||||
record.setCreate_time(new Date());
|
// 创建新记录
|
||||||
record.setUpdate_time(new Date());
|
AcsAgvUsageRecord record = new AcsAgvUsageRecord();
|
||||||
|
record.setId(IdUtil.simpleUUID());
|
||||||
usageRecordMapper.insert(record);
|
record.setDevice_code(deviceCode);
|
||||||
log.info("AGV {} 开始工作,任务号: {}, 指令号: {}", deviceCode, taskCode, instructionCode);
|
record.setDevice_name(deviceName);
|
||||||
|
record.setTask_code(taskCode);
|
||||||
|
record.setInstruction_code(instructionCode);
|
||||||
|
record.setStart_time(new Date());
|
||||||
|
record.setWork_date(new Date());
|
||||||
|
record.setStatus("0");
|
||||||
|
record.setWork_duration(0L);
|
||||||
|
record.setIs_active("1");
|
||||||
|
record.setCreate_time(new Date());
|
||||||
|
record.setUpdate_time(new Date());
|
||||||
|
usageRecordMapper.insert(record);
|
||||||
|
log.info("AGV 工作记录已创建,任务号: {}, 指令号: {}", taskCode, instructionCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void endWork(String deviceCode, String taskCode, String instructionCode) {
|
public void endWork(String deviceCode, String taskCode, String instructionCode) {
|
||||||
AcsAgvUsageRecord record = usageRecordMapper.selectActiveByDeviceCode(deviceCode);
|
AcsAgvUsageRecord record = null;
|
||||||
|
|
||||||
|
// 优先根据设备号查找记录
|
||||||
|
if (StringUtils.isNotBlank(deviceCode)) {
|
||||||
|
record = usageRecordMapper.selectActiveByDeviceCode(deviceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果根据设备号找不到,且指令号不为空,根据指令号查找
|
||||||
|
if (record == null && StringUtils.isNotBlank(instructionCode)) {
|
||||||
|
record = usageRecordMapper.selectActiveByInstructionCode(instructionCode);
|
||||||
|
}
|
||||||
|
|
||||||
if (record == null) {
|
if (record == null) {
|
||||||
log.warn("AGV {} 没有找到工作中的记录", deviceCode);
|
log.warn("未找到工作中的记录,设备号: {}, 指令号: {}", deviceCode, instructionCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,9 +103,12 @@ public class AcsAgvUsageServiceImpl implements AcsAgvUsageService {
|
|||||||
|
|
||||||
usageRecordMapper.updateById(record);
|
usageRecordMapper.updateById(record);
|
||||||
|
|
||||||
updateDailyStatistics(deviceCode, record.getWork_date());
|
// 只有当设备号不为空时,才更新每日统计
|
||||||
|
if (StringUtils.isNotBlank(record.getDevice_code())) {
|
||||||
|
updateDailyStatistics(record.getDevice_code(), record.getWork_date());
|
||||||
|
}
|
||||||
|
|
||||||
log.info("AGV {} 结束工作,任务号: {}, 工作时长: {}秒", deviceCode, taskCode, workDuration);
|
log.info("AGV {} 结束工作,任务号: {}, 工作时长: {}秒", record.getDevice_code(), taskCode, workDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -107,13 +133,27 @@ public class AcsAgvUsageServiceImpl implements AcsAgvUsageService {
|
|||||||
|
|
||||||
AcsAgvDailyStatistics existingStats = dailyStatisticsMapper.selectByDeviceCodeAndDate(deviceCode, workDate);
|
AcsAgvDailyStatistics existingStats = dailyStatisticsMapper.selectByDeviceCodeAndDate(deviceCode, workDate);
|
||||||
|
|
||||||
long totalIdleDuration = DAY_SECONDS - totalWorkDuration;
|
// 计算总时长:如果是当天,使用当天0点到当前时间的差值;否则使用24小时
|
||||||
|
long totalDuration;
|
||||||
|
Date today = new Date();
|
||||||
|
Date workDateStart = DateUtil.beginOfDay(workDate);
|
||||||
|
Date todayStart = DateUtil.beginOfDay(today);
|
||||||
|
|
||||||
|
if (workDateStart.equals(todayStart)) {
|
||||||
|
// 当天,计算0点到当前时间的差值
|
||||||
|
totalDuration = (System.currentTimeMillis() - workDateStart.getTime()) / 1000;
|
||||||
|
} else {
|
||||||
|
// 非当天,使用24小时
|
||||||
|
totalDuration = DAY_SECONDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
long totalIdleDuration = totalDuration - totalWorkDuration;
|
||||||
if (totalIdleDuration < 0) {
|
if (totalIdleDuration < 0) {
|
||||||
totalIdleDuration = 0;
|
totalIdleDuration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigDecimal usageRate = BigDecimal.valueOf(totalWorkDuration)
|
BigDecimal usageRate = BigDecimal.valueOf(totalWorkDuration)
|
||||||
.divide(BigDecimal.valueOf(DAY_SECONDS), 4, RoundingMode.HALF_UP)
|
.divide(BigDecimal.valueOf(totalDuration), 4, RoundingMode.HALF_UP)
|
||||||
.multiply(BigDecimal.valueOf(100))
|
.multiply(BigDecimal.valueOf(100))
|
||||||
.setScale(2, RoundingMode.HALF_UP);
|
.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
|
||||||
@@ -218,4 +258,66 @@ public class AcsAgvUsageServiceImpl implements AcsAgvUsageService {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> getMonthlyAgvUsageRate() {
|
||||||
|
// 获取所有每日统计数据
|
||||||
|
List<AcsAgvDailyStatistics> statistics = dailyStatisticsMapper.selectList(null);
|
||||||
|
|
||||||
|
// 按月份分组
|
||||||
|
Map<String, Map<String, Object>> monthlyStatsMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
for (AcsAgvDailyStatistics stat : statistics) {
|
||||||
|
Date workDate = stat.getWork_date();
|
||||||
|
String month = DateUtil.format(workDate, "yyyy-MM");
|
||||||
|
|
||||||
|
if (!monthlyStatsMap.containsKey(month)) {
|
||||||
|
Map<String, Object> monthlyData = new HashMap<>();
|
||||||
|
monthlyData.put("month", month);
|
||||||
|
monthlyData.put("totalWorkDuration", 0L);
|
||||||
|
monthlyData.put("totalTaskCount", 0);
|
||||||
|
monthlyData.put("usageRateSum", BigDecimal.ZERO);
|
||||||
|
monthlyData.put("dayCount", 0);
|
||||||
|
monthlyData.put("maxUsageRate", BigDecimal.ZERO);
|
||||||
|
monthlyData.put("minUsageRate", BigDecimal.valueOf(100));
|
||||||
|
monthlyStatsMap.put(month, monthlyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> monthlyData = monthlyStatsMap.get(month);
|
||||||
|
monthlyData.put("totalWorkDuration", (Long) monthlyData.get("totalWorkDuration") + stat.getTotal_work_duration());
|
||||||
|
monthlyData.put("totalTaskCount", (Integer) monthlyData.get("totalTaskCount") + stat.getTask_count());
|
||||||
|
monthlyData.put("usageRateSum", ((BigDecimal) monthlyData.get("usageRateSum")).add(stat.getUsage_rate()));
|
||||||
|
monthlyData.put("dayCount", (Integer) monthlyData.get("dayCount") + 1);
|
||||||
|
|
||||||
|
// 更新最高和最低使用率
|
||||||
|
BigDecimal usageRate = stat.getUsage_rate();
|
||||||
|
if (usageRate.compareTo((BigDecimal) monthlyData.get("maxUsageRate")) > 0) {
|
||||||
|
monthlyData.put("maxUsageRate", usageRate);
|
||||||
|
}
|
||||||
|
if (usageRate.compareTo((BigDecimal) monthlyData.get("minUsageRate")) < 0) {
|
||||||
|
monthlyData.put("minUsageRate", usageRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算月度平均使用率并整理结果
|
||||||
|
List<Map<String, Object>> result = new ArrayList<>();
|
||||||
|
for (Map<String, Object> monthlyData : monthlyStatsMap.values()) {
|
||||||
|
int dayCount = (Integer) monthlyData.get("dayCount");
|
||||||
|
if (dayCount > 0) {
|
||||||
|
BigDecimal avgUsageRate = ((BigDecimal) monthlyData.get("usageRateSum"))
|
||||||
|
.divide(BigDecimal.valueOf(dayCount), 2, RoundingMode.HALF_UP);
|
||||||
|
monthlyData.put("avgUsageRate", avgUsageRate);
|
||||||
|
} else {
|
||||||
|
monthlyData.put("avgUsageRate", BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
monthlyData.remove("usageRateSum");
|
||||||
|
monthlyData.remove("dayCount");
|
||||||
|
result.add(monthlyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按月份降序排序
|
||||||
|
result.sort((a, b) -> b.get("month").toString().compareTo(a.get("month").toString()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ public class OneNDCSocketConnectionAutoRun extends AbstractAutoRunnable {
|
|||||||
} else {
|
} else {
|
||||||
//上报异常信息
|
//上报异常信息
|
||||||
//(不需要WCS反馈)
|
//(不需要WCS反馈)
|
||||||
if (phase == 0x70 || phase == 0x71 || phase == 0x72 || phase == 0x73 || phase == 0x74) {
|
if (phase == 0x70 || phase == 0x71 || phase == 0x72 || phase == 0x73 || phase == 0x74 || phase == 0x67 || phase == 0x68) {
|
||||||
device = deviceAppService.findDeviceByCode("agv" + Integer.toString(agvaddr));
|
device = deviceAppService.findDeviceByCode("agv" + Integer.toString(agvaddr));
|
||||||
} else {
|
} else {
|
||||||
device = deviceAppService.findDeviceByCode("agv" + Integer.toString(arr[20]));
|
device = deviceAppService.findDeviceByCode("agv" + Integer.toString(arr[20]));
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.nl.acs.task.domain.Task;
|
|||||||
import org.nl.acs.task.service.TaskService;
|
import org.nl.acs.task.service.TaskService;
|
||||||
import org.nl.acs.task.service.dto.TaskDto;
|
import org.nl.acs.task.service.dto.TaskDto;
|
||||||
import org.nl.acs.task.service.impl.TaskServiceImpl;
|
import org.nl.acs.task.service.impl.TaskServiceImpl;
|
||||||
|
import org.nl.common.utils.AlarmUtil;
|
||||||
import org.nl.common.utils.ThrowableUtil;
|
import org.nl.common.utils.ThrowableUtil;
|
||||||
import org.nl.system.service.dict.ISysDictService;
|
import org.nl.system.service.dict.ISysDictService;
|
||||||
import org.nl.system.service.dict.dao.Dict;
|
import org.nl.system.service.dict.dao.Dict;
|
||||||
@@ -136,14 +137,55 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
|
|||||||
|
|
||||||
if (phase == 0x67) {
|
if (phase == 0x67) {
|
||||||
//故障信息
|
//故障信息
|
||||||
if (arr[18] * 256 + arr[19] == 0) {
|
// if (arr[18] * 256 + arr[19] == 0) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
|
||||||
|
// request.setDevice_code(this.device_code);
|
||||||
|
// request.setState("故障");
|
||||||
|
// acsToWmsService.notify(request);
|
||||||
|
// data = NDCAgvService.sendAgvOneModeInst(phase, index, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
// 更新AGV状态
|
||||||
|
try {
|
||||||
|
log.info("接收到phase=0x67的情况:ikey {}", ikey);
|
||||||
|
String agvDeviceCode = "agv" + agvaddr;
|
||||||
|
String agvDeviceName = this.device_code;
|
||||||
|
Device agvDevice = deviceAppService.findDeviceByCode(agvDeviceCode);
|
||||||
|
if (agvDevice != null) {
|
||||||
|
agvDeviceName = agvDevice.getDevice_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ikey == 0) {
|
||||||
|
agvAlarmService.updateAgvStatus(agvDeviceCode, agvDeviceName, 2,"正常", x, y, angle, electric_qty);
|
||||||
|
} else {
|
||||||
|
agvAlarmService.updateAgvStatus(agvDeviceCode, agvDeviceName, 6,
|
||||||
|
AlarmUtil.parseAlarm(Integer.toHexString(ikey),phase), x, y, angle, electric_qty);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("AGV状态更新失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (phase == 0x68) {
|
||||||
|
// 更新AGV状态
|
||||||
|
try {
|
||||||
|
log.info("接收到phase=0x68的情况:ikey {}", ikey);
|
||||||
|
String agvDeviceCode = "agv" + agvaddr;
|
||||||
|
String agvDeviceName = this.device_code;
|
||||||
|
Device agvDevice = deviceAppService.findDeviceByCode(agvDeviceCode);
|
||||||
|
if (agvDevice != null) {
|
||||||
|
agvDeviceName = agvDevice.getDevice_name();
|
||||||
|
}
|
||||||
|
if (ikey == 0) {
|
||||||
|
agvAlarmService.updateAgvStatus(agvDeviceCode, agvDeviceName, 2,"正常", x, y, angle, electric_qty);
|
||||||
|
} else {
|
||||||
|
agvAlarmService.updateAgvStatus(agvDeviceCode, agvDeviceName, 6,
|
||||||
|
AlarmUtil.parseAlarm(Integer.toHexString(ikey),phase), x, y, angle, electric_qty);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("AGV状态更新失败: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
|
|
||||||
request.setDevice_code(this.device_code);
|
|
||||||
request.setState("故障");
|
|
||||||
acsToWmsService.notify(request);
|
|
||||||
data = NDCAgvService.sendAgvOneModeInst(phase, index, 0, 0, 0, 0, 0);
|
|
||||||
}
|
}
|
||||||
TaskDto task = new TaskDto();
|
TaskDto task = new TaskDto();
|
||||||
|
|
||||||
@@ -151,7 +193,17 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
|
|||||||
task = taskService.findById(inst.getTask_id());
|
task = taskService.findById(inst.getTask_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//接到任务,因为无法判断是哪辆车 先不处理
|
||||||
|
if (phase == 0x01) {
|
||||||
|
// AGV使用率统计 - 开始工作
|
||||||
|
try {
|
||||||
|
String agvDeviceCode = null;
|
||||||
|
String agvDeviceName = null;
|
||||||
|
agvUsageService.startWork(agvDeviceCode, agvDeviceName, inst.getTask_code(), inst.getInstruction_code());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("AGV使用率统计-开始工作失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
//分配 车id
|
//分配 车id
|
||||||
//(不需要WCS反馈)
|
//(不需要WCS反馈)
|
||||||
if (phase == 0x02) {
|
if (phase == 0x02) {
|
||||||
@@ -621,35 +673,6 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
|
|||||||
} else if (phase == 0x74) {
|
} else if (phase == 0x74) {
|
||||||
//三色灯状态
|
//三色灯状态
|
||||||
status = ikey;
|
status = ikey;
|
||||||
|
|
||||||
// 更新AGV状态
|
|
||||||
try {
|
|
||||||
String agvDeviceCode = "agv" + agvaddr;
|
|
||||||
String agvDeviceName = this.device_code;
|
|
||||||
Device agvDevice = deviceAppService.findDeviceByCode(agvDeviceCode);
|
|
||||||
if (agvDevice != null) {
|
|
||||||
agvDeviceName = agvDevice.getDevice_name();
|
|
||||||
}
|
|
||||||
String statusStr = "正常";
|
|
||||||
if (status == 1) {
|
|
||||||
statusStr = "关机";
|
|
||||||
} else if (status == 2) {
|
|
||||||
statusStr = "运行中";
|
|
||||||
}else if (status == 3) {
|
|
||||||
statusStr = "交通管制";
|
|
||||||
}else if (status == 4) {
|
|
||||||
statusStr = "任务等待";
|
|
||||||
}else if (status == 5) {
|
|
||||||
statusStr = "充电中";
|
|
||||||
}else if (status == 6) {
|
|
||||||
statusStr = "故障中";
|
|
||||||
}else if (status == 7) {
|
|
||||||
statusStr = "低电量";
|
|
||||||
}
|
|
||||||
agvAlarmService.updateAgvStatus(agvDeviceCode, agvDeviceName, status,statusStr, x, y, angle, electric_qty);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("AGV状态更新失败: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!ObjectUtil.isEmpty(data)) {
|
if (!ObjectUtil.isEmpty(data)) {
|
||||||
logServer.deviceExecuteLog(this.device_code, "", "", "agvphase:" + phase + "反馈:" + data);
|
logServer.deviceExecuteLog(this.device_code, "", "", "agvphase:" + phase + "反馈:" + data);
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.nl.common.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AlarmUtil {
|
||||||
|
private static final String[] ALARM_67 = {
|
||||||
|
"货叉光电报警", // 0
|
||||||
|
"安全避障报警", // 1
|
||||||
|
"触边/防撞报警", // 2
|
||||||
|
"导航激光报警", // 3
|
||||||
|
"急停按钮触发", // 4
|
||||||
|
"载货状态改变", // 5
|
||||||
|
"需要复位", // 6
|
||||||
|
"没有操作码", // 7
|
||||||
|
"取货时无货", // 8
|
||||||
|
"取货前有货", // 9
|
||||||
|
"放货前无货", //10
|
||||||
|
"放货完有货", //11
|
||||||
|
"充电异常", //12
|
||||||
|
"超出安全区域", //13
|
||||||
|
"货叉太高或太低" //14
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final String[] ALARM_68 = {
|
||||||
|
"车轮打滑", // 0
|
||||||
|
"手动模式", // 1
|
||||||
|
"没有定位", // 2
|
||||||
|
"车辆不在系统中", // 3
|
||||||
|
"正在充电", // 4
|
||||||
|
"转向编码器同步失败",// 5
|
||||||
|
"货叉左右限位未触发" // 6
|
||||||
|
};
|
||||||
|
public static String parseAlarm(String hexStr, int phase) {
|
||||||
|
if (hexStr == null || StringUtils.isBlank(hexStr) || hexStr.length() > 4) {
|
||||||
|
throw new IllegalArgumentException("十六进制字符串无效");
|
||||||
|
}
|
||||||
|
if (0x67 != phase && 0x68 != phase) {
|
||||||
|
throw new IllegalArgumentException("phase只能是67或68");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 直接转16位二进制,保留所有前导0
|
||||||
|
int value = Integer.parseInt(hexStr.trim(), 16);
|
||||||
|
String binary = String.format("%16s", Integer.toBinaryString(value)).replace(' ', '0');
|
||||||
|
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
|
||||||
|
if (0x67 == phase) {
|
||||||
|
// 核心:遍历16位,从左到右 = 位1 ~ 位15,最后一位=位0
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (binary.charAt(i) == '1') {
|
||||||
|
int bit;
|
||||||
|
if (i == 15) {
|
||||||
|
bit = 0; // 最后一位 = 第0位
|
||||||
|
} else {
|
||||||
|
bit = i + 1; // 左边第i位 = 第(i+1)位
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bit < ALARM_67.length) {
|
||||||
|
res.add(ALARM_67[bit]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 68模式 8位
|
||||||
|
String bin8 = String.format("%8s", Integer.toBinaryString(value)).replace(' ', '0');
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (bin8.charAt(i) == '1') {
|
||||||
|
int bit = (i == 7) ? 0 : (i + 1);
|
||||||
|
if (bit < ALARM_68.length) {
|
||||||
|
res.add(ALARM_68[bit]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.join(",", res);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,4 +16,9 @@ public class CallEmpVo {
|
|||||||
* 设备工序
|
* 设备工序
|
||||||
*/
|
*/
|
||||||
private String region_code;
|
private String region_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目标点位是有货点位,是否强制修改成无货。
|
||||||
|
*/
|
||||||
|
private Boolean check_flag;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.nl.wms.ext.fab.service.impl;
|
package org.nl.wms.ext.fab.service.impl;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
@@ -9,8 +10,12 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|||||||
import nl.basjes.shaded.org.springframework.util.Assert;
|
import nl.basjes.shaded.org.springframework.util.Assert;
|
||||||
import org.checkerframework.checker.units.qual.A;
|
import org.checkerframework.checker.units.qual.A;
|
||||||
import org.nl.common.enums.GoodsEnum;
|
import org.nl.common.enums.GoodsEnum;
|
||||||
|
import org.nl.common.enums.VehicleTypeEnum;
|
||||||
import org.nl.common.enums.region.RegionEnum;
|
import org.nl.common.enums.region.RegionEnum;
|
||||||
import org.nl.common.exception.BadRequestException;
|
import org.nl.common.exception.BadRequestException;
|
||||||
|
import org.nl.common.utils.SecurityUtils;
|
||||||
|
import org.nl.system.service.dict.ISysDictService;
|
||||||
|
import org.nl.system.service.dict.dao.Dict;
|
||||||
import org.nl.system.service.param.dao.Param;
|
import org.nl.system.service.param.dao.Param;
|
||||||
import org.nl.wms.database.vehicle.service.IMdBaseVehicleService;
|
import org.nl.wms.database.vehicle.service.IMdBaseVehicleService;
|
||||||
import org.nl.wms.database.vehicle.service.dao.MdBaseVehicle;
|
import org.nl.wms.database.vehicle.service.dao.MdBaseVehicle;
|
||||||
@@ -33,11 +38,14 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class FabServiceImpl {
|
public class FabServiceImpl {
|
||||||
@@ -61,6 +69,10 @@ public class FabServiceImpl {
|
|||||||
private PcOperationSNTTask pcOperationSNTTask;
|
private PcOperationSNTTask pcOperationSNTTask;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PcOperationCNTask pcOperationCNTask;
|
private PcOperationCNTask pcOperationCNTask;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysDictService dictService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISchBaseVehiclematerialgroupService iSchBaseVehiclematerialgroupService;
|
private ISchBaseVehiclematerialgroupService iSchBaseVehiclematerialgroupService;
|
||||||
|
|
||||||
@@ -230,8 +242,20 @@ public class FabServiceImpl {
|
|||||||
if (ObjectUtil.isEmpty(schBasePoint1)) {
|
if (ObjectUtil.isEmpty(schBasePoint1)) {
|
||||||
throw new BadRequestException("点位不存在");
|
throw new BadRequestException("点位不存在");
|
||||||
}
|
}
|
||||||
if (StrUtil.isNotEmpty(schBasePoint1.getVehicle_code())) {
|
if (Boolean.TRUE.equals(callEmpVo.getCheck_flag())){
|
||||||
throw new BadRequestException("该点位不是空站点,请确认再呼叫");
|
String currentUserId = SecurityUtils.getCurrentUserId();
|
||||||
|
String nickName = SecurityUtils.getCurrentNickName();
|
||||||
|
String now = DateUtil.now();
|
||||||
|
iSchBasePointService.update(Wrappers.lambdaUpdate(SchBasePoint.class)
|
||||||
|
.eq(SchBasePoint::getPoint_code, form.getString("device_code"))
|
||||||
|
.set(SchBasePoint::getVehicle_code, null)
|
||||||
|
.set(SchBasePoint::getPoint_status, GoodsEnum.OUT_OF_STOCK.getValue())
|
||||||
|
.set(SchBasePoint::getUpdate_id, currentUserId)
|
||||||
|
.set(SchBasePoint::getUpdate_name, nickName)
|
||||||
|
.set(SchBasePoint::getUpdate_time, now)
|
||||||
|
);
|
||||||
|
} else if (StrUtil.isNotEmpty(schBasePoint1.getVehicle_code())) {
|
||||||
|
throw new BadRequestException("该点位不是空站点,请确认是否设置成空站点并继续呼叫?");
|
||||||
}
|
}
|
||||||
param.put("device_code", callEmpVo.getDevice_code());
|
param.put("device_code", callEmpVo.getDevice_code());
|
||||||
param.put("config_code", "TOSTOREHOUSETask");
|
param.put("config_code", "TOSTOREHOUSETask");
|
||||||
@@ -257,6 +281,20 @@ public class FabServiceImpl {
|
|||||||
} else {
|
} else {
|
||||||
param.put("config_code", "PcOperationSMTTask");
|
param.put("config_code", "PcOperationSMTTask");
|
||||||
}
|
}
|
||||||
|
List<Dict> dictList = dictService.getDictByName("fork_type_point");
|
||||||
|
if(!CollectionUtils.isEmpty(dictList)) {
|
||||||
|
List<String> valueList = dictList.stream()
|
||||||
|
.map(Dict::getValue) // 提取每个Dict的value属性
|
||||||
|
.filter(Objects::nonNull) // 过滤掉 null
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(valueList)
|
||||||
|
&& valueList.contains( sendMaterVo.getDevice_code())
|
||||||
|
&& VehicleTypeEnum.FRAME_R02.getVehicleCode().equals(vehicle.getVehicle_type())) {
|
||||||
|
param.put("car_type", "small");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
param.put("vehicle_code", sendMaterVo.getVehicle_code());
|
param.put("vehicle_code", sendMaterVo.getVehicle_code());
|
||||||
param.put("vehicle_type", vehicle.getVehicle_type());
|
param.put("vehicle_type", vehicle.getVehicle_type());
|
||||||
iSchBasePointService.update(Wrappers.lambdaUpdate(SchBasePoint.class)
|
iSchBasePointService.update(Wrappers.lambdaUpdate(SchBasePoint.class)
|
||||||
@@ -275,6 +313,28 @@ public class FabServiceImpl {
|
|||||||
param.put("vehicle_code", schBasePoint.getVehicle_code());
|
param.put("vehicle_code", schBasePoint.getVehicle_code());
|
||||||
param.put("vehicle_type", schBasePoint.getVehicle_type());
|
param.put("vehicle_type", schBasePoint.getVehicle_type());
|
||||||
param.put("ext_data", sendVehicleVo);
|
param.put("ext_data", sendVehicleVo);
|
||||||
|
|
||||||
|
SchBasePoint schBasePointSnt = iSchBasePointService.selectByPointCode(form.getString("device_code"));
|
||||||
|
if (ObjectUtil.isEmpty(schBasePointSnt)) {
|
||||||
|
throw new BadRequestException("点位不存在");
|
||||||
|
}
|
||||||
|
if(StringUtils.isEmpty(schBasePointSnt.getVehicle_code())){
|
||||||
|
throw new BadRequestException("点位不存在载具");
|
||||||
|
}
|
||||||
|
MdBaseVehicle vehicle2 = iMdBaseVehicleService.getOne(new QueryWrapper<MdBaseVehicle>().eq("vehicle_code", schBasePointSnt.getVehicle_code()));
|
||||||
|
List<Dict> dictList2 = dictService.getDictByName("fork_type_point");
|
||||||
|
if(!CollectionUtils.isEmpty(dictList2)) {
|
||||||
|
List<String> valueList = dictList2.stream()
|
||||||
|
.map(Dict::getValue) // 提取每个Dict的value属性
|
||||||
|
.filter(Objects::nonNull) // 过滤掉 null
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(valueList)
|
||||||
|
&& valueList.contains(sendVehicleVo.getDevice_code())
|
||||||
|
&& VehicleTypeEnum.FRAME_R02.getVehicleCode().equals(vehicle2.getVehicle_type())) {
|
||||||
|
param.put("car_type", "small");
|
||||||
|
}
|
||||||
|
}
|
||||||
pcOperationSNTTask.apply(param);
|
pcOperationSNTTask.apply(param);
|
||||||
iSchBasePointService.update(Wrappers.lambdaUpdate(SchBasePoint.class)
|
iSchBasePointService.update(Wrappers.lambdaUpdate(SchBasePoint.class)
|
||||||
.eq(SchBasePoint::getPoint_code, sendVehicleVo.getDevice_code())
|
.eq(SchBasePoint::getPoint_code, sendVehicleVo.getDevice_code())
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
@@ -115,6 +115,9 @@ public class HandheldServiceImpl implements HandheldService {
|
|||||||
private SchBasePointMapper schBasePointMapper;
|
private SchBasePointMapper schBasePointMapper;
|
||||||
static final Map<String, String> STATUS = MapOf.of("释放", "0", "锁定", "1");
|
static final Map<String, String> STATUS = MapOf.of("释放", "0", "锁定", "1");
|
||||||
|
|
||||||
|
// 线程池,用于异步执行任务
|
||||||
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emptyCageStorageTask(JSONObject param) {
|
public void emptyCageStorageTask(JSONObject param) {
|
||||||
@@ -239,16 +242,36 @@ public class HandheldServiceImpl implements HandheldService {
|
|||||||
Map<String, List<VehicleDto>> point2VehicleMap = vehicleList.stream()
|
Map<String, List<VehicleDto>> point2VehicleMap = vehicleList.stream()
|
||||||
.collect(Collectors.groupingBy(VehicleDto::getPoint_code));
|
.collect(Collectors.groupingBy(VehicleDto::getPoint_code));
|
||||||
|
|
||||||
for (SchBasePoint schBasePoint : sortedPointList) {
|
// 异步执行任务生成,每个任务间隔12秒
|
||||||
String pointCode = schBasePoint.getPoint_code();
|
executorService.submit(() -> {
|
||||||
List<VehicleDto> matchVehicleDtos = point2VehicleMap.get(pointCode);
|
try {
|
||||||
if (CollectionUtil.isNotEmpty(matchVehicleDtos)) {
|
for (SchBasePoint schBasePoint : sortedPointList) {
|
||||||
for (VehicleDto vehicleDto : matchVehicleDtos) {
|
String pointCode = schBasePoint.getPoint_code();
|
||||||
// 生成任务(可添加日志记录,便于生产环境排查问题)
|
List<VehicleDto> matchVehicleDtos = point2VehicleMap.get(pointCode);
|
||||||
artificialBendingNew(vehicleDto.getVehicle_code(), vehicleDto.getPoint_code());
|
if (CollectionUtil.isNotEmpty(matchVehicleDtos)) {
|
||||||
|
for (VehicleDto vehicleDto : matchVehicleDtos) {
|
||||||
|
try {
|
||||||
|
// 生成任务(可添加日志记录,便于生产环境排查问题)
|
||||||
|
log.info("异步生成任务:载具号={}, 点位={}", vehicleDto.getVehicle_code(), vehicleDto.getPoint_code());
|
||||||
|
artificialBendingNew(vehicleDto.getVehicle_code(), vehicleDto.getPoint_code());
|
||||||
|
// 每个任务间隔12秒
|
||||||
|
Thread.sleep(12000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("任务生成线程被中断:{}", e.getMessage());
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成任务失败:载具号={}, 点位={}, 错误信息:{}", vehicleDto.getVehicle_code(), vehicleDto.getPoint_code(), e.getMessage(), e);
|
||||||
|
// 继续执行下一个任务
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("异步执行任务生成失败:{}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,6 +318,19 @@ public class HandheldServiceImpl implements HandheldService {
|
|||||||
jo.put("region_code", RegionEnum.NBGD.getRegion_code());
|
jo.put("region_code", RegionEnum.NBGD.getRegion_code());
|
||||||
param.put("region_code", RegionEnum.NBGD.getRegion_code());
|
param.put("region_code", RegionEnum.NBGD.getRegion_code());
|
||||||
jo.put("car_type","start");
|
jo.put("car_type","start");
|
||||||
|
List<Dict> dictList = dictService.getDictByName("fork_type_point");
|
||||||
|
if(!CollectionUtils.isEmpty(dictList)) {
|
||||||
|
List<String> valueList = dictList.stream()
|
||||||
|
.map(Dict::getValue) // 提取每个Dict的value属性
|
||||||
|
.filter(Objects::nonNull) // 过滤掉 null
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(valueList)
|
||||||
|
&& valueList.contains(device_code)
|
||||||
|
&& VehicleTypeEnum.FRAME_R02.getVehicleCode().equals( mdBaseVehicle.getVehicle_type())) {
|
||||||
|
jo.put("car_type", "small");
|
||||||
|
}
|
||||||
|
}
|
||||||
jo.put("ext_data", param);
|
jo.put("ext_data", param);
|
||||||
connectorTask.apply(jo);
|
connectorTask.apply(jo);
|
||||||
}
|
}
|
||||||
@@ -326,6 +362,22 @@ public class HandheldServiceImpl implements HandheldService {
|
|||||||
jo.put("create_mode", GeneralDefinition.AUTO_CREATION);
|
jo.put("create_mode", GeneralDefinition.AUTO_CREATION);
|
||||||
jo.put("vehicle_code", vehicle_code);
|
jo.put("vehicle_code", vehicle_code);
|
||||||
jo.put("car_type","end");
|
jo.put("car_type","end");
|
||||||
|
|
||||||
|
MdBaseVehicle mdBaseVehicle = iMdBaseVehicleService.selectByVehicleCode(vehicle_code);
|
||||||
|
if (ObjectUtil.isEmpty(mdBaseVehicle)) throw new BadRequestException("载具不存在!");
|
||||||
|
List<Dict> dictList = dictService.getDictByName("fork_type_point");
|
||||||
|
if(!CollectionUtils.isEmpty(dictList)) {
|
||||||
|
List<String> valueList = dictList.stream()
|
||||||
|
.map(Dict::getValue) // 提取每个Dict的value属性
|
||||||
|
.filter(Objects::nonNull) // 过滤掉 null
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(valueList)
|
||||||
|
&& valueList.contains(point_code)
|
||||||
|
&& VehicleTypeEnum.FRAME_R02.getVehicleCode().equals(mdBaseVehicle.getVehicle_type())) {
|
||||||
|
jo.put("car_type", "small");
|
||||||
|
}
|
||||||
|
}
|
||||||
connectorTask.apply(jo);
|
connectorTask.apply(jo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +406,20 @@ public class HandheldServiceImpl implements HandheldService {
|
|||||||
jo.put("vehicle_code", vehicle);
|
jo.put("vehicle_code", vehicle);
|
||||||
jo.put("car_type","start");
|
jo.put("car_type","start");
|
||||||
|
|
||||||
|
List<Dict> dictList = dictService.getDictByName("fork_type_point");
|
||||||
|
if(!CollectionUtils.isEmpty(dictList)) {
|
||||||
|
List<String> valueList = dictList.stream()
|
||||||
|
.map(Dict::getValue) // 提取每个Dict的value属性
|
||||||
|
.filter(Objects::nonNull) // 过滤掉 null
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(valueList)
|
||||||
|
&& valueList.contains(device_code)
|
||||||
|
&& VehicleTypeEnum.FRAME_R02.getVehicleCode().equals(mdBaseVehicle.getVehicle_type())) {
|
||||||
|
jo.put("car_type", "small");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
jo.put("ext_data", param);
|
jo.put("ext_data", param);
|
||||||
connectorTask.apply(jo);
|
connectorTask.apply(jo);
|
||||||
}
|
}
|
||||||
@@ -748,7 +814,19 @@ public class HandheldServiceImpl implements HandheldService {
|
|||||||
jo.put("create_mode", GeneralDefinition.AUTO_CREATION);
|
jo.put("create_mode", GeneralDefinition.AUTO_CREATION);
|
||||||
jo.put("vehicle_code", vehicle_code);
|
jo.put("vehicle_code", vehicle_code);
|
||||||
jo.put("vehicle_type", mdBaseVehicle.getVehicle_type());
|
jo.put("vehicle_type", mdBaseVehicle.getVehicle_type());
|
||||||
jo.put("car_type","start");
|
jo.put("car_type","end");
|
||||||
|
List<Dict> dictList = dictService.getDictByName("fork_type_point");
|
||||||
|
if(!CollectionUtils.isEmpty(dictList)) {
|
||||||
|
List<String> valueList = dictList.stream()
|
||||||
|
.map(Dict::getValue) // 提取每个Dict的value属性
|
||||||
|
.filter(Objects::nonNull) // 过滤掉 null
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!CollectionUtils.isEmpty(valueList)
|
||||||
|
&& valueList.contains(device_code)
|
||||||
|
&& VehicleTypeEnum.FRAME_R02.getVehicleCode().equals(mdBaseVehicle.getVehicle_type())) {
|
||||||
|
jo.put("car_type", "small");
|
||||||
|
}
|
||||||
|
}
|
||||||
jo.put("ext_data", param);
|
jo.put("ext_data", param);
|
||||||
connectorTask.apply(jo);
|
connectorTask.apply(jo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,4 +60,12 @@ public class AgvUsageController {
|
|||||||
Map<String, Object> result = agvUsageService.getAgvUsageRateToday();
|
Map<String, Object> result = agvUsageService.getAgvUsageRateToday();
|
||||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/monthly")
|
||||||
|
@Log("获取月度AGV使用率统计")
|
||||||
|
@ApiOperation("获取月度AGV使用率统计")
|
||||||
|
public ResponseEntity<Object> getMonthlyStatistics() {
|
||||||
|
List<Map<String, Object>> result = agvUsageService.getMonthlyAgvUsageStatistics();
|
||||||
|
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ public interface IAgvUsageService {
|
|||||||
Map<String, Object> getAgvRealtimeStatus();
|
Map<String, Object> getAgvRealtimeStatus();
|
||||||
|
|
||||||
Map<String, Object> getAgvUsageRateToday();
|
Map<String, Object> getAgvUsageRateToday();
|
||||||
|
|
||||||
|
List<Map<String, Object>> getMonthlyAgvUsageStatistics();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public class AgvUsageServiceImpl implements IAgvUsageService {
|
|||||||
String endDate = sdf.format(query.getEndDate());
|
String endDate = sdf.format(query.getEndDate());
|
||||||
|
|
||||||
StringBuilder urlBuilder = new StringBuilder(acsUrl)
|
StringBuilder urlBuilder = new StringBuilder(acsUrl)
|
||||||
.append("/api/agv_usage/statistics/detail?startDate=")
|
.append("api/agv_usage/statistics/detail?startDate=")
|
||||||
.append(startDate)
|
.append(startDate)
|
||||||
.append("&endDate=")
|
.append("&endDate=")
|
||||||
.append(endDate);
|
.append(endDate);
|
||||||
@@ -177,4 +177,32 @@ public class AgvUsageServiceImpl implements IAgvUsageService {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> getMonthlyAgvUsageStatistics() {
|
||||||
|
if (!isConnectAcs()) {
|
||||||
|
log.warn("未连接ACS系统");
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
String acsUrl = getAcsUrl();
|
||||||
|
if (StrUtil.isEmpty(acsUrl)) {
|
||||||
|
log.warn("ACS地址未配置");
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = acsUrl + "api/agv_usage/monthly";
|
||||||
|
|
||||||
|
try {
|
||||||
|
String result = HttpRequest.get(url)
|
||||||
|
.setConnectionTimeout(5000)
|
||||||
|
.execute()
|
||||||
|
.body();
|
||||||
|
// 使用TypeReference指定泛型类型,保证类型匹配
|
||||||
|
return JSON.parseObject(result, new TypeReference<List<Map<String, Object>>>() {});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("调用ACS获取月度AGV使用率统计失败: {}", e.getMessage());
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,6 @@ public class SchBasePointServiceImpl extends ServiceImpl<SchBasePointMapper, Sch
|
|||||||
pointMapper.update(entity, Wrappers.lambdaUpdate(SchBasePoint.class)
|
pointMapper.update(entity, Wrappers.lambdaUpdate(SchBasePoint.class)
|
||||||
.eq(SchBasePoint::getPoint_code, entity.getPoint_code())
|
.eq(SchBasePoint::getPoint_code, entity.getPoint_code())
|
||||||
.set(SchBasePoint::getVehicle_code, vehicle_code));
|
.set(SchBasePoint::getVehicle_code, vehicle_code));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class CombineSourceStoreInTask extends AbstractTask {
|
|||||||
GoodsEnum.OUT_OF_STOCK.getValue(), vehicle_type, 1, 1);
|
GoodsEnum.OUT_OF_STOCK.getValue(), vehicle_type, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ObjectUtil.isEmpty(schBasePoint)) {
|
if (ObjectUtil.isEmpty(schBasePoint)) {
|
||||||
task.setRemark("未找到所需点位!");
|
task.setRemark("未找到所需点位!");
|
||||||
taskService.updateById(task);
|
taskService.updateById(task);
|
||||||
@@ -203,13 +203,7 @@ public class CombineSourceStoreInTask extends AbstractTask {
|
|||||||
String point_code2 = taskObj.getPoint_code2();
|
String point_code2 = taskObj.getPoint_code2();
|
||||||
SchBasePoint schBasePoint2 = pointService.selectByPointCode(point_code2);
|
SchBasePoint schBasePoint2 = pointService.selectByPointCode(point_code2);
|
||||||
if (ObjectUtil.isNotEmpty(schBasePoint2)) {
|
if (ObjectUtil.isNotEmpty(schBasePoint2)) {
|
||||||
String vehicle_type = taskObj.getVehicle_type();
|
schBasePoint2.setVehicle_code(taskObj.getVehicle_code());
|
||||||
if (vehicle_type.equals(VehicleTypeEnum.FRAME_R01.getVehicleCode()) || vehicle_type.equals(VehicleTypeEnum.FRAME_R02.getVehicleCode())) {
|
|
||||||
schBasePoint2.setVehicles(taskObj.getVehicle_code());
|
|
||||||
schBasePoint2.setVehicle_qty(taskObj.getVehicle_qty());
|
|
||||||
} else {
|
|
||||||
schBasePoint2.setVehicle_code(taskObj.getVehicle_code());
|
|
||||||
}
|
|
||||||
schBasePoint2.setPoint_status(GoodsEnum.EMPTY_PALLETS.getValue());
|
schBasePoint2.setPoint_status(GoodsEnum.EMPTY_PALLETS.getValue());
|
||||||
schBasePoint2.setIs_lock(false);
|
schBasePoint2.setIs_lock(false);
|
||||||
PointUtils.setUpdateByAcs(schBasePoint2);
|
PointUtils.setUpdateByAcs(schBasePoint2);
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ public class EmptyCageNewTask extends AbstractTask {
|
|||||||
switch (vehicle_type) {
|
switch (vehicle_type) {
|
||||||
case "R01":
|
case "R01":
|
||||||
schBasePoint = schBasePointService.selectStackPoint(RegionEnum.S.getRegion_code(),
|
schBasePoint = schBasePointService.selectStackPoint(RegionEnum.S.getRegion_code(),
|
||||||
GoodsEnum.OUT_OF_STOCK.getValue(), VehicleTypeEnum.FRAME_R01.getVehicleCode(), IS_VEHICLE.get("vehicles"), POINT_TYPE.get("空托盘"));
|
GoodsEnum.OUT_OF_STOCK.getValue(), VehicleTypeEnum.FRAME_R01.getVehicleCode(), IS_VEHICLE.get("vehicle_code"), POINT_TYPE.get("空托盘"));
|
||||||
break;
|
break;
|
||||||
case "R02":
|
case "R02":
|
||||||
schBasePoint = schBasePointService.selectStackPoint(RegionEnum.S.getRegion_code(),
|
schBasePoint = schBasePointService.selectStackPoint(RegionEnum.S.getRegion_code(),
|
||||||
GoodsEnum.OUT_OF_STOCK.getValue(), VehicleTypeEnum.FRAME_R02.getVehicleCode(), IS_VEHICLE.get("vehicles"), POINT_TYPE.get("空托盘"));
|
GoodsEnum.OUT_OF_STOCK.getValue(), VehicleTypeEnum.FRAME_R02.getVehicleCode(), IS_VEHICLE.get("vehicle_code"), POINT_TYPE.get("空托盘"));
|
||||||
break;
|
break;
|
||||||
case "S04":
|
case "S04":
|
||||||
schBasePoint = schBasePointService.selectStackPoint(RegionEnum.LAG.getRegion_code(),
|
schBasePoint = schBasePointService.selectStackPoint(RegionEnum.LAG.getRegion_code(),
|
||||||
@@ -219,13 +219,7 @@ public class EmptyCageNewTask extends AbstractTask {
|
|||||||
String point_code2 = taskObj.getPoint_code2();
|
String point_code2 = taskObj.getPoint_code2();
|
||||||
SchBasePoint schBasePoint2 = pointService.selectByPointCode(point_code2);
|
SchBasePoint schBasePoint2 = pointService.selectByPointCode(point_code2);
|
||||||
if (ObjectUtil.isNotEmpty(schBasePoint2)) {
|
if (ObjectUtil.isNotEmpty(schBasePoint2)) {
|
||||||
String vehicle_type = taskObj.getVehicle_type();
|
schBasePoint2.setVehicle_code(taskObj.getVehicle_code());
|
||||||
if (vehicle_type.equals(VehicleTypeEnum.FRAME_R01.getVehicleCode()) || vehicle_type.equals(VehicleTypeEnum.FRAME_R02.getVehicleCode())) {
|
|
||||||
schBasePoint2.setVehicles(taskObj.getVehicle_code());
|
|
||||||
schBasePoint2.setVehicle_qty(taskObj.getVehicle_qty());
|
|
||||||
} else {
|
|
||||||
schBasePoint2.setVehicle_code(taskObj.getVehicle_code());
|
|
||||||
}
|
|
||||||
schBasePoint2.setPoint_status(GoodsEnum.EMPTY_PALLETS.getValue());
|
schBasePoint2.setPoint_status(GoodsEnum.EMPTY_PALLETS.getValue());
|
||||||
schBasePoint2.setIs_lock(false);
|
schBasePoint2.setIs_lock(false);
|
||||||
PointUtils.setUpdateByAcs(schBasePoint2);
|
PointUtils.setUpdateByAcs(schBasePoint2);
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ export default {
|
|||||||
popSecList: [],
|
popSecList: [],
|
||||||
currentRow: null,
|
currentRow: null,
|
||||||
value: '',
|
value: '',
|
||||||
options: [{ value: 'G01', label: 'G01' }, { value: 'R01', label: 'R01' }, { value: 'R02', label: 'R02' }, { value: 'R03', label: 'R03' }, { value: 'S04', label: 'S04' }, { value: 'S06', label: 'S06' }],
|
options: [{ value: 'G01', label: 'G01' }, { value: 'R01', label: 'R01(大框)' }, { value: 'R02', label: 'R02(小框)' }, { value: 'R03', label: 'R03' }, { value: 'S04', label: 'S04(侧板架)' }, { value: 'S06', label: 'S06(A字架)' }],
|
||||||
value1: '',
|
value1: '',
|
||||||
options1: [{ value: '1', label: '货架' }, { value: '2', label: '仓库收货区' }, { value: '3', label: '外协' }, { value: '4', label: '内部过道' }, { value: '5', label: '精加工' }],
|
options1: [{ value: '1', label: '货架' }, { value: '2', label: '仓库收货区' }, { value: '3', label: '外协' }, { value: '4', label: '内部过道' }, { value: '5', label: '精加工' }],
|
||||||
value2: '',
|
value2: '',
|
||||||
@@ -577,8 +577,62 @@ export default {
|
|||||||
crudProduceScreen.callEmp({ vehicle_type: this.value, device_code: this.popData.device_code }).then(res => {
|
crudProduceScreen.callEmp({ vehicle_type: this.value, device_code: this.popData.device_code }).then(res => {
|
||||||
this.disabled = false
|
this.disabled = false
|
||||||
this.$message(res.msg)
|
this.$message(res.msg)
|
||||||
}).catch(() => {
|
}).catch(error => {
|
||||||
this.disabled = false
|
this.disabled = false
|
||||||
|
console.log('Error object:', error)
|
||||||
|
console.log('Error response:', error.response)
|
||||||
|
console.log('Error response data:', error.response && error.response.data)
|
||||||
|
console.log('Error message:', error.message)
|
||||||
|
// 检查错误信息格式
|
||||||
|
let errorMsg = ''
|
||||||
|
if (error.response && error.response.data) {
|
||||||
|
if (error.response.data.msg) {
|
||||||
|
errorMsg = error.response.data.msg
|
||||||
|
} else if (error.response.data.message) {
|
||||||
|
errorMsg = error.response.data.message
|
||||||
|
} else if (error.response.data.error) {
|
||||||
|
errorMsg = error.response.data.error
|
||||||
|
}
|
||||||
|
} else if (error.message) {
|
||||||
|
errorMsg = error.message
|
||||||
|
}
|
||||||
|
console.log('Extracted error message:', errorMsg)
|
||||||
|
if (errorMsg === '该点位不是空站点,请确认是否设置成空站点并继续呼叫?') {
|
||||||
|
this.$confirm('该点位不是空站点,请确认是否设置成空站点并继续呼叫?', '确认操作', {
|
||||||
|
confirmButtonText: '是',
|
||||||
|
cancelButtonText: '否',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
// 用户确认,重新调用接口,传入 check_flag: true
|
||||||
|
crudProduceScreen.callEmp({
|
||||||
|
vehicle_type: this.value,
|
||||||
|
device_code: this.popData.device_code,
|
||||||
|
check_flag: true
|
||||||
|
}).then(res => {
|
||||||
|
this.$message(res.msg)
|
||||||
|
}).catch(error => {
|
||||||
|
// 二次失败,显示后端返回的错误信息
|
||||||
|
let secondErrorMsg = ''
|
||||||
|
if (error.response && error.response.data) {
|
||||||
|
if (error.response.data.msg) {
|
||||||
|
secondErrorMsg = error.response.data.msg
|
||||||
|
} else if (error.response.data.message) {
|
||||||
|
secondErrorMsg = error.response.data.message
|
||||||
|
} else if (error.response.data.error) {
|
||||||
|
secondErrorMsg = error.response.data.error
|
||||||
|
}
|
||||||
|
} else if (error.message) {
|
||||||
|
secondErrorMsg = error.message
|
||||||
|
}
|
||||||
|
this.$message.error(secondErrorMsg || '操作失败')
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
// 用户取消,不做任何操作
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 其他错误,显示错误信息
|
||||||
|
this.$message.error(errorMsg || '操作失败')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else if (this.type === 'SCANER') {
|
} else if (this.type === 'SCANER') {
|
||||||
if (!this.vcode) {
|
if (!this.vcode) {
|
||||||
@@ -666,11 +720,11 @@ export default {
|
|||||||
if (res && res.length > 0) {
|
if (res && res.length > 0) {
|
||||||
// 转换报警信息格式:先过滤再映射,避免undefined
|
// 转换报警信息格式:先过滤再映射,避免undefined
|
||||||
this.errorDetails = res
|
this.errorDetails = res
|
||||||
.filter(status => status.isActive === '1') // 先过滤出激活的报警
|
.filter(status => status.is_active === '1') // 先过滤出激活的报警
|
||||||
.map(status => { // 再映射成目标格式
|
.map(status => { // 再映射成目标格式
|
||||||
return {
|
return {
|
||||||
type: 'AGV报警',
|
type: 'AGV报警',
|
||||||
message: `${status.deviceName || status.deviceCode}: ${status.status}`,
|
message: `${status.device_name || status.device_code}: ${status.status}`,
|
||||||
time: new Date(status.updateTime).toLocaleString('zh-CN')
|
time: new Date(status.updateTime).toLocaleString('zh-CN')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ export default {
|
|||||||
popSecList: [],
|
popSecList: [],
|
||||||
currentRow: null,
|
currentRow: null,
|
||||||
value: '',
|
value: '',
|
||||||
options: [{ value: 'G01', label: 'G01' }, { value: 'R01', label: 'R01' }, { value: 'R02', label: 'R02' }, { value: 'R03', label: 'R03' }, { value: 'S04', label: 'S04' }, { value: 'S06', label: 'S06' }],
|
options: [{ value: 'G01', label: 'G01' }, { value: 'R01', label: 'R01(大框)' }, { value: 'R02', label: 'R02(小框)' }, { value: 'R03', label: 'R03' }, { value: 'S04', label: 'S04(侧板架)' }, { value: 'S06', label: 'S06(A字架)' }],
|
||||||
value1: '',
|
value1: '',
|
||||||
options1: [{ value: '1', label: '货架' }, { value: '2', label: '内部' }, { value: '3', label: '外协' }, { value: '4', label: '内部过道' }],
|
options1: [{ value: '1', label: '货架' }, { value: '2', label: '内部' }, { value: '3', label: '外协' }, { value: '4', label: '内部过道' }],
|
||||||
value2: '',
|
value2: '',
|
||||||
@@ -351,8 +351,62 @@ export default {
|
|||||||
crudProduceScreen.callEmp({ vehicle_type: this.value, device_code: this.popData.device_code }).then(res => {
|
crudProduceScreen.callEmp({ vehicle_type: this.value, device_code: this.popData.device_code }).then(res => {
|
||||||
this.disabled = false
|
this.disabled = false
|
||||||
this.$message(res.msg)
|
this.$message(res.msg)
|
||||||
}).catch(() => {
|
}).catch(error => {
|
||||||
this.disabled = false
|
this.disabled = false
|
||||||
|
console.log('Error object:', error)
|
||||||
|
console.log('Error response:', error.response)
|
||||||
|
console.log('Error response data:', error.response && error.response.data)
|
||||||
|
console.log('Error message:', error.message)
|
||||||
|
// 检查错误信息格式
|
||||||
|
let errorMsg = ''
|
||||||
|
if (error.response && error.response.data) {
|
||||||
|
if (error.response.data.msg) {
|
||||||
|
errorMsg = error.response.data.msg
|
||||||
|
} else if (error.response.data.message) {
|
||||||
|
errorMsg = error.response.data.message
|
||||||
|
} else if (error.response.data.error) {
|
||||||
|
errorMsg = error.response.data.error
|
||||||
|
}
|
||||||
|
} else if (error.message) {
|
||||||
|
errorMsg = error.message
|
||||||
|
}
|
||||||
|
console.log('Extracted error message:', errorMsg)
|
||||||
|
if (errorMsg === '该点位不是空站点,请确认是否设置成空站点并继续呼叫?') {
|
||||||
|
this.$confirm('该点位不是空站点,请确认是否设置成空站点并继续呼叫?', '确认操作', {
|
||||||
|
confirmButtonText: '是',
|
||||||
|
cancelButtonText: '否',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
// 用户确认,重新调用接口,传入 check_flag: true
|
||||||
|
crudProduceScreen.callEmp({
|
||||||
|
vehicle_type: this.value,
|
||||||
|
device_code: this.popData.device_code,
|
||||||
|
check_flag: true
|
||||||
|
}).then(res => {
|
||||||
|
this.$message(res.msg)
|
||||||
|
}).catch(error => {
|
||||||
|
// 二次失败,显示后端返回的错误信息
|
||||||
|
let secondErrorMsg = ''
|
||||||
|
if (error.response && error.response.data) {
|
||||||
|
if (error.response.data.msg) {
|
||||||
|
secondErrorMsg = error.response.data.msg
|
||||||
|
} else if (error.response.data.message) {
|
||||||
|
secondErrorMsg = error.response.data.message
|
||||||
|
} else if (error.response.data.error) {
|
||||||
|
secondErrorMsg = error.response.data.error
|
||||||
|
}
|
||||||
|
} else if (error.message) {
|
||||||
|
secondErrorMsg = error.message
|
||||||
|
}
|
||||||
|
this.$message.error(secondErrorMsg || '操作失败')
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
// 用户取消,不做任何操作
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 其他错误,显示错误信息
|
||||||
|
this.$message.error(errorMsg || '操作失败')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else if (this.type === 'SCANER') {
|
} else if (this.type === 'SCANER') {
|
||||||
if (!this.vcode) {
|
if (!this.vcode) {
|
||||||
|
|||||||
@@ -30,4 +30,11 @@ export function getTodayUsageRate() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { getAgvUsageStatistics, getAgvUsageDetail, getAgvRealtimeStatus, getTodayUsageRate }
|
export function getMonthlyUsageStatistics() {
|
||||||
|
return request({
|
||||||
|
url: 'api/agv_usage/monthly',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { getAgvUsageStatistics, getAgvUsageDetail, getAgvRealtimeStatus, getTodayUsageRate, getMonthlyUsageStatistics }
|
||||||
|
|||||||
@@ -62,7 +62,42 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 月度统计报表 -->
|
||||||
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>月度统计报表</span>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-loading="monthlyLoading"
|
||||||
|
:data="monthlyData"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-table-column prop="month" label="月份" width="100" />
|
||||||
|
<el-table-column prop="totalWorkDuration" label="总工作时长(秒)" width="150">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ formatDuration(scope.row.totalWorkDuration) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="totalTaskCount" label="任务数量" width="100" />
|
||||||
|
<el-table-column prop="avgUsageRate" label="平均使用率(%)">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-progress
|
||||||
|
:percentage="scope.row.avgUsageRate || 0"
|
||||||
|
:color="getProgressColor(scope.row.avgUsageRate)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="maxUsageRate" label="最高使用率(%)" width="120" />
|
||||||
|
<el-table-column prop="minUsageRate" label="最低使用率(%)" width="120" />
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@@ -114,6 +149,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
detailLoading: false,
|
detailLoading: false,
|
||||||
|
monthlyLoading: false,
|
||||||
detailVisible: false,
|
detailVisible: false,
|
||||||
query: {
|
query: {
|
||||||
startDate: new Date(),
|
startDate: new Date(),
|
||||||
@@ -121,11 +157,18 @@ export default {
|
|||||||
},
|
},
|
||||||
tableData: [],
|
tableData: [],
|
||||||
detailData: [],
|
detailData: [],
|
||||||
currentDeviceCode: null
|
monthlyData: [],
|
||||||
|
currentDeviceCode: null,
|
||||||
|
refreshTimer: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.toQuery()
|
this.toQuery()
|
||||||
|
this.getMonthlyStatistics()
|
||||||
|
this.startAutoRefresh()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.clearAutoRefresh()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toQuery() {
|
toQuery() {
|
||||||
@@ -198,6 +241,31 @@ export default {
|
|||||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
const day = String(date.getDate()).padStart(2, '0')
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
return `${year}-${month}-${day}`
|
return `${year}-${month}-${day}`
|
||||||
|
},
|
||||||
|
// 获取月度统计数据
|
||||||
|
getMonthlyStatistics() {
|
||||||
|
this.monthlyLoading = true
|
||||||
|
crudAgvUsage.getMonthlyUsageStatistics().then(res => {
|
||||||
|
this.monthlyData = res || []
|
||||||
|
this.monthlyLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.monthlyLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 开始自动刷新
|
||||||
|
startAutoRefresh() {
|
||||||
|
// 每10秒刷新一次数据
|
||||||
|
this.refreshTimer = setInterval(() => {
|
||||||
|
this.toQuery()
|
||||||
|
this.getMonthlyStatistics()
|
||||||
|
}, 10000)
|
||||||
|
},
|
||||||
|
// 清除自动刷新
|
||||||
|
clearAutoRefresh() {
|
||||||
|
if (this.refreshTimer) {
|
||||||
|
clearInterval(this.refreshTimer)
|
||||||
|
this.refreshTimer = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,5 +280,21 @@ export default {
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 确保所有进度条组件都应用此样式 */
|
||||||
|
.el-progress {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column !important;
|
||||||
|
align-items: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-progress .el-progress-bar {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-progress .el-progress__text {
|
||||||
|
margin-top: 4px !important;
|
||||||
|
white-space: nowrap !important;
|
||||||
|
text-align: center !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,9 @@
|
|||||||
<el-form-item label="载具编码" prop="vehicle_code">
|
<el-form-item label="载具编码" prop="vehicle_code">
|
||||||
<el-input v-model="form.vehicle_code" clearable style="width: 370px;" />
|
<el-input v-model="form.vehicle_code" clearable style="width: 370px;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="多个载具编码" prop="vehicles">
|
||||||
|
<el-input v-model="form.vehicles" clearable style="width: 370px;" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="允许载具类型" prop="can_vehicle_type">
|
<el-form-item label="允许载具类型" prop="can_vehicle_type">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.can_vehicle_type"
|
v-model="form.can_vehicle_type"
|
||||||
@@ -317,6 +320,7 @@
|
|||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<!-- <el-table-column prop="vehicle_type" label="物料类型" :min-width="flexWidth('vehicle_type',crud.data,'物料类型')" />-->
|
<!-- <el-table-column prop="vehicle_type" label="物料类型" :min-width="flexWidth('vehicle_type',crud.data,'物料类型')" />-->
|
||||||
<el-table-column prop="vehicle_code" label="载具编码" :min-width="flexWidth('vehicle_code',crud.data,'载具编码')" />
|
<el-table-column prop="vehicle_code" label="载具编码" :min-width="flexWidth('vehicle_code',crud.data,'载具编码')" />
|
||||||
|
<el-table-column prop="vehicles" label="多个载具编码" :min-width="flexWidth('vehicles',crud.data,'多个载具编码')" />
|
||||||
<el-table-column v-if="false" prop="vehicle_qty" label="载具数量" :min-width="flexWidth('vehicle_qty',crud.data,'载具数量')" />
|
<el-table-column v-if="false" prop="vehicle_qty" label="载具数量" :min-width="flexWidth('vehicle_qty',crud.data,'载具数量')" />
|
||||||
<el-table-column label="是否锁定" :min-width="flexWidth('is_lock',crud.data,'是否锁定')">
|
<el-table-column label="是否锁定" :min-width="flexWidth('is_lock',crud.data,'是否锁定')">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
@@ -382,6 +386,7 @@ const defaultForm = {
|
|||||||
vehicle_max_qty: null,
|
vehicle_max_qty: null,
|
||||||
vehicle_type: null,
|
vehicle_type: null,
|
||||||
vehicle_code: null,
|
vehicle_code: null,
|
||||||
|
vehicles: null,
|
||||||
vehicle_qty: 0,
|
vehicle_qty: 0,
|
||||||
block_num: null,
|
block_num: null,
|
||||||
row_num: null,
|
row_num: null,
|
||||||
|
|||||||
Reference in New Issue
Block a user