Browse Source

ptw统计

yanghao 1 ngày trước cách đây
mục cha
commit
f9dcbbe501
3 tập tin đã thay đổi với 171 bổ sung4 xóa
  1. 2 2
      .env.local
  2. 8 0
      src/api/pms/qhse/index.ts
  3. 161 2
      src/views/pms/qhse/ptw/index.vue

+ 2 - 2
.env.local

@@ -3,8 +3,8 @@ NODE_ENV=development
 
 VITE_DEV=true
 
-# 请求路径  http://192.168.188.60:48080  https://iot.deepoil.cc:5443  http://172.26.0.56:48080  http://192.168.188.198:48080
-VITE_BASE_URL='https://iot.deepoil.cc:5443'
+# 请求路径  http://192.168.188.86:48080  https://iot.deepoil.cc:5443  http://172.26.0.56:48080  http://192.168.188.198:48080
+VITE_BASE_URL='http://192.168.188.86:48080'
 
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
 VITE_UPLOAD_TYPE=server

+ 8 - 0
src/api/pms/qhse/index.ts

@@ -490,6 +490,14 @@ export const QHSEPtwApi = {
   // 导出PTW管理 Excel
   exportPtw: async (params) => {
     return await request.download({ url: `/rq/qhse-ptw/export-excel`, params })
+  },
+  // 获取PTW分类
+  getPtwCategory: async (id) => {
+    return await request.get({ url: `/rq/qhse-ptw/type?deptId=${id}` })
+  },
+  // 获取传入区间范围内的每天的数量
+  getPtwCountByDateRange: async (data) => {
+    return await request.post({ url: `/rq/qhse-ptw/time`, data })
   }
 }
 

+ 161 - 2
src/views/pms/qhse/ptw/index.vue

@@ -3,6 +3,16 @@
     <!-- 左侧部门树 -->
     <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />
     <el-col :span="isLeftContentCollapsed ? 24 : 20" :xs="24">
+      <div class="ptw-stats mb-15px">
+        <div class="ptw-stats-card">
+          <div class="ptw-stats-card__label">作业票总数</div>
+          <div class="ptw-stats-card__value">{{ totalStaticCount }}</div>
+        </div>
+        <div class="ptw-stats-chart-card">
+          <div class="ptw-stats-card__label">作业票分类统计</div>
+          <Echart :height="220" :options="staticChartOptions" />
+        </div>
+      </div>
       <div class="bg-white rounded-sm px-2 py-2">
         <!-- 搜索工作栏 -->
         <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
@@ -527,6 +537,7 @@ import DeptTree from '@/views/system/user/DeptTree2.vue'
 import { handleTree, defaultProps } from '@/utils/tree'
 import * as DeptApi from '@/api/system/dept'
 import { ElMessageBox, ElMessage } from 'element-plus'
+import type { EChartsOption } from 'echarts'
 const deptList2 = ref<Tree[]>([]) // 树形结构
 import { formatDate } from '@/utils/formatTime'
 import { useUserStore } from '@/store/modules/user'
@@ -551,9 +562,16 @@ const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   ptwXh: '',
-  ptwNo: ''
+  ptwNo: '',
+  deptId: ''
 })
 
+type StaticItem = {
+  classify: string
+  count: number
+  sort?: number
+}
+
 const queryParams2 = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -673,6 +691,7 @@ const handleExport = async () => {
 /** 首页处理部门被点击 */
 const handleDeptNodeClick = async (row) => {
   queryParams.deptId = row.id
+  await getStatic()
   await getList()
 }
 
@@ -686,6 +705,7 @@ const handleQuery = () => {
 const resetQuery = () => {
   queryParams.deptId = ''
   queryFormRef.value?.resetFields()
+  getStatic()
   handleQuery()
 }
 
@@ -852,13 +872,104 @@ const extractFileName = (url: string): string => {
   }
 }
 
+let staticList = ref<StaticItem[]>([])
+const totalStaticCount = computed(() =>
+  staticList.value.reduce((sum: number, item: StaticItem) => sum + Number(item.count || 0), 0)
+)
+const staticChartOptions = computed<EChartsOption>(() => ({
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: 16,
+    right: 16,
+    top: 24,
+    bottom: 24,
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    data: staticList.value.map((item: StaticItem) => item.classify),
+    axisTick: {
+      show: false
+    },
+    axisLine: {
+      lineStyle: {
+        color: '#d9e2ef'
+      }
+    },
+    axisLabel: {
+      color: '#6b7280',
+      fontSize: 12,
+      interval: 0
+    }
+  },
+  yAxis: {
+    type: 'value',
+    axisLine: {
+      show: false
+    },
+    axisTick: {
+      show: false
+    },
+    axisLabel: {
+      color: '#94a3b8',
+      fontSize: 12
+    },
+    splitLine: {
+      lineStyle: {
+        color: '#edf2f7',
+        type: 'dashed'
+      }
+    }
+  },
+  series: [
+    {
+      type: 'bar',
+      barWidth: 32,
+      data: staticList.value.map((item: StaticItem) => item.count),
+      itemStyle: {
+        borderRadius: [8, 8, 0, 0],
+        color: {
+          type: 'linear',
+          x: 0,
+          y: 0,
+          x2: 0,
+          y2: 1,
+          colorStops: [
+            { offset: 0, color: '#79b8ff' },
+            { offset: 1, color: '#2f78f6' }
+          ]
+        }
+      },
+      label: {
+        show: true,
+        position: 'top',
+        color: '#2563eb',
+        fontSize: 12,
+        fontWeight: 700
+      }
+    }
+  ]
+}))
+async function getStatic() {
+  const deptId = queryParams.deptId || userStore.user.deptId
+  const res = await QHSEPtwApi.getPtwCategory(deptId)
+  staticList.value = Array.isArray(res)
+    ? [...res].sort((a: StaticItem, b: StaticItem) => (a.sort || 0) - (b.sort || 0))
+    : []
+}
+
 onMounted(async () => {
   getList()
   deptList2.value = handleTree(await DeptApi.getSimpleDeptList())
 
   const users = await getUserProfile()
   userInfo.value = users
-  console.log('xxxxxxxxxxxxxxxxxx', userInfo.value)
+  getStatic()
 })
 
 let personDialogVisible = ref(false)
@@ -1027,6 +1138,54 @@ const handleRadioChange2 = (row: any) => {
 </script>
 
 <style scoped>
+.ptw-stats {
+  display: grid;
+  grid-template-columns: 240px minmax(0, 1fr);
+  gap: 16px;
+}
+
+.ptw-stats-card,
+.ptw-stats-chart-card {
+  background: #fff;
+  border-radius: 8px;
+  padding: 16px;
+}
+
+.ptw-stats-card {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  min-height: 220px;
+  background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
+}
+
+.ptw-stats-card__label {
+  font-size: 14px;
+  color: #64748b;
+  margin-bottom: 12px;
+}
+
+.ptw-stats-card__value {
+  font-size: 42px;
+  line-height: 1;
+  font-weight: 700;
+  color: #1d4ed8;
+}
+
+.ptw-stats-chart-card {
+  min-width: 0;
+}
+
+@media (max-width: 768px) {
+  .ptw-stats {
+    grid-template-columns: 1fr;
+  }
+
+  .ptw-stats-card {
+    min-height: 160px;
+  }
+}
+
 .file-name-text {
   display: block;
   white-space: nowrap;