Răsfoiți Sursa

调整瑞鹰看板

Zimo 6 zile în urmă
părinte
comite
cdf96c6cd8

+ 5 - 5
src/views/pms/stat/rykb.vue

@@ -3,11 +3,11 @@ import { DESIGN_HEIGHT, DESIGN_WIDTH } from '@/utils/kb'
 import rysummary from './rykb/rysummary.vue'
 import safeday from './rykb/safeday.vue'
 import rydeviceStatus from './rykb/rydeviceStatus.vue'
-import zjfinish from './rykb/zjfinish.vue'
-import zjwork from './rykb/zjwork.vue'
+import zjStatsSwitch from './rykb/zjStatsSwitch.vue'
 import xjwork from './rykb/xjwork.vue'
 import rydeviceList from './rykb/rydeviceList.vue'
 import ryProductionBriefs from './rykb/ryProductionBriefs.vue'
+import rydeviceType from './rykb/rydeviceType.vue'
 
 defineOptions({
   name: 'IotRyStatt'
@@ -83,10 +83,10 @@ onUnmounted(() => {
           <rysummary class="kb-stage-card kb-stage-card--1" />
           <div class="w-full h-148 grid grid-rows-2 grid-cols-3 gap-3 mt-3">
             <rydeviceStatus class="kb-stage-card kb-stage-card--2" />
-            <safeday class="kb-stage-card kb-stage-card--3" />
+            <rydeviceType class="kb-stage-card kb-stage-card--6" />
             <rydeviceList class="kb-stage-card kb-stage-card--4 kb-stage-card--list" />
-            <zjfinish class="kb-stage-card kb-stage-card--5" />
-            <zjwork class="kb-stage-card kb-stage-card--6" />
+            <safeday class="kb-stage-card kb-stage-card--3" />
+            <zjStatsSwitch class="kb-stage-card kb-stage-card--5" />
             <xjwork class="kb-stage-card kb-stage-card--7" />
           </div>
           <ryProductionBriefs class="kb-stage-card kb-stage-card--8 kb-stage-card--list" />

+ 178 - 0
src/views/pms/stat/rykb/rydeviceType.vue

@@ -0,0 +1,178 @@
+<script lang="ts" setup>
+import * as echarts from 'echarts'
+import { ANIMATION, ChartItem, createTooltip, FONT_FAMILY, THEME } from '@/utils/kb'
+import { IotStatApi } from '@/api/pms/stat'
+
+const chartData = ref<ChartItem[]>([])
+
+const chartRef = ref<HTMLDivElement>()
+let chart: echarts.ECharts | null = null
+
+function getChartOption(data: ChartItem[]): echarts.EChartsOption {
+  const names = data.map((item) => item.name)
+  const values = data.map((item) => item.value)
+
+  return {
+    ...ANIMATION,
+    grid: { ...THEME.grid, right: 36 },
+    tooltip: createTooltip({
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow',
+        shadowStyle: {
+          color: THEME.split
+        }
+      }
+    }),
+    xAxis: {
+      type: 'value',
+      splitNumber: 4,
+      axisLine: {
+        show: false
+      },
+      axisTick: {
+        show: false
+      },
+      axisLabel: {
+        color: THEME.text.regular,
+        fontSize: 14,
+        fontFamily: FONT_FAMILY
+      },
+      splitLine: {
+        lineStyle: {
+          color: THEME.split,
+          type: 'dashed'
+        }
+      }
+    },
+    yAxis: {
+      type: 'category',
+      data: names,
+      inverse: true,
+      axisLine: {
+        show: false
+      },
+      axisTick: {
+        show: false
+      },
+      axisLabel: {
+        color: THEME.text.regular,
+        fontSize: 14,
+        margin: 16,
+        fontWeight: 500,
+        fontFamily: FONT_FAMILY
+      }
+    },
+    series: [
+      {
+        name: '设备类型',
+        type: 'bar',
+        data: values,
+        barWidth: 14,
+        showBackground: true,
+        backgroundStyle: {
+          color: THEME.split,
+          borderRadius: 999
+        },
+        itemStyle: {
+          borderRadius: 999,
+          shadowBlur: 12,
+          shadowColor: THEME.color.blue.bg,
+          color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+            { offset: 0, color: THEME.color.blue.light },
+            { offset: 0.5, color: THEME.color.blue.mid },
+            { offset: 1, color: THEME.color.blue.line }
+          ])
+        },
+        label: {
+          show: true,
+          position: 'right',
+          distance: 8,
+          color: THEME.color.blue.strong,
+          fontSize: 16,
+          fontWeight: 700,
+          fontFamily: FONT_FAMILY
+        },
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 16,
+            shadowColor: THEME.color.blue.shadow
+          }
+        }
+      }
+    ]
+  }
+}
+
+function initChart() {
+  if (!chartRef.value) return
+  if (chart) {
+    chart.dispose()
+  }
+  chart = echarts.init(chartRef.value, undefined, {
+    renderer: 'svg'
+  })
+  renderChart()
+}
+
+function renderChart() {
+  if (!chart) return
+
+  const data = chartData.value || []
+
+  chart.setOption(getChartOption(data), true)
+}
+
+function resizeChart() {
+  chart?.resize()
+}
+
+function destroyChart() {
+  if (chart) {
+    chart.dispose()
+    chart = null
+  }
+}
+
+async function loadChart() {
+  try {
+    const res = await IotStatApi.getDeviceTypeCount('ry')
+    chartData.value = Array.isArray(res)
+      ? res.map((item) => ({ name: item.category, value: item.value }))
+      : []
+    renderChart()
+  } catch (error) {
+    console.error('获取设备类型失败:', error)
+    chartData.value = []
+    renderChart()
+  }
+}
+
+onMounted(() => {
+  initChart()
+  loadChart()
+  window.addEventListener('resize', resizeChart)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', resizeChart)
+  destroyChart()
+})
+</script>
+
+<template>
+  <div class="panel flex flex-col">
+    <div class="panel-title h-9">
+      <div class="icon-decorator">
+        <span></span>
+        <span></span>
+      </div>
+      设备类别top
+    </div>
+    <div ref="chartRef" class="flex-1 min-h-0"></div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+@import url('@/styles/kb.scss');
+</style>

+ 66 - 0
src/views/pms/stat/rykb/zjStatsSwitch.vue

@@ -0,0 +1,66 @@
+<script lang="ts" setup>
+import zjfinish from './zjfinish.vue'
+import zjwork from './zjwork.vue'
+
+type ActivePanel = 'finish' | 'work'
+
+const activePanel = ref<ActivePanel>('finish')
+
+const panelOptions: Array<{ label: string; value: ActivePanel }> = [
+  {
+    label: '完成情况',
+    value: 'finish'
+  },
+  {
+    label: '工作量',
+    value: 'work'
+  }
+]
+
+const activeTitle = computed(() =>
+  activePanel.value === 'finish' ? '钻井完成情况' : '钻井工作量情况'
+)
+</script>
+
+<template>
+  <div class="panel flex flex-col">
+    <div class="panel-title h-9 flex items-center justify-between">
+      <div class="kb-panel-title-text flex items-center">
+        <div class="icon-decorator">
+          <span></span>
+          <span></span>
+        </div>
+        {{ activeTitle }}
+      </div>
+      <el-segmented v-model="activePanel" :options="panelOptions" size="small" class="zj-switch" />
+    </div>
+    <div class="flex-1 min-h-0">
+      <zjfinish v-if="activePanel === 'finish'" embedded />
+      <zjwork v-else embedded />
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+@import url('@/styles/kb.scss');
+
+.zj-switch {
+  --el-segmented-item-selected-color: #03409b;
+  --el-segmented-item-selected-bg-color: rgb(255 255 255 / 86%);
+  --el-segmented-bg-color: rgb(31 91 184 / 10%);
+  --el-segmented-item-hover-bg-color: rgb(255 255 255 / 56%);
+
+  min-height: 26px;
+  padding: 2px;
+  border: 1px solid rgb(31 91 184 / 12%);
+  transform: translateY(-2px);
+
+  :deep(.el-segmented__item) {
+    min-height: 22px;
+    padding: 0 8px;
+    font-size: 13px;
+    font-weight: 600;
+    color: #29527f;
+  }
+}
+</style>

+ 6 - 2
src/views/pms/stat/rykb/zjfinish.vue

@@ -11,6 +11,10 @@ import {
 } from '@/utils/kb'
 import { IotStatApi } from '@/api/pms/stat'
 
+defineProps<{
+  embedded?: boolean
+}>()
+
 const chartData = ref<ChartData>({
   xAxis: [],
   series: []
@@ -207,8 +211,8 @@ onUnmounted(() => {
 </script>
 
 <template>
-  <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+  <div :class="embedded ? 'h-full flex flex-col' : 'panel flex flex-col'">
+    <div v-if="!embedded" class="panel-title h-9">
       <div class="icon-decorator">
         <span></span>
         <span></span>

+ 6 - 2
src/views/pms/stat/rykb/zjwork.vue

@@ -11,6 +11,10 @@ import {
 } from '@/utils/kb'
 import { IotStatApi } from '@/api/pms/stat'
 
+defineProps<{
+  embedded?: boolean
+}>()
+
 const chartData = ref<ChartData>({
   xAxis: [],
   series: []
@@ -250,8 +254,8 @@ onUnmounted(() => {
 </script>
 
 <template>
-  <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+  <div :class="embedded ? 'h-full flex flex-col' : 'panel flex flex-col'">
+    <div v-if="!embedded" class="panel-title h-9">
       <div class="icon-decorator">
         <span></span>
         <span></span>