zhangjie 1 年之前
父節點
當前提交
b873330221

二進制
src/assets/imgs/bg_report_title.png


+ 25 - 4
src/components/global/report-header/index.vue

@@ -1,7 +1,9 @@
 <template>
   <div class="report-header flex items-center justify-between">
-    <div class="title flex items-center"
-      ><span style="margin-right: 10px">{{ props.title }}</span>
+    <div class="title flex items-center">
+      <span class="report-header-title" style="margin-right: 10px">{{
+        props.title
+      }}</span>
       <slot />
       <CustomDatePicker
         v-if="!props.hideTimePicker"
@@ -13,7 +15,21 @@
     <div class="right-box flex h-full items-center">
       <img class="time-icon" src="../../../assets//imgs/time.png" />
       <p>{{ timeText }} &nbsp; {{ getCurrentWeek() }}</p>
-      <t-button variant="outline" class="m-l-16px">
+      <t-button
+        v-if="appStore.isFullscreen"
+        variant="outline"
+        class="m-l-16px"
+        @click="switchFullscreen"
+      >
+        <template #icon><SwapLeftIcon /></template>
+        返回
+      </t-button>
+      <t-button
+        v-else
+        variant="outline"
+        class="m-l-16px"
+        @click="switchFullscreen"
+      >
         <template #icon><Fullscreen2Icon /></template>
         全屏
       </t-button>
@@ -26,7 +42,11 @@ import { useIntervalFn } from '@vueuse/core';
 import { dateFormat } from '@/utils/tool';
 import { useVModel } from '@vueuse/core';
 import CustomDatePicker from '../custom-date-picker';
-import { Fullscreen2Icon } from 'tdesign-icons-vue-next';
+import { Fullscreen2Icon, SwapLeftIcon } from 'tdesign-icons-vue-next';
+import { useAppStore } from '@/store';
+import useFullscreen from '@/hooks/useFullscreen';
+const { switchFullscreen } = useFullscreen();
+
 const emit = defineEmits(['update:dateRange', 'timeChange']);
 const timeChange = (value) => {
   emit('timeChange', value);
@@ -36,6 +56,7 @@ const props = defineProps({
   dateRange: Array,
   hideTimePicker: Boolean,
 });
+const appStore = useAppStore();
 const range = useVModel(props, 'dateRange', emit);
 const currentTime = ref(Date.now());
 const updateTime = () => {

+ 78 - 0
src/hooks/useFullscreen.js

@@ -0,0 +1,78 @@
+import { useAppStore } from '@/store';
+import { MessagePlugin } from 'tdesign-vue-next';
+import { onMounted } from 'vue';
+
+export default function () {
+  const appStore = useAppStore();
+
+  function checkDocIsFullscreen() {
+    return (
+      document.fullscreenElement ||
+      document.msFullscreenElement ||
+      document.mozFullscreenElement ||
+      document.webkitFullscreenElement
+    );
+  }
+
+  async function switchFullscreen() {
+    const fullscreenEnabled =
+      document.fullscreenEnabled ||
+      document.mozFullScreenEnabled ||
+      document.webkitFullscreenEnabled ||
+      document.msFullscreenEnabled;
+    if (!fullscreenEnabled) {
+      MessagePlugin.error('当前浏览器不支持全屏!');
+      return;
+    }
+    const de = document.documentElement;
+    const requestFullscreen =
+      de.requestFullscreen ||
+      de.mozRequestFullScreen ||
+      de.webkitRequestFullscreen;
+    const exitFullscreen =
+      document.exitFullscreen ||
+      document.mozCancelFullScreen ||
+      document.webkitCancelFullScreen;
+
+    if (appStore.isFullscreen) {
+      await exitFullscreen.call(document).catch((err) => {
+        console.log(err);
+      });
+    } else {
+      await requestFullscreen.call(de).catch(() => {});
+    }
+  }
+
+  function registFullscreenChange() {
+    document.documentElement.onfullscreenchange = () => {
+      const isFullscreen = checkDocIsFullscreen();
+      appStore.setIsFullScreen(isFullscreen);
+      if (isFullscreen) {
+        document.body.className += ' app-fullscreen';
+        document.documentElement.setAttribute('theme-mode', 'dark');
+      } else {
+        document.body.className = document.body.className.replace(
+          'app-fullscreen',
+          ''
+        );
+        document.documentElement.removeAttribute('theme-mode');
+      }
+    };
+
+    document.addEventListener('keydown', (e) => {
+      if (e.keyCode === 122 || (e.keyCode === 27 && checkDocIsFullscreen())) {
+        e.preventDefault();
+        switchFullscreen();
+      }
+    });
+  }
+
+  onMounted(() => {
+    registFullscreenChange();
+    appStore.setIsFullScreen(checkDocIsFullscreen());
+  });
+
+  return {
+    switchFullscreen,
+  };
+}

+ 2 - 0
src/layout/index.vue

@@ -79,6 +79,8 @@ import { useRouter, useRoute } from 'vue-router';
 import LeftMenu from './left-menu.vue';
 import { moduleMap } from '@/router/asyncRoutes';
 import { MessagePlugin } from 'tdesign-vue-next';
+import useFullscreen from '@/hooks/useFullscreen';
+useFullscreen();
 
 const router = useRouter();
 const route = useRoute();

+ 1 - 0
src/main.js

@@ -12,6 +12,7 @@ import 'tdesign-vue-next/es/style/index.css';
 // import 'tdesign-vue-next/dist/reset.css';
 import './style/index.less';
 import './style/global.less';
+import './style/black.less';
 import 'uno.css';
 import { setGlobalOptions } from 'vue-request';
 import packageJson from '../package.json';

+ 4 - 0
src/store/modules/app.js

@@ -11,6 +11,7 @@ const useAppStore = defineStore('app', {
     flowParams: null,
     // new
     showSubmenu: true,
+    isFullscreen: false,
   }),
   getters: {
     appCurrentSetting(state) {
@@ -40,6 +41,9 @@ const useAppStore = defineStore('app', {
     toggleSubMenu() {
       this.showSubmenu = !this.showSubmenu;
     },
+    setIsFullScreen(isFullscreen) {
+      this.isFullscreen = isFullscreen;
+    },
   },
 });
 

+ 112 - 0
src/style/black.less

@@ -0,0 +1,112 @@
+body.app-fullscreen {
+  .app-menu,
+  .app-submenu {
+    display: none;
+  }
+  .report-header {
+    background: #09182f;
+    position: relative;
+    border-bottom: 1px solid #0a3367;
+    .right-box p {
+      color: #bedaff;
+    }
+  }
+  .report-header-title {
+    position: absolute;
+    left: 50%;
+    top: 0;
+    transform: translateX(-50%);
+    height: 60px;
+    width: 464px;
+    font-size: 24px;
+    font-weight: bold;
+    color: #ffffff;
+    line-height: 32px;
+    text-align: center;
+    padding: 14px 0;
+    margin: 0 !important;
+    background-image: url(../assets/imgs/bg_report_title.png);
+    background-size: 100% 100%;
+  }
+  .page-main {
+    background-color: #060606;
+    color: #fff;
+
+    .card {
+      background: #09182f !important;
+      border: 1px solid #0a3367 !important;
+
+      .title {
+        .t-button {
+          color: #e5e5e5;
+        }
+      }
+
+      .label {
+        color: #fff !important;
+      }
+    }
+  }
+
+  // tdesign-ui
+  .t-button {
+    border: 1px solid #0a3367;
+    background-color: transparent;
+    color: #bedaff;
+    &:hover {
+      opacity: 0.8;
+    }
+  }
+  .t-input,
+  .t-range-input {
+    background-color: transparent;
+    border-color: #0a3367;
+    box-shadow: none;
+  }
+  .t-input__inner {
+    color: #bedaff;
+  }
+  .t-icon,
+  .t-fake-arrow {
+    color: #bedaff !important;
+  }
+  .t-progress__bar {
+    background: #0a3367;
+  }
+  .t-progress__info {
+    color: #fff;
+  }
+  .t-table,
+  .t-table tr {
+    background-color: transparent !important;
+    border-color: #0a3367 !important;
+  }
+  .t-table td,
+  .t-table th,
+  .t-table__content {
+    border-color: #0a3367 !important;
+    color: #fff;
+  }
+  .t-table th {
+    color: #8c8c8c;
+  }
+  .t-popup__content {
+    background-color: #0a3367 !important;
+  }
+  .t-select-option {
+    color: #fff;
+    &.t-is-selected {
+      background-color: #114c9a;
+    }
+  }
+  .t-select-option__hover {
+    background-color: #114c9a !important;
+  }
+
+  // quality-analysis
+  .quality-analysis {
+    .page-main .col1 .chart-wrap::after {
+      border-bottom: 1px solid #0a3367;
+    }
+  }
+}

+ 4 - 1
src/utils/chart.js

@@ -1,5 +1,8 @@
 import 'echarts-liquidfill/src/liquidFill.js';
 import { cloneDeep } from 'lodash';
+import { useAppStore } from '@/store';
+const appStore = useAppStore();
+
 const getTotal = (data) => {
   return data.reduce((num, item) => {
     return num + item.value;
@@ -78,7 +81,7 @@ export const createStackingBarOption = ({ xData, seriesData }, extend = {}) => {
         bottom: '1%',
         containLabel: true,
         show: true,
-        borderColor: '#e5e5e5',
+        borderColor: appStore.isFullscreen ? '#0A3367' : '#e5e5e5',
       },
       xAxis: {
         type: 'value',

+ 21 - 11
src/views/report/quality-analysis/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="project-analysis">
+  <div class="quality-analysis">
     <report-header
       title="质量监控分析"
       v-model:dateRange="curTimeRange"
@@ -25,10 +25,16 @@
           </div>
           <div class="chart-wrap">
             <div class="chart-part">
-              <my-chart :options="overallPieOptions"></my-chart>
+              <my-chart
+                v-if="overallPieData"
+                :options="overallPieOptions"
+              ></my-chart>
             </div>
             <div class="chart-part">
-              <my-chart :options="overallRadarOptions"></my-chart>
+              <my-chart
+                v-if="overallRadarData"
+                :options="overallRadarOptions"
+              ></my-chart>
             </div>
           </div>
         </div>
@@ -54,7 +60,7 @@
                 </t-button>
               </div>
               <div class="chart-wrap">
-                <my-chart :options="options11"></my-chart>
+                <my-chart v-if="result11" :options="options11"></my-chart>
               </div>
             </div>
             <div class="card">
@@ -65,7 +71,7 @@
                 </t-button>
               </div>
               <div class="chart-wrap">
-                <my-chart :options="options12"></my-chart>
+                <my-chart v-if="result12" :options="options12"></my-chart>
               </div>
             </div>
           </div>
@@ -78,7 +84,7 @@
                 </t-button>
               </div>
               <div class="chart-wrap">
-                <my-chart :options="options21"></my-chart>
+                <my-chart v-if="result21" :options="options21"></my-chart>
               </div>
             </div>
             <div class="card">
@@ -89,7 +95,7 @@
                 </t-button>
               </div>
               <div class="chart-wrap">
-                <my-chart :options="options22"></my-chart>
+                <my-chart v-if="result22" :options="options22"></my-chart>
               </div>
             </div>
           </div>
@@ -286,15 +292,17 @@ const options22 = computed(() => {
 </script>
 
 <style lang="less" scoped>
-.project-analysis {
+.quality-analysis {
   .page-main {
     height: calc(100vh - 57px);
+    min-width: 1000px;
+    min-height: 600px;
     padding: 16px;
     overflow: auto;
     display: flex;
+    justify-content: stretch;
 
     .col1 {
-      height: 100%;
       width: 360px;
       margin-right: 16px;
       flex-grow: 0;
@@ -325,14 +333,14 @@ const options22 = computed(() => {
       flex-grow: 2;
       display: flex;
       flex-direction: column;
-      height: 100%;
 
       .col2-head {
         flex-grow: 0;
         flex-shrink: 0;
+        height: 85px;
       }
       .col2-body {
-        flex-grow: 2;
+        height: calc(100% - 85px);
       }
 
       .col2-row {
@@ -360,6 +368,7 @@ const options22 = computed(() => {
     border-radius: 4px;
     display: flex;
     flex-direction: column;
+    justify-content: space-between;
 
     .title {
       display: flex;
@@ -388,6 +397,7 @@ const options22 = computed(() => {
     }
     .chart-wrap {
       flex-grow: 2;
+      overflow: hidden;
     }
   }
 }