Răsfoiți Sursa

Merge remote-tracking branch 'origin/master'

wenhongquan 3 luni în urmă
părinte
comite
9e9ac415c9

+ 7 - 2
plus-ui-ts/src/api/system/event/index.ts

@@ -8,14 +8,19 @@ import { EventVO, EventForm, EventQuery } from '@/api/system/event/types';
  * @returns {*}
  */
 
-export const listEvent = (query?: EventQuery): AxiosPromise<EventVO[]> => {
+export const listEvent = (query) => {
   return request({
     url: '/system/event/list',
     method: 'get',
     params: query
   });
 };
-
+export const generateReport = (id) => {
+  return request({
+    url: `/system/event/generate/${id}`,
+    method: 'post'
+  });
+};
 /**
  * 查询事件详细
  * @param id

+ 1 - 1
plus-ui-ts/src/layout/components/AppMain.vue

@@ -60,7 +60,7 @@ function addIframe() {
   height: calc(100vh - 50px);
   width: 100%;
   position: relative;
-  overflow: hidden;
+  overflow: auto;
 }
 
 .fixed-header + .app-main {

+ 23 - 0
plus-ui-ts/src/utils/index.ts

@@ -1,5 +1,28 @@
 import { parseTime } from '@/utils/ruoyi';
 
+export function dateFormat(date, format = 'yyyy-MM-dd HH:mm:ss') {
+  const o = {
+    'M+': date.getMonth() + 1, // 月份
+    'd+': date.getDate(), // 日
+    'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时
+    'H+': date.getHours(), // 小时
+    'm+': date.getMinutes(), // 分
+    's+': date.getSeconds(), // 秒
+    'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
+    S: date.getMilliseconds(), // 毫秒
+    a: date.getHours() < 12 ? '上午' : '下午', // 上午/下午
+    A: date.getHours() < 12 ? 'AM' : 'PM' // AM/PM
+  };
+  if (/(y+)/.test(format)) {
+    format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
+  }
+  for (const k in o) {
+    if (new RegExp('(' + k + ')').test(format)) {
+      format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length));
+    }
+  }
+  return format;
+}
 /**
  * 表格时间格式化
  */

+ 288 - 164
plus-ui-ts/src/views/index.vue

@@ -11,19 +11,19 @@
         </template>
         <div class="custom-card">
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthCount }}</span>
             <span>所有数量</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthAlready }}</span>
             <span>已解决</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthNot }}</span>
             <span>未解决</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthReport }}</span>
             <span>已上报</span>
           </div>
         </div>
@@ -37,19 +37,19 @@
         </template>
         <div class="custom-card week-card">
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthCount }}</span>
             <span>所有数量</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthAlready }}</span>
             <span>已解决</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthNot }}</span>
             <span>未解决</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthReport }}</span>
             <span>已上报</span>
           </div>
         </div>
@@ -63,19 +63,19 @@
         </template>
         <div class="custom-card day-card">
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthCount }}</span>
             <span>所有数量</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthAlready }}</span>
             <span>已解决</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthNot }}</span>
             <span>未解决</span>
           </div>
           <div class="card-item">
-            <span>147</span>
+            <span>{{ statData.monthReport }}</span>
             <span>已上报</span>
           </div>
         </div>
@@ -87,7 +87,7 @@
             <span>统计分析</span>
           </div>
         </template>
-        <BaseChart width="100%" height="230px" :option="pieOptions" />
+        <BaseChart width="100%" height="100%" :option="pieOptions" />
       </el-card>
     </div>
     <div class="right-part">
@@ -96,9 +96,7 @@
           <el-select style="width: 100px" v-model="queryParams.level" clearable placeholder="事件等级">
             <el-option v-for="dict in event_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
           </el-select>
-          <el-select style="width: 100px; margin-left: 10px" v-model="queryParams.level" clearable placeholder="事件类型">
-            <el-option v-for="dict in event_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-          </el-select>
+          <el-input v-model="queryParams.ext2.lx" style="width: 110px; margin-left: 10px" placeholder="事件类型" />
           <el-date-picker
             v-model="queryParams.dateRange"
             style="margin-left: 10px"
@@ -108,22 +106,34 @@
             start-placeholder="开始日期"
             end-placeholder="结束日期"
             :shortcuts="shortcuts"
+            value-format="YYYY-MM-DD HH:mm:ss"
           />
         </div>
         <div style="margin-top: 10px">
           <el-input v-model="queryParams.addr" style="width: 210px" placeholder="输入地点关键词" :suffix-icon="Search" />
           <div style="margin-left: 10px">
-            <el-button color="#3CBBED" style="color: #fff">查询</el-button>
-            <el-button>重置</el-button>
+            <el-button color="#1890FF" style="color: #fff" @click="getList">查询</el-button>
+            <el-button @click="resetQuery">重置</el-button>
           </div>
         </div>
       </div>
       <div class="event-list">
-        <el-table :data="tableData" :show-header="false" :border="false" style="width: 100%; --el-table-border-color: none">
-          <el-table-column prop="level" />
-          <el-table-column prop="type" />
+        <el-table :data="eventList" :show-header="false" :border="false" style="width: 100%; --el-table-border-color: none">
+          <el-table-column prop="level" width="80">
+            <template #default="{ row }">
+              {{ event_level.filter((item) => item.value == row.level)[0]?.label }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="ext2.lx" show-overflow-tooltip width="100" />
           <el-table-column prop="addr" show-overflow-tooltip />
-          <el-table-column prop="date" />
+          <el-table-column prop="createTimeFormat" width="100" />
+          <el-table-column prop="status" width="70">
+            <template #default="{ row }">
+              <span v-if="row.status == 3" style="color: #5f86fd">已上报</span>
+              <span v-else-if="row.status == 1" style="color: #26c768">已解决</span>
+              <span v-else style="color: #ff6124">未解决</span>
+            </template>
+          </el-table-column>
           <el-table-column width="60">
             <template #default="{ row }">
               <el-button link type="primary" @click="showDetails(row)">查看</el-button>
@@ -132,106 +142,119 @@
         </el-table>
       </div>
       <div class="event-footer">
-        <el-pagination background layout="prev, pager, next" :total="1000" />
+        <pagination
+          background
+          layout="prev, pager, next"
+          v-show="total > 0"
+          :total="total"
+          v-model:page="queryParams.pageNum"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+        />
       </div>
     </div>
-    <el-dialog v-model="dialog.visible" :title="dialog.title" width="1000px" top="0">
-      <el-form ref="addFormRef" :model="form" label-position="top" label-width="90px" label-suffix=":">
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="事件ID" prop="handler" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
-              <el-input v-model="form.handler" placeholder="请输入" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="事件类型" prop="handleWay">
-              <el-select v-model="form.level" clearable placeholder="请选择">
+    <el-dialog v-model="dialog.visible" :title="dialog.title" width="1000px" top="0" append-to-body @close="dialogClose">
+      <div class="dialog-loading-warp">
+        <el-form ref="addFormRef" :model="form" label-position="top" label-width="90px" label-suffix=":">
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="事件ID" prop="id">
+                <el-input v-model="form.id" placeholder="请输入" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="事件类型" prop="ext2.lx">
+                <el-input v-model="form.ext2.lx" placeholder="请输入" />
+                <!-- <el-select v-model="form.ext2.lx" clearable placeholder="请选择">
                 <el-option v-for="dict in event_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="发生时间" prop="handleContent">
-              <el-date-picker style="width: 100%" v-model="form.value1" type="date" placeholder="请选择" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="事件等级" prop="handleWay">
-              <el-select v-model="form.level" clearable placeholder="请选择">
-                <el-option v-for="dict in event_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="桩号" prop="handleWay">
-              <el-input v-model="form.handler" placeholder="请输入" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="地点描述" prop="handleWay">
-              <el-input v-model="form.handler" type="textarea" placeholder="请输入" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <div class="event-media">
-        <div class="event-media-title">现场画面</div>
-        <div class="event-media-content">
-          <div class="imgs">
-            <el-image :src="imgUrl" show-progress :preview-src-list="imgList" fit="cover" />
-            <el-image :src="imgUrl" show-progress :preview-src-list="imgList" fit="cover" />
-          </div>
-        </div>
-      </div>
-      <div class="event-media" style="margin-top: 10px">
-        <div class="event-media-title">现场视频</div>
-        <div class="event-media-content">
-          <div class="videos">
-            <div id="dplayer1"></div>
-            <div id="dplayer2"></div>
-            <div id="dplayer3"></div>
-            <div id="dplayer4"></div>
+              </el-select> -->
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="发生时间" prop="createTime">
+                <el-date-picker style="width: 100%" v-model="form.createTime" type="date" placeholder="请选择" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="事件等级" prop="level">
+                <el-select v-model="form.level" clearable placeholder="请选择" @change="formSubmit('level')">
+                  <el-option v-for="dict in event_level" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="桩号" prop="ext2.zh">
+                <el-input v-model="form.ext2.zh" placeholder="请输入" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="状态" prop="status">
+                <el-select v-model="form.status" clearable placeholder="请选择" @change="formSubmit('status')">
+                  <el-option v-for="dict in event_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="地点描述" prop="addr">
+                <el-input v-model="form.addr" type="textarea" placeholder="请输入" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+        <div class="event-media" v-if="form.imgList.length">
+          <div class="event-media-title">现场画面</div>
+          <div class="event-media-content">
+            <div class="imgs">
+              <el-image v-for="item in form.imgList" :key="item" :src="item" show-progress :preview-src-list="form.imgList" fit="cover" />
+            </div>
           </div>
         </div>
-      </div>
-      <div class="report-btn">
-        <img @click="generateReport" src="@/assets/images/report.svg" alt="" />
-      </div>
-      <template v-if="showReport">
-        <div class="report-editor">
-          <div class="report-title">报告内容:</div>
-          <div style="border: 1px solid #d9d9d9; margin-top: 10px">
-            <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" mode="default" />
-            <Editor style="height: 500px; overflow-y: hidden" v-model="valueHtml" :defaultConfig="editorConfig" @onCreated="handleCreated" />
+        <div class="event-media" v-if="form.videoList.length" style="margin-top: 10px">
+          <div class="event-media-title">现场视频</div>
+          <div class="event-media-content">
+            <div class="videos">
+              <div v-for="(item, index) in form.videoList" :key="index" :id="`dplayer${index}`"></div>
+            </div>
           </div>
         </div>
-        <div style="margin-top: 20px">
-          <div class="report-title">格式选择:</div>
-          <el-select style="width: 300px; margin-top: 10px" v-model="fileType" clearable placeholder="请选择">
-            <el-option label="pdf" :value="1"></el-option>
-            <el-option label="word" :value="2"></el-option>
-            <el-option label="图片" :value="3"></el-option>
-          </el-select>
-        </div>
-        <div>
-          <el-button color="#2AB55C" style="color: #fff; margin-top: 20px; margin-bottom: 30px" @click="htmlToPdfFn">导出报告</el-button>
-        </div>
-      </template>
-      <!-- <template #footer>
-        <div class="dialog-footer">
+        <div class="report-btn">
+          <img @click="generateClick" src="@/assets/images/report.svg" alt="" />
         </div>
-      </template> -->
+        <template v-if="showReport">
+          <div class="report-editor">
+            <div class="report-title">报告内容:</div>
+            <div style="border: 1px solid #d9d9d9; margin-top: 10px">
+              <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" mode="default" />
+              <Editor style="height: 500px; overflow-y: hidden" v-model="valueHtml" :defaultConfig="editorConfig" @onCreated="handleCreated" />
+            </div>
+          </div>
+          <div style="margin-top: 20px">
+            <div class="report-title">格式选择:</div>
+            <el-select style="width: 300px; margin-top: 10px" v-model="fileType" clearable placeholder="请选择">
+              <el-option label="pdf" :value="1"></el-option>
+              <el-option label="word" :value="2"></el-option>
+              <el-option label="图片" :value="3"></el-option>
+            </el-select>
+          </div>
+          <div>
+            <el-button color="#2AB55C" style="color: #fff; margin-top: 20px; margin-bottom: 30px" @click="htmlToPdfFn">导出报告</el-button>
+          </div>
+        </template>
+      </div>
     </el-dialog>
   </div>
 </template>
 <script lang="ts" setup>
-import { Search, Location } from '@element-plus/icons-vue';
+import { Search } from '@element-plus/icons-vue';
 import BaseChart from '@/components/BaseChart/index.vue';
 import monitorIcon from '@/assets/images/monitor.svg';
 import DPlayer from 'dplayer';
 import '@wangeditor/editor/dist/css/style.css'; // 引入 css
 import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
 import { exportAsPdf, exportAsWord, exportAsImage } from 'html2image-pdf-word';
+import { listEvent, generateReport, updateEvent } from '@/api/system/event';
+import { dateFormat } from '@/utils/index';
+import { ElLoading } from 'element-plus';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const bdmap = ref(null);
 const marks = ref([
@@ -249,11 +272,11 @@ const marks = ref([
   }
 ]);
 const { event_level } = toRefs<any>(proxy?.useDict('event_level'));
+const { event_status } = toRefs<any>(proxy?.useDict('event_status'));
 const editorRef = shallowRef();
-const toolbarConfig = {};
 const editorConfig = { placeholder: '请输入内容...' };
 // 内容 HTML
-const valueHtml = ref('<p>hello</p>');
+const valueHtml = ref('');
 const handleCreated = (editor) => {
   console.log('created', editor);
   editorRef.value = editor; // 记录 editor 实例,重要!
@@ -278,15 +301,42 @@ const htmlToPdfFn = async () => {
 };
 
 const queryParams = ref({
+  pageNum: 1,
+  pageSize: 15,
   level: undefined,
+  ext2: {
+    lx: undefined
+  },
   dateRange: undefined,
-  addr: undefined
+  addr: undefined,
+  params: {
+    beginTime: '',
+    endTime: ''
+  }
 });
 const dialog = reactive({
   visible: false,
-  title: '事件详情'
+  title: '事件详情',
+  loading: null
+});
+const form = ref<any>({});
+const statData = reactive({
+  monthCount: undefined,
+  monthAlready: undefined,
+  monthNot: undefined,
+  monthReport: undefined,
+  weekCount: undefined,
+  weekAlready: undefined,
+  weekNot: undefined,
+  weekReport: undefined,
+  dayCount: undefined,
+  dayAlready: undefined,
+  dayNot: undefined,
+  dayReport: undefined,
+  already: undefined,
+  not: undefined,
+  report: undefined
 });
-const form = reactive({});
 const shortcuts = [
   {
     text: '最近一周',
@@ -331,26 +381,25 @@ const pieOptions = computed(() => {
     series: [
       {
         type: 'pie',
-        radius: '50%',
         radius: ['40%', '80%'],
         center: ['50%', '60%'],
         data: [
           {
-            value: 40,
+            value: statData.monthAlready,
             name: '已解决',
             itemStyle: {
               color: '#FAC858'
             }
           },
           {
-            value: 17,
+            value: statData.monthNot,
             name: '未解决',
             itemStyle: {
               color: '#93BEFF'
             }
           },
           {
-            value: 15,
+            value: statData.monthReport,
             name: '已上报',
             itemStyle: {
               color: '#507AFC'
@@ -369,28 +418,8 @@ const pieOptions = computed(() => {
   };
   return options;
 });
-const tableData = [
-  {
-    date: '2016-05-03',
-    level: '严重',
-    addr: '地点',
-    type: '交通事故'
-  },
-  {
-    date: '2016-05-03',
-    level: '严重',
-    addr: '地点',
-    type: '交通事故'
-  },
-  {
-    date: '2016-05-03',
-    level: '严重',
-    addr: '地点',
-    type: '交通事故'
-  }
-];
-const imgUrl = new URL(`@/assets/images/profile.jpg`, import.meta.url).href;
-const imgList = [new URL(`@/assets/images/profile.jpg`, import.meta.url).href, new URL(`@/assets/images/profile.jpg`, import.meta.url).href];
+const eventList = ref([]);
+const total = ref(0);
 onMounted(() => {
   const map = new BMapGL.Map('map'); // 创建地图实例
   const point = new BMapGL.Point(118.879999, 32.016216); // 创建点坐标
@@ -402,7 +431,52 @@ onMounted(() => {
     console.log(e.latlng);
   });
   showMarks();
+  getList();
+  getStat();
 });
+const getList = async () => {
+  const { dateRange } = queryParams.value;
+  if (dateRange && dateRange.length) {
+    queryParams.value.params.beginTime = dateRange[0];
+    queryParams.value.params.endTime = dateRange[1];
+  } else {
+    queryParams.value.params.beginTime = undefined;
+    queryParams.value.params.endTime = undefined;
+  }
+  const res = await listEvent(queryParams.value);
+  eventList.value = res.rows.map((item: any) => ({
+    ...item,
+    status: item.status || '2',
+    createTimeFormat: dateFormat(new Date(item.createTime), 'yyyy-MM-dd'),
+    ext1: item.ext1 ? JSON.parse(item.ext1) : [],
+    ext2: item.ext2 ? JSON.parse(item.ext2) : {}
+  }));
+  total.value = res.total;
+};
+const getStat = async () => {
+  const res = await listEvent({});
+  statData.monthCount = res.total;
+  statData.monthAlready = res.rows.filter((item) => item.status == '1').length;
+  statData.monthNot = res.rows.filter((item) => item.status == '2' || item.status === null).length;
+  statData.monthReport = res.rows.filter((item) => item.status == '3').length;
+};
+const resetQuery = () => {
+  queryParams.value = {
+    pageNum: 1,
+    pageSize: 15,
+    level: undefined,
+    ext2: {
+      lx: undefined
+    },
+    dateRange: undefined,
+    addr: undefined,
+    params: {
+      beginTime: '',
+      endTime: ''
+    }
+  };
+  getList();
+};
 onBeforeUnmount(() => {
   const editor = editorRef.value;
   if (editor == null) return;
@@ -417,39 +491,59 @@ const showMarks = () => {
     bdmap.value.addOverlay(marker);
   });
 };
-const showDetails = () => {
-  showReport.value = false;
+const showDetails = (row) => {
   dialog.visible = true;
+  let imgList = [];
+  let videoList = [];
+  if (row.ext1 && row.ext1.length) {
+    videoList = row.ext1.filter((item) => item.includes('mp4')).map((item) => `http://jtjai.xt.wenhq.top:8083/api/oss/local/upload/${item}`);
+    imgList = row.ext1.filter((item) => !item.includes('mp4')).map((item) => `http://jtjai.xt.wenhq.top:8083/api/oss/local/upload/${item}`);
+  }
+  Object.assign(form.value, JSON.parse(JSON.stringify(row)), { imgList, videoList });
   nextTick(() => {
-    const dp = new DPlayer({
-      container: document.getElementById('dplayer1'),
-      video: {
-        url: new URL(`@/assets/images/demo.mp4`, import.meta.url).href
-      }
-    });
-    const dp2 = new DPlayer({
-      container: document.getElementById('dplayer2'),
-      video: {
-        url: new URL(`@/assets/images/demo.mp4`, import.meta.url).href
-      }
-    });
-    const dp3 = new DPlayer({
-      container: document.getElementById('dplayer3'),
-      video: {
-        url: new URL(`@/assets/images/demo.mp4`, import.meta.url).href
-      }
-    });
-    const dp4 = new DPlayer({
-      container: document.getElementById('dplayer4'),
-      video: {
-        url: new URL(`@/assets/images/demo.mp4`, import.meta.url).href
-      }
+    form.value.videoList.forEach((item, index) => {
+      new DPlayer({
+        container: document.getElementById(`dplayer${index}`),
+        video: {
+          url: item
+        }
+      });
     });
   });
 };
-const generateReport = () => {
-  showReport.value = true;
-  proxy?.$modal.msgSuccess('报告生成成功');
+
+const generateClick = () => {
+  dialog.loading = ElLoading.service({
+    lock: true,
+    text: '正在生成报告,请稍候...',
+    fullscreen: false,
+    target: '.dialog-loading-warp',
+    background: 'rgba(255, 255, 255, 0.6)'
+  });
+  generateReport(form.value.id).then(({ code, msg }) => {
+    dialog.loading.close();
+    if (code == 200 && msg) {
+      showReport.value = true;
+      valueHtml.value = JSON.parse(msg).data.outputs.report;
+      proxy?.$modal.msgSuccess('报告生成成功');
+    } else {
+      proxy?.$modal.msgError('报告生成失败');
+    }
+  });
+};
+const dialogClose = () => {
+  showReport.value = false;
+  dialog.loading && dialog.loading.close();
+};
+const formSubmit = async (field) => {
+  const { id } = form.value;
+  const params = {
+    id
+  };
+  params[field] = form.value[field];
+  await updateEvent(params);
+  getList();
+  getStat();
 };
 </script>
 <style lang="scss" scoped>
@@ -463,7 +557,27 @@ const generateReport = () => {
     width: 300px;
     top: 10px;
     left: 20px;
+    bottom: 10px;
     z-index: 10;
+    display: flex;
+    flex-direction: column;
+
+    > .el-card:nth-child(-n + 3) {
+      height: 22%;
+      flex-shrink: 0;
+
+      :deep(.el-card__body) {
+        height: 70%;
+      }
+    }
+
+    > .el-card:last-child {
+      flex: 1;
+
+      :deep(.el-card__body) {
+        height: 80%;
+      }
+    }
   }
 
   .right-part {
@@ -496,6 +610,7 @@ const generateReport = () => {
 .custom-card {
   display: flex;
   justify-content: space-between;
+  height: 100%;
 
   .card-item {
     display: flex;
@@ -503,7 +618,7 @@ const generateReport = () => {
     flex-direction: column;
     justify-content: center;
     align-items: center;
-    height: 71px;
+    height: 100%;
     background: #e3eefe;
     color: #2d5794;
     border-radius: 4.8px;
@@ -512,6 +627,8 @@ const generateReport = () => {
       flex: 1;
       font-size: 22px;
       margin-top: 10px;
+      display: flex;
+      align-items: center;
     }
 
     span:last-child {
@@ -594,6 +711,10 @@ const generateReport = () => {
   align-items: center;
   padding-right: 20px;
 
+  .pagination-container {
+    margin-top: 0;
+  }
+
   :deep() {
     .el-pagination.is-background .btn-next,
     .el-pagination.is-background .btn-prev,
@@ -662,6 +783,7 @@ const generateReport = () => {
     cursor: pointer;
   }
 }
+
 .hidden-report {
   position: absolute;
   visibility: hidden;
@@ -680,9 +802,11 @@ const generateReport = () => {
   background-color: #fff;
   border: 1px solid #eee;
 }
+
 .report-editor {
   margin-top: 20px;
 }
+
 .report-title {
   color: #5d5d5dd9;
   font-size: 14px;