Browse Source

实现视频标签,修复bug

Hwf 8 months ago
parent
commit
5dbbb65f67

+ 69 - 0
src/api/knowledge/index.ts

@@ -0,0 +1,69 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import {QueryParams, ReportItem, FetchReportsResponse, AddReportParams} from './types';
+import {UnwrapNestedRefs, UnwrapRef} from "vue";
+
+// 获取报告列表
+export const fetchReports = (params: QueryParams): AxiosPromise<FetchReportsResponse> => {
+  return request({
+    url: '/api/knowledge/select',
+    method: 'get',
+    params: {
+      pageNum: params.pageNum,  // 分页参数中的页码
+      pageSize: params.pageSize,  // 分页参数中的每页大小
+      eventType: params.eventType,  // 事件类型(可选)
+      publishDate: params.publishDate,  // 发布日期范围(可选)
+      subject: params.subject,  // 关键字(可选)
+      sortBy: params.sortBy, // 排序字段
+      sortOrder: params.sortOrder, // 排序方式
+      query: params.query,
+      publishDateRange: params.publishDateRange,
+    }
+  });
+};
+
+// 新增报告
+export const addReport = (data: UnwrapNestedRefs<AddReportParams>): AxiosPromise<void> => {
+  return request({
+    url: '/api/knowledge/create',
+    method: 'post',
+    data: data,
+  });
+};
+
+// 获取报告详情
+export const fetchReportDetail = (reportId: string): AxiosPromise<ReportItem> => {
+  return request({
+    url: `/api/knowledge/detail?reportID=${reportId}`,
+    method: 'get',
+  });
+};
+
+// 修改报告
+export const updateReport = (data: {
+  summary: UnwrapRef<AddReportParams["summary"]>;
+  publishingUnit: UnwrapRef<AddReportParams["publishingUnit"]>;
+  reportName: UnwrapRef<AddReportParams["reportName"]>;
+  reportId: string;
+  subject: UnwrapRef<AddReportParams["subject"]>;
+  publishDate: UnwrapRef<AddReportParams["publishDate"]>;
+  eventType: UnwrapRef<AddReportParams["eventType"]>;
+  fileNames: UnwrapRef<AddReportParams["fileNames"]>
+}): AxiosPromise<void> => {
+  return request({
+    url: `/api/knowledge/update`,
+    method: 'post',
+    data: data,
+  });
+};
+
+// 删除报告
+export const deleteReport = (reportId: string): AxiosPromise<void> => {
+  return request({
+    url: `/api/knowledge/delete`,
+    method: 'post',
+    data: {
+      reportID:reportId
+    }
+  });
+};

+ 64 - 0
src/api/knowledge/types.ts

@@ -0,0 +1,64 @@
+// 定义获取报告列表接口的请求参数类型
+import {UnwrapRef} from "vue";
+
+// 定义查询参数的类型
+export interface QueryParams {
+  pageNum: number;
+  pageSize: number;
+  eventType?: string;
+  publishDate?: [string, string];
+  subject?: string;
+  sortBy: string;
+  sortOrder: string;
+  query: string;
+  publishDateRange?: string;
+}
+
+// 定义报告项的类型
+export interface ReportItem {
+  reportName: string;
+  reportId?: string;
+  publishDate: string;
+  summary: string;
+  updateTime: string | null;
+  subject: string;
+  eventType: string;
+  publishingUnit: string;
+  notificationType: string;
+  base_code: string;
+}
+
+// 定义新增报告接口的请求参数类型
+export interface AddReportParams {
+  reportName: string;
+  summary: string;
+  publishDate: string;
+  subject: string;
+  eventType: string;
+  publishingUnit: string;
+  fileNames: [];
+}
+
+// 定义获取报告列表接口响应的数据结构,total
+export interface FetchReportsResponse {
+  code: number;
+  msg: string;
+  pages: number;
+  total: number;
+  currentPage: number;
+  pageSize: number;
+  data: ReportItem[];
+
+  map(param: (item: ReportItem) => {
+    summary: string;
+    publishingUnit: string;
+    reportName: string;
+    reportId?: string;
+    subject: string;
+    publishDate: string;
+    base_code: string;
+    updateTime: string | null;
+    eventType: string;
+    notificationType: string
+  }): UnwrapRef<ReportItem[]>;
+}

+ 23 - 0
src/api/videoMonitor/index.ts

@@ -64,3 +64,26 @@ export function addVideoTag(data) {
     data: data
   });
 }
+// 视频点位标签信息-添加
+export function addVideoTagLabel(data) {
+  return request({
+    url: '/api/videoResource/videoinfo/add_video_tag_label',
+    method: 'post',
+    data: data
+  });
+}
+// 视频 最近标签
+export function getRecentlyVideoTagInfo() {
+  return request({
+    url: '/api/videoResource/videoinfo/get_recently_video_tag_info',
+    method: 'get'
+  });
+}
+// 视频点位标签信息-类型、行业下钻接口
+export function getLxHyVideoTagInfo(params) {
+  return request({
+    url: '/api/videoResource/videoinfo/get_lx_hy_video_tag_info',
+    method: 'get',
+    params: params
+  });
+}

+ 13 - 2
src/components/Dialog/index.vue

@@ -21,7 +21,7 @@
         <div :class="confirmClass ? confirmClass + ' common-btn-primary' : 'common-btn-primary'" @click="confirm">{{ confirmText }}</div>
       </div>
     </template>
-    <VideoTagEdit v-model="showAddTag" :id="getTagId" />
+    <VideoTagEdit v-model="showAddTag" :tags="tags" :id="getTagId" @updateVideoTag="getData" />
     <i class="triangle1" />
     <i class="triangle2" />
     <i class="triangle3" />
@@ -30,6 +30,8 @@
 </template>
 
 <script lang="ts" setup name="Dialog">
+import { getVideoTagInfo } from '@/api/videoMonitor';
+
 interface Tag {
   name: string;
 }
@@ -49,7 +51,6 @@ interface Props {
   customShow?: boolean;
   headerType?: string;
   getTagId?: string;
-  tags?: Tag[];
 }
 const props = withDefaults(defineProps<Props>(), {
   modelValue: false,
@@ -89,6 +90,7 @@ const computedHeight = computed(() => {
     return '1560px';
   }
 });
+let tags = ref([]);
 // 关闭弹窗
 const closeDialog = () => {
   emit('close');
@@ -108,6 +110,15 @@ let showAddTag = ref(false);
 const handleShowAddTag = () => {
   showAddTag.value = true;
 };
+
+const getData = () => {
+  getVideoTagInfo({ video_code: props.getTagId }).then((res) => {
+    tags.value = res.data;
+  });
+};
+onMounted(() => {
+  getData();
+});
 </script>
 
 <style lang="scss" scoped>

+ 40 - 32
src/components/VideoTagEdit/index.vue

@@ -9,7 +9,7 @@
         <div class="title">当前标签</div>
       </div>
       <div class="tags">
-        <div v-for="(item, index) in currentTags" :key="index" class="tag">{{ item.dict_label }}</div>
+        <div v-for="(item, index) in tags" :key="index" class="tag">{{ item.dict_label }}</div>
       </div>
       <div class="title-box">
         <div class="title">新建标签</div>
@@ -22,7 +22,7 @@
         <div class="title">最近标签</div>
       </div>
       <div class="tags">
-        <div v-for="(item, index) in recentTags" :key="index" class="tag">{{ item.name }}</div>
+        <div v-for="(item, index) in recentTags" :key="index" class="tag" @click="handleAdd2(item)">{{ item.dict_label }}</div>
       </div>
       <div class="title-box3">
         <i class="icon-type" />
@@ -33,12 +33,14 @@
           class="custom-select"
           popper-class="custom-select-popper"
           style="width: 340px; margin-bottom: 20px"
+          @change="getTypeList"
         >
-          <el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
+          <el-option label="全部" value="lx" />
+          <el-option v-for="item in video_tag_type" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
       </div>
       <div class="tags">
-        <div v-for="(item, index) in typeTags" :key="index" class="tag">{{ item.name }}</div>
+        <div v-for="(item, index) in typeTags" :key="index" class="tag" @click="handleAdd2(item)">{{ item.dict_label }}</div>
       </div>
       <div class="title-box3">
         <i class="icon-industry" />
@@ -49,58 +51,57 @@
           class="custom-select"
           popper-class="custom-select-popper"
           style="width: 340px; margin-bottom: 20px"
+          @change="getIndustryList"
         >
-          <el-option v-for="item in industryOptions" :key="item.value" :label="item.label" :value="item.value" />
+          <el-option label="全部" value="hy" />
+          <el-option v-for="item in video_tag_industry" :key="item.value" :label="item.label" :value="item.value" />
         </el-select>
       </div>
       <div class="tags">
-        <div v-for="(item, index) in industryTags" :key="index" class="tag">{{ item.name }}</div>
+        <div v-for="(item, index) in industryTags" :key="index" class="tag" @click="handleAdd2(item)">{{ item.dict_label }}</div>
       </div>
     </div>
   </div>
 </template>
 
 <script lang="ts" setup name="VideoTagEdit">
-import { addVideoTag, getVideoTagInfo } from '@/api/videoMonitor';
+import { addVideoTag, addVideoTagLabel, getLxHyVideoTagInfo, getRecentlyVideoTagInfo } from '@/api/videoMonitor';
 
 const props = defineProps({
   modelValue: Boolean,
+  tags: [],
   id: String
 });
-const emits = defineEmits(['update:modelValue']);
-let currentTags = ref([]);
+const emits = defineEmits(['update:modelValue', 'updateVideoTag']);
+const proxy = getCurrentInstance()?.proxy;
+const { video_tag_type, video_tag_industry } = toRefs<any>(proxy?.useDict('video_tag_type', 'video_tag_industry'));
 let addTag = ref('');
 let recentTags = ref([]);
-let type = ref('');
+let type = ref('lx');
 let typeTags = ref([]);
-let typeOptions = ref([]);
-let industry = ref('');
+let industry = ref('hy');
 let industryTags = ref([]);
-let industryOptions = ref([]);
 
-const getData = () => {
-  getVideoTagInfo({ video_code: props.id }).then((res) => {
-    currentTags.value = res.data;
+const getTypeList = () => {
+  getLxHyVideoTagInfo({ dict_value: type.value }).then((res) => {
+    typeTags.value = res.data;
+  });
+};
+const getIndustryList = () => {
+  getLxHyVideoTagInfo({ dict_value: industry.value }).then((res) => {
+    industryTags.value = res.data;
   });
 };
 watch(
   () => props.id,
   () => {
     if (!!props.id) {
-      getData();
-      recentTags.value = [{ name: '河坝' }, { name: '水库' }, { name: '山塘' }];
-      typeTags.value = [{ name: '河坝' }, { name: '水库' }, { name: '山塘' }];
-      industryTags.value = [{ name: '河坝' }, { name: '水库' }, { name: '山塘' }];
-      typeOptions.value = [
-        { label: '全部', value: '' },
-        { label: '水库', value: '1' }
-      ];
-      industryOptions.value = [
-        { label: '全部', value: '' },
-        { label: '水库', value: '1' }
-      ];
+      getRecentlyVideoTagInfo().then((res) => {
+        recentTags.value = res.data;
+      });
+      getTypeList();
+      getIndustryList();
     } else {
-      currentTags.value = [];
       addTag.value = '';
       recentTags.value = [];
       typeTags.value = [];
@@ -111,20 +112,26 @@ watch(
     immediate: true
   }
 );
+
 //关闭
 const handleClose = () => {
   emits('update:modelValue', false);
 };
 const handleAdd = () => {
-  addVideoTag({
+  addVideoTagLabel({
     video_code: props.id,
-    dict_value: addTag.value,
+    dict_label: addTag.value,
     dict_type: 'video_type'
   }).then(() => {
-    getData();
+    emits('updateVideoTag');
   });
   addTag.value = '';
 };
+const handleAdd2 = (item) => {
+  addVideoTag({ video_code: props.id, dict_value: item.dict_value, dict_type: 'video_type' }).then(() => {
+    emits('updateVideoTag');
+  });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -247,6 +254,7 @@ const handleAdd = () => {
         justify-content: center;
         margin-top: 20px;
         padding: 0 20px 0 15px;
+        cursor: pointer;
       }
       .custom-input {
         width: 667px;

+ 5 - 0
src/store/modules/app.ts

@@ -12,6 +12,7 @@ export const useAppStore = defineStore('app', () => {
   });
   const device = ref<string>('desktop');
   const size = useStorage<'large' | 'default' | 'small'>('size', 'default');
+  const zIndex = ref(9999);
 
   // 语言
   const language = useStorage('language', 'zh_CN');
@@ -62,6 +63,10 @@ export const useAppStore = defineStore('app', () => {
   const toggleRightSection = (): void => {
     showRightSection.value = !showRightSection.value;
   };
+  const getZIndex = (): number => {
+    zIndex.value = zIndex.value + 1;
+    return zIndex.value;
+  };
   return {
     device,
     sidebar,

+ 19 - 0
src/types/components.d.ts

@@ -21,6 +21,7 @@ declare module 'vue' {
     ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCard: typeof import('element-plus/es')['ElCard']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
@@ -37,20 +38,34 @@ declare module 'vue' {
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElLink: typeof import('element-plus/es')['ElLink']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElPopover: typeof import('element-plus/es')['ElPopover']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
+    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
+    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
+    ElStep: typeof import('element-plus/es')['ElStep']
+    ElSteps: typeof import('element-plus/es')['ElSteps']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTabPane: typeof import('element-plus/es')['ElTabPane']
+    ElTabs: typeof import('element-plus/es')['ElTabs']
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
+    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
     FooterSection: typeof import('./../components/FooterSection/index.vue')['default']
@@ -61,6 +76,7 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
+    IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default']
     IFrame: typeof import('./../components/iFrame/index.vue')['default']
     ImagePreview: typeof import('./../components/ImagePreview/index.vue')['default']
     ImageUpload: typeof import('./../components/ImageUpload/index.vue')['default']
@@ -97,4 +113,7 @@ declare module 'vue' {
     YMapold: typeof import('./../components/Map/YMapold.vue')['default']
     YztMap: typeof import('./../components/Map/YztMap/index.vue')['default']
   }
+  export interface ComponentCustomProperties {
+    vLoading: typeof import('element-plus/es')['ElLoadingDirective']
+  }
 }

+ 8 - 1
src/views/emergencyCommandMap/RightSection/index.vue

@@ -13,7 +13,7 @@
         </div>
         <div class="task-text gradient-text">启动预案</div>
       </div>
-      <div class="task-item">
+      <div class="task-item" @click="openGroupChat">
         <div class="icon">
           <div class="icon3"></div>
         </div>
@@ -47,6 +47,9 @@
     <RenWuDengJi v-if="renWuDengJiState.show" v-model:show="renWuDengJiState.show" :event-id="eventId" />
     <dutyManagement v-if="dutyManagementState.show" v-model:show="dutyManagementState.show" :event-id="eventId" />
     <knowledgeWarehouse v-if="knowledgeWarehouseState.show" v-model:show="knowledgeWarehouseState.show" :event-id="eventId" />
+    <Dialog v-model="showTip" title="提示" type="xs">
+      <div style="display: flex; justify-content: center; align-items: center; font-size: 44px;">功能建设中……</div>
+    </Dialog>
   </div>
 </template>
 
@@ -90,6 +93,10 @@ const openKnowledgeWarehouse = () => {
 const renWuDengJiState = reactive({
   show: false
 });
+let showTip = ref(false);
+const openGroupChat = () => {
+  showTip.value = true;
+};
 // 打开任务登记弹窗
 const openRenWuDengJi = () => {
   renWuDengJiState.show = true;

+ 97 - 56
src/views/emergencyCommandMap/RightSection/knowledgeWarehouse.vue

@@ -1,5 +1,5 @@
 <template>
-  <Dialog custom-show type="xl" title="知识库列表" @close="closeDialog">
+  <Dialog custom-show type="xl" title="知识库列表" hide-footer @close="closeDialog">
     <!-- 表格组件 -->
     <div class="common-table">
       <div class="table-header">
@@ -12,73 +12,114 @@
         <div class="td">发布时间</div>
       </div>
       <div v-for="(item, index) in tableData" :key="index" class="tr">
-        <div class="td">{{ item.report_id }}</div>
-        <div class="td">{{ item.report_name }}</div>
-        <div class="td">{{ item.source_unit }}</div>
-        <div class="td">{{ item.keyword }}</div>
-        <div class="td">{{ item.event_type }}</div>
-        <div class="td">{{ item.abstract }}</div>
-        <div class="td">{{ item.release_time }}</div>
+        <div class="td">{{ item.reportId }}</div>
+        <div class="td">{{ item.reportName }}</div>
+        <div class="td">{{ item.subject }}</div>
+        <div class="td">{{ item.eventType }}</div>
+        <div class="td">{{ item.summary }}</div>
+        <div class="td">{{ item.publishingUnit }}</div>
+        <div class="td">{{ item.publishDate }}</div>
       </div>
     </div>
-    <!--    <div class="footer">-->
-    <!--      <pagination-->
-    <!--        v-show="total > 0"-->
-    <!--        v-model:page="queryParams.page"-->
-    <!--        v-model:limit="queryParams.page_size"-->
-    <!--        :total="total"-->
-    <!--        layout="total, prev, pager, next"-->
-    <!--        @pagination="getList"-->
-    <!--      />-->
-    <!--    </div>-->
-    <!--    <CloseEventDialog-->
-    <!--      v-model="closeDialogState.show"-->
-    <!--      :data="closeDialogState.form"-->
-    <!--      :event-id="eventId"-->
-    <!--      @update:model-value="handleCloseEventDialog"-->
-    <!--    />-->
+    <div class="footer">
+      <el-pagination
+        background
+        :hide-on-single-page="true"
+        :total="total"
+        :page-size="queryParams.pageSize"
+        :current-page="queryParams.pageNum"
+        @current-change="handleChangePage"
+      />
+    </div>
   </Dialog>
 </template>
 <script setup lang="ts">
-import CloseEventDialog from '@/views/routineCommandMap/eventing/CloseEventDialog.vue';
 import { reactive } from 'vue';
+import { fetchReports } from '@/api/knowledge/index';
 
 const emit = defineEmits(['update:show']);
 const closeDialog = () => {
   emit('update:show', false);
 };
 const queryParams = reactive({
-  page: 1,
-  page_size: 10
+  pageNum: 1,
+  pageSize: 7,
+  sortBy: 'publishDate',
+  sortOrder: 'desc'
 });
+let total = ref(0);
+const tableData = ref([]);
 
-const tableData = [
-  {
-    report_id: '001',
-    report_name: '测试报告1',
-    source_unit: '市应急局',
-    keyword: '干旱',
-    event_type: ' drought',
-    abstract: '干旱事件',
-    release_time: '2023-05-01'
-  },
-  {
-    report_id: '002',
-    report_name: '测试报告2',
-    source_unit: '市应急局',
-    keyword: ' flood',
-    event_type: 'flood',
-    abstract: '水灾事件',
-    release_time: '2023-05-02'
-  },
-  {
-    report_id: '003',
-    report_name: '测试报告3',
-    source_unit: '市应急局',
-    keyword: ' wildfire',
-    event_type: 'wildfire',
-    abstract: ' bushfire事件',
-    release_time: '2023-05-03'
-  }
-];
+const handleChangePage = (newNum) => {
+  queryParams.pageNum = newNum;
+  getList();
+};
+
+// getLists是获取列表数据的方法
+const getList = async () => {
+  fetchReports(queryParams).then((res) => {
+    total.value = res.total;
+    tableData.value = res.data;
+  });
+};
+
+onMounted(() => {
+  getList();
+});
 </script>
+
+<style lang="scss" scoped>
+.footer {
+  height: 64px;
+  display: flex;
+  justify-content: flex-end;
+  margin: 30px 0;
+  .pagination-container {
+    height: 64px;
+    margin: 0;
+  }
+  :deep(.el-pagination__total) {
+    color: #a7ccdf;
+    font-size: 32px;
+  }
+  :deep(.el-pagination) {
+    .btn-next,
+    .btn-prev {
+      background-color: transparent;
+      border: none;
+      .el-icon {
+        font-size: 22px;
+        color: #a7ccdf;
+      }
+    }
+    .btn-prev:disabled,
+    .btn-next:disabled {
+      background-color: transparent;
+      border: none;
+    }
+    .el-pager li {
+      width: 64px;
+      height: 64px;
+      line-height: 64px;
+      text-align: center;
+      font-size: 38px;
+      color: #a7ccdf;
+      background-color: #0e3064;
+      border: 1px solid #0c57a7;
+      margin: 0 6px;
+      &:hover {
+        background-color: #038dff;
+        border: 1px solid #038dff;
+      }
+    }
+    .el-pager li.is-active {
+      background-color: #038dff;
+      border: 1px solid #038dff;
+    }
+    .el-pagination__goto {
+      font-size: 38px;
+      color: #a7ccdf;
+    }
+  }
+}
+</style>

+ 0 - 1
src/views/globalMap/LeftMenu.vue

@@ -119,7 +119,6 @@
     <Dialog
       v-if="showDialog"
       v-model="showDialog"
-      v-model:tags="videoMonitorData.tag_info"
       type="lg"
       header-type="header2"
       title="视频"