yanghao hai 4 días
pai
achega
6133d9ce91
Modificáronse 1 ficheiros con 140 adicións e 53 borrados
  1. 140 53
      src/views/pms/qhse/kanban/index.vue

+ 140 - 53
src/views/pms/qhse/kanban/index.vue

@@ -50,9 +50,8 @@ type RiskZone = {
 
 type PermitStat = {
   label: string
-  value: string
-  accent: string
-  soft: string
+  value: number
+  color: string
 }
 
 type BottomCard = {
@@ -65,12 +64,14 @@ type BottomCard = {
 
 const wrapperRef = ref<HTMLDivElement>()
 const hazardChartRef = ref<HTMLDivElement>()
+const socChartRef = ref<HTMLDivElement>()
 const scale = ref(1)
 const supportsZoom = ref(false)
 
 let resizeObserver: ResizeObserver | null = null
 let resizeRaf = 0
 let hazardChart: echarts.ECharts | null = null
+let socChart: echarts.ECharts | null = null
 
 const pageTitle = 'QHSE管理看板'
 
@@ -94,15 +95,15 @@ const summaryCards: SummaryCard[] = [
   {
     title: '隐患整改率',
     value: '92.3%',
-    note: '较昨日 +1.6%',
+    note: '',
     accent: '#2ac7c9',
     glow: 'rgba(42, 199, 201, 0.26)',
     icon: DataAnalysis
   },
   {
-    title: '本月在线作业许可',
+    title: '本月作业许可',
     value: '11',
-    note: 'Active',
+    note: '',
     accent: '#4f8dff',
     glow: 'rgba(79, 141, 255, 0.22)',
     icon: DocumentChecked
@@ -136,8 +137,11 @@ const riskZones: RiskZone[] = [
 ]
 
 const permitStats: PermitStat[] = [
-  { label: '在线作业', value: '11', accent: '#4d8cff', soft: 'rgba(77, 140, 255, 0.16)' },
-  { label: '异常预警', value: '2', accent: '#d0a400', soft: 'rgba(208, 164, 0, 0.14)' }
+  { label: '个人防护', value: 18, color: '#4f8dff' },
+  { label: '规范操作', value: 26, color: '#43c7ca' },
+  { label: '规范指挥', value: 12, color: '#ffb14a' },
+  { label: '人员位置', value: 9, color: '#ff7a7a' },
+  { label: '作业场所', value: 15, color: '#8d8cff' }
 ]
 
 const qualificationWarnings = [
@@ -165,7 +169,7 @@ const bottomCards: BottomCard[] = [
     icon: AlarmClock,
     accent: '#ff5b61',
     glow: 'rgba(255, 91, 97, 0.22)',
-    lines: ['年度计划完成率', '89%(需补1次)']
+    lines: ['年度应急演练:80次']
   },
   {
     title: '质量检验',
@@ -226,16 +230,20 @@ onMounted(() => {
     resizeObserver.observe(wrapperRef.value)
   }
   initHazardChart()
+  initSocChart()
   window.addEventListener('resize', updateScale)
   window.addEventListener('resize', resizeHazardChart)
+  window.addEventListener('resize', resizeSocChart)
 })
 
 onUnmounted(() => {
   resizeObserver?.disconnect()
   window.removeEventListener('resize', updateScale)
   window.removeEventListener('resize', resizeHazardChart)
+  window.removeEventListener('resize', resizeSocChart)
   cancelAnimationFrame(resizeRaf)
   destroyHazardChart()
+  destroySocChart()
 })
 
 function getHazardChartOption(): echarts.EChartsOption {
@@ -361,6 +369,123 @@ function destroyHazardChart() {
     hazardChart = null
   }
 }
+
+function getSocChartOption(): echarts.EChartsOption {
+  return {
+    ...ANIMATION,
+    tooltip: createTooltip({
+      trigger: 'item',
+      formatter(params: any) {
+        return `${params.name}<br/>数量:${params.value}<br/>占比:${params.percent}%`
+      }
+    }),
+    legend: {
+      orient: 'vertical',
+      right: 4,
+      top: 'center',
+      itemWidth: 12,
+      itemHeight: 12,
+      icon: 'circle',
+      textStyle: {
+        color: '#5b6f8f',
+        fontSize: 15,
+        fontWeight: 600,
+        fontFamily: FONT_FAMILY
+      }
+    },
+    series: [
+      {
+        name: 'SOC卡类型',
+        type: 'pie',
+        radius: ['50%', '74%'],
+        center: ['34%', '54%'],
+        avoidLabelOverlap: true,
+        itemStyle: {
+          borderColor: 'rgba(255, 255, 255, 0.85)',
+          borderWidth: 2,
+          shadowBlur: 10,
+          shadowColor: 'rgba(31, 91, 184, 0.12)'
+        },
+        label: {
+          show: true,
+          color: '#4e6483',
+          fontSize: 13,
+          fontWeight: 700,
+          formatter: '{d}%'
+        },
+        labelLine: {
+          lineStyle: {
+            color: 'rgba(91, 111, 143, 0.5)'
+          },
+          length: 10,
+          length2: 8
+        },
+        data: permitStats.map((item) => ({
+          name: item.label,
+          value: item.value,
+          itemStyle: {
+            color: item.color
+          }
+        })),
+        emphasis: {
+          scale: true,
+          scaleSize: 6
+        }
+      }
+    ],
+    graphic: [
+      {
+        type: 'text',
+        left: '28.8%',
+        top: '43%',
+        style: {
+          text: 'SOC卡',
+
+          fill: '#6b7f9c',
+          fontSize: 18,
+          fontWeight: 700,
+          fontFamily: FONT_FAMILY
+        }
+      },
+      {
+        type: 'text',
+        left: '26.5%',
+        top: '50%',
+        textAlign: 'center',
+        style: {
+          text: `${permitStats.reduce((sum, item) => sum + item.value, 0)}`,
+
+          fill: '#114a9b',
+          fontSize: 30,
+          fontWeight: 700,
+          fontFamily: 'YouSheBiaoTiHei, sans-serif'
+        }
+      }
+    ]
+  }
+}
+
+function initSocChart() {
+  if (!socChartRef.value) return
+  if (socChart) {
+    socChart.dispose()
+  }
+  socChart = echarts.init(socChartRef.value, undefined, {
+    renderer: CHART_RENDERER
+  })
+  socChart.setOption(getSocChartOption(), true)
+}
+
+function resizeSocChart() {
+  socChart?.resize()
+}
+
+function destroySocChart() {
+  if (socChart) {
+    socChart.dispose()
+    socChart = null
+  }
+}
 </script>
 
 <template>
@@ -460,18 +585,9 @@ function destroyHazardChart() {
               <section class="panel board-panel kb-stage-card kb-stage-card--5">
                 <div class="panel-title">
                   <span class="icon-decorator"><span></span><span></span></span>
-                  作业许可实时监控
-                </div>
-                <div class="permit-grid">
-                  <div
-                    v-for="item in permitStats"
-                    :key="item.label"
-                    class="permit-card"
-                    :style="{ '--permit-accent': item.accent, '--permit-soft': item.soft } as any">
-                    <div class="permit-card__label">{{ item.label }}</div>
-                    <div class="permit-card__value">{{ item.value }}</div>
-                  </div>
+                  SOC卡类型
                 </div>
+                <div ref="socChartRef" class="soc-chart-panel"></div>
               </section>
 
               <section class="panel board-panel kb-stage-card kb-stage-card--6">
@@ -628,7 +744,7 @@ function destroyHazardChart() {
 
 .incident-panel {
   display: grid;
-  margin-top: 22px;
+  margin-top: 50px;
   grid-template-columns: 180px 1fr;
   align-items: center;
   gap: 28px;
@@ -738,38 +854,9 @@ function destroyHazardChart() {
   line-height: 1.55;
 }
 
-.permit-grid {
-  display: grid;
-  // margin-top: 32px;
-  padding: 28px;
-  grid-template-columns: repeat(2, minmax(0, 1fr));
-  gap: 20px;
-}
-
-.permit-card {
-  min-height: 128px;
-  padding: 28px 20px;
-  text-align: center;
-  background: linear-gradient(180deg, var(--permit-soft) 0%, rgb(255 255 255 / 18%) 100%);
-  border: 1px solid rgb(255 255 255 / 54%);
-  border-radius: 18px;
-  box-shadow:
-    inset 0 1px 0 rgb(255 255 255 / 68%),
-    0 8px 18px rgb(63 103 171 / 6%);
-}
-
-.permit-card__label {
-  font-size: 18px;
-  font-weight: 700;
-  color: #506684;
-}
-
-.permit-card__value {
-  margin-top: 18px;
-  font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 44px;
-  line-height: 1;
-  color: var(--permit-accent);
+.soc-chart-panel {
+  height: 220px;
+  // margin-top: 10px;
 }
 
 .qualification-panel {