From beaed6d077e7c3e9abfad68acb8c587835b5a406 Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期六, 12 四月 2025 16:17:16 +0800
Subject: [PATCH] feat(eims): 添加点检计划和保养计划的导入功能

---
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/MaintCheckItemImportListener.java   |  118 ++++
 eims-ui/apps/web-antd/src/api/eims/insp-plan/index.ts                                                  |   28 +
 eims/ruoyi-admin/src/main/resources/template/by.xls                                                    |    0 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/InspectCheckItemVo.java            |   32 +
 eims-ui/apps/web-antd/src/views/eims/insp-plan/index.vue                                               |   18 
 eims-ui/apps/web-antd/src/views/eims/insp-plan/insp-plan-import-modal.vue                              |  112 ++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EasyExcelCellListener.java          |   44 +
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectPlanServiceImpl.java |   70 ++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsMaintPlanServiceImpl.java   |  175 +++++++
 eims-ui/apps/web-antd/src/views/eims/maint-plan/maint-plan-import-modal.vue                            |  112 ++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsMaintPlanController.java      |   60 ++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsMaintPlanService.java           |    5 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/MaintCheckItemVo.java              |   95 +++
 eims-ui/apps/web-antd/src/api/eims/maint-plan/index.ts                                                 |   27 +
 eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx                                                |  284 +++++-----
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/InspectCheckItemImportListener.java |  147 ++++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectPlanService.java         |    3 
 eims-ui/apps/web-antd/src/views/eims/maint-plan/index.vue                                              |   18 
 eims/ruoyi-admin/src/main/resources/template/dj.xlsx                                                   |    0 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectPlanController.java    |   53 ++
 20 files changed, 1,244 insertions(+), 157 deletions(-)

diff --git a/eims-ui/apps/web-antd/src/api/eims/insp-plan/index.ts b/eims-ui/apps/web-antd/src/api/eims/insp-plan/index.ts
index 792501d..075d144 100644
--- a/eims-ui/apps/web-antd/src/api/eims/insp-plan/index.ts
+++ b/eims-ui/apps/web-antd/src/api/eims/insp-plan/index.ts
@@ -1,14 +1,15 @@
 import type { InspectPlanVO } from './model';
 
 import type { ID, IDS } from '#/api/common';
-
-import { commonExport } from '#/api/helper';
+import { commonExport, ContentTypeEnum } from '#/api/helper';
 import { requestClient } from '#/api/request';
 
 enum Api {
   inspectPlanExport = '/eims/inspectPlan/export',
   inspectPlanList = '/eims/inspectPlan/list',
-  root = '/eims/inspectPlan'
+  root = '/eims/inspectPlan',
+  inspectPlanImport = '/eims/inspectPlan/importData',
+  inspectPlanImportTemplate = '/eims/inspectPlan/importTemplate'
 }
 
 /**
@@ -61,3 +62,24 @@
 export function inspPlanExport(data: any) {
   return commonExport(Api.inspectPlanExport, data);
 }
+
+/**
+ * 涓嬭浇鐐规璁″垝瀵煎叆妯℃澘
+ */
+export function downloadImportTemplate() {
+  return commonExport(Api.inspectPlanImportTemplate);
+}
+
+/**
+ * 浠巈xcel瀵煎叆鐐规璁″垝鏁版嵁
+ * @param data
+ * @returns void
+ */
+export function inspPlanImportData(data: any) {
+  return requestClient.post<{ code: number; msg: string }>(Api.inspectPlanImport, data, {
+    headers: {
+      'Content-Type': ContentTypeEnum.FORM_DATA
+    },
+    isTransformResponse: false
+  });
+}
diff --git a/eims-ui/apps/web-antd/src/api/eims/maint-plan/index.ts b/eims-ui/apps/web-antd/src/api/eims/maint-plan/index.ts
index bba8da4..9ff0fff 100644
--- a/eims-ui/apps/web-antd/src/api/eims/maint-plan/index.ts
+++ b/eims-ui/apps/web-antd/src/api/eims/maint-plan/index.ts
@@ -2,13 +2,15 @@
 
 import type { ID, IDS } from '#/api/common';
 
-import { commonExport } from '#/api/helper';
+import { commonExport, ContentTypeEnum } from '#/api/helper';
 import { requestClient } from '#/api/request';
 
 enum Api {
   maintPlanExport = '/eims/maintPlan/export',
   maintPlanList = '/eims/maintPlan/list',
-  root = '/eims/maintPlan'
+  root = '/eims/maintPlan',
+  maintPlanImport = '/eims/maintPlan/importData',
+  maintPlanImportTemplate = '/eims/maintPlan/importTemplate'
 }
 
 /**
@@ -59,3 +61,24 @@
 export function maintPlanExport(data: any) {
   return commonExport(Api.maintPlanExport, data);
 }
+
+/**
+ * 涓嬭浇淇濆吇璁″垝瀵煎叆妯℃澘
+ */
+export function downloadImportTemplate() {
+  return commonExport(Api.maintPlanImportTemplate);
+}
+
+/**
+ * 浠巈xcel瀵煎叆淇濆吇璁″垝鏁版嵁
+ * @param data
+ * @returns void
+ */
+export function maintPlanImportData(data: any) {
+  return requestClient.post<{ code: number; msg: string }>(Api.maintPlanImport, data, {
+    headers: {
+      'Content-Type': ContentTypeEnum.FORM_DATA
+    },
+    isTransformResponse: false
+  });
+}
diff --git a/eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx b/eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx
index b07a476..5afb308 100644
--- a/eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx
+++ b/eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx
@@ -82,51 +82,51 @@
     field: 'inspName',
     minWidth: 200
   },
-  {
-    title: '鐐规绫诲瀷',
-    field: 'inspType',
-    minWidth: 120,
-    slots: {
-      default: ({ row }) => {
-        return renderDict(row.inspType, DictEnum.EIMS_INSPECT_TYPE);
-      }
-    }
-  },
-  {
-    title: '鐐规浜�',
-    field: 'inspUserName',
-    minWidth: 100
-  },
-  {
-    title: '寰幆鍛ㄦ湡',
-    field: 'inspCycleUnitName',
-    minWidth: 80
-  },
-  {
-    title: '鏃堕棿璁$畻瑙勫垯',
-    field: 'inspRule',
-    minWidth: 140,
-    slots: {
-      default: ({ row }) => {
-        return renderDict(row.inspRule, DictEnum.MAINT_TIME_RULE);
-      }
-    }
-  },
-  {
-    title: '棣栨鎵ц鏃堕棿',
-    field: 'inspFirstTime',
-    minWidth: 160
-  },
-  {
-    title: '涓婃鎵ц鏃堕棿',
-    field: 'inspLastTime',
-    minWidth: 160
-  },
-  {
-    title: '涓嬫鎵ц鏃堕棿',
-    field: 'inspNextTime',
-    minWidth: 160
-  },
+  // {
+  //   title: '鐐规绫诲瀷',
+  //   field: 'inspType',
+  //   minWidth: 120,
+  //   slots: {
+  //     default: ({ row }) => {
+  //       return renderDict(row.inspType, DictEnum.EIMS_INSPECT_TYPE);
+  //     }
+  //   }
+  // },
+  // {
+  //   title: '鐐规浜�',
+  //   field: 'inspUserName',
+  //   minWidth: 100
+  // },
+  // {
+  //   title: '寰幆鍛ㄦ湡',
+  //   field: 'inspCycleUnitName',
+  //   minWidth: 80
+  // },
+  // {
+  //   title: '鏃堕棿璁$畻瑙勫垯',
+  //   field: 'inspRule',
+  //   minWidth: 140,
+  //   slots: {
+  //     default: ({ row }) => {
+  //       return renderDict(row.inspRule, DictEnum.MAINT_TIME_RULE);
+  //     }
+  //   }
+  // },
+  // {
+  //   title: '棣栨鎵ц鏃堕棿',
+  //   field: 'inspFirstTime',
+  //   minWidth: 160
+  // },
+  // {
+  //   title: '涓婃鎵ц鏃堕棿',
+  //   field: 'inspLastTime',
+  //   minWidth: 160
+  // },
+  // {
+  //   title: '涓嬫鎵ц鏃堕棿',
+  //   field: 'inspNextTime',
+  //   minWidth: 160
+  // },
   {
     title: '鍒涘缓鏃堕棿',
     field: 'createTime',
@@ -169,75 +169,75 @@
     fieldName: 'inspName',
     label: '鐐规椤�'
   },
-  {
-    component: 'RadioGroup',
-    componentProps: {
-      buttonStyle: 'solid',
-      options: getDictOptions(DictEnum.EIMS_INSPECT_TYPE),
-      optionType: 'button'
-    },
-    fieldName: 'inspType',
-    defaultValue: '1',
-    label: '鐐规绫诲瀷'
-  },
+  // {
+  //   component: 'RadioGroup',
+  //   componentProps: {
+  //     buttonStyle: 'solid',
+  //     options: getDictOptions(DictEnum.EIMS_INSPECT_TYPE),
+  //     optionType: 'button'
+  //   },
+  //   fieldName: 'inspType',
+  //   defaultValue: '1',
+  //   label: '鐐规绫诲瀷'
+  // },
   {
     component: 'Input',
     fieldName: 'inspDesc',
     label: '鐐规璇存槑'
   },
-  {
-    component: 'InputNumber',
-    fieldName: 'inspCycle',
-    label: '鐐规鍛ㄦ湡',
-    formItemClass: 'col-span-1',
-    componentProps: {
-      min: 1
-    }
-  },
-  {
-    component: 'Select',
-    componentProps: {
-      getPopupContainer,
-      options: getDictOptions(DictEnum.MAINT_CYCLE_UNIT)
-    },
-    fieldName: 'inspCycleUnit',
-    formItemClass: 'col-span-1 w-[80px]',
-    labelWidth: 0,
-    label: ''
-  },
-
-  {
-    component: 'Select',
-    componentProps: {
-      getPopupContainer,
-      options: getDictOptions(DictEnum.MAINT_TIME_RULE)
-    },
-    fieldName: 'inspRule',
-    label: '鐐规瑙勫垯 '
-  },
-  {
-    component: 'Input',
-    fieldName: 'inspUser',
-    label: '鐢ㄦ埛id',
-    dependencies: {
-      show: () => false,
-      triggerFields: ['']
-    }
-  },
-  {
-    component: 'Input',
-    fieldName: 'inspUserName',
-    label: '鐐规浜�'
-  },
-  {
-    component: 'Input',
-    fieldName: 'inspDept',
-    label: '閮ㄩ棬id',
-    dependencies: {
-      show: () => false,
-      triggerFields: ['']
-    }
-  },
+  // {
+  //   component: 'InputNumber',
+  //   fieldName: 'inspCycle',
+  //   label: '鐐规鍛ㄦ湡',
+  //   formItemClass: 'col-span-1',
+  //   componentProps: {
+  //     min: 1
+  //   }
+  // },
+  // {
+  //   component: 'Select',
+  //   componentProps: {
+  //     getPopupContainer,
+  //     options: getDictOptions(DictEnum.MAINT_CYCLE_UNIT)
+  //   },
+  //   fieldName: 'inspCycleUnit',
+  //   formItemClass: 'col-span-1 w-[80px]',
+  //   labelWidth: 0,
+  //   label: ''
+  // },
+  //
+  // {
+  //   component: 'Select',
+  //   componentProps: {
+  //     getPopupContainer,
+  //     options: getDictOptions(DictEnum.MAINT_TIME_RULE)
+  //   },
+  //   fieldName: 'inspRule',
+  //   label: '鐐规瑙勫垯 '
+  // },
+  // {
+  //   component: 'Input',
+  //   fieldName: 'inspUser',
+  //   label: '鐢ㄦ埛id',
+  //   dependencies: {
+  //     show: () => false,
+  //     triggerFields: ['']
+  //   }
+  // },
+  // {
+  //   component: 'Input',
+  //   fieldName: 'inspUserName',
+  //   label: '鐐规浜�'
+  // },
+  // {
+  //   component: 'Input',
+  //   fieldName: 'inspDept',
+  //   label: '閮ㄩ棬id',
+  //   dependencies: {
+  //     show: () => false,
+  //     triggerFields: ['']
+  //   }
+  // },
   {
     component: 'RadioGroup',
     componentProps: {
@@ -249,39 +249,39 @@
     defaultValue: '0',
     label: '鐘舵��'
   },
-  {
-    component: 'DatePicker',
-    componentProps: {
-      format: 'YYYY-MM-DD',
-      showTime: false,
-      valueFormat: 'YYYY-MM-DD',
-      getPopupContainer
-    },
-    fieldName: 'inspFirstTime',
-    label: '棣栨鐐规鏃堕棿'
-  },
-  {
-    component: 'DatePicker',
-    componentProps: {
-      format: 'YYYY-MM-DD',
-      showTime: false,
-      valueFormat: 'YYYY-MM-DD',
-      getPopupContainer
-    },
-    fieldName: 'inspLastTime',
-    label: '涓婃鐐规鏃堕棿'
-  },
-  {
-    component: 'DatePicker',
-    componentProps: {
-      format: 'YYYY-MM-DD',
-      showTime: false,
-      valueFormat: 'YYYY-MM-DD',
-      getPopupContainer
-    },
-    fieldName: 'inspNextTime',
-    label: '涓嬫鐐规鏃堕棿',
-  },
+  // {
+  //   component: 'DatePicker',
+  //   componentProps: {
+  //     format: 'YYYY-MM-DD',
+  //     showTime: false,
+  //     valueFormat: 'YYYY-MM-DD',
+  //     getPopupContainer
+  //   },
+  //   fieldName: 'inspFirstTime',
+  //   label: '棣栨鐐规鏃堕棿'
+  // },
+  // {
+  //   component: 'DatePicker',
+  //   componentProps: {
+  //     format: 'YYYY-MM-DD',
+  //     showTime: false,
+  //     valueFormat: 'YYYY-MM-DD',
+  //     getPopupContainer
+  //   },
+  //   fieldName: 'inspLastTime',
+  //   label: '涓婃鐐规鏃堕棿'
+  // },
+  // {
+  //   component: 'DatePicker',
+  //   componentProps: {
+  //     format: 'YYYY-MM-DD',
+  //     showTime: false,
+  //     valueFormat: 'YYYY-MM-DD',
+  //     getPopupContainer
+  //   },
+  //   fieldName: 'inspNextTime',
+  //   label: '涓嬫鐐规鏃堕棿',
+  // },
   {
     component: 'Textarea',
     fieldName: 'remark',
diff --git a/eims-ui/apps/web-antd/src/views/eims/insp-plan/index.vue b/eims-ui/apps/web-antd/src/views/eims/insp-plan/index.vue
index 3b1b351..191f18e 100644
--- a/eims-ui/apps/web-antd/src/views/eims/insp-plan/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/insp-plan/index.vue
@@ -3,7 +3,7 @@
 
 import { onMounted, ref } from 'vue';
 
-import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
+import { Page, useVbenDrawer, useVbenModal, type VbenFormProps } from '@vben/common-ui';
 import { $t } from '@vben/locales';
 import { addFullName, getPopupContainer, getVxePopupContainer } from '@vben/utils';
 
@@ -19,6 +19,7 @@
 
 import { columns, querySchema } from './data';
 import inspPlanDrawer from './insp-plan-drawer.vue';
+import inspPlanImportModal from './insp-plan-import-modal.vue';
 
 defineExpose({
   tableSelect
@@ -94,6 +95,17 @@
 const [InspRecordDrawer, inspRecordDrawerApi] = useVbenDrawer({
   connectedComponent: inspRecordDrawer
 });
+
+/**
+ * 瀵煎叆
+ */
+const [InspPlanImportModal, inspPlanImportModalApi] = useVbenModal({
+  connectedComponent: inspPlanImportModal
+});
+
+function handleImport() {
+  inspPlanImportModalApi.open();
+}
 
 function handleAdd() {
   inspPlanDrawerApi.setData({});
@@ -251,6 +263,9 @@
             <a-button v-access:code="['eims:inspectPlan:export']" @click="handleDownloadExcel">
               {{ $t('pages.common.export') }}
             </a-button>
+            <a-button v-access:code="['eims:inspectPlan:import']" @click="handleImport">
+              {{ $t('pages.common.import') }}
+            </a-button>
             <a-button
               :disabled="!vxeCheckboxChecked(tableApi)"
               danger
@@ -298,5 +313,6 @@
     </div>
     <InspPlanDrawer @reload="tableApi.query()" />
     <InspRecordDrawer @reload="tableApi.query()" />
+    <InspPlanImportModal @reload="tableApi.query()" />
   </Page>
 </template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/insp-plan/insp-plan-import-modal.vue b/eims-ui/apps/web-antd/src/views/eims/insp-plan/insp-plan-import-modal.vue
new file mode 100644
index 0000000..3baa409
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/insp-plan/insp-plan-import-modal.vue
@@ -0,0 +1,112 @@
+<script setup lang="ts">
+import type { UploadFile } from 'ant-design-vue/es/upload/interface';
+
+import { h, ref, unref } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+import { ExcelIcon, InBoxIcon } from '@vben/icons';
+
+import { Modal, Switch, Upload } from 'ant-design-vue';
+
+import { downloadImportTemplate, inspPlanImportData } from '#/api/eims/insp-plan';
+import { commonDownloadExcel } from '#/utils/file/download';
+
+const emit = defineEmits<{ reload: [] }>();
+
+const UploadDragger = Upload.Dragger;
+
+const [BasicModal, modalApi] = useVbenModal({
+  onCancel: handleCancel,
+  onConfirm: handleSubmit,
+});
+
+const fileList = ref<UploadFile[]>([]);
+const checked = ref(false);
+
+async function handleSubmit() {
+  try {
+    modalApi.modalLoading(true);
+    if (fileList.value.length !== 1) {
+      handleCancel();
+      return;
+    }
+    const data = {
+      file: fileList.value[0]!.originFileObj as Blob,
+      updateSupport: unref(checked),
+    };
+    const { code, msg } = await inspPlanImportData(data);
+    let modal = Modal.success;
+    if (code === 200) {
+      emit('reload');
+    } else {
+      emit('reload');
+      modal = Modal.error;
+    }
+    handleCancel();
+    modal({
+      content: h('div', {
+        class: 'max-h-[260px] overflow-y-auto',
+        innerHTML: msg, // 鍚庡彴宸茬粡澶勭悊xss闂
+      }),
+      title: '鎻愮ず',
+    });
+  } catch (error) {
+    console.warn(error);
+    modalApi.close();
+  } finally {
+    modalApi.modalLoading(false);
+  }
+}
+
+function handleCancel() {
+  modalApi.close();
+  fileList.value = [];
+  checked.value = false;
+}
+</script>
+
+<template>
+  <BasicModal
+    :close-on-click-modal="false"
+    :fullscreen-button="false"
+    title="鐐规璁″垝瀵煎叆"
+  >
+    <!-- z-index涓嶈缃細閬尅妯℃澘涓嬭浇loading -->
+    <!-- 鎵嬪姩澶勭悊 鑰屼笉鏄斁鍏ユ枃浠跺氨涓婁紶 -->
+    <UploadDragger
+      v-model:file-list="fileList"
+      :before-upload="() => false"
+      :max-count="1"
+      :show-upload-list="true"
+      accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
+    >
+      <p class="ant-upload-drag-icon flex items-center justify-center">
+        <InBoxIcon class="text-primary size-[48px]" />
+      </p>
+      <p class="ant-upload-text">鐐瑰嚮鎴栬�呮嫋鎷藉埌姝ゅ涓婁紶鏂囦欢</p>
+    </UploadDragger>
+    <div class="mt-2 flex flex-col gap-2">
+      <div class="flex items-center gap-2">
+        <span>鍏佽瀵煎叆xlsx, xls鏂囦欢</span>
+        <a-button
+          type="link"
+          @click="commonDownloadExcel(downloadImportTemplate, '鐐规璁″垝瀵煎叆妯℃澘')"
+        >
+          <div class="flex items-center gap-[4px]">
+            <ExcelIcon />
+            <span>涓嬭浇妯℃澘</span>
+          </div>
+        </a-button>
+      </div>
+      <div class="flex items-center gap-2">
+        <span class="text-red-500">鈿狅笍鐗瑰埆娉ㄦ剰鈿狅笍锛氳涓嬭浇妯$増淇濇寔瀵煎叆鏂囦欢琛ㄥご鍜屾ā鐗堜竴鑷村悗瀵煎叆</span>
+      </div>
+<!--      <div class="flex items-center gap-2">-->
+<!--        <span :class="{ 'text-red-500': checked }">-->
+<!--          鏄惁鏇存柊/瑕嗙洊宸插瓨鍦ㄧ殑鐐规璁″垝鏁版嵁-->
+<!--        </span>-->
+<!--        <Switch v-model:checked="checked" />-->
+<!--      </div>-->
+    </div>
+  </BasicModal>
+</template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/maint-plan/index.vue b/eims-ui/apps/web-antd/src/views/eims/maint-plan/index.vue
index 2ddc20e..4190da9 100644
--- a/eims-ui/apps/web-antd/src/views/eims/maint-plan/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/maint-plan/index.vue
@@ -3,7 +3,7 @@
 
 import { onMounted, ref } from 'vue';
 
-import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
+import { Page, useVbenDrawer, useVbenModal, type VbenFormProps } from '@vben/common-ui';
 import { $t } from '@vben/locales';
 import { addFullName, getPopupContainer, getVxePopupContainer } from '@vben/utils';
 
@@ -19,6 +19,7 @@
 
 import { columns, querySchema } from './data';
 import maintPlanDrawer from './maint-plan-drawer.vue';
+import maintPlanImportModal from './maint-plan-import-modal.vue';
 
 
 defineExpose({
@@ -93,6 +94,17 @@
 const [MaintOrderDrawer, maintOrderDrawerApi] = useVbenDrawer({
   connectedComponent: maintOrderDrawer,
 });
+
+/**
+ * 瀵煎叆
+ */
+const [MaintPlanImportModal, maintPlanImportModalApi] = useVbenModal({
+  connectedComponent: maintPlanImportModal
+});
+
+function handleImport() {
+  maintPlanImportModalApi.open();
+}
 
 function handleAdd() {
   maintPlanDrawerApi.setData({});
@@ -250,6 +262,9 @@
             <a-button v-access:code="['eims:maintPlan:export']" @click="handleDownloadExcel">
               {{ $t('pages.common.export') }}
             </a-button>
+            <a-button v-access:code="['eims:maintPlan:import']" @click="handleImport">
+              {{ $t('pages.common.import') }}
+            </a-button>
             <a-button
               :disabled="!vxeCheckboxChecked(tableApi)"
               danger
@@ -297,5 +312,6 @@
     </div>
     <MaintPlanDrawer @reload="tableApi.query()" />
     <MaintOrderDrawer @reload="tableApi.query()" />
+    <MaintPlanImportModal @reload="tableApi.query()" />
   </Page>
 </template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/maint-plan/maint-plan-import-modal.vue b/eims-ui/apps/web-antd/src/views/eims/maint-plan/maint-plan-import-modal.vue
new file mode 100644
index 0000000..380d446
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/maint-plan/maint-plan-import-modal.vue
@@ -0,0 +1,112 @@
+<script setup lang="ts">
+import type { UploadFile } from 'ant-design-vue/es/upload/interface';
+
+import { h, ref, unref } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+import { ExcelIcon, InBoxIcon } from '@vben/icons';
+
+import { Modal, Switch, Upload } from 'ant-design-vue';
+
+import { downloadImportTemplate, maintPlanImportData } from '#/api/eims/maint-plan';
+import { commonDownloadExcel } from '#/utils/file/download';
+
+const emit = defineEmits<{ reload: [] }>();
+
+const UploadDragger = Upload.Dragger;
+
+const [BasicModal, modalApi] = useVbenModal({
+  onCancel: handleCancel,
+  onConfirm: handleSubmit,
+});
+
+const fileList = ref<UploadFile[]>([]);
+const checked = ref(false);
+
+async function handleSubmit() {
+  try {
+    modalApi.modalLoading(true);
+    if (fileList.value.length !== 1) {
+      handleCancel();
+      return;
+    }
+    const data = {
+      file: fileList.value[0]!.originFileObj as Blob,
+      updateSupport: unref(checked),
+    };
+    const { code, msg } = await maintPlanImportData(data);
+    let modal = Modal.success;
+    if (code === 200) {
+      emit('reload');
+    } else {
+      emit('reload');
+      modal = Modal.error;
+    }
+    handleCancel();
+    modal({
+      content: h('div', {
+        class: 'max-h-[260px] overflow-y-auto',
+        innerHTML: msg, // 鍚庡彴宸茬粡澶勭悊xss闂
+      }),
+      title: '鎻愮ず',
+    });
+  } catch (error) {
+    console.warn(error);
+    modalApi.close();
+  } finally {
+    modalApi.modalLoading(false);
+  }
+}
+
+function handleCancel() {
+  modalApi.close();
+  fileList.value = [];
+  checked.value = false;
+}
+</script>
+
+<template>
+  <BasicModal
+    :close-on-click-modal="false"
+    :fullscreen-button="false"
+    title="淇濆吇璁″垝瀵煎叆"
+  >
+    <!-- z-index涓嶈缃細閬尅妯℃澘涓嬭浇loading -->
+    <!-- 鎵嬪姩澶勭悊 鑰屼笉鏄斁鍏ユ枃浠跺氨涓婁紶 -->
+    <UploadDragger
+      v-model:file-list="fileList"
+      :before-upload="() => false"
+      :max-count="1"
+      :show-upload-list="true"
+      accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
+    >
+      <p class="ant-upload-drag-icon flex items-center justify-center">
+        <InBoxIcon class="text-primary size-[48px]" />
+      </p>
+      <p class="ant-upload-text">鐐瑰嚮鎴栬�呮嫋鎷藉埌姝ゅ涓婁紶鏂囦欢</p>
+    </UploadDragger>
+    <div class="mt-2 flex flex-col gap-2">
+      <div class="flex items-center gap-2">
+        <span>鍏佽瀵煎叆xlsx, xls鏂囦欢</span>
+        <a-button
+          type="link"
+          @click="commonDownloadExcel(downloadImportTemplate, '淇濆吇璁″垝瀵煎叆妯℃澘')"
+        >
+          <div class="flex items-center gap-[4px]">
+            <ExcelIcon />
+            <span>涓嬭浇妯℃澘</span>
+          </div>
+        </a-button>
+      </div>
+      <div class="flex items-center gap-2">
+        <span class="text-red-500">鈿狅笍鐗瑰埆娉ㄦ剰鈿狅笍锛氳涓嬭浇妯$増淇濇寔瀵煎叆鏂囦欢琛ㄥご鍜屾ā鐗堜竴鑷村悗瀵煎叆</span>
+      </div>
+<!--      <div class="flex items-center gap-2">-->
+<!--        <span :class="{ 'text-red-500': checked }">-->
+<!--          鏄惁鏇存柊/瑕嗙洊宸插瓨鍦ㄧ殑淇濆吇璁″垝鏁版嵁-->
+<!--        </span>-->
+<!--        <Switch v-model:checked="checked" />-->
+<!--      </div>-->
+    </div>
+  </BasicModal>
+</template>
diff --git a/eims/ruoyi-admin/src/main/resources/template/by.xls b/eims/ruoyi-admin/src/main/resources/template/by.xls
new file mode 100644
index 0000000..fb73467
--- /dev/null
+++ b/eims/ruoyi-admin/src/main/resources/template/by.xls
Binary files differ
diff --git a/eims/ruoyi-admin/src/main/resources/template/dj.xlsx b/eims/ruoyi-admin/src/main/resources/template/dj.xlsx
new file mode 100644
index 0000000..ccb85ec
--- /dev/null
+++ b/eims/ruoyi-admin/src/main/resources/template/dj.xlsx
Binary files differ
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectPlanController.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectPlanController.java
index a528722..2151c89 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectPlanController.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectPlanController.java
@@ -1,11 +1,18 @@
 package org.dromara.eims.controller;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
 import java.util.List;
 
+import jakarta.servlet.ServletOutputStream;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -21,6 +28,7 @@
 import org.dromara.eims.domain.bo.EimsInspectPlanBo;
 import org.dromara.eims.service.IEimsInspectPlanService;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 鐐规璁″垝
@@ -103,4 +111,49 @@
                           @PathVariable Long[] ids) {
         return toAjax(eimsInspectPlanService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /**
+     * 瀵煎叆鏁版嵁
+     *
+     * @param file          瀵煎叆鏂囦欢
+     * @param updateSupport 鏄惁鏇存柊宸插瓨鍦ㄦ暟鎹�
+     */
+    @Log(title = "鐐规璁″垝", businessType = BusinessType.IMPORT)
+    @SaCheckPermission("eims:inspectPlan:import")
+    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
+        // ExcelResult<InspectCheckItemVo> result = ExcelUtil.importExcel(file.getInputStream(), InspectCheckItemVo.class, new InspectCheckItemImportListener(updateSupport));
+        String res = eimsInspectPlanService.importData(file, updateSupport);
+        return R.ok(res);
+    }
+
+    /**
+     * 鑾峰彇瀵煎叆妯℃澘
+     */
+    @PostMapping("/importTemplate")
+    public void importTemplate(HttpServletResponse response) throws UnsupportedEncodingException {
+        // 璁剧疆鍝嶅簲绫诲瀷
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+
+        // 璁剧疆鏂囦欢鍚�
+        String fileName = URLEncoder.encode("鐐规璁″垝瀵煎叆妯℃澘", "UTF-8");
+        response.setHeader("Content-Disposition",
+            "attachment;filename=" + fileName + ".xlsx");
+
+        // 璇诲彇妯℃澘鏂囦欢
+        ClassPathResource templateResource = new ClassPathResource("template/dj.xlsx");
+        try (InputStream inputStream = templateResource.getInputStream();
+             ServletOutputStream outputStream = response.getOutputStream()) {
+
+            // 娴佹嫹璐�
+            byte[] buffer = new byte[1024];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("妯℃澘鏂囦欢璇诲彇澶辫触", e);
+        }
+    }
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsMaintPlanController.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsMaintPlanController.java
index d2005dc..c00d56b 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsMaintPlanController.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsMaintPlanController.java
@@ -1,11 +1,17 @@
 package org.dromara.eims.controller;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
 import java.util.List;
 
+import jakarta.servlet.ServletOutputStream;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -21,6 +27,7 @@
 import org.dromara.eims.domain.bo.EimsMaintPlanBo;
 import org.dromara.eims.service.IEimsMaintPlanService;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 淇濆吇璁″垝
@@ -65,7 +72,7 @@
     @SaCheckPermission("eims:maintPlan:query")
     @GetMapping("/{id}")
     public R<EimsMaintPlanVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
-                                     @PathVariable Long id) {
+                                      @PathVariable Long id) {
         return R.ok(eimsMaintPlanService.queryById(id));
     }
 
@@ -103,4 +110,55 @@
                           @PathVariable Long[] ids) {
         return toAjax(eimsMaintPlanService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /**
+     * 瀵煎叆鏁版嵁
+     *
+     * @param file          瀵煎叆鏂囦欢
+     * @param updateSupport 鏄惁鏇存柊宸插瓨鍦ㄦ暟鎹�
+     */
+    @Log(title = "淇濆吇璁″垝", businessType = BusinessType.IMPORT)
+    @SaCheckPermission("eims:maintPlan:import")
+    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
+        //ExcelResult<MaintCheckItemVo> result = ExcelUtil.importExcel(file.getInputStream(), MaintCheckItemVo.class, new MaintCheckItemImportListener(updateSupport));
+
+
+        String res = eimsMaintPlanService.importData(file, updateSupport);
+
+        return R.ok(res);
+    }
+
+    /**
+     * 鑾峰彇瀵煎叆妯℃澘
+     */
+    @PostMapping("/importTemplate")
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        // 璁剧疆鍝嶅簲绫诲瀷
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+
+        // 璁剧疆鏂囦欢鍚�
+        String fileName = URLEncoder.encode("淇濆吇璁″垝瀵煎叆妯℃澘", "UTF-8");
+        response.setHeader("Content-Disposition",
+            "attachment;filename=" + fileName + ".xls");
+
+        // 璇诲彇妯℃澘鏂囦欢
+        ClassPathResource templateResource = new ClassPathResource("template/by.xls");
+        try (InputStream inputStream = templateResource.getInputStream();
+             ServletOutputStream outputStream = response.getOutputStream()) {
+
+            // 娴佹嫹璐�
+            byte[] buffer = new byte[1024];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("妯℃澘鏂囦欢璇诲彇澶辫触", e);
+        }
+    }
 }
+
+
+
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/InspectCheckItemVo.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/InspectCheckItemVo.java
new file mode 100644
index 0000000..d636bc1
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/InspectCheckItemVo.java
@@ -0,0 +1,32 @@
+package org.dromara.eims.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 鐐规椤圭洰瀵煎叆VO
+ *
+ * @author zhuguifei
+ */
+@Data
+@NoArgsConstructor
+public class InspectCheckItemVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+
+
+    /**
+     * 鐐规椤瑰悕绉�
+     */
+    @ExcelProperty(value = "鍐呭")
+    private String itemName;
+
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/MaintCheckItemVo.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/MaintCheckItemVo.java
new file mode 100644
index 0000000..7962bcf
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/MaintCheckItemVo.java
@@ -0,0 +1,95 @@
+package org.dromara.eims.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+/**
+ * 淇濆吇鐐规椤圭洰瀹炰綋
+ */
+@Data
+public class MaintCheckItemVo {
+
+    /**
+     * 瀹炴柦椤圭洰
+     */
+    @ExcelProperty("瀹炴柦椤圭洰")
+    private String itemName;
+
+    /**
+     * 鍛ㄦ湡锛堟湀锛�
+     */
+    @ExcelProperty("鍛ㄦ湡")
+    private String period;
+
+    /**
+     * 1鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("1鏈�")
+    private String january;
+
+    /**
+     * 2鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("2鏈�")
+    private String february;
+
+    /**
+     * 3鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("3鏈�")
+    private String march;
+
+    /**
+     * 4鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("4鏈�")
+    private String april;
+
+    /**
+     * 5鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("5鏈�")
+    private String may;
+
+    /**
+     * 6鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("6鏈�")
+    private String june;
+
+    /**
+     * 7鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("7鏈�")
+    private String july;
+
+    /**
+     * 8鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("8鏈�")
+    private String august;
+
+    /**
+     * 9鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("9鏈�")
+    private String september;
+
+    /**
+     * 10鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("10鏈�")
+    private String october;
+
+    /**
+     * 11鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("11鏈�")
+    private String november;
+
+    /**
+     * 12鏈堟鏌ョ姸鎬�
+     */
+    @ExcelProperty("12鏈�")
+    private String december;
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EasyExcelCellListener.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EasyExcelCellListener.java
new file mode 100644
index 0000000..5bc5758
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EasyExcelCellListener.java
@@ -0,0 +1,44 @@
+package org.dromara.eims.listener;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.read.listener.ReadListener;
+
+import java.util.Map;
+
+public class EasyExcelCellListener implements ReadListener<Map<Integer,String>> {
+
+    private String cellValue;
+    private int targetRow;
+    private int targetColumn;
+
+    private boolean isCellRead = false;
+
+    public EasyExcelCellListener(int targetRow, int targetColumn) {
+        this.targetRow = targetRow;
+        this.targetColumn = targetColumn;
+    }
+
+    @Override
+    //invoke鏂规硶鐨勫弬鏁扮被鍨嬭窡闅忓疄鐜扮殑ReadListener鐨勭被鍨�
+    public void invoke(Map<Integer,String> map, AnalysisContext analysisContext) {
+        if(isCellRead){
+            return;
+        }
+        int currentRow = analysisContext.readRowHolder().getRowIndex()+1;
+        if(currentRow == targetRow ){
+            cellValue = map.get(targetColumn-1);
+            isCellRead = true;
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+    }
+
+    public String getCellValue() {
+        return cellValue;
+    }
+
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/InspectCheckItemImportListener.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/InspectCheckItemImportListener.java
new file mode 100644
index 0000000..f1176e9
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/InspectCheckItemImportListener.java
@@ -0,0 +1,147 @@
+package org.dromara.eims.listener;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.exception.ExcelDataConvertException;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.service.DictService;
+import org.dromara.common.core.utils.SpringUtils;
+import org.dromara.common.excel.core.ExcelListener;
+import org.dromara.common.excel.core.ExcelResult;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.eims.domain.vo.EimsEquVo;
+import org.dromara.eims.domain.vo.InspectCheckItemVo;
+import org.dromara.eims.service.IEimsEquService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鐐规椤圭洰瀵煎叆鐩戝惉鍣�
+ *
+ * @author zhuguifei
+ */
+@Data
+@Slf4j
+public class InspectCheckItemImportListener extends AnalysisEventListener<InspectCheckItemVo> implements ExcelListener<InspectCheckItemVo> {
+
+    private final IEimsEquService equService;
+    private final DictService dictService;
+    private final Long operUserId;
+    private final Boolean isUpdateSupport;
+
+    /**
+     * 鎴愬姛鏉℃暟
+     */
+    private Integer successCount = 0;
+
+    /**
+     * 澶辫触鏉℃暟
+     */
+    private Integer failureCount = 0;
+
+    /**
+     * 瀵煎叆鎴愬姛鏁版嵁鍒楄〃
+     */
+    private List<InspectCheckItemVo> successList = new ArrayList<>();
+
+    /**
+     * 瀵煎叆澶辫触鏁版嵁鍒楄〃
+     */
+    private List<InspectCheckItemVo> failureList = new ArrayList<>();
+
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+
+    public InspectCheckItemImportListener(Boolean isUpdateSupport) {
+        this.equService = SpringUtils.getBean(IEimsEquService.class);
+        this.dictService = SpringUtils.getBean(DictService.class);
+        this.isUpdateSupport = isUpdateSupport;
+        this.operUserId = LoginHelper.getUserId();
+    }
+
+    @Override
+    public void invoke(InspectCheckItemVo data, AnalysisContext context) {
+        try {
+            // 鏁版嵁鏍¢獙
+            if (!validateData(data)) {
+                failureList.add(data);
+                failureCount++;
+                failureMsg.append("<br/>").append(failureCount).append("銆佺偣妫�椤� ")
+                    .append(data.getItemName()).append(" 鏁版嵁鏍¢獙澶辫触");
+                return;
+            }
+
+
+            successList.add(data);
+            successCount++;
+            successMsg.append("<br/>").append(successCount).append("銆佺偣妫�椤� ")
+                .append(data.getItemName()).append(" 瀵煎叆鎴愬姛");
+
+        } catch (Exception e) {
+            failureList.add(data);
+            failureCount++;
+            String msg = "<br/>" + failureCount + "銆佺偣妫�椤� " + data.getItemName() + " 瀵煎叆澶辫触锛�";
+            failureMsg.append(msg).append(e.getMessage());
+            log.error("瀵煎叆鐐规椤圭洰澶辫触锛�", e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        log.info("鐐规椤圭洰瀵煎叆瀹屾垚锛屾垚鍔燂細{}鏉★紝澶辫触锛歿}鏉�", successCount, failureCount);
+    }
+
+    @Override
+    public void onException(Exception exception, AnalysisContext context) throws Exception {
+        log.error("瀵煎叆寮傚父", exception);
+        if (exception instanceof ExcelDataConvertException) {
+            ExcelDataConvertException e = (ExcelDataConvertException) exception;
+            failureMsg.append("<br/>").append("绗�").append(e.getRowIndex()).append("琛岋紝绗�").append(e.getColumnIndex())
+                .append("鍒楄В鏋愬紓甯革細").append(e.getCause().getMessage());
+        } else {
+            failureMsg.append(exception.getMessage());
+        }
+    }
+
+    @Override
+    public ExcelResult<InspectCheckItemVo> getExcelResult() {
+        return new ExcelResult<InspectCheckItemVo>() {
+            @Override
+            public List<InspectCheckItemVo> getList() {
+                return successList;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return List.of();
+            }
+
+            @Override
+            public String getAnalysis() {
+                if (successCount > 0) {
+                    successMsg.insert(0, "鎭枩鎮紝鍏� " + successCount + " 鏉℃暟鎹鍏ユ垚鍔燂紒");
+                }
+                if (failureCount > 0) {
+                    failureMsg.insert(0, "寰堟姳姝夛紝鍏� " + failureCount + " 鏉℃暟鎹鍏ュけ璐ワ紒");
+                }
+                return successMsg + failureMsg.toString();
+            }
+        };
+    }
+
+    /**
+     * 鏍¢獙鏁版嵁
+     *
+     * @param data 寰呮牎楠屾暟鎹�
+     * @return 鏍¢獙缁撴灉
+     */
+    private boolean validateData(InspectCheckItemVo data) {
+        if (data.getItemName() == null || data.getItemName().trim().isEmpty()) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/MaintCheckItemImportListener.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/MaintCheckItemImportListener.java
new file mode 100644
index 0000000..b1e02a8
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/MaintCheckItemImportListener.java
@@ -0,0 +1,118 @@
+package org.dromara.eims.listener;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.excel.core.ExcelListener;
+import org.dromara.common.excel.core.ExcelResult;
+import org.dromara.eims.domain.vo.MaintCheckItemVo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 淇濆吇鐐规椤圭洰瀵煎叆鐩戝惉鍣�
+ *
+ * @author Lion Li
+ */
+@Data
+@Slf4j
+public class MaintCheckItemImportListener extends AnalysisEventListener<MaintCheckItemVo> implements ExcelListener<MaintCheckItemVo> {
+
+    /**
+     * 鎴愬姛鏉℃暟
+     */
+    private Integer successCount = 0;
+
+    /**
+     * 澶辫触鏉℃暟
+     */
+    private Integer failureCount = 0;
+
+    /**
+     * 瀵煎叆鎴愬姛鏁版嵁鍒楄〃
+     */
+    private List<MaintCheckItemVo> successList = new ArrayList<>();
+
+    /**
+     * 瀵煎叆澶辫触鏁版嵁鍒楄〃
+     */
+    private List<MaintCheckItemVo> failureList = new ArrayList<>();
+
+    public MaintCheckItemImportListener(Boolean isUpdateSupport) {
+        super();
+    }
+
+    @Override
+    public void invoke(MaintCheckItemVo data, AnalysisContext context) {
+        try {
+            // 鏁版嵁鏍¢獙
+            if (!validateData(data)) {
+                failureList.add(data);
+                failureCount++;
+                return;
+            }
+            successList.add(data);
+            successCount++;
+        } catch (Exception e) {
+            failureList.add(data);
+            failureCount++;
+            log.error("瀵煎叆淇濆吇鐐规椤圭洰澶辫触锛�", e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        log.info("淇濆吇鐐规椤圭洰瀵煎叆瀹屾垚锛屾垚鍔燂細{}鏉★紝澶辫触锛歿}鏉�", successCount, failureCount);
+    }
+
+    /**
+     * 鏍¢獙鏁版嵁
+     *
+     * @param data 寰呮牎楠屾暟鎹�
+     * @return 鏍¢獙缁撴灉
+     */
+    private boolean validateData(MaintCheckItemVo data) {
+        if (data.getItemName() == null || data.getItemName().trim().isEmpty()) {
+            return false;
+        }
+        if (data.getPeriod() == null || data.getPeriod().trim().isEmpty()) {
+            return false;
+        }
+
+        // 鏍¢獙1-12鏈堜唤鐘舵�佸��
+        return validateMonthStatus(data.getJanuary())
+            && validateMonthStatus(data.getFebruary())
+            && validateMonthStatus(data.getMarch())
+            && validateMonthStatus(data.getApril())
+            && validateMonthStatus(data.getMay())
+            && validateMonthStatus(data.getJune())
+            && validateMonthStatus(data.getJuly())
+            && validateMonthStatus(data.getAugust())
+            && validateMonthStatus(data.getSeptember())
+            && validateMonthStatus(data.getOctober())
+            && validateMonthStatus(data.getNovember())
+            && validateMonthStatus(data.getDecember());
+    }
+
+    /**
+     * 鏍¢獙鏈堜唤鐘舵�佸��
+     *
+     * @param status 鐘舵�佸��
+     * @return 鏍¢獙缁撴灉
+     */
+    private boolean validateMonthStatus(String status) {
+        // 鐘舵�佸�煎彲浠ヤ负绌�
+        if (status == null || status.trim().isEmpty()) {
+            return true;
+        }
+        // 鐘舵�佸�煎繀椤荤鍚堣鑼冿紙鏍规嵁瀹為檯涓氬姟闇�姹傚畾涔夋湁鏁堢殑鐘舵�佸�硷級
+        return true;
+    }
+
+    @Override
+    public ExcelResult<MaintCheckItemVo> getExcelResult() {
+        return null;
+    }
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectPlanService.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectPlanService.java
index 9334744..12588ff 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectPlanService.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectPlanService.java
@@ -4,7 +4,9 @@
 import org.dromara.eims.domain.bo.EimsInspectPlanBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.List;
 
@@ -75,4 +77,5 @@
      */
     TableDataInfo<EimsInspectPlanVo> queryPageListCustom(EimsInspectPlanBo bo, PageQuery pageQuery);
 
+    String importData(MultipartFile file, boolean updateSupport) throws IOException;
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsMaintPlanService.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsMaintPlanService.java
index e7b98ce..f0c98c4 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsMaintPlanService.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsMaintPlanService.java
@@ -4,7 +4,10 @@
 import org.dromara.eims.domain.bo.EimsMaintPlanBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Collection;
 import java.util.List;
 
@@ -74,4 +77,6 @@
      * @return 淇濆吇璁″垝鍒嗛〉鍒楄〃
      */
     TableDataInfo<EimsMaintPlanVo> queryPageListCustom(EimsMaintPlanBo bo, PageQuery pageQuery);
+
+    String importData(MultipartFile inputStream, boolean updateSupport) throws IOException;
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectPlanServiceImpl.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectPlanServiceImpl.java
index 865f6de..52e43d2 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectPlanServiceImpl.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectPlanServiceImpl.java
@@ -1,6 +1,9 @@
 package org.dromara.eims.service.impl;
 
+import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.DateUtils;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -9,7 +12,13 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
+import org.dromara.eims.domain.EimsEqu;
+import org.dromara.eims.domain.vo.EimsEquVo;
 import org.dromara.eims.domain.vo.EimsMaintPlanVo;
+import org.dromara.eims.domain.vo.InspectCheckItemVo;
+import org.dromara.eims.listener.EasyExcelCellListener;
+import org.dromara.eims.listener.InspectCheckItemImportListener;
+import org.dromara.eims.mapper.EimsEquMapper;
 import org.dromara.system.domain.SysDept;
 import org.dromara.system.domain.vo.SysDeptVo;
 import org.dromara.system.mapper.SysDeptMapper;
@@ -19,11 +28,10 @@
 import org.dromara.eims.domain.EimsInspectPlan;
 import org.dromara.eims.mapper.EimsInspectPlanMapper;
 import org.dromara.eims.service.IEimsInspectPlanService;
+import org.springframework.web.multipart.MultipartFile;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
+import java.io.IOException;
+import java.util.*;
 
 /**
  * 鐐规璁″垝Service涓氬姟灞傚鐞�
@@ -37,6 +45,7 @@
 
     private final EimsInspectPlanMapper baseMapper;
     private final SysDeptMapper sysDeptMapper;
+    private final EimsEquMapper equMapper;
 
 
     /**
@@ -196,5 +205,58 @@
         return baseMapper.deleteByIds(ids) > 0;
     }
 
+    @Override
+    public String importData(MultipartFile file, boolean updateSupport) throws IOException, IOException {
+        int successNum = 0;
+        int failureNum = 0;
+        StringBuilder successMsg = new StringBuilder();
+        StringBuilder failureMsg = new StringBuilder();
+
+        // 鐐规椤圭洰鍒楄〃锛堝亣璁惧瓨鍦ㄥ搴旂殑鐐规椤筕O锛�
+        InspectCheckItemImportListener checkItemImportListener = new InspectCheckItemImportListener(updateSupport);
+        EasyExcel.read(file.getInputStream(), InspectCheckItemVo.class, checkItemImportListener).headRowNumber(3).sheet().doRead();
+        List<InspectCheckItemVo> successList = checkItemImportListener.getSuccessList();
+
+        // 璇诲彇鍥哄畾璧勪骇缂栧彿锛堝亣璁句綅缃笉鍚岋級
+        EasyExcelCellListener assetNoListener = new EasyExcelCellListener(2, 23);
+        EasyExcel.read(file.getInputStream(), assetNoListener).headRowNumber(0).sheet().doReadSync();
+        String assetNo = Optional.ofNullable(assetNoListener.getCellValue())
+            .map(value -> {
+                int colonIndex = Math.max(value.indexOf(":"), value.indexOf("锛�")); // 鍚堝苟鍐掑彿澶勭悊
+                return colonIndex != -1 ? value.substring(colonIndex + 1) : value;
+            })
+            .map(String::trim)
+            .orElseThrow(() -> new ServiceException("瀵煎叆澶辫触锛屾棤娉曡鍙栧浐瀹氳祫浜х紪鍙�"));
+
+
+
+        // 鏌ヨ璁惧淇℃伅
+        QueryWrapper<EimsEqu> query = new QueryWrapper<>();
+        query.eq("asset_no", assetNo);
+        EimsEquVo equVo = equMapper.selectVoOne(query);
+        if (equVo == null) throw new ServiceException("璁惧鏈壘鍒帮紝璇峰厛鍦ㄨ澶囧彴甯愪腑娣诲姞");
+
+
+        for (InspectCheckItemVo itemVo : successList) {
+            if ("璁惧鐘舵�佸崱鐘舵��".equals(itemVo.getItemName())) break;
+            EimsInspectPlanBo bo = new EimsInspectPlanBo();
+            bo.setEquId(equVo.getEquId());
+            bo.setInspName(itemVo.getItemName());
+            bo.setStatus("0");
+            bo.setInspType("1");
+            bo.setInspRule("0");
+
+            if (!insertByBo(bo)) {
+                failureNum++;
+                failureMsg.append(failureNum).append("銆佸鍏ュけ璐�<br>");
+            } else {
+                successNum++;
+                successMsg.append(successNum).append("銆佸鍏ユ垚鍔�<br>");
+            }
+        }
+
+        return failureNum > 0 ? failureMsg.toString() : successMsg.toString();
+    }
+
 
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsMaintPlanServiceImpl.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsMaintPlanServiceImpl.java
index 937832b..f1e2647 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsMaintPlanServiceImpl.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsMaintPlanServiceImpl.java
@@ -1,8 +1,8 @@
 package org.dromara.eims.service.impl;
 
+import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import lombok.SneakyThrows;
-import org.dromara.common.core.constant.DictConstants;
+import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.DateUtils;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
@@ -12,7 +12,12 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
-import org.dromara.eims.domain.vo.EimsRepairResVo;
+import org.dromara.eims.domain.EimsEqu;
+import org.dromara.eims.domain.vo.EimsEquVo;
+import org.dromara.eims.domain.vo.MaintCheckItemVo;
+import org.dromara.eims.listener.EasyExcelCellListener;
+import org.dromara.eims.listener.MaintCheckItemImportListener;
+import org.dromara.eims.mapper.EimsEquMapper;
 import org.dromara.system.domain.SysDept;
 import org.dromara.system.domain.vo.SysDeptVo;
 import org.dromara.system.mapper.SysDeptMapper;
@@ -22,7 +27,9 @@
 import org.dromara.eims.domain.EimsMaintPlan;
 import org.dromara.eims.mapper.EimsMaintPlanMapper;
 import org.dromara.eims.service.IEimsMaintPlanService;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.util.*;
 
 /**
@@ -37,6 +44,7 @@
 
     private final EimsMaintPlanMapper baseMapper;
     private final SysDeptMapper sysDeptMapper;
+    private final EimsEquMapper equMapper;
 
     /**
      * 鏌ヨ淇濆吇璁″垝
@@ -194,4 +202,165 @@
     }
 
 
+    public String importData(MultipartFile is, boolean updateSupport) throws IOException {
+    int successNum = 0;
+    int failureNum = 0;
+    StringBuilder successMsg = new StringBuilder();
+    StringBuilder failureMsg = new StringBuilder();
+
+
+        // 淇濆吇椤圭洰鍒楄〃
+        MaintCheckItemImportListener checkItemImportListener = new MaintCheckItemImportListener(updateSupport);
+        EasyExcel.read(is.getInputStream(), MaintCheckItemVo.class, checkItemImportListener).headRowNumber(4).sheet().doRead();
+        List<MaintCheckItemVo> successList = checkItemImportListener.getSuccessList();
+
+
+        // 璇诲彇鍥哄畾璧勪骇缂栧彿
+        EasyExcelCellListener readListener = new EasyExcelCellListener(3, 1);
+        EasyExcel.read(is.getInputStream(), readListener).headRowNumber(0).sheet().doReadSync();
+        String assetNo = Optional.ofNullable(readListener.getCellValue())
+            .map(value -> {
+                int colonIndex = Math.max(value.indexOf(":"), value.indexOf("锛�")); // 鍚堝苟鍐掑彿澶勭悊
+                return colonIndex != -1 ? value.substring(colonIndex + 1) : value;
+            })
+            .map(String::trim)
+            .orElseThrow(() -> new ServiceException("瀵煎叆澶辫触锛屾棤娉曡鍙栧浐瀹氳祫浜х紪鍙�"));
+
+
+
+        // 璇诲彇淇濆吇璁″垝骞翠唤
+        EasyExcelCellListener readYearListener = new EasyExcelCellListener(2, 3);
+        EasyExcel.read(is.getInputStream(), readYearListener).headRowNumber(0).sheet().doReadSync();
+        String yearStr = readYearListener.getCellValue();
+        String year = yearStr.replaceAll("[^\\d]", ""); // 鍘婚櫎闈炴暟瀛楀瓧绗�
+        year = (year.length() == 4) ? year : DateUtils.getDate().substring(0,4);
+
+        QueryWrapper<EimsEqu> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("asset_no", assetNo);
+        EimsEquVo eimsEquVo = equMapper.selectVoOne(queryWrapper);
+        if (eimsEquVo == null) throw new ServiceException("瀵煎叆澶辫触锛岃澶囨湭鎵惧埌璇峰湪璁惧鍙板笎涓坊鍔�");
+
+        // 鏈堜唤瀛楁澶勭悊浼樺寲
+        String[] monthFields = {"january","february","march","april","may","june",
+                              "july","august","september","october","november","december"};
+
+        for (MaintCheckItemVo itemVo : successList) {
+            if ("鎵ц浜虹鍚�".equals(itemVo.getItemName())) break;
+
+            EimsMaintPlanBo maintPlanBo = new EimsMaintPlanBo();
+            maintPlanBo.setEquId(eimsEquVo.getEquId());
+            maintPlanBo.setMaintName(itemVo.getItemName());
+            maintPlanBo.setStatus("0");
+            maintPlanBo.setMaintType("1");
+            maintPlanBo.setMaintRule("0");
+            // 娣诲姞period鏍¢獙
+            String period = itemVo.getPeriod();
+            if (StringUtils.isBlank(period)) {
+                failureNum++;
+                failureMsg.append(failureNum).append("銆佸懆鏈熷瓧娈典负绌�<br>");
+                continue;
+            }
+
+            try {
+                if (period.length() > 1) {
+                    maintPlanBo.setMaintCycle(Long.parseLong(period.substring(0, period.length() - 1)));
+                    String substring = period.substring(period.length() - 1);
+                    // 杞崲鍛ㄦ湡鍗曚綅锛孧杞崲涓�3锛孌杞崲涓�1锛孻杞崲涓�5锛學杞崲涓�2锛孮杞崲涓�4
+                    switch (substring) {
+                        case "M":
+                            substring = "3";
+                            break;
+                        case "D":
+                            substring = "1";
+                            break;
+                        case "Y":
+                            substring = "5";
+                            break;
+                        case "W":
+                            substring = "2";
+                            break;
+                        case "Q":
+                            substring = "4";
+                            break;
+                        default:
+                    }
+                    maintPlanBo.setMaintCycleUnit(substring);
+                } else {
+                    maintPlanBo.setMaintCycle(Long.parseLong(period));
+                    maintPlanBo.setMaintCycleUnit("");
+                }
+            } catch (NumberFormatException e) {
+                failureNum++;
+                failureMsg.append(failureNum).append("銆佹棤鏁堢殑鍛ㄦ湡鏍煎紡:").append(period).append("<br>");
+                continue;
+            }
+
+            // 鏈堜唤鍒ゆ柇浼樺寲
+            for (int i = 0; i < monthFields.length; i++) {
+                try {
+                    String monthValue = (String) MaintCheckItemVo.class
+                        .getMethod("get" + StringUtils.capitalize(monthFields[i]))
+                        .invoke(itemVo);
+
+                    if (StringUtils.isNotBlank(monthValue)) {
+                        String month = String.format("%02d", i+1); // 淇濊瘉涓や綅鏈堜唤
+                        maintPlanBo.setMaintFirstTime(DateUtils.parseDate(year + "-" + month + "-01"));
+                        break;
+                    }
+                } catch (Exception e) {
+                    // 鍙嶅皠寮傚父澶勭悊
+                    failureNum++;
+                    failureMsg.append(failureNum).append("銆佹湀浠藉瓧娈佃闂紓甯�<br>");
+                    continue;
+                }
+            }
+
+            if (maintPlanBo.getMaintFirstTime() != null) {
+                Date firstTime = maintPlanBo.getMaintFirstTime();
+                Date nextTime = calcNextTime(firstTime, maintPlanBo.getMaintCycle().intValue(), 1);
+                maintPlanBo.setMaintNextTime(nextTime);
+            }
+
+            if (!insertByBo(maintPlanBo)) {
+                failureNum++;
+                failureMsg.append(failureNum).append("銆佽澶囷細").append(eimsEquVo.getEquName()).append("锛屽鍏ュけ璐�<br>");
+            } else {
+                successNum++;
+                successMsg.append("<br/>").append(successNum).append("銆佽澶囷細").append(eimsEquVo.getEquName()).append("锛屽鍏ユ垚鍔�");
+            }
+        }
+
+    if (failureNum > 0) {
+        failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細");
+        return failureMsg.toString();
+    } else {
+        successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�");
+        return successMsg.toString();
+    }
+}
+
+
+private Date calcNextTime(Date firstTime, int intervalMonths, int initialOffset) {
+    if (intervalMonths <= 0) {
+        throw new IllegalArgumentException("Interval months must be positive");
+    }
+    if (firstTime == null) {
+        throw new IllegalArgumentException("First time cannot be null");
+    }
+
+    Date current = new Date();
+    int adjustmentCount = initialOffset;
+
+    Date workingDate = (Date) firstTime.clone();
+    while (workingDate.before(current)) {
+        adjustmentCount++;
+        workingDate = DateUtils.addMonths(workingDate, intervalMonths);
+    }
+
+    return (Date) workingDate.clone();
+}
+
+
+
+
 }

--
Gitblit v1.9.3