From 2f0009c750de4d47a18cce4a5a403fa83ba0c209 Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期三, 02 七月 2025 08:58:27 +0800
Subject: [PATCH] feat(report): 新增设备稼动率统计功能

---
 eims-ui/apps/web-antd/src/api/eims/report/index.ts                                            |    7 +
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java     |    2 
 eims-ui/apps/web-antd/src/views/eims/equ-efficency/index.vue                                  |   93 ++++++++++++++++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java    |    9 +
 eims-ui/apps/web-antd/src/views/eims/equ-efficency/data.tsx                                   |   34 ++++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInspectStMapper.java     |   17 +++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java |   69 +++++++++++++
 eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue                                    |    2 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java         |    8 +
 9 files changed, 239 insertions(+), 2 deletions(-)

diff --git a/eims-ui/apps/web-antd/src/api/eims/report/index.ts b/eims-ui/apps/web-antd/src/api/eims/report/index.ts
index 84ae85c..7b637de 100644
--- a/eims-ui/apps/web-antd/src/api/eims/report/index.ts
+++ b/eims-ui/apps/web-antd/src/api/eims/report/index.ts
@@ -1,6 +1,7 @@
 import { requestClient } from '#/api/request';
 
 enum Api {
+  equEfficiency = '/eims/report/equEfficiency',
   insp = '/eims/report/insp',
   maint = '/eims/report/maint',
 }
@@ -26,3 +27,9 @@
   return requestClient.get<any[]>(Api.maint, { params });
 }
 
+/**
+ * 鏌ヨ璁惧绋煎姩鐜囧垪琛�
+ */
+export function getEquEfficiency() {
+  return requestClient.get<any[]>(Api.equEfficiency);
+}
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-efficency/data.tsx b/eims-ui/apps/web-antd/src/views/eims/equ-efficency/data.tsx
new file mode 100644
index 0000000..df172ef
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-efficency/data.tsx
@@ -0,0 +1,34 @@
+import type { VxeGridProps } from '#/adapter/vxe-table';
+import { ref } from 'vue';
+import dayjs from 'dayjs';
+import { type FormSchemaGetter } from '#/adapter/form';
+
+export const querySchema: FormSchemaGetter = () => [
+  {
+    component: 'DatePicker',
+    componentProps: {
+      picker: 'year',
+      format: 'YYYY',
+      valueFormat: 'YYYY',
+      placeholder: '璇烽�夋嫨骞翠唤',
+      allowClear: true,
+      defaultValue: dayjs().format('YYYY'),
+      getPopupContainer: (triggerNode: HTMLElement) => triggerNode.parentNode as HTMLElement
+    },
+    fieldName: 'selectYear',
+    defaultValue: dayjs().format('YYYY'),
+    label: '骞翠唤閫夋嫨'
+  }
+];
+
+export function getEfficiencyColumns() {
+  const months = Array.from({ length: 12 }, (_, i) => `${i + 1}鏈坄);
+  const columns: VxeGridProps['columns'] = [
+    { title: '椤圭洰', field: 'item', width: 160, fixed: 'left' },
+    ...months.map(month => ({ title: month, field: month, align: 'center' as const })),
+    { title: '鍏ㄥ勾鍚堣', field: 'total', align: 'center' as const }
+  ];
+  return columns;
+}
+
+export const columns = ref<VxeGridProps['columns']>(getEfficiencyColumns()); 
\ No newline at end of file
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-efficency/index.vue b/eims-ui/apps/web-antd/src/views/eims/equ-efficency/index.vue
new file mode 100644
index 0000000..a0eefab
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-efficency/index.vue
@@ -0,0 +1,93 @@
+<script setup lang="ts">
+import { onMounted, ref, toRaw, computed } from 'vue';
+
+import { Page, type VbenFormProps } from '@vben/common-ui';
+
+import { Space } from 'ant-design-vue';
+
+import { useVbenVxeGrid, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
+import { getEquEfficiency } from '#/api/eims/report';
+
+import { columns, querySchema } from './data';
+
+const selYear = ref('');
+
+const formOptions: VbenFormProps = {
+  commonConfig: {
+    labelWidth: 80,
+    componentProps: {
+      allowClear: true
+    }
+  },
+  schema: querySchema(),
+  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
+  handleReset: async () => {
+    const { formApi, reload } = tableApi;
+    await formApi.resetForm();
+    const formValues = formApi.form.values;
+    formApi.setLatestSubmissionValues(formValues);
+    await reload(formValues);
+  }
+};
+
+const gridOptions: VxeGridProps = {
+  border: true,
+  size: 'mini',
+  columns: columns.value,
+  height: 'auto',
+  keepSource: true,
+  proxyConfig: {
+    ajax: {
+      query: async (_ctx, formValues = {}) => {
+        const params = toRaw(formValues);
+        return await getEquEfficiency(params);
+      }
+    }
+  },
+  rowConfig: {
+    isHover: true,
+    keyField: 'item'
+  },
+  id: 'equ-efficency-index'
+};
+
+const [BasicTable, tableApi] = useVbenVxeGrid({
+  formOptions,
+  gridOptions,
+  gridEvents: {
+    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
+  }
+});
+
+onMounted(() => {
+  tableApi.formApi.updateSchema([
+    {
+      component: 'DatePicker',
+      componentProps: {
+        onChange: (sYear: string) => {
+          selYear.value = sYear;
+        }
+      },
+      fieldName: 'selectYear'
+    }
+  ]);
+  // 鍒濆鍖栧勾浠�
+  selYear.value = tableApi.formApi.form.values.selectYear;
+});
+
+const tableTitle = computed(() => `${selYear.value || new Date().getFullYear()}骞寸敓浜ц澶囨甯歌繍杞巼`);
+</script>
+
+<template>
+  <Page :auto-content-height="true">
+    <div class="flex h-full gap-[8px]">
+      <BasicTable class="flex-1 overflow-hidden" :table-title="tableTitle">
+        <template #toolbar-tools>
+          <Space>
+            <span class="ml-4 mr-2">绋煎姩鐜� = (鎬昏繍琛屾椂闂�-鍋滄満鏃堕棿) 梅 鎬昏繍琛屾椂闂� 脳 100%</span>
+          </Space>
+        </template>
+      </BasicTable>
+    </div>
+  </Page>
+</template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue b/eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue
index bc56f0e..2aca43a 100644
--- a/eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/insp-report/index.vue
@@ -83,7 +83,7 @@
           pageNum: page.currentPage,
           pageSize: page.pageSize,
           ...params
-        });;
+        });
       }
     }
   },
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java
index 7e71d80..962a35a 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/ReportController.java
@@ -47,4 +47,13 @@
         return reportService.queryMaintList(queryParams, pageQuery);
     }
 
+    /**
+     * 鏌ヨ璁惧绋煎姩鐜囩粺璁″垪琛�
+     */
+    @SaCheckPermission("eims:equEfficiency:list")
+    @GetMapping("/equEfficiency")
+    public TableDataInfo<Map<String,Object>> equEfficiency(@RequestParam Map<String, Object> queryParams, PageQuery pageQuery) {
+        return reportService.queryEquEfficiencyList(queryParams, pageQuery);
+    }
+
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java
index 73aa548..0c31efe 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java
@@ -50,7 +50,7 @@
         planBoQueryWrapper.eq("ip.status", DictConstants.SYS_NORMAL_DISABLE_DETAIL.NORMAL)
             .eq("equ.status", DictConstants.EIMS_EQU_STATUS_DETAIL.SHIYONG);
         // 澧炲姞杩囨护鏉′欢 涓婃鐢熸垚鏃ユ湡灏忎簬褰撳墠鏃ユ湡
-        planBoQueryWrapper.and(wrapper -> wrapper.lt("ip.insp_next_time", DateUtils.getDate()).or().isNull("ip.insp_next_time"));
+        planBoQueryWrapper.and(wrapper -> wrapper.le("ip.insp_next_time", DateUtils.getDate()).or().isNull("ip.insp_next_time"));
 //        // 杩囨护娌℃湁涓嬫杩愯鏃堕棿
 //        planBoQueryWrapper.isNotNull(EimsInspectPlan::getInspNextTime);
 //        // 杩囨护娌℃湁鐐规鍛ㄦ湡鐨勬暟鎹�
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInspectStMapper.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInspectStMapper.java
index e82f58e..2adf3d4 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInspectStMapper.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInspectStMapper.java
@@ -4,11 +4,15 @@
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.dromara.eims.domain.EimsInspectSt;
 import org.dromara.eims.domain.EimsMaintSt;
 import org.dromara.eims.domain.vo.EimsInspectStVo;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 import org.dromara.eims.domain.vo.EimsMaintStVo;
+
+import java.util.List;
+import java.util.Map;
 
 /**
  * 鐐规姹囨�籑apper鎺ュ彛
@@ -19,4 +23,17 @@
 public interface EimsInspectStMapper extends BaseMapperPlus<EimsInspectSt, EimsInspectStVo> {
     Page<EimsInspectStVo> selectInspStList(@Param("page") Page<EimsInspectStVo> page, @Param(Constants.WRAPPER) Wrapper<EimsInspectSt> queryWrapper);
 
+    @Select({
+        "<script>",
+        "SELECT",
+        "  MONTH(plan_time) AS month,",
+        "  SUM(run_times) AS runTimes,",
+        "  SUM(fault_times) AS faultTimes",
+        "FROM eims_inspect_st",
+        "WHERE plan_time BETWEEN #{start} AND #{end}",
+        "  AND type = 'Day'",
+        "GROUP BY MONTH(plan_time)",
+        "</script>"
+    })
+    List<Map<String, Object>> statEquEfficiency(@Param("start") String start, @Param("end") String end);
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java
index 3036927..033483c 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IReportService.java
@@ -30,4 +30,12 @@
      * @return
      */
     TableDataInfo<Map<String, Object>> queryMaintList(Map<String, Object> queryParams, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ璁惧绋煎姩鐜囩粺璁�
+     * @param queryParams
+     * @param pageQuery
+     * @return
+     */
+    TableDataInfo<Map<String, Object>> queryEquEfficiencyList(Map<String, Object> queryParams, PageQuery pageQuery);
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java
index 2a5c4a6..d103bce 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/ReportServiceImpl.java
@@ -1,9 +1,11 @@
 package org.dromara.eims.service.impl;
 
+import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.utils.DateUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -318,4 +320,71 @@
 
         return item;
     }
+
+    @Override
+    public TableDataInfo<Map<String, Object>> queryEquEfficiencyList(Map<String, Object> queryParams, PageQuery pageQuery) {
+        Integer selectYear = getYearFromParams(queryParams);
+        String start = Year.of(selectYear).atDay(1).toString(); // yyyy-MM-dd
+        String end = Year.of(selectYear).atDay(Year.of(selectYear).length()).toString();
+
+        List<Map<String, Object>> statList = inspectStMapper.statEquEfficiency(start, end);
+
+        // 缁勮缁熻缁撴灉
+        Map<Integer, Integer> runTimes = new HashMap<>();
+        Map<Integer, Integer> faultTimes = new HashMap<>();
+        Map<Integer, Integer> totalTimes = new HashMap<>();
+        int runTotal = 0, faultTotal = 0, totalTotal = 0;
+
+        for (Map<String, Object> row : statList) {
+            int month = Integer.parseInt(row.get("month").toString());
+            int run = row.get("runTimes") == null ? 0 : Integer.parseInt(row.get("runTimes").toString());
+            int fault = row.get("faultTimes") == null ? 0 : Integer.parseInt(row.get("faultTimes").toString());
+            int total = run + fault;
+            runTimes.put(month, run);
+            faultTimes.put(month, fault);
+            totalTimes.put(month, total);
+            runTotal += run;
+            faultTotal += fault;
+            totalTotal += total;
+        }
+
+        // 缁勮杩斿洖鏁版嵁锛堝悓鍓嶏級
+        String targetValue = "98.00%";
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        Map<String, Object> row1 = new LinkedHashMap<>(); // 姝e父杩愯浆鏃堕棿
+        Map<String, Object> row2 = new LinkedHashMap<>(); // 鎬昏繍杞椂闂�
+        Map<String, Object> row3 = new LinkedHashMap<>(); // 鏁呴殰鏃堕棿
+        Map<String, Object> row4 = new LinkedHashMap<>(); // 鐩爣鍊�
+        Map<String, Object> row5 = new LinkedHashMap<>(); // 姝e父杩愯浆鐜囷紙绋煎姩鐜囷級
+
+        row1.put("item", "姝e父杩愯浆鏃堕棿");
+        row2.put("item", "鎬昏繍杞椂闂�");
+        row3.put("item", "鏁呴殰鏃堕棿");
+        row4.put("item", "鐩爣鍊�");
+        row5.put("item", "姝e父杩愯浆鐜囷紙绋煎姩鐜囷級");
+
+        for (int m = 1; m <= 12; m++) {
+            row1.put(m + "鏈�", runTimes.getOrDefault(m, 0));
+            row2.put(m + "鏈�", totalTimes.getOrDefault(m, 0));
+            row3.put(m + "鏈�", faultTimes.getOrDefault(m, 0));
+            row4.put(m + "鏈�", targetValue);
+            int run = runTimes.getOrDefault(m, 0);
+            int total = totalTimes.getOrDefault(m, 0);
+            String eff = total > 0 ? String.format("%.2f%%", run * 100.0 / total) : "-";
+            row5.put(m + "鏈�", eff);
+        }
+        row1.put("total", runTotal);
+        row2.put("total", totalTotal);
+        row3.put("total", faultTotal);
+        row4.put("total", targetValue);
+        row5.put("total", totalTotal > 0 ? String.format("%.2f%%", runTotal * 100.0 / totalTotal) : "-");
+
+        resultList.add(row1);
+        resultList.add(row2);
+        resultList.add(row3);
+        resultList.add(row4);
+        resultList.add(row5);
+
+        return TableDataInfo.build(resultList);
+    }
 }

--
Gitblit v1.9.3