Преглед изворни кода

feat: handle remove device push

lihao16 пре 6 месеци
родитељ
комит
7187bd1318

+ 5 - 0
smsb-modules/smsb-netty/src/main/java/com/inspur/netty/message/push/PushMessageType.java

@@ -21,6 +21,11 @@ public enum PushMessageType {
      */
     CONTENT_UPDATE("/content/update"),
 
+    /**
+     * 内容发布下架
+     */
+    CONTENT_REMOVE("/content/remove"),
+
     /**
      * 下发状态更新 replay
      */

+ 11 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/controller/SmsbItemPushDeviceController.java

@@ -104,4 +104,15 @@ public class SmsbItemPushDeviceController extends BaseController {
                           @PathVariable Long[] ids) {
         return toAjax(smsbItemPushDeviceService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /**
+     * 内容发布设备下架
+     *
+     * @param bo
+     */
+    @Log(title = "内容发布下架", businessType = BusinessType.DELETE)
+    @DeleteMapping("/remove")
+    public R<Void> pushRemoveDevice(@RequestBody SmsbItemPushDeviceBo bo) {
+        return smsbItemPushDeviceService.pushRemoveDevice(bo);
+    }
 }

+ 4 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/domain/bo/SmsbItemPushDeviceBo.java

@@ -6,6 +6,8 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 
+import java.util.List;
+
 /**
  * 内容发布设备业务对象 smsb_item_push_device
  *
@@ -42,5 +44,7 @@ public class SmsbItemPushDeviceBo extends BaseEntity {
      */
     private Long pushState;
 
+    private List<Long> deviceIds;
+
 
 }

+ 8 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/service/ISmsbItemPushDeviceService.java

@@ -2,6 +2,7 @@ package com.inspur.source.service;
 
 import com.inspur.source.domain.bo.SmsbItemPushDeviceBo;
 import com.inspur.source.domain.vo.SmsbItemPushDeviceVo;
+import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 
@@ -68,4 +69,11 @@ public interface ISmsbItemPushDeviceService {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 内容发布下架
+     * @param bo
+     * @return
+     */
+    public R<Void> pushRemoveDevice(SmsbItemPushDeviceBo bo);
 }

+ 44 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/service/impl/SmsbItemPushDeviceServiceImpl.java

@@ -1,17 +1,28 @@
 package com.inspur.source.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.inspur.device.domain.constants.ResultCodeEnum;
+import com.inspur.device.domain.vo.SmsbDeviceVo;
+import com.inspur.device.service.ISmsbDeviceService;
+import com.inspur.netty.message.push.PushMessageType;
+import com.inspur.netty.util.PushMsgUtil;
 import com.inspur.source.domain.SmsbItemPushDevice;
 import com.inspur.source.domain.bo.SmsbItemPushDeviceBo;
 import com.inspur.source.domain.vo.SmsbItemPushDeviceVo;
 import com.inspur.source.mapper.SmsbItemPushDeviceMapper;
 import com.inspur.source.service.ISmsbItemPushDeviceService;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.DateUtils;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Collection;
@@ -26,10 +37,14 @@ import java.util.Map;
  */
 @RequiredArgsConstructor
 @Service
+@Slf4j
 public class SmsbItemPushDeviceServiceImpl implements ISmsbItemPushDeviceService {
 
     private final SmsbItemPushDeviceMapper baseMapper;
 
+    @Autowired
+    private ISmsbDeviceService smsbDeviceService;
+
     /**
      * 查询内容发布设备
      *
@@ -136,4 +151,33 @@ public class SmsbItemPushDeviceServiceImpl implements ISmsbItemPushDeviceService
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    @Override
+    public R<Void> pushRemoveDevice(SmsbItemPushDeviceBo bo) {
+        if (CollectionUtil.isEmpty(bo.getDeviceIds())) {
+            return R.fail(Integer.parseInt(ResultCodeEnum.DEVICE_IDS_IS_NULL.getValue()), ResultCodeEnum.DEVICE_IDS_IS_NULL.getMessage());
+        }
+        Integer pushState = 4;
+        for (Long deviceId : bo.getDeviceIds()) {
+            baseMapper.update(new LambdaUpdateWrapper<SmsbItemPushDevice>()
+                .set(SmsbItemPushDevice::getPushState, pushState)
+                .set(SmsbItemPushDevice::getUpdateTime, DateUtils.getNowDate())
+                .eq(SmsbItemPushDevice::getDeviceId, deviceId)
+                .eq(SmsbItemPushDevice::getPushId, bo.getPushId()));
+            // 发送长连接消息给设备
+            pushRemoveMessage(deviceId, bo.getPushId());
+        }
+        return R.ok();
+    }
+
+    private void pushRemoveMessage(Long deviceId, Long pushId) {
+        SmsbDeviceVo deviceVo = smsbDeviceService.getDeviceCacheById(deviceId);
+        if (null == deviceVo) {
+            return;
+        }
+        String identifier = deviceVo.getIdentifier();
+        String nettyMessage = PushMessageType.CONTENT_REMOVE.getValue() + "/" + pushId;
+        boolean pushResult = PushMsgUtil.sendV2(identifier, nettyMessage);
+        log.info("push content remove identifier: {}, result:{}", identifier, pushResult);
+    }
 }

+ 8 - 0
smsb-plus-ui/src/api/smsb/source/item_push_device.ts

@@ -24,6 +24,14 @@ export const listItemPushDeviceV2 = (query?: ItemPushDeviceQuery): AxiosPromise<
   });
 };
 
+export const removeItemPushDevice = (param: ItemPushDeviceVO) => {
+  return request({
+    url: '/source/itemPushDevice/remove',
+    method: 'delete',
+    data: param
+  });
+};
+
 /**
  * 查询内容发布设备详细
  * @param id

+ 4 - 0
smsb-plus-ui/src/api/smsb/source/item_push_device_type.ts

@@ -33,6 +33,10 @@ export interface ItemPushDeviceVO {
    * 更新时间
    */
   updateTime: string;
+
+  pushId: number | string;
+
+  deviceIds: Array<number | string>;
 }
 
 export interface ItemPushDeviceForm extends BaseEntity {

+ 25 - 11
smsb-plus-ui/src/views/smsb/device/index.vue

@@ -199,18 +199,32 @@
       <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClickTab">
         <el-tab-pane label="状态检测" name="info">
           <div>
-            <el-row :gutter="20" style="height: 100%; display: flex">
-              <el-col :span="8">
-                <div class="grid-content">
-                  <div>CPU : {{ deviceRunInfo.cpuInfo }}</div>
-                  <div>内存 : {{ deviceRunInfo.memoryInfo }}</div>
-                  <div>硬盘 : {{ deviceRunInfo.diskInfo }}</div>
-                  <div>ROM : {{ deviceRunInfo.rom }}</div>
-                  <div>系统信息 : {{ deviceRunInfo.osInfo }}</div>
-                  <div>APK版本 : {{ deviceRunInfo.apkVersion }}</div>
+            <div style="display: flex; justify-content: space-around; align-items: center">
+              <div style="text-align: center">
+                <div style="position: relative">
+                  CPU :
+                  <el-progress type="circle" :percentage="deviceRunInfo.cpuInfo"></el-progress>
+                  <div style="position: absolute; top: -30px; left: 50%; transform: translateX(-50%)">{{ deviceRunInfo.cpuInfo }}%</div>
                 </div>
-              </el-col>
-            </el-row>
+              </div>
+              <div style="text-align: center">
+                <div style="position: relative">
+                  内存 :
+                  <el-progress type="circle" :percentage="deviceRunInfo.memoryInfo"></el-progress>
+                  <div style="position: absolute; top: -30px; left: 50%; transform: translateX(-50%)">{{ deviceRunInfo.memoryInfo }}%</div>
+                </div>
+              </div>
+              <div style="text-align: center">
+                <div style="position: relative">
+                  硬盘 :
+                  <el-progress type="circle" :percentage="deviceRunInfo.diskInfo"></el-progress>
+                  <div style="position: absolute; top: -30px; left: 50%; transform: translateX(-50%)">{{ deviceRunInfo.diskInfo }}%</div>
+                </div>
+              </div>
+            </div>
+            <div>ROM : {{ deviceRunInfo.rom }}</div>
+            <div>系统信息 : {{ deviceRunInfo.osInfo }}</div>
+            <div>APK版本 : {{ deviceRunInfo.apkVersion }}</div>
           </div>
         </el-tab-pane>
         <el-tab-pane label="远程操作" name="control">

+ 109 - 55
smsb-plus-ui/src/views/smsb/itemPush/index.vue

@@ -106,12 +106,22 @@
             <el-tooltip content="删除" placement="top">
               <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['source:itemPush:remove']"></el-button>
             </el-tooltip>
-<!--            <el-tooltip content="提交审核" placement="top">
-              <el-button link type="primary" icon="Top" @click="handleReview(scope.row)" v-hasPermi="['source:minioData:add']"></el-button>
-            </el-tooltip>-->
+            <!--            <el-tooltip content="提交审核" placement="top">
+                          <el-button link type="primary" icon="Top" @click="handleReview(scope.row)" v-hasPermi="['source:minioData:add']"></el-button>
+                        </el-tooltip>-->
             <el-tooltip content="下发详情" placement="top">
               <el-button link type="primary" icon="List" @click="handleDevice(scope.row)" v-hasPermi="['source:itemPush:edit']"></el-button>
             </el-tooltip>
+            <el-tooltip content="下架" placement="top">
+              <el-button
+                link
+                type="primary"
+                icon="Bottom"
+                v-if="scope.row.status == 'finish'"
+                @click="handleRemoveItem(scope.row)"
+                v-hasPermi="['source:itemPush:edit']"
+              ></el-button>
+            </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
@@ -199,9 +209,9 @@
               </el-table-column>
               <el-table-column label="名称" align="left" prop="itemName" :show-overflow-tooltip="true" />
               <el-table-column label="资源数量" align="center" prop="sourceNum" width="80" />
-  <!--
-                <el-table-column label="创建人" align="left" prop="createUser" width="100" :show-overflow-tooltip="true" />
-  -->
+              <!--
+                            <el-table-column label="创建人" align="left" prop="createUser" width="100" :show-overflow-tooltip="true" />
+              -->
             </el-table>
           </div>
         </el-col>
@@ -216,51 +226,50 @@
 
     <!-- 下发详情弹窗 -->
     <el-dialog :title="deviceDialog.title" v-model="deviceDialog.visible" width="900px" append-to-body>
-      <el-row :gutter="20" style="height: 100%; display: flex">
-        <!--发布名称-->
-        <el-col :span="10" style="height: 100%; overflow: auto; padding-left: 10px">
-          <el-form ref="itemPushFormRef" :model="form" :rules="rules" label-width="60px">
-            <el-form-item label="名称" prop="name">
-              <el-input v-model="form.name" placeholder="请输入名称" :disabled="true" />
-            </el-form-item>
-            <el-row>
-              <el-col :span="12">
-                <el-form-item label="类型" prop="itemType">
-                  <el-select v-model="form.itemType" placeholder="请选择类型" @change="getItemList" :disabled="true">
-                    <el-option v-for="dict in smsb_push_type" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
-                  </el-select>
-                </el-form-item>
-              </el-col>
-              <el-col :span="12">
-                <el-form-item label="优先级" prop="level">
-                  <el-select v-model="form.level" placeholder="请选择优先级" :disabled="true">
-                    <el-option v-for="dict in smsb_push_level" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
-                  </el-select>
-                </el-form-item>
-              </el-col>
-            </el-row>
-          </el-form>
-        </el-col>
-        <!--设备列表-->
-        <el-col :span="14" style="height: 100%; overflow: auto; border-right: 1px solid #eee; padding-right: 10px">
-          <el-table v-loading="loading" :data="pushDeviceList">
-            <el-table-column label="设备名称" align="left" prop="deviceName" :show-overflow-tooltip="true" />
-            <el-table-column label="发布排序" align="center" prop="sortNum" width="100" :show-overflow-tooltip="true" />
-            <el-table-column label="发布状态" align="center" prop="pushState" width="120" :show-overflow-tooltip="true">
-              <template #default="scope">
-                <dict-tag :options="smsb_push_device_state" :value="scope.row.pushState" />
-              </template>
-            </el-table-column>
-          </el-table>
-          <pagination
-            v-show="deviceTotal > 0"
-            :total="deviceTotal"
-            v-model:page="dialogQueryParams.pageNum"
-            v-model:limit="dialogQueryParams.pageSize"
-            @pagination="getList"
-          />
-        </el-col>
-      </el-row>
+      <!--发布名称-->
+      <div>
+        <el-form ref="itemPushFormRef" :model="form" :rules="rules" label-width="70px">
+          <el-form-item label="发布名称" prop="name">
+            <el-input v-model="form.name" style="width: 500px" placeholder="请输入名称" :disabled="true" />
+          </el-form-item>
+          <el-row>
+            <el-col :span="12">
+              <el-form-item label="发布类型" prop="itemType">
+                <el-select v-model="form.itemType" placeholder="请选择类型" @change="getItemList" :disabled="true">
+                  <el-option v-for="dict in smsb_push_type" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="优先级" prop="level">
+                <el-select v-model="form.level" placeholder="请选择优先级" :disabled="true">
+                  <el-option v-for="dict in smsb_push_level" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </div>
+      <!--设备列表-->
+      <el-button type="primary" v-if="removeItemTag" icon="Bottom" :disabled="removeButtonTag" @click="handleDoRemoveItem()"> 下架 </el-button>
+      <el-table v-loading="deviceLoading" :data="pushDeviceList" style="height: 500px; margin-top: 10px" @selection-change="handleDeviceSelectionChange">
+        <el-table-column type="selection" v-if="removeItemTag" width="55" align="center" />
+        <el-table-column label="设备名称" align="left" prop="deviceName" :show-overflow-tooltip="true" />
+        <el-table-column label="发布排序" align="center" prop="sortNum" width="100" :show-overflow-tooltip="true" />
+        <el-table-column label="发布状态" align="center" prop="pushState" width="120" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <dict-tag :options="smsb_push_device_state" :value="scope.row.pushState" />
+          </template>
+        </el-table-column>
+        <el-table-column label="发布时间" align="left" prop="createTime" width="170" :show-overflow-tooltip="true" />
+        <el-table-column label="操作" v-if="removeItemTag" align="center" class-name="small-padding fixed-width" width="150">
+          <template #default="scope">
+            <el-tooltip content="下架" placement="top">
+              <el-button link type="primary" icon="Bottom" @click="handleDoRemoveItem(scope.row)" v-hasPermi="['source:itemPush:edit']"></el-button>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
       <template #footer>
         <div class="dialog-footer">
           <el-button @click="cancel">取 消</el-button>
@@ -278,7 +287,7 @@ import { listDevice } from '@/api/smsb/device/device';
 import { ItemQuery, ItemVO } from '@/api/smsb/source/item_type';
 import { listItem } from '@/api/smsb/source/item';
 import { ItemPushDeviceVO } from '@/api/smsb/source/item_push_device_type';
-import { listItemPushDeviceV2 } from '@/api/smsb/source/item_push_device';
+import { listItemPushDeviceV2, removeItemPushDevice } from '@/api/smsb/source/item_push_device';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { smsb_push_state, smsb_push_device_state, smsb_push_type, smsb_push_level } = toRefs<any>(
@@ -289,8 +298,11 @@ const itemPushList = ref<ItemPushVO[]>([]);
 const itemList = ref<ItemVO[]>([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
+const deviceLoading = ref(true);
 const showSearch = ref(true);
 const ids = ref<Array<string | number>>([]);
+const removePushId = ref<number | string>();
+const removeIds = ref<Array<string | number>>([]);
 const deviceIds = ref<Array<string | number>>([]);
 const itemIds = ref<Array<string | number>>([]);
 const single = ref(true);
@@ -307,7 +319,8 @@ const deviceList = ref<DeviceVO[]>([]);
 const pushDeviceList = ref<ItemPushDeviceVO[]>([]);
 // 存储选中行的唯一标识
 const selectedRowId = ref<number | null>(null);
-
+const removeItemTag = ref(false);
+const removeButtonTag = ref(true);
 const queryFormRef = ref<ElFormInstance>();
 const itemPushFormRef = ref<ElFormInstance>();
 
@@ -434,21 +447,57 @@ const handleQuery = () => {
 };
 
 const handleDevice = async (row?: ItemPushVO) => {
+  removeItemTag.value = false;
   const pushId = row.id;
   deviceDialog.title = '发布详情';
   deviceDialog.visible = true;
   dialogQueryParams.value.pushId = pushId;
+  dialogQueryParams.value.pageSize = 1000;
+  pushDeviceList.value = [];
+  const pushInfo = await getItemPush(pushId);
+  Object.assign(form.value, pushInfo.data);
+  await getItemDeviceList(pushId);
+};
+const handleRemoveItem = async (row?: ItemPushVO) => {
+  removeItemTag.value = true;
+  removeButtonTag.value = true;
+  removeIds.value = [];
+  const pushId = row.id;
+  deviceDialog.title = '内容下架';
+  deviceDialog.visible = true;
+  dialogQueryParams.value.pushId = pushId;
+  removePushId.value = pushId;
+  dialogQueryParams.value.pageSize = 1000;
+  pushDeviceList.value = [];
   const pushInfo = await getItemPush(pushId);
   Object.assign(form.value, pushInfo.data);
-  getItemDeviceList(pushId);
+  await getItemDeviceList(pushId);
+};
+const handleDoRemoveItem = async (row?: ItemPushDeviceVO) => {
+  const deviceIds = Array<number | string>();
+  if (null != row) {
+    deviceIds.push(row.deviceId);
+  }
+  if (removeIds.value.length > 0) {
+    removeIds.value.forEach((deviceId) => {
+      deviceIds.push(deviceId);
+    });
+  }
+  const removeParam = {
+    pushId: removePushId.value,
+    deviceIds: deviceIds
+  };
+  await removeItemPushDevice(removeParam);
+  await getItemDeviceList(removePushId.value);
 };
 
 const getItemDeviceList = async (pushId: number | string) => {
+  deviceLoading.value = true;
   dialogQueryParams.value.pushId = pushId;
   const res = await listItemPushDeviceV2(dialogQueryParams.value);
   pushDeviceList.value = res.rows;
   deviceTotal.value = res.total;
-  loading.value = false;
+  deviceLoading.value = false;
 };
 
 /** 重置按钮操作 */
@@ -465,6 +514,11 @@ const handleSelectionChange = (selection: ItemPushVO[]) => {
   multiple.value = !selection.length;
 };
 
+const handleDeviceSelectionChange = (selection: ItemPushDeviceVO[]) => {
+  removeIds.value = selection.map((item) => item.deviceId);
+  removeButtonTag.value = removeIds.value.length == 0;
+};
+
 /** 多选框选中数据 */
 const handleSelectDevice = (selection: DeviceVO[]) => {
   deviceIds.value = selection.map((item) => item.id);

Разлика између датотеке није приказан због своје велике величине
+ 0 - 225
smsb-plus-ui/vite.config.ts.timestamp-1737700502429-c6453b1b35b5e.mjs


Разлика између датотеке није приказан због своје велике величине
+ 0 - 225
smsb-plus-ui/vite.config.ts.timestamp-1738734766950-3118c61dd84be.mjs


Разлика између датотеке није приказан због своје велике величине
+ 0 - 225
smsb-plus-ui/vite.config.ts.timestamp-1740461761631-438ca296213cc.mjs


Неке датотеке нису приказане због велике количине промена