Sfoglia il codice sorgente

运行记录统计

yuanchao 1 mese fa
parent
commit
655fe838ec

+ 3 - 0
src/api/pms/iotopeationfill/index.ts

@@ -46,6 +46,9 @@ export const IotOpeationFillApi = {
   getIotOpeationFillPage1: async (params: any) => {
     return await request.get({ url: `/rq/iot-opeation-fill/page1`, params })
   },
+  getDeviceData: async (params: any) => {
+    return await request.get({ url: `/rq/iot-opeation-fill/countPage`, params })
+  },
 
   getFillRecordsPage: async (params: any) => {
     return await request.get({ url: `/rq/iot-opeation-fill/fillRecordPage`, params })

+ 3 - 0
src/api/pms/stat/index.ts

@@ -92,4 +92,7 @@ export const IotStatApi = {
   getDeptStatistics: async (params: any) => {
       return await request.get({ url: `/rq/iot-opeation-fill/getCount`, params })
   },
+  getDevSta: async (params: any) => {
+    return await request.get({ url: `/rq/iot-opeation-fill/getDeviceCount`, params })
+  },
 }

+ 25 - 0
src/router/modules/remaining.ts

@@ -185,6 +185,31 @@ const remainingRouter: AppRouteRecordRaw[] = [
           activeMenu: '/template/info'
         }
       },
+      {
+        path: 'template/detail/:deptId/:orderStatus',
+        component: () => import('@/views/pms/iotopeationfill/index.vue'),
+        name: 'FillOrderInfo1',
+        meta: {
+          title: t('rem.FillInInformation'),
+          noCache: false,
+          hidden: true,
+          canTo: true,
+          activeMenu: '/template/info'
+        }
+      },
+      {
+        path: 'template/detail/:deptId/:isFill',
+        component: () => import('@/views/pms/iotopeationfill/StatisticsForm.vue' +
+        ''),
+        name: 'FillOrderInfo2',
+        meta: {
+          title: t('rem.FillInInformation'),
+          noCache: false,
+          hidden: true,
+          canTo: true,
+          activeMenu: '/template/info'
+        }
+      },
       {
         path: 'template/detail/:id/:deviceid/:status/:deptid/:createtime',
         component: () => import('@/views/pms/device/record/RecordInfo.vue'),

+ 1 - 0
src/utils/dict.ts

@@ -110,6 +110,7 @@ export enum DICT_TYPE {
   IOT_DEVICE_STATUS = 'iot_device_status', // IOT 设备状态
   PMS_INSPECT_ORDER_STATUS = "pms_inspect_order_status",
   OPERATION_FILL_ORDER_STATUS = "operation_fill_order_status",
+  OPERATION_FILL_DEVICE_STATUS = "operation_fill_device_status",
   PMS_INSPECT_UNIT = "pms_inspect_unit",
   PMS_MAIN_STATUS_NO = 'pms_maintain_status_no',
   PMS_MAIN_STATUS = 'pms_maintain_status',

+ 238 - 0
src/views/pms/iotopeationfill/StatisticsForm.vue

@@ -0,0 +1,238 @@
+<template>
+  <el-row :gutter="20">
+    <el-col :span="4" :xs="24">
+      <ContentWrap class="h-1/1">
+        <DeptTree @node-click="handleDeptNodeClick" />
+      </ContentWrap>
+    </el-col>
+    <el-col :span="20" :xs="24">
+      <ContentWrap>
+        <!-- 搜索工作栏 -->
+        <el-form
+          class="-mb-15px"
+          :model="queryParams"
+          ref="queryFormRef"
+          :inline="true"
+          label-width="68px"
+        >
+          <el-form-item label="查询条件" prop="orderName">
+            <el-input
+              v-model="queryParams.orderName"
+              placeholder="请输入设备负责人"
+              clearable
+              @keyup.enter="handleQuery"
+              class="!w-240px"
+            />
+          </el-form-item>
+          <el-form-item label="创建时间" prop="createTime">
+            <el-date-picker
+              v-model="queryParams.createTime"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              type="daterange"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+              class="!w-220px"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+            <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+            <el-button
+              type="success"
+              plain
+              @click="handleExport"
+              :loading="exportLoading"
+              v-hasPermi="['rq:iot-opeation-fill:export']"
+            >
+              <Icon icon="ep:download" class="mr-5px" /> 导出
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </ContentWrap>
+      <!-- 列表 -->
+      <ContentWrap>
+        <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+          <el-table-column :label="t('iotDevice.serial')" width="70" align="center">
+            <template #default="scope">
+              {{ scope.$index + 1 }}
+            </template>
+          </el-table-column>
+          <el-table-column label="工单名称" align="center" prop="orderName" />
+          <el-table-column label="所属组织" align="center" prop="deptName" />
+          <el-table-column label="设备负责人" align="center" prop="nickname" />
+          <el-table-column label="设备编号" align="center" prop="deviceCode" />
+          <el-table-column label="设备名称" align="center" prop="deviceName" />
+          <el-table-column label="是否填写" align="center" prop="isFill">
+            <template #default="scope">
+              <dict-tag :type="DICT_TYPE.OPERATION_FILL_DEVICE_STATUS" :value="scope.row.isFill" />
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="创建时间"
+            align="center"
+            prop="createTime"
+            :formatter="dateFormatter"
+            width="180px"
+          />
+        </el-table>
+        <Pagination
+          :total="total"
+          v-model:page="queryParams.pageNo"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </ContentWrap>
+    </el-col>
+  </el-row>
+
+
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { IotOpeationFillApi, IotOpeationFillVO } from '@/api/pms/iotopeationfill'
+import IotOpeationFillForm from './IotOpeationFillForm.vue'
+import * as UserApi from "@/api/system/user";
+import {defaultProps,handleTree} from "@/utils/tree";
+import * as DeptApi from "@/api/system/dept";
+import * as PostApi from "@/api/system/post";
+import {onMounted, ref} from "vue";
+import {DeptTreeItem} from "@/api/system/dept";
+import DeptTree from "@/views/system/user/DeptTree.vue";
+import {useUserStore} from "@/store/modules/user";
+import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
+/** 运行记录填报 列表 */
+defineOptions({ name: 'StatisticsForm' })
+const deptList = ref<DeptTreeItem[]>([]) // 树形结构部门列表
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<IotOpeationFillVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const { params, name } = useRoute() // 查询参数
+const deptId = params.deptId;
+const isFill = params.isFill;
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const selectedDeptId = ref(null);  // 通过store存储的部门id 由父组件传递过来
+
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  deviceCode: undefined,
+  deviceName: undefined,
+  fillContent: undefined,
+  deviceType: undefined,
+  deviceComponent: undefined,
+  deptId: undefined,
+  orgName: undefined,
+  proId: undefined,
+  proName: undefined,
+  teamId: undefined,
+  teamName: undefined,
+  dutyName: undefined,
+  creDate: [],
+  createTime: [],
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+const handleDeptNodeClick = async (row) => {
+  queryParams.deptId = row.id
+  await getList()
+}
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await IotOpeationFillApi.getDeviceData(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = type
+  formType.value = type
+  queryParams.deptId = id;
+  // 修改时,设置数据
+  if (id) {
+    getList();
+  }
+
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryParams.deptId = useUserStore().getUser.deptId;
+  queryParams.createTime = null
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await IotOpeationFillApi.deleteIotOpeationFill(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await IotOpeationFillApi.exportIotOpeationFill(queryParams)
+    download.excel(data, '运行记录填报.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(async () => {
+  if (deptId) {
+    queryParams.deptId = deptId;
+  }
+  if (isFill == 2) {
+    queryParams.isFill = null;
+  } else {
+    if (isFill) {
+      queryParams.isFill = isFill;
+    }
+  }
+  getList()
+  deptList.value = handleTree(await DeptApi.getSimpleDeptList());
+})
+</script>

+ 14 - 0
src/views/pms/iotopeationfill/index.vue

@@ -167,6 +167,9 @@ import DeptTree from "@/views/system/user/DeptTree.vue";
 import {IotOpeationFillApi, IotOpeationFillVO} from "@/api/pms/iotopeationfill";
 import {useUserStore} from "@/store/modules/user";
 const { push } = useRouter()
+const { params, name } = useRoute() // 查询参数
+const deptId= params.deptId;
+const orderStatus = params.orderStatus;
 /** 巡检工单 列表 */
 defineOptions({ name: 'IotOpeationFill' })
 
@@ -186,6 +189,7 @@ const queryParams = reactive({
   createTime: [],
   deptId: useUserStore().getUser.deptId,
   deviceIds: undefined,
+  orderStatus:undefined
   //userId:useUserStore().getUser.id
 })
 const queryFormRef = ref() // 搜索的表单
@@ -274,6 +278,16 @@ const handleExport = async () => {
 
 /** 初始化 **/
 onMounted(() => {
+  if(deptId != null){
+
+    queryParams.deptId = deptId;
+  }
+  if(orderStatus === 3){
+    queryParams.orderStatus = null
+  }
+  if(orderStatus != null && orderStatus != 3){
+    queryParams.orderStatus = orderStatus;
+  }
   getList()
 })
 </script>

+ 89 - 14
src/views/pms/iotopeationfill/statistics .vue → src/views/pms/iotopeationfill/statistics.vue

@@ -59,33 +59,33 @@
   </el-row>
   <!-- 第二行:图表行 -->
   <el-row :gutter="16" class="mb-4">
-    <el-col :span="24">
+    <el-col :span="12">
       <el-card class="chart-card" shadow="never">
         <template #header>
           <div class="flex items-center">
-            <span class="text-base font-medium text-gray-600">运行记录填写统计</span>
+            <span class="text-base font-medium text-gray-600">运行记录工单统计</span>
           </div>
         </template>
         <el-row class="h-[220px]">
-          <el-col :span="6" class="flex flex-col items-center">
+          <el-col :span="6" class="flex flex-col items-center" @click="openFill(queryParams.deptId,3)">
             <div ref="reportingChartRef" class="h-[160px] w-full"></div>
-            <div class="text-center mt-2">
+            <div class="text-center mt-2"  >
               <span class="text-sm text-gray-600">总数</span>
             </div>
           </el-col>
-          <el-col :span="6" class="flex flex-col items-center">
+          <el-col :span="6" class="flex flex-col items-center" @click="openFill(queryParams.deptId,1)">
             <div ref="dealFinishedChartRef" class="h-[160px] w-full"></div>
             <div class="text-center mt-2">
               <span class="text-sm text-gray-600">已填写</span>
             </div>
           </el-col>
-          <el-col :span="6" class="flex flex-col items-center">
+          <el-col :span="6" class="flex flex-col items-center" @click="openFill(queryParams.deptId,0)">
             <div ref="transOrderChartRef" class="h-[160px] w-full"></div>
             <div class="text-center mt-2">
               <span class="text-sm text-gray-600">未填写</span>
             </div>
           </el-col>
-          <el-col :span="6" class="flex flex-col items-center">
+          <el-col :span="6" class="flex flex-col items-center" @click="openFill(queryParams.deptId,2)">
             <div ref="writeChartRef" class="h-[160px] w-full"></div>
             <div class="text-center mt-2">
               <span class="text-sm text-gray-600">填写中</span>
@@ -94,6 +94,35 @@
         </el-row>
       </el-card>
     </el-col>
+    <el-col :span="12">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">运行记录设备统计</span>
+          </div>
+        </template>
+        <el-row class="h-[220px]">
+          <el-col :span="6" class="flex flex-col items-center" @click="openForm(queryParams.deptId,2)">
+            <div ref="reportingChartRef1" class="h-[160px] w-full"></div>
+            <div class="text-center mt-2"  >
+              <span class="text-sm text-gray-600">总数</span>
+            </div>
+          </el-col>
+          <el-col :span="6" class="flex flex-col items-center" @click="openForm(queryParams.deptId,1)">
+            <div ref="dealFinishedChartRef1" class="h-[160px] w-full"></div>
+            <div class="text-center mt-2">
+              <span class="text-sm text-gray-600">已填写</span>
+            </div>
+          </el-col>
+          <el-col :span="6" class="flex flex-col items-center" @click="openForm(queryParams.deptId,0)">
+            <div ref="transOrderChartRef1" class="h-[160px] w-full"></div>
+            <div class="text-center mt-2">
+              <span class="text-sm text-gray-600">待填写</span>
+            </div>
+          </el-col>
+        </el-row>
+      </el-card>
+    </el-col>
   </el-row>
 
   <!-- 第三行:消息统计行 -->
@@ -102,14 +131,13 @@
       <el-card class="chart-card" shadow="never">
         <template #header>
           <div class="flex items-center justify-between">
-            <span class="text-base font-medium text-gray-600">部门数量统计</span>
+            <span class="text-base font-medium text-gray-600">运行记录工单统计</span>
           </div>
         </template>
         <div ref="chartContainer" class="h-[300px]"></div>
       </el-card>
     </el-col>
   </el-row>
-
 </template>
 
 <script setup lang="ts" name="Index">
@@ -139,7 +167,8 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import {useUserStore} from "@/store/modules/user";
 // 导入部门数据类型
 import { DeptTreeItem } from '@/api/system/dept'
-
+import StatisticsForm from './StatisticsForm.vue'
+const { push } = useRouter()
 // 初始化echarts
 echarts.use([
   TooltipComponent,
@@ -178,6 +207,7 @@ const dateRange = ref<[Date, Date] | null>(null)
 const queryParams = reactive({
   startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
   endTime: Date.now(), // 设置默认结束时间为当前时间
+  createTime: [],
   deptId: null, // 选中的部门ID
   status: null // 填写状态
 })
@@ -185,9 +215,24 @@ const queryParams = reactive({
 const handleQuery = () => {
   // 重新获取数据
   getStats()
+  getDevStats()
   initChart()
 }
 
+const formRef = ref()
+const openForm = (deptId?:string,isFill?:string) => {
+  /*const type = '填写设备明细';
+  const id = queryParams.deptId
+  formRef.value.open(type,id)*/
+
+  push({ name: 'FillOrderInfo2',params:{deptId,isFill}})
+}
+const openFill = (deptId?:string,orderStatus?:string) => {
+  push({ name: 'FillOrderInfo1',params:{deptId,orderStatus}})
+}
+
+
+
 const resetQuery = () => {
   // 重置查询参数
   queryParams.startTime = Date.now() - 7 * 24 * 60 * 60 * 1000
@@ -200,13 +245,17 @@ const resetQuery = () => {
   initChart()
 }
 
+//运行记录工单统计
 const reportingChartRef = ref() // 在线设备统计的图表
 const dealFinishedChartRef = ref() // 离线设备统计的图表
 const transOrderChartRef = ref() // 待激活设备统计的图表
-const orderFinishChartRef = ref()
-const deviceMessageCountChartRef = ref() // 上下行消息量统计的图表
 const writeChartRef = ref() // 待填写图表
-const finishedChartRef = ref() // 已完成图表
+
+//运行记录设备统计
+const reportingChartRef1 = ref() // 在线设备统计的图表
+const dealFinishedChartRef1 = ref() // 离线设备统计的图表
+const transOrderChartRef1 = ref() // 待激活设备统计的图表
+
 
 // 基础统计数据
 const statsData = ref<IotStatisticsSummaryRespVO>({
@@ -242,7 +291,7 @@ const total = ref({
 })
 
 const status = ref<IotStatusItem[]>([])
-
+const status1 = ref<IotStatusItem[]>([])
 // 定义状态项接口
 interface IotStatusItem {
   totalCount: number
@@ -315,29 +364,54 @@ const getStats = async () => {
     initCharts()
   })
 }
+const getDevStats = async () => {
+  // 获取基础统计数据
+  // 获取部门统计数据
+  IotStatApi.getDevSta(queryParams).then((res) => {
+    status1.value = res.totalList || [];
+    initChart()
+    initCharts()
+  })
+}
 
 /** 初始化图表 */
 const initCharts = () => {
   // 使用数组的第一个元素(如果存在)
   const firstStatus = status.value[0] || {}
+  const firstStatus1 = status1.value[0] || {}
   // 上报中
   initGaugeChart(
     reportingChartRef.value,
     firstStatus.totalCount === undefined ? 0 : firstStatus.totalCount,
     '#0d9'
   )
+  initGaugeChart(
+    reportingChartRef1.value,
+    firstStatus1.totalCount === undefined ? 0 : firstStatus1.totalCount,
+    '#0d9'
+  )
   // 处理完成
   initGaugeChart(
     dealFinishedChartRef.value,
     firstStatus.filledCount === undefined ? 0 : firstStatus.filledCount,
     '#f50'
   )
+  initGaugeChart(
+    dealFinishedChartRef1.value,
+    firstStatus1.filledCount === undefined ? 0 : firstStatus1.filledCount,
+    '#f50'
+  )
   // 转工单
   initGaugeChart(
     transOrderChartRef.value,
     firstStatus.unfilledCount === undefined ? 0 : firstStatus.unfilledCount,
     '#05b'
   )
+  initGaugeChart(
+    transOrderChartRef1.value,
+    firstStatus1.unfilledCount === undefined ? 0 : firstStatus1.unfilledCount,
+    '#05b'
+  )
   // 待填写
   initGaugeChart(
     writeChartRef.value,
@@ -525,6 +599,7 @@ const handleResize = () => {
 onMounted(async () => {
   queryParams.deptId = useUserStore().getUser.deptId;
   getStats()
+  getDevStats();
   deptList.value = handleTree(await DeptApi.getSimpleDeptList())
 })