From 820bd9563220f9d8de9558dbd7aeb0b6c1b23052 Mon Sep 17 00:00:00 2001 From: zhugongping Date: Sun, 28 Jun 2026 08:22:03 +0800 Subject: [PATCH] =?UTF-8?q?20260627:=E7=BD=91=E5=85=B3=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=94=AF=E6=8C=81=E5=88=A0=E9=99=A4=E5=AD=90?= =?UTF-8?q?=E8=AE=BE=E5=A4=87&=E5=B9=B3=E5=8F=B0=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E3=80=81=E7=B3=BB=E7=BB=9F=E8=AE=BE=E5=A4=87=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=9F=A5=E6=90=9C=E3=80=81=E6=94=AF=E6=8C=81=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=BC=96=E5=8F=B7=E6=9F=A5=E6=90=9C=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E5=85=B3=E7=B3=BB=E6=9D=A1=E7=9B=AE=EF=BC=88=E7=BB=86=E8=8A=82?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/device/DeviceController.java | 2 +- .../platform/PlatformPushLogController.java | 9 + .../fastbee/iot/mapper/SubGatewayMapper.java | 8 + .../mapper/PlatformDeviceMappingMapper.java | 2 + .../PlatformDeviceMappingServiceImpl.java | 7 + .../fastbee/iot/service/IDeviceService.java | 8 + .../iot/service/impl/DeviceServiceImpl.java | 156 ++++++++++++++++-- .../resources/mapper/iot/SubGatewayMapper.xml | 6 + .../platform/PlatformDeviceMappingMapper.xml | 12 ++ sql/platform-menu.sql | 1 + yack-web/src/api/platform/pushLog.js | 4 + .../views/platform/device-mapping/index.vue | 55 ++++-- .../src/views/platform/push-log/index.vue | 26 ++- 13 files changed, 264 insertions(+), 32 deletions(-) diff --git a/fastbee-open-api/src/main/java/com/fastbee/controller/device/DeviceController.java b/fastbee-open-api/src/main/java/com/fastbee/controller/device/DeviceController.java index 55c6dee7..00b35c94 100644 --- a/fastbee-open-api/src/main/java/com/fastbee/controller/device/DeviceController.java +++ b/fastbee-open-api/src/main/java/com/fastbee/controller/device/DeviceController.java @@ -277,7 +277,7 @@ public class DeviceController extends BaseController { @DeleteMapping("/{deviceIds}") @ApiOperation("批量删除设备") public AjaxResult remove(@PathVariable Long[] deviceIds) throws SchedulerException { - return deviceService.deleteDeviceByDeviceId(deviceIds[0]); + return deviceService.deleteDeviceByDeviceIds(deviceIds); } /** diff --git a/fastbee-open-api/src/main/java/com/fastbee/controller/platform/PlatformPushLogController.java b/fastbee-open-api/src/main/java/com/fastbee/controller/platform/PlatformPushLogController.java index 9744a971..bb675122 100644 --- a/fastbee-open-api/src/main/java/com/fastbee/controller/platform/PlatformPushLogController.java +++ b/fastbee-open-api/src/main/java/com/fastbee/controller/platform/PlatformPushLogController.java @@ -11,6 +11,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import java.util.Arrays; + @RestController @RequestMapping("/platform/push-log") @Api(tags = "平台推送日志") @@ -41,4 +43,11 @@ public class PlatformPushLogController extends BaseController { pushLogService.retry(id); return success("重推成功"); } + + @PreAuthorize("@ss.hasPermi('platform:pushLog:remove')") + @DeleteMapping("/{ids}") + @ApiOperation("批量删除推送日志") + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(pushLogService.removeByIds(Arrays.asList(ids))); + } } diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/mapper/SubGatewayMapper.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/mapper/SubGatewayMapper.java index 9c8eaab6..d2030721 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/mapper/SubGatewayMapper.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/mapper/SubGatewayMapper.java @@ -110,4 +110,12 @@ public interface SubGatewayMapper { * @param gwDeviceId */ void deleteGatewayByGwDeviceId(Long gwDeviceId); + + /** + * 根据网关设备ID查询子设备ID列表 + * + * @param gwDeviceId 网关设备ID + * @return 子设备ID列表 + */ + List selectSubDeviceIdsByGwDeviceId(Long gwDeviceId); } diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/mapper/PlatformDeviceMappingMapper.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/mapper/PlatformDeviceMappingMapper.java index c2433a68..31179aa8 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/mapper/PlatformDeviceMappingMapper.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/mapper/PlatformDeviceMappingMapper.java @@ -9,4 +9,6 @@ import java.util.List; public interface PlatformDeviceMappingMapper extends BaseMapperX { List selectBySerialNumber(@Param("serialNumber") String serialNumber); + + int countByReportSerialNumber(@Param("serialNumber") String serialNumber); } diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/service/impl/PlatformDeviceMappingServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/service/impl/PlatformDeviceMappingServiceImpl.java index 0036ad56..9975ab8c 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/service/impl/PlatformDeviceMappingServiceImpl.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/service/impl/PlatformDeviceMappingServiceImpl.java @@ -42,9 +42,16 @@ public class PlatformDeviceMappingServiceImpl extends ServiceImpl selectList(PlatformDeviceMapping query) { + String serialNumber = query.getSerialNumber(); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() .eq(query.getPlatformId() != null, PlatformDeviceMapping::getPlatformId, query.getPlatformId()) .eq(query.getDeviceId() != null, PlatformDeviceMapping::getDeviceId, query.getDeviceId()) + .and(StringUtils.hasText(serialNumber), w -> w + .like(PlatformDeviceMapping::getSerialNumber, serialNumber) + .or() + .apply("EXISTS (SELECT 1 FROM platform_device_sub_mapping s " + + "WHERE s.parent_mapping_id = platform_device_mapping.id AND s.sub_serial_number LIKE {0})", + "%" + serialNumber + "%")) .eq(StringUtils.hasText(query.getSensorType()), PlatformDeviceMapping::getSensorType, query.getSensorType()) .eq(query.getNetStatus() != null, PlatformDeviceMapping::getNetStatus, query.getNetStatus()) .eq(StringUtils.hasText(query.getEnable()), PlatformDeviceMapping::getEnable, query.getEnable()) diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/IDeviceService.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/IDeviceService.java index 8144ccd8..3fc21521 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/IDeviceService.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/IDeviceService.java @@ -227,6 +227,14 @@ public interface IDeviceService { */ public AjaxResult deleteDeviceByDeviceId(Long deviceId) throws SchedulerException; + /** + * 批量删除设备 + * + * @param deviceIds 需要删除的设备主键集合 + * @return 结果 + */ + public AjaxResult deleteDeviceByDeviceIds(Long[] deviceIds) throws SchedulerException; + /** * 生成设备唯一编号 * diff --git a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java index 8ce4fa7e..8ea974a0 100644 --- a/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java +++ b/fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/service/impl/DeviceServiceImpl.java @@ -7,6 +7,7 @@ import com.alibaba.fastjson2.JSONObject; import com.baomidou.dynamic.datasource.annotation.DSTransactional; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fastbee.common.constant.FastBeeConstant; +import com.fastbee.common.constant.HttpStatus; import com.fastbee.common.constant.ProductAuthConstant; import com.fastbee.common.core.device.DeviceAndProtocol; import com.fastbee.common.core.domain.AjaxResult; @@ -46,6 +47,7 @@ import com.fastbee.iot.model.dto.ThingsModelDTO; import com.fastbee.iot.model.gateWay.ProductSubGatewayVO; import com.fastbee.iot.model.gateWay.SubDeviceCreateByProductVO; import com.fastbee.iot.model.gateWay.SubDeviceListVO; +import com.fastbee.iot.platform.mapper.PlatformDeviceMappingMapper; import com.fastbee.iot.service.*; import com.fastbee.iot.tdengine.service.ILogService; import com.fastbee.system.mapper.SysDeptMapper; @@ -143,6 +145,8 @@ public class DeviceServiceImpl implements IDeviceService { private SubGatewayMapper subGatewayMapper; @Autowired private DeviceMapper deviceMapper; + @Resource + private PlatformDeviceMappingMapper platformDeviceMappingMapper; @Autowired private DeviceUserMapper deviceUserMapper; @Resource @@ -331,14 +335,71 @@ public class DeviceServiceImpl implements IDeviceService { /** * 删除设备 * - * @param deviceId 需要删除的设备主键 + * @param deviceIds 需要删除的设备主键 * @return 结果 */ @CacheEvict(cacheNames = "Device", allEntries = true) + @Transactional(rollbackFor = Exception.class) + @Override + public AjaxResult deleteDeviceByDeviceIds(Long[] deviceIds) throws SchedulerException { + if (deviceIds == null || deviceIds.length == 0) { + return AjaxResult.error("请选择要删除的设备"); + } + + SysUser user = getLoginUser().getUser(); + List devices = new ArrayList<>(); + List existsDeviceIds = new ArrayList<>(); + for (Long deviceId : deviceIds) { + if (deviceId == null || existsDeviceIds.contains(deviceId)) { + continue; + } + Device device = deviceMapper.selectDeviceByDeviceId(deviceId); + if (device == null) { + continue; + } + devices.add(device); + existsDeviceIds.add(deviceId); + } + if (CollectionUtils.isEmpty(devices)) { + return AjaxResult.error("设备不存在"); + } + + for (Device device : devices) { + if (isGeneralUserForDelete(device, user)) { + continue; + } + AjaxResult platformMappingCheck = checkPlatformMappingBeforeDelete(device); + if (!isSuccessResult(platformMappingCheck)) { + return platformMappingCheck; + } + } + + int deletedCount = 0; + for (Device device : devices) { + if (deviceMapper.selectDeviceByDeviceId(device.getDeviceId()) == null) { + continue; + } + AjaxResult result = deleteDeviceByDeviceId(device.getDeviceId()); + if (!isSuccessResult(result)) { + if (deletedCount == 0) { + return result; + } + throw new ServiceException(Objects.toString(result.get(AjaxResult.MSG_TAG), "删除设备失败")); + } + deletedCount++; + } + return AjaxResult.success(); + } + + @CacheEvict(cacheNames = "Device", allEntries = true) + @Transactional(rollbackFor = Exception.class) @Override public AjaxResult deleteDeviceByDeviceId(Long deviceId) { // 查询设备 Device device = deviceMapper.selectDeviceByDeviceId(deviceId); + if (device == null) { + return AjaxResult.error("设备不存在"); + } SysUser user = getLoginUser().getUser(); Long sceneUserId; Long deptUserId = user.getDept().getDeptUserId(); @@ -349,19 +410,7 @@ public class DeviceServiceImpl implements IDeviceService { } // 2.3版本更改 设备管理者和设备拥有者为true,普通用户如果不是设备所有者,只能删除设备用户和用户自己的设备关联分组信息 // 删除当前层级分配记录,将设备改回到上一级 - boolean isGeneralUser; - if (isAdmin(user.getUserId())) { - isGeneralUser = false; - } else { - // 终端用户和非设备所属机构用户不允许删除设备 - if (null == user.getDeptId()) { - isGeneralUser = true; - } else if (!Objects.equals(device.getTenantId(), deptUserId)) { - isGeneralUser = true; - } else { - isGeneralUser = false; - } - } + boolean isGeneralUser = isGeneralUserForDelete(device, user); // 设备下不能有场景联动 List sceneDeviceBindVOList = sceneDeviceMapper.listSceneDeviceBind(device.getSerialNumber()); if (null != sceneDeviceBindVOList.stream().filter(s -> s.getUserId().equals(sceneUserId)).findAny() @@ -416,6 +465,13 @@ public class DeviceServiceImpl implements IDeviceService { } } + AjaxResult platformMappingCheck = checkPlatformMappingBeforeDelete(device); + if (!isSuccessResult(platformMappingCheck)) { + return platformMappingCheck; + } + // 删除网关设备 + deleteGatewaySubDevices(device); + if (null != shareSceneIds && shareSceneIds.length > 0) { sceneService.deleteSceneBySceneIds(shareSceneIds); } @@ -463,7 +519,6 @@ public class DeviceServiceImpl implements IDeviceService { // 删除网关绑定子设备关系 if (DeviceType.GATEWAY.getCode() == device.getDeviceType()) { subGatewayMapper.deleteGatewayByGwDeviceId(deviceId); - // todo 需要删子设备 } // 删除modbus轮询指令 String keyModbus = RedisKeyBuilder.buildModbusRuntimeCacheKey(device.getSerialNumber()); @@ -472,6 +527,77 @@ public class DeviceServiceImpl implements IDeviceService { return AjaxResult.success(); } + private boolean isGeneralUserForDelete(Device device, SysUser user) { + if (isAdmin(user.getUserId())) { + return false; + } + // 终端用户和非设备所属机构用户不是真正删除设备,只解除自己的设备关系。 + if (user.getDeptId() == null) { + return true; + } + return !Objects.equals(device.getTenantId(), user.getDept().getDeptUserId()); + } + + private AjaxResult checkPlatformMappingBeforeDelete(Device device) { + List devices = new ArrayList<>(); + devices.add(device); + if (DeviceType.GATEWAY.getCode() == device.getDeviceType()) { + devices.addAll(selectGatewaySubDevices(device)); + } + for (Device item : devices) { + if (item == null || StringUtils.isEmpty(item.getSerialNumber())) { + continue; + } + if (platformDeviceMappingMapper.countByReportSerialNumber(item.getSerialNumber()) > 0) { + String prefix = Objects.equals(item.getDeviceId(), device.getDeviceId()) ? "设备" : "子设备"; + String name = StringUtils.isNotEmpty(item.getDeviceName()) ? item.getDeviceName() : item.getSerialNumber(); + return AjaxResult.error(prefix + "【" + name + "】存在数据推送关系,请先删除数据推送关系才能删除本设备"); + } + } + return AjaxResult.success(); + } + + private void deleteGatewaySubDevices(Device device) { + if (DeviceType.GATEWAY.getCode() != device.getDeviceType()) { + return; + } + List subDevices = selectGatewaySubDevices(device); + for (Device subDevice : subDevices) { + if (subDevice == null || subDevice.getDeviceId() == null) { + continue; + } + AjaxResult result = deleteDeviceByDeviceId(subDevice.getDeviceId()); + if (!isSuccessResult(result)) { + String msg = result == null ? "未知错误" : Objects.toString(result.get(AjaxResult.MSG_TAG), "未知错误"); + String name = StringUtils.isNotEmpty(subDevice.getDeviceName()) + ? subDevice.getDeviceName() : subDevice.getSerialNumber(); + throw new ServiceException("删除网关子设备【" + name + "】失败:" + msg); + } + } + } + + private List selectGatewaySubDevices(Device device) { + if (device.getDeviceId() == null) { + return Collections.emptyList(); + } + List subDeviceIds = subGatewayMapper.selectSubDeviceIdsByGwDeviceId(device.getDeviceId()); + if (CollectionUtils.isEmpty(subDeviceIds)) { + return Collections.emptyList(); + } + List subDevices = new ArrayList<>(); + for (Long subDeviceId : subDeviceIds) { + Device subDevice = deviceMapper.selectDeviceByDeviceId(subDeviceId); + if (subDevice != null) { + subDevices.add(subDevice); + } + } + return subDevices; + } + + private boolean isSuccessResult(AjaxResult result) { + return result != null && Objects.equals(result.get(AjaxResult.CODE_TAG), HttpStatus.SUCCESS); + } + /** * TODO-2.3 查询设备统计信息 * diff --git a/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/SubGatewayMapper.xml b/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/SubGatewayMapper.xml index 2f3db55f..1527375e 100644 --- a/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/SubGatewayMapper.xml +++ b/fastbee-service/fastbee-iot-service/src/main/resources/mapper/iot/SubGatewayMapper.xml @@ -127,6 +127,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" delete from iot_sub_gateway where gw_device_id = #{gwDeviceId} + + + + diff --git a/sql/platform-menu.sql b/sql/platform-menu.sql index c55fbb17..c3794fed 100644 --- a/sql/platform-menu.sql +++ b/sql/platform-menu.sql @@ -42,6 +42,7 @@ INSERT INTO `sys_menu` VALUES(3524, '绑定删除', 3520, 4, '#', '', NULL, 1, 0 INSERT INTO `sys_menu` VALUES(3530, '推送日志', 3500, 4, 'push-log', 'platform/push-log/index', NULL, 1, 0, 'C', '0', '0', 'platform:pushLog:list', 'log', 'admin', NOW(), '', NULL, '推送日志菜单'); INSERT INTO `sys_menu` VALUES(3531, '日志查询', 3530, 1, '#', '', NULL, 1, 0, 'F', '0', '0', 'platform:pushLog:list', '#', 'admin', NOW(), '', NULL, ''); INSERT INTO `sys_menu` VALUES(3532, '日志详情', 3530, 2, '#', '', NULL, 1, 0, 'F', '0', '0', 'platform:pushLog:query', '#', 'admin', NOW(), '', NULL, ''); +INSERT INTO `sys_menu` VALUES(3533, '日志删除', 3530, 3, '#', '', NULL, 1, 0, 'F', '0', '0', 'platform:pushLog:remove', '#', 'admin', NOW(), '', NULL, ''); -- ---------------------------- -- 二级菜单:接口配置(高级,默认隐藏) diff --git a/yack-web/src/api/platform/pushLog.js b/yack-web/src/api/platform/pushLog.js index 084a688e..dd7ef0a7 100644 --- a/yack-web/src/api/platform/pushLog.js +++ b/yack-web/src/api/platform/pushLog.js @@ -11,3 +11,7 @@ export function getPlatformPushLog(id) { export function retryPlatformPushLog(id) { return request({ url: `/platform/push-log/${id}/retry`, method: 'post' }) } + +export function delPlatformPushLog(ids) { + return request({ url: `/platform/push-log/${ids}`, method: 'delete' }) +} diff --git a/yack-web/src/views/platform/device-mapping/index.vue b/yack-web/src/views/platform/device-mapping/index.vue index 46ff5f40..6ce02e6f 100644 --- a/yack-web/src/views/platform/device-mapping/index.vue +++ b/yack-web/src/views/platform/device-mapping/index.vue @@ -8,6 +8,9 @@ + + + @@ -115,10 +118,11 @@ - - + @@ -254,7 +258,7 @@ import { listPlatformDeviceMapping, addPlatformDeviceMapping, updatePlatformDeviceMapping, delPlatformDeviceMapping, onboardDevice, listSubMappings, syncSubMappings } from '@/api/platform/deviceMapping' import { listPlatformInstance } from '@/api/platform/instance' import { listPlatformInterface } from '@/api/platform/interface' -import { listDevice, listThingsModel, getDevice } from '@/api/iot/device' +import { listDevice, listThingsModel, getDevice, listDeviceShort } from '@/api/iot/device' import { listGateway } from '@/api/iot/gateway' import { getDicts } from '@/api/system/dict/data' @@ -278,7 +282,7 @@ export default { // 子表缓存 (列表展开行使用) subMappingCache: {}, sensorTypeDictOptions: [], - queryParams: { pageNum: 1, pageSize: 20, platformId: null, sensorType: '', netStatus: null }, + queryParams: { pageNum: 1, pageSize: 20, platformId: null, serialNumber: '', sensorType: '', netStatus: null }, form: { enable: '1', deviceType: 0, reportIntervalSec: 300 }, rules: { platformId: [{ required: true, message: '请选择平台', trigger: 'change' }], @@ -353,6 +357,12 @@ export default { }, platformName(id) { const p = this.platformList.find(x => x.id === id); return p ? p.name : id }, deviceName(id) { return this.deviceMap[id] || id }, + deviceOptionLabel(device) { + const typeText = device.deviceType === 2 || device.subDeviceCount > 0 ? '网关' : '直连' + const name = device.deviceName || device.serialNumber || device.deviceId + const sn = device.serialNumber ? `(${device.serialNumber})` : '' + return `${name}${sn} - ${typeText}` + }, sensorLabel(v) { const option = this.sensorTypeOptions.find(item => item.value === v) return option ? option.label : v @@ -481,24 +491,43 @@ export default { this.form.serialNumber = d.serialNumber this.loadSubDeviceOptions(d) } else { + this.form.serialNumber = '' this.subDeviceOptions = [] + this.thingsModelOptions = [] } this.loadThingsModel(deviceId) }, + onDeviceSelectVisible(visible) { + if (visible && this.deviceOptions.length === 0) { + this.searchDevice('') + } + }, searchDevice(query) { const keyword = (query || '').trim() - if (!keyword) return this.deviceSearchLoading = true - listDevice({ pageNum: 1, pageSize: 50, ...this.buildDeviceSearchParams(keyword) }).then(res => { - this.deviceOptions = res.rows; this.deviceSearchLoading = false + const base = { pageNum: 1, pageSize: 50, entrance: 1 } + const requests = [] + if (!keyword) { + requests.push(listDeviceShort(base)) + } else { + requests.push(listDeviceShort({ ...base, deviceName: keyword })) + requests.push(listDeviceShort({ ...base, serialNumber: keyword })) + } + Promise.all(requests.map(req => req.catch(() => ({ rows: [] })))).then(results => { + this.deviceOptions = this.mergeDeviceOptions(results.flatMap(res => res.rows || [])) + }).finally(() => { + this.deviceSearchLoading = false }) }, - buildDeviceSearchParams(query) { - const keyword = (query || '').trim() - if (keyword.length === 12) { - return { serialNumber: keyword } - } - return { deviceName: keyword } + mergeDeviceOptions(rows) { + const map = new Map() + ;(rows || []).forEach(item => { + if (!item || !item.deviceId || item.gwDevCode) return + if (!map.has(item.deviceId)) { + map.set(item.deviceId, item) + } + }) + return Array.from(map.values()) }, loadDeviceContext(deviceId) { if (!deviceId) return diff --git a/yack-web/src/views/platform/push-log/index.vue b/yack-web/src/views/platform/push-log/index.vue index be7149a2..3893068a 100644 --- a/yack-web/src/views/platform/push-log/index.vue +++ b/yack-web/src/views/platform/push-log/index.vue @@ -26,14 +26,20 @@ - + + + 删除 + + + - + + @@ -99,7 +105,7 @@