yanghao 5 dní pred
rodič
commit
ef8dfec928
1 zmenil súbory, kde vykonal 144 pridanie a 42 odobranie
  1. 144 42
      src/views/pms/qhse/kanban/index.vue

+ 144 - 42
src/views/pms/qhse/kanban/index.vue

@@ -1,4 +1,5 @@
 <script lang="ts" setup>
+import * as echarts from 'echarts'
 import {
   AlarmClock,
   Checked,
@@ -12,7 +13,15 @@ import {
   Postcard,
   Warning
 } from '@element-plus/icons-vue'
-import { DESIGN_HEIGHT, DESIGN_WIDTH } from '@/utils/kb'
+import {
+  ANIMATION,
+  CHART_RENDERER,
+  DESIGN_HEIGHT,
+  DESIGN_WIDTH,
+  FONT_FAMILY,
+  THEME,
+  createTooltip
+} from '@/utils/kb'
 
 defineOptions({
   name: 'PmsQhseKanban'
@@ -55,11 +64,13 @@ type BottomCard = {
 }
 
 const wrapperRef = ref<HTMLDivElement>()
+const hazardChartRef = ref<HTMLDivElement>()
 const scale = ref(1)
 const supportsZoom = ref(false)
 
 let resizeObserver: ResizeObserver | null = null
 let resizeRaf = 0
+let hazardChart: echarts.ECharts | null = null
 
 const pageTitle = 'QHSE管理看板'
 
@@ -214,14 +225,143 @@ onMounted(() => {
   if (wrapperRef.value) {
     resizeObserver.observe(wrapperRef.value)
   }
+  initHazardChart()
   window.addEventListener('resize', updateScale)
+  window.addEventListener('resize', resizeHazardChart)
 })
 
 onUnmounted(() => {
   resizeObserver?.disconnect()
   window.removeEventListener('resize', updateScale)
+  window.removeEventListener('resize', resizeHazardChart)
   cancelAnimationFrame(resizeRaf)
+  destroyHazardChart()
 })
+
+function getHazardChartOption(): echarts.EChartsOption {
+  return {
+    ...ANIMATION,
+    grid: {
+      left: 20,
+      right: 10,
+      top: 24,
+      bottom: 24,
+      containLabel: true
+    },
+    tooltip: createTooltip({
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow',
+        shadowStyle: {
+          color: 'rgba(31, 91, 184, 0.08)'
+        }
+      },
+      formatter(params: any) {
+        const item = Array.isArray(params) ? params[0] : params
+        return `${item.name}<br/>数量:${item.value}`
+      }
+    }),
+    xAxis: {
+      type: 'category',
+      data: hazardBars.map((item) => item.label),
+      axisLine: {
+        show: false
+      },
+      axisTick: {
+        show: false
+      },
+      axisLabel: {
+        color: '#5b6f8f',
+        fontSize: 16,
+        fontWeight: 700,
+        fontFamily: FONT_FAMILY,
+        interval: 0
+      }
+    },
+    yAxis: {
+      type: 'value',
+      axisLine: {
+        show: false
+      },
+      axisTick: {
+        show: false
+      },
+      axisLabel: {
+        color: '#8a9bb5',
+        fontSize: 13,
+        fontFamily: FONT_FAMILY
+      },
+      splitLine: {
+        lineStyle: {
+          color: THEME.split,
+          type: 'dashed'
+        }
+      }
+    },
+    series: [
+      {
+        type: 'bar',
+        data: hazardBars.map((item) => ({
+          value: item.value,
+          itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              { offset: 0, color: item.color },
+              { offset: 1, color: `${item.color}99` }
+            ]),
+            shadowBlur: 14,
+            shadowColor: item.color,
+            borderRadius: [0, 0, 0, 0]
+          }
+        })),
+        barWidth: 70,
+        showBackground: true,
+        backgroundStyle: {
+          color: 'rgba(31, 91, 184, 0.06)',
+          borderRadius: 0
+        },
+        label: {
+          show: true,
+          position: 'bottom',
+          offset: [0, 36],
+          color: '#5b6f8f',
+          fontSize: 18,
+          fontWeight: 700,
+          fontFamily: FONT_FAMILY,
+          formatter(params: any) {
+            return params.name
+          }
+        },
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 18
+          }
+        }
+      }
+    ]
+  }
+}
+
+function initHazardChart() {
+  if (!hazardChartRef.value) return
+  if (hazardChart) {
+    hazardChart.dispose()
+  }
+  hazardChart = echarts.init(hazardChartRef.value, undefined, {
+    renderer: CHART_RENDERER
+  })
+  hazardChart.setOption(getHazardChartOption(), true)
+}
+
+function resizeHazardChart() {
+  hazardChart?.resize()
+}
+
+function destroyHazardChart() {
+  if (hazardChart) {
+    hazardChart.dispose()
+    hazardChart = null
+  }
+}
 </script>
 
 <template>
@@ -272,14 +412,7 @@ onUnmounted(() => {
                   <span class="icon-decorator"><span></span><span></span></span>
                   隐患排查治理统计
                 </div>
-                <div class="chart-panel chart-panel--bars">
-                  <div v-for="bar in hazardBars" :key="bar.label" class="bar-card">
-                    <div class="bar-card__chart">
-                      <div class="bar-card__fill" :style="{ height: `${bar.value}%`, background: bar.color }"></div>
-                    </div>
-                    <div class="bar-card__label">{{ bar.label }}</div>
-                  </div>
-                </div>
+                <div ref="hazardChartRef" class="chart-panel chart-panel--echart"></div>
               </section>
 
               <section class="panel board-panel kb-stage-card kb-stage-card--3">
@@ -487,42 +620,11 @@ onUnmounted(() => {
 }
 
 .chart-panel--bars {
-  display: flex;
   height: 176px;
-  padding: 6px 10px 0;
-  align-items: flex-end;
-  gap: 34px;
-}
-
-.bar-card {
-  display: flex;
-  height: 100%;
-  flex: 1;
-  flex-direction: column;
-  align-items: center;
-  justify-content: flex-end;
 }
 
-.bar-card__chart {
-  display: flex;
-  width: 100%;
-  height: 120px;
-  padding: 0 20px;
-  align-items: flex-end;
-}
-
-.bar-card__fill {
-  width: 100%;
-  min-height: 32px;
-  border-radius: 0;
-  box-shadow: 0 10px 24px rgb(31 91 184 / 10%);
-}
-
-.bar-card__label {
-  margin-top: 14px;
-  font-size: 18px;
-  font-weight: 700;
-  color: #5b6f8f;
+.chart-panel--echart {
+  height: 188px;
 }
 
 .incident-panel {