Shinohara Haruna преди 5 месеца
родител
ревизия
48fb2988cc

+ 13 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/controller/SmsbDeviceController.java

@@ -4,6 +4,7 @@ import java.util.List;
 
 import com.inspur.device.domain.bo.SmsbDeviceBo;
 import com.inspur.device.domain.vo.DeviceStatisticsVo;
+import com.inspur.device.domain.vo.SmsbDeviceMultiCardVo;
 import com.inspur.device.domain.vo.SmsbDeviceRunInfoVo;
 import com.inspur.device.domain.vo.SmsbDeviceVo;
 import com.inspur.device.service.ISmsbDeviceService;
@@ -78,6 +79,18 @@ public class SmsbDeviceController extends BaseController {
         return R.ok(smsbDeviceService.queryById(id));
     }
 
+    /**
+     * 获取设备多功能卡信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("smsb:device:query")
+    @GetMapping("/multiCard/{id}")
+    public R<List<SmsbDeviceMultiCardVo>> getDeviceMultiCardList(@NotNull(message = "主键不能为空")
+                                   @PathVariable Long id) {
+        return R.ok(smsbDeviceService.getDeviceMultiCardList(id));
+    }
+
     /**
      * 获取设备详细信息
      *

+ 3 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/domain/constants/DeviceConstants.java

@@ -48,4 +48,7 @@ public class DeviceConstants {
     public static final String REDIS_DEVICE_AUTH_KEY = "global:device:auth:key:";
 
 
+    /** 设备多功能卡上报信息 */
+    public static final String REDIS_DEVICE_MULTI_CARD_KEY = "global:device:multi:card:";
+
 }

+ 18 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/domain/vo/FrontMultiCardUploadVo.java

@@ -0,0 +1,18 @@
+package com.inspur.device.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 前端设备上报多功能卡
+ * @author lihao16
+ */
+@Data
+public class FrontMultiCardUploadVo {
+
+    private String identifier;
+
+    private List<SmsbDeviceMultiCardVo> portList;
+
+}

+ 31 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/domain/vo/SmsbDeviceMultiCardVo.java

@@ -0,0 +1,31 @@
+package com.inspur.device.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 多功能卡Vo
+ * @author lihao16
+ */
+@Data
+public class SmsbDeviceMultiCardVo {
+
+    /**
+     * 电源端口
+     */
+    private Integer indexNum;
+
+    /**
+     * 电源类型
+     */
+    private Integer powerType;
+
+    /**
+     * 同步时间
+     */
+    private String syncTime;
+
+    /**
+     * 电源状态 0-关闭 1-开启
+     */
+    private Integer powerStatus;
+}

+ 15 - 4
smsb-modules/smsb-device/src/main/java/com/inspur/device/service/ISmsbDeviceService.java

@@ -3,10 +3,7 @@ package com.inspur.device.service;
 import com.inspur.device.domain.SmsbDevice;
 import com.inspur.device.domain.bo.HttpHeartbeatReq;
 import com.inspur.device.domain.bo.SmsbDeviceBo;
-import com.inspur.device.domain.vo.DeviceStatisticsVo;
-import com.inspur.device.domain.vo.HttpHeartbeatRspVo;
-import com.inspur.device.domain.vo.SmsbDeviceRunInfoVo;
-import com.inspur.device.domain.vo.SmsbDeviceVo;
+import com.inspur.device.domain.vo.*;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -140,4 +137,18 @@ public interface ISmsbDeviceService {
      * @return
      */
     R<HttpHeartbeatRspVo> heartbeat(HttpHeartbeatReq requestParam);
+
+    /**
+     * 前端设备多功能卡上报
+     * @param frontMultiCardUploadVo
+     * @return
+     */
+    R<Void> uploadMultiCard(FrontMultiCardUploadVo frontMultiCardUploadVo);
+
+    /**
+     * 根据设备ID获取多功能卡数据
+     * @param id
+     * @return
+     */
+    List<SmsbDeviceMultiCardVo> getDeviceMultiCardList(Long id);
 }

+ 41 - 9
smsb-modules/smsb-device/src/main/java/com/inspur/device/service/impl/SmsbDeviceServiceImpl.java

@@ -1,6 +1,7 @@
 package com.inspur.device.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
 import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -20,7 +21,6 @@ import com.inspur.device.mapper.SmsbDeviceMapper;
 import com.inspur.device.mapper.SmsbDeviceRunInfoMapper;
 import com.inspur.device.service.ISmsbDeviceManufacturerService;
 import com.inspur.device.service.ISmsbDeviceService;
-import com.inspur.device.service.ISmsbProductService;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.exception.ServiceException;
@@ -42,15 +42,13 @@ import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 设备Service业务层处理
@@ -289,12 +287,17 @@ public class SmsbDeviceServiceImpl implements ISmsbDeviceService {
     @Override
     public SmsbDeviceRunInfoVo getRunInfo(Long deviceId) {
         SmsbDeviceRunInfoVo result = new SmsbDeviceRunInfoVo();
-        // 设备运行详情
-        SmsbDeviceRunInfoVo runInfoVo = smsbDeviceRunInfoMapper.selectVoOne(new LambdaQueryWrapper<SmsbDeviceRunInfo>()
-            .eq(SmsbDeviceRunInfo::getDeviceId, deviceId).orderByDesc(SmsbDeviceRunInfo::getCreateTime).last(DeviceConstants.LIMIT_ONE));
-        BeanUtil.copyProperties(runInfoVo, result);
         // 设备基础详情
         SmsbDeviceVo deviceVo = getDeviceCacheById(deviceId);
+        SmsbDeviceRunInfo cacheRunInfo = RedisUtils.getCacheObject(DeviceConstants.REDIS_DEVICE_RUN_INFO_KEY + deviceVo.getIdentifier());
+        if (cacheRunInfo == null) {
+            // 设备运行详情
+            SmsbDeviceRunInfoVo runInfoVo = smsbDeviceRunInfoMapper.selectVoOne(new LambdaQueryWrapper<SmsbDeviceRunInfo>()
+                .eq(SmsbDeviceRunInfo::getDeviceId, deviceId).orderByDesc(SmsbDeviceRunInfo::getCreateTime).last(DeviceConstants.LIMIT_ONE));
+            BeanUtil.copyProperties(runInfoVo, result);
+        }else {
+            BeanUtils.copyProperties(cacheRunInfo, result);
+        }
         result.setDeviceBase(deviceVo);
         return result;
     }
@@ -403,7 +406,36 @@ public class SmsbDeviceServiceImpl implements ISmsbDeviceService {
         deviceRunInfo.setRamTotalOfByte(requestParam.getRamTotalOfByte().toString());
         deviceRunInfo.setRamUsageOfByte(requestParam.getRamUsageOfByte().toString());
         smsbDeviceRunInfoMapper.insert(deviceRunInfo);
+        // 6 Redis 缓存
+        RedisUtils.setCacheObject(DeviceConstants.REDIS_DEVICE_RUN_INFO_KEY + requestParam.getIdentifier(), deviceRunInfo, Duration.ofMinutes(1));
 
         return R.ok();
     }
+
+    @Override
+    public R<Void> uploadMultiCard(FrontMultiCardUploadVo frontMultiCardUploadVo) {
+        String identifier = frontMultiCardUploadVo.getIdentifier();
+        List<SmsbDeviceMultiCardVo> multiCardVoList = frontMultiCardUploadVo.getPortList();
+        // 将多功能卡信息缓存至Redis
+        if (CollectionUtils.isEmpty(multiCardVoList)) {
+            return R.ok();
+        }
+        String syncTime = DateUtil.formatDateTime(new Date());
+        for (SmsbDeviceMultiCardVo multiCardVo : multiCardVoList) {
+            multiCardVo.setSyncTime(syncTime);
+        }
+        RedisUtils.setCacheObject(DeviceConstants.REDIS_DEVICE_MULTI_CARD_KEY + identifier, multiCardVoList, Duration.ofMinutes(30));
+        return R.ok();
+    }
+
+    @Override
+    public List<SmsbDeviceMultiCardVo> getDeviceMultiCardList(Long id) {
+        List<SmsbDeviceMultiCardVo> deviceMultiCardVoList = new ArrayList<>();
+        SmsbDeviceVo smsbDeviceVo = this.getDeviceCacheById(id);
+        if (smsbDeviceVo == null) {
+            return deviceMultiCardVoList;
+        }
+        deviceMultiCardVoList = RedisUtils.getCacheObject(DeviceConstants.REDIS_DEVICE_MULTI_CARD_KEY + smsbDeviceVo.getIdentifier());
+        return deviceMultiCardVoList;
+    }
 }

+ 12 - 3
smsb-modules/smsb-source/src/main/java/com/inspur/source/controller/SmsbFrontController.java

@@ -2,9 +2,7 @@ package com.inspur.source.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import com.inspur.device.domain.bo.HttpHeartbeatReq;
-import com.inspur.device.domain.vo.HttpHeartbeatRspVo;
-import com.inspur.device.domain.vo.SmsbDeviceTaskVo;
-import com.inspur.device.domain.vo.SmsbOtaRecordVo;
+import com.inspur.device.domain.vo.*;
 import com.inspur.device.service.*;
 import com.inspur.source.domain.vo.FrontPushInfoVo;
 import com.inspur.source.service.ISmsbItemPushService;
@@ -149,4 +147,15 @@ public class SmsbFrontController {
         return smsbDeviceTaskService.uploadTaskStatus(taskId,taskStatus);
     }
 
+    /**
+     * 前端设备多功能卡上报
+     *
+     * @param frontMultiCardUploadVo
+     */
+    @SaIgnore
+    @PostMapping("/multiCard")
+    public R<Void> uploadTaskStatus(@RequestBody FrontMultiCardUploadVo frontMultiCardUploadVo) {
+        return smsbDeviceService.uploadMultiCard(frontMultiCardUploadVo);
+    }
+
 }

+ 8 - 1
smsb-plus-ui/src/api/smsb/device/device.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request';
 import {AxiosPromise} from 'axios';
-import {DeviceForm, DeviceQuery, DeviceVO} from '@/api/smsb/device/device_type';
+import {DeviceForm, DeviceMultiCardVo, DeviceQuery, DeviceVO} from '@/api/smsb/device/device_type';
 
 /**
  * 查询设备列表
@@ -53,6 +53,13 @@ export const getDeviceRunInfo = (id: string | number): AxiosPromise<DeviceVO> =>
   });
 };
 
+export const getDeviceMultiCardList = (id: string | number): AxiosPromise<DeviceMultiCardVo[]> => {
+  return request({
+    url: '/smsb/device/multiCard/' + id,
+    method: 'get',
+  });
+};
+
 /**
  * 新增设备
  * @param data

+ 6 - 0
smsb-plus-ui/src/api/smsb/device/device_type.ts

@@ -435,3 +435,9 @@ export interface DeviceStatisticsVo {
   offlineNum: number;
   initNum: number;
 }
+export interface DeviceMultiCardVo {
+  indexNum: number;
+  powerType: number;
+  syncTime: string;
+  powerStatus: number;
+}

+ 1 - 0
smsb-plus-ui/src/assets/styles/element-ui.scss

@@ -77,6 +77,7 @@
       margin: 0 auto !important;
 
       .el-dialog__body {
+        margin-top: 15px !important;
         padding: 15px !important;
       }
       .el-dialog__header {

+ 68 - 37
smsb-plus-ui/src/views/smsb/device/index.vue

@@ -40,24 +40,24 @@
           </el-row>
         </el-card>
         <el-card shadow="hover" :style="{ marginTop: '10px', height: '60px' }">
-          <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="40px">
-            <el-form-item label="名称" prop="name">
-              <el-input v-model="queryParams.name" style="width: 150px" placeholder="请输入设备名称" clearable
-                @keyup.enter="handleQuery" />
+          <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="0px">
+            <el-form-item label="" prop="name">
+              <el-input v-model="queryParams.name" style="width: 120px" placeholder="请输入设备名称" clearable
+                        @keyup.enter="handleQuery"/>
             </el-form-item>
-            <el-form-item label="SN" prop="serialNumber">
-              <el-input v-model="queryParams.serialNumber" style="width: 150px" placeholder="请输入设备SN" clearable
-                @keyup.enter="handleQuery" />
+            <el-form-item label="" prop="serialNumber">
+              <el-input v-model="queryParams.serialNumber" style="width: 120px" placeholder="请输入设备SN" clearable
+                        @keyup.enter="handleQuery"/>
             </el-form-item>
-            <el-form-item label="MAC" prop="mac">
-              <el-input v-model="queryParams.mac" style="width: 150px" placeholder="请输入设备MAC" clearable
-                @keyup.enter="handleQuery" />
+            <el-form-item label="" prop="mac">
+              <el-input v-model="queryParams.mac" style="width: 125px" placeholder="请输入设备MAC" clearable
+                        @keyup.enter="handleQuery"/>
             </el-form-item>
-            <el-form-item label="状态" prop="onlineStatus">
+            <el-form-item label="" prop="onlineStatus">
               <el-select v-model="queryParams.onlineStatus" placeholder="请选择设备状态" clearable @change="handleQuery"
-                style="width: 150px">
+                         style="width: 150px">
                 <el-option v-for="item in sys_device_online" :key="item.label" :value="item.value"
-                  :label="item.label"></el-option>
+                           :label="item.label"></el-option>
               </el-select>
             </el-form-item>
             <el-form-item>
@@ -275,13 +275,30 @@
           </div>
         </el-tab-pane>
         <el-tab-pane label="远程操作" name="control">
-          <el-button :loading="buttonLoading" type="primary" @click="handleControl('reboot')">设备重启</el-button>
-          <el-button :loading="buttonLoading" type="primary" @click="handleControl('restartApp')">应用重启</el-button>
-<!--          <el-button :loading="buttonLoading" type="primary" @click="handleControl('shutdown')">远程关机</el-button>-->
-          <el-button :loading="buttonLoading" type="primary" @click="handleControl('standby/true')">设备亮屏</el-button>
-          <el-button :loading="buttonLoading" type="primary" @click="handleControl('standby/false')">设备息屏</el-button>
-          <el-button :loading="buttonLoading" type="primary" @click="handleVoice">音量调节</el-button>
-          <el-button :loading="buttonLoading" type="primary" @click="handleBrightness">亮度调节</el-button>
+          <div style="margin-top: 10px">
+            <el-button :loading="buttonLoading" type="primary" @click="handleControl('reboot')">设备重启</el-button>
+            <el-button :loading="buttonLoading" type="primary" @click="handleControl('restartApp')">应用重启</el-button>
+            <!--          <el-button :loading="buttonLoading" type="primary" @click="handleControl('shutdown')">远程关机</el-button>-->
+            <el-button :loading="buttonLoading" type="primary" @click="handleControl('standby/true')">设备亮屏</el-button>
+            <el-button :loading="buttonLoading" type="primary" @click="handleControl('standby/false')">设备息屏</el-button>
+            <el-button :loading="buttonLoading" type="primary" @click="handleVoice">音量调节</el-button>
+            <el-button :loading="buttonLoading" type="primary" @click="handleBrightness">亮度调节</el-button>
+          </div>
+          <el-divider border-style="double"/>
+          <el-table :data="deviceMultiCardList">
+            <el-table-column label="电源端口" align="center" prop="indexNum"/>
+            <el-table-column label="电源类型" align="center" prop="powerType">
+              <template #default="scope">
+                <dict-tag :options="smsb_multi_card_type" :value="scope.row.powerType"/>
+              </template>
+            </el-table-column>
+            <el-table-column label="同步时间" align="center" prop="syncTime"/>
+            <el-table-column label="状态" align="center" prop="powerStatus">
+              <template #default="scope">
+                <dict-tag :options="smsb_multi_card_status" :value="scope.row.powerStatus"/>
+              </template>
+            </el-table-column>
+          </el-table>
         </el-tab-pane>
         <el-tab-pane label="报警信息" name="alarm">
           <div class="table-content">
@@ -311,6 +328,7 @@
         </div>
       </template>
     </el-dialog>
+    <!--推流弹窗-->
     <el-dialog v-model="watchDialog.visible" :title="watchDialog.title" width="900px" append-to-body
       @closed="onDialogClosed">
       <div v-if="watchDialog.visible" style="width: 100%; height: 500px">
@@ -322,6 +340,7 @@
         </div>
       </template>
     </el-dialog>
+    <!--截图弹窗-->
     <el-dialog v-model="shotDialog.visible" :title="shotDialog.title" width="900px" append-to-body
       @closed="onDialogClosed">
       <div style="text-align: center">
@@ -355,40 +374,51 @@
 <script setup name="Device" lang="ts">
 import {
   addDevice,
+  brightSet,
   delDevice,
   deviceStatistics,
   getDevice,
+  getDeviceMultiCardList,
   getDeviceRunInfo,
   getDeviceScreenshot,
   listDevice,
-  reboot, restartApp,
+  reboot,
+  restartApp,
   shutdown,
   standby,
   startStream,
   stopStream,
-  updateDevice, volumeSet,brightSet
+  updateDevice,
+  volumeSet
 } from '@/api/smsb/device/device';
-import { DeviceForm, DeviceQuery, DeviceStatisticsVo, DeviceVO } from '@/api/smsb/device/device_type';
-import { ProductVO } from '@/api/smsb/device/product_types';
-import { DeviceManufacturerVO } from '@/api/smsb/device/deviceManufacturer_type';
-import { listDeviceManufacturer } from '@/api/smsb/device/deviceManufacturer';
-import type { TabsPaneContext } from 'element-plus';
-import { onBeforeUnmount, ref } from 'vue';
+import {DeviceForm, DeviceMultiCardVo, DeviceQuery, DeviceStatisticsVo, DeviceVO} from '@/api/smsb/device/device_type';
+import {DeviceManufacturerVO} from '@/api/smsb/device/deviceManufacturer_type';
+import {listDeviceManufacturer} from '@/api/smsb/device/deviceManufacturer';
+import type {TabsPaneContext} from 'element-plus';
+import {onBeforeUnmount, ref} from 'vue';
 import flvjs from 'flv.js';
-import { DeviceRunInfoVO } from '@/api/smsb/device/device_run_type';
-import { DeviceErrorRecordQuery, DeviceErrorRecordVO } from '@/api/smsb/device/errorRecord_type';
-import { listDeviceErrorRecord } from '@/api/smsb/device/errorRecord';
-import { storeToRefs } from 'pinia';
+import {DeviceRunInfoVO} from '@/api/smsb/device/device_run_type';
+import {DeviceErrorRecordQuery, DeviceErrorRecordVO} from '@/api/smsb/device/errorRecord_type';
+import {listDeviceErrorRecord} from '@/api/smsb/device/errorRecord';
+import {storeToRefs} from 'pinia';
 import useScreenshotStore from '@/store/modules/screenshot';
 
 const screenshotStore = storeToRefs(useScreenshotStore());
 const screenshotImageUrl = ref<string>();
 const alarmList = ref<DeviceErrorRecordVO[]>([]);
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { sys_device_online, smsb_yes_no, smsb_device_error_level, smsb_device_error_type } = toRefs<any>(
-  proxy?.useDict('sys_device_online', 'smsb_yes_no', 'smsb_device_error_level', 'smsb_device_error_type')
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {
+  sys_device_online,
+  smsb_yes_no,
+  smsb_device_error_level,
+  smsb_device_error_type,
+  smsb_multi_card_type,
+  smsb_multi_card_status
+} = toRefs<any>(
+  proxy?.useDict('sys_device_online', 'smsb_yes_no', 'smsb_device_error_level', 'smsb_device_error_type', 'smsb_multi_card_type', 'smsb_multi_card_status')
 );
 const deviceList = ref<DeviceVO[]>([]);
+const deviceMultiCardList = ref<DeviceMultiCardVo[]>([]);
 const deviceStatisticsVo = ref<DeviceStatisticsVo>();
 const manufacturerList = ref<DeviceManufacturerVO[]>([]);
 const buttonLoading = ref(false);
@@ -699,7 +729,8 @@ const handleInfo = async (row?: DeviceVO) => {
   deviceRunInfo.ramUsage = (parseFloat(deviceRunInfo.ramUsageOfByte) * 100 / parseFloat(deviceRunInfo.ramTotalOfByte)).toFixed(1)
   viewDialog.title = '设备详情';
   viewDialog.visible = true;
-  console.log(deviceRunInfo);
+  const multiCardRsp = await getDeviceMultiCardList(deviceId.value);
+  deviceMultiCardList.value = multiCardRsp.data;
 };
 
 const handleControl = async (type: string) => {
@@ -774,7 +805,7 @@ const startMonitor = async (row?: DeviceVO) => {
         flvPlayer.value.load();
         // 处理浏览器自动播放策略
         flvPlayer.value.play().catch(() => {
-          proxy?.$modal.msgWarning('请点击视频播放按钮以开始播放');
+          // proxy?.$modal.msgWarning('请点击视频播放按钮以开始播放');
         });
       }
     } else {

+ 2 - 2
smsb-plus-ui/src/views/smsb/item/index.vue

@@ -117,7 +117,7 @@
         v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
     <!-- 添加或修改轮播组对话框 -->
-    <el-dialog :title="dialog.title" v-model="dialog.visible" width="1200px" append-to-body @close="onDialogClose">
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="1400px" append-to-body @close="onDialogClose">
       <div class="dialog-container">
         <!-- 左侧文件列表 -->
         <div class="table-container">
@@ -164,7 +164,7 @@
                 <el-tooltip effect="dark" :content="element.name" placement="top">
                   <span style="
                       flex: 1;
-                      max-width: 240px;
+                      max-width: 410px;
                       overflow: hidden;
                       text-overflow: ellipsis;
                       white-space: nowrap;