소스 검색

feat:增加资源播放记录数据展示模块

lihao16 2 달 전
부모
커밋
56e103baee

+ 1 - 0
smsb-modules/smsb-netty/src/main/java/com/inspur/netty/handler/SourcePlayRecordHandler.java

@@ -94,6 +94,7 @@ public class SourcePlayRecordHandler extends ChannelInboundHandlerAdapter {
                 MinioDataVo minioDataVo = getMinioDataFromCache(esSmsbSourcePlayRecord.getSourceId());
                 esSmsbSourcePlayRecord.setSourceName(minioDataVo.getOriginalName());
                 esSmsbSourcePlayRecord.setSourceUrl(minioDataVo.getFileUrl());
+                esSmsbSourcePlayRecord.setDeviceName(smsbDeviceVo.getName());
                 esSmsbSourcePlayRecordMapper.insert(esSmsbSourcePlayRecord);
             }
             sourcePlayRecordMapper.insert(sourcePlayRecord);

+ 12 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/domain/bo/SmsbSourcePlayRecordBo.java

@@ -2,12 +2,15 @@ package com.inspur.source.domain.bo;
 
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.inspur.source.domain.SmsbSourcePlayRecord;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * 资源播放记录业务对象 smsb_source_play_record
@@ -30,6 +33,8 @@ public class SmsbSourcePlayRecordBo {
      */
     private Long deviceId;
 
+    private String deviceName;
+
     /**
      * 节目ID
      */
@@ -63,4 +68,11 @@ public class SmsbSourcePlayRecordBo {
     private String endTime;
 
     private String sourceName;
+
+    /**
+     * 请求参数
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @TableField(exist = false)
+    private Map<String, Object> params = new HashMap<>();
 }

+ 2 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/domain/vo/SmsbSourcePlayRecordVo.java

@@ -69,6 +69,8 @@ public class SmsbSourcePlayRecordVo implements Serializable {
 
     private Integer sourceTag;
 
+    private String sourceUrl;
+
     /**
      * 播放时长
      */

+ 2 - 0
smsb-modules/smsb-source/src/main/java/com/inspur/source/mapper/SmsbSourcePlayRecordMapper.java

@@ -45,4 +45,6 @@ public interface SmsbSourcePlayRecordMapper extends BaseMapperPlus<SmsbSourcePla
     List<SmsbSourcePlayRecordVo> devicePlayList(@Param("bo") SmsbSourcePlayRecordBo bo);
 
     List<SmsbSourcePlayRecordVo> itemPlayList(@Param("bo") SmsbSourcePlayRecordBo bo);
+
+    Page<SmsbSourcePlayRecordVo> selectPageVoList(@Param("page") Page<SmsbSourcePlayRecord> page, @Param("bo") SmsbSourcePlayRecordBo bo);
 }

+ 1 - 2
smsb-modules/smsb-source/src/main/java/com/inspur/source/service/impl/SmsbSourcePlayRecordServiceImpl.java

@@ -63,8 +63,7 @@ public class SmsbSourcePlayRecordServiceImpl implements ISmsbSourcePlayRecordSer
      */
     @Override
     public TableDataInfo<SmsbSourcePlayRecordVo> queryPageList(SmsbSourcePlayRecordBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<SmsbSourcePlayRecord> lqw = buildQueryWrapper(bo);
-        Page<SmsbSourcePlayRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        Page<SmsbSourcePlayRecordVo> result = baseMapper.selectPageVoList(pageQuery.build(), bo);
         return TableDataInfo.build(result);
     }
 

+ 32 - 6
smsb-modules/smsb-source/src/main/resources/mapper/SmsbSourcePlayRecordMapper.xml

@@ -3,13 +3,39 @@
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.inspur.source.mapper.SmsbSourcePlayRecordMapper">
-    <select id="playTopCountTimes" resultType="com.inspur.source.domain.vo.DashBoardPlayVo">
+
+    <select id="selectPageVoList" parameterType="com.inspur.source.domain.bo.SmsbSourcePlayRecordBo"
+            resultType="com.inspur.source.domain.vo.SmsbSourcePlayRecordVo">
         SELECT
-            mi.original_name AS fileName,
-            spr.sourceNum
-        FROM
-            ( SELECT
-                  source_id, COUNT(*) AS sourceNum
+        spr.id,
+        spr.device_id AS deviceId,
+        spr.item_id AS itemId,
+        spr.source_id AS sourceId,
+        spr.source_type AS sourceType,
+        spr.duration,
+        spr.create_time AS createTime,
+        dev.name AS deviceName,
+        mi.original_name AS sourceName,
+        mi.screenshot AS sourceUrl
+        FROM smsb_source_play_record spr
+        LEFT JOIN smsb_device dev ON spr.device_id = dev.id
+        LEFT JOIN smsb_minio_data mi ON spr.source_id = mi.id
+        WHERE 1=1
+        <if test="bo.params.beginTime != '' and bo.params.beginTime != null
+                  and bo.params.endTime != '' and bo.params.endTime != null">
+            and spr.create_time between #{bo.params.beginTime} AND #{bo.params.endTime}
+        </if>
+        <if test="bo.deviceName != null and bo.deviceName != ''">
+            AND dev.name LIKE CONCAT(CONCAT('%', #{bo.deviceName}), '%')
+        </if>
+        order by spr.id desc
+    </select>
+
+    <select id="playTopCountTimes" resultType="com.inspur.source.domain.vo.DashBoardPlayVo">
+        SELECT mi.original_name AS fileName,
+               spr.sourceNum
+        FROM (SELECT source_id,
+                     COUNT(*) AS sourceNum
               FROM smsb_source_play_record
               WHERE
                   source_type = #{fileType} AND create_time between #{startTime} AND #{endTime}

+ 216 - 0
smsb-plus-ui/src/views/smsb/playRecord/index.vue

@@ -0,0 +1,216 @@
+<template>
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter"
+                :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover" :style="{ height: '60px' }">
+          <div class="form-wrapper">
+            <div class="form-container">
+              <el-form ref="queryFormRef" :model="queryParams" :inline="true">
+                <el-form-item label="播放设备" prop="deviceId">
+                  <el-input v-model="queryParams.deviceName" placeholder="请输入设备ID" clearable
+                            @keyup.enter="handleQuery"/>
+                </el-form-item>
+                <el-form-item label="播放时间" prop="createTime">
+                  <el-date-picker
+                    v-model="dateRange"
+                    value-format="YYYY-MM-DD HH:mm:ss"
+                    type="daterange"
+                    range-separator="-"
+                    start-placeholder="开始日期"
+                    end-placeholder="结束日期"
+                    :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
+                  ></el-date-picker>
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+                  <el-button type="warning" plain icon="Download" @click="handleExport"
+                             v-hasPermi="['sourcePlayRecord:sourcePlayRecord:export']">导出
+                  </el-button>
+                </el-form-item>
+              </el-form>
+            </div>
+          </div>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never">
+      <div class="table-content">
+        <el-table v-loading="loading" :data="sourcePlayRecordList" @selection-change="handleSelectionChange">
+          <el-table-column label="" align="left" prop="" width="10"/>
+          <el-table-column label="ID" align="left" prop="id" v-if="true" width="220"/>
+          <el-table-column label="播放设备" align="left" prop="deviceName" :show-overflow-tooltip="true"/>
+          <el-table-column label="资源名称" align="left" prop="sourceName" :show-overflow-tooltip="true"/>
+          <el-table-column label="资源类型" align="center" prop="sourceType" width="90">
+            <template #default="scope">
+              <dict-tag :options="smsb_source_type" :value="scope.row.sourceType"/>
+            </template>
+          </el-table-column>
+          <el-table-column label="资源预览" align="center" prop="sourceUrl" width="90">
+            <template #default="scope">
+              <div v-if="scope.row.sourceType === 1">
+                <!-- 图片类型 -->
+                <image-preview :src="scope.row.sourceUrl" style="width: 40px; height: 40px; cursor: pointer"/>
+              </div>
+              <div v-else-if="scope.row.sourceType === 2">
+                <!-- 视频类型 -->
+                <el-icon class="VideoPlay" @click="viewVideo(scope.row.sourceUrl)" size="40" style="cursor: pointer">
+                  <VideoPlay/>
+                </el-icon>
+              </div>
+              <div v-else-if="scope.row.sourceType === 4">
+                <!-- PPT类型 -->
+                <el-icon :size="40" @click="downloadFile(scope.row.sourceUrl)" style="cursor: pointer;">
+                  <Document/>
+                </el-icon>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="播放时长" align="center" prop="duration" width="80"/>
+          <el-table-column label="创建时间" align="left" prop="createTime" width="170"/>
+          <el-table-column label="操作" width="120" align="center" class-name="small-padding fixed-width">
+            <template #default="scope">
+              <el-tooltip content="删除" placement="top">
+                <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
+                           v-hasPermi="['sourcePlayRecord:sourcePlayRecord:remove']">删除
+                </el-button>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+                  v-model:limit="queryParams.pageSize" @pagination="getList"/>
+    </el-card>
+
+    <!-- 用于展示播放的视频 -->
+    <el-dialog v-model="videoDialogVisible" v-if="videoDialogVisible" title="视频预览">
+      <VideoPlayer :url="videoUrl" />
+    </el-dialog>
+
+  </div>
+</template>
+
+<script setup name="SourcePlayRecord" lang="ts">
+import {delSourcePlayRecord, listSourcePlayRecord} from '@/api/smsb/source/play_record';
+import {SourcePlayRecordForm, SourcePlayRecordQuery, SourcePlayRecordVO} from '@/api/smsb/source/play_record_type';
+
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {smsb_source_type} = toRefs<any>(proxy?.useDict('smsb_source_type'));
+const sourcePlayRecordList = ref<SourcePlayRecordVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
+const queryFormRef = ref<ElFormInstance>();
+const sourcePlayRecordFormRef = ref<ElFormInstance>();
+const videoUrl = ref('');
+const videoDialogVisible = ref(false);
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
+});
+
+const data = reactive<PageData<SourcePlayRecordForm, SourcePlayRecordQuery>>({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 20,
+    deviceId: undefined,
+    sourceType: undefined,
+    createTime: undefined,
+    params: {}
+  },
+  rules: {}
+});
+
+const {queryParams, form, rules} = toRefs(data);
+
+/** 查询资源播放记录列表 */
+const getList = async () => {
+  loading.value = true;
+  const res = await listSourcePlayRecord(proxy?.addDateRange(queryParams.value, dateRange.value));
+  sourcePlayRecordList.value = res.rows;
+  total.value = res.total;
+  loading.value = false;
+}
+/** 取消按钮 */
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+  videoDialogVisible.value = false;
+}
+
+/** 表单重置 */
+const reset = () => {
+  form.value = {...initFormData};
+  sourcePlayRecordFormRef.value?.resetFields();
+}
+const downloadFile = (fileUrl) => {
+  if (fileUrl) {
+    // 创建一个隐藏的a标签来触发下载
+    const link = document.createElement('a');
+    link.href = fileUrl;
+    link.download = ''; // 浏览器会自动使用URL中的文件名
+    link.target = '_blank';
+    link.style.display = 'none';
+
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+  } else {
+    proxy?.$modal.msgError('文件地址不存在,无法下载');
+  }
+};
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+// 播放视频
+const viewVideo = (url: string) => {
+  videoUrl.value = url;
+  console.log(videoUrl.value);
+  videoDialogVisible.value = true;
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  handleQuery();
+}
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: SourcePlayRecordVO[]) => {
+  ids.value = selection.map(item => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: SourcePlayRecordVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除资源播放记录编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
+  await delSourcePlayRecord(_ids);
+  proxy?.$modal.msgSuccess("删除成功");
+  await getList();
+}
+
+/** 导出按钮操作 */
+const handleExport = () => {
+  proxy?.download('sourcePlayRecord/sourcePlayRecord/export', {
+    ...queryParams.value
+  }, `sourcePlayRecord_${new Date().getTime()}.xlsx`)
+}
+
+onMounted(() => {
+  getList();
+});
+</script>