车间能级提升-智能设备管理系统
朱桂飞
2025-02-14 fc76b6c4a7ccd2d875b0fb998a868fe4bea188f7
新增设备台账导入
已添加5个文件
已修改19个文件
1280 ■■■■ 文件已修改
eims-ui/apps/web-antd/src/api/eims/equ/index.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/equ/model.d.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/components/user-modal.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/data.tsx 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/equ-drawer.vue 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/equ-import-modal.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/index.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/repair-req/data.tsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/system/user/index.vue 128 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/effects/request/src/request-client/request-client.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/pom.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsEquController.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsEqu.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsEquBo.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquImportVo.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquVo.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsEquService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsEquServiceImpl.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/equ/index.ts
@@ -1,13 +1,15 @@
import type { IDS, PageQuery, PageResult } from '#/api/common';
import type { EquVO } from '#/api/eims/equ/model';
import type { EquImportParam, EquVO } from '#/api/eims/equ/model';
import { commonExport } from '#/api/helper';
import { commonExport, ContentTypeEnum } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  equExport = '/eims/equ/export',
  equImport = '/eims/equ/importData',
  equList = '/eims/equ/list',
  root = '/eims/equ'
  root = '/eims/equ',
  userImportTemplate = '/eims/equ/importTemplate'
}
/**
@@ -59,3 +61,32 @@
export function equExport(data: any) {
  return commonExport(Api.equExport, data);
}
/**
 * ä»Žexcel导入设备
 * @param data
 * @returns void
 */
export function equImportData(data: EquImportParam) {
  return requestClient.post<{ code: number; msg: string }>(Api.equImport, data, {
    headers: {
      'Content-Type': ContentTypeEnum.FORM_DATA
    },
    isTransformResponse: false
  });
}
/**
 * ä¸‹è½½å¯¼å…¥æ¨¡æ¿
 * @returns blob
 */
export function downloadImportTemplate() {
  return requestClient.post<Blob>(
    Api.userImportTemplate,
    {},
    {
      isTransformResponse: false,
      responseType: 'blob'
    }
  );
}
eims-ui/apps/web-antd/src/api/eims/equ/model.d.ts
@@ -122,3 +122,12 @@
   */
  serviceLife: number;
}
/**
 * @description: è®¾å¤‡å¯¼å…¥
 * @param updateSupport æ˜¯å¦è¦†ç›–数据
 * @param file excel文件
 */
export interface EquImportParam {
  updateSupport: boolean;
  file: Blob | File;
}
eims-ui/apps/web-antd/src/views/eims/components/user-modal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import UserView from '#/views/system/user/index.vue';
const emit = defineEmits<{ selectUser: [any] }>();
const [BasicModal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel: handleCancel,
  onConfirm: handleConfirm
});
const userView = ref();
async function handleConfirm() {
  try {
    modalApi.modalLoading(true);
    const tableSelect = userView.value.tableSelect();
    if (tableSelect.length > 1) {
      message.error('最多只能选择一个成员!');
      modalApi.modalLoading(false);
      return false;
    }
    emit('selectUser', tableSelect[0]);
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    modalApi.modalLoading(false);
  }
}
async function handleCancel() {
  modalApi.close();
}
</script>
<template>
  <BasicModal :fullscreen-button="true" class="w-[800px]">
    <UserView ref="userView" />
  </BasicModal>
</template>
<style scoped></style>
eims-ui/apps/web-antd/src/views/eims/equ/data.tsx
@@ -38,7 +38,7 @@
  {
    title: '设备名称',
    field: 'equName',
    minWidth: 100,
    minWidth: 140,
    fixed: 'left',
    slots: { default: 'equName' }
  },
@@ -49,6 +49,9 @@
    sortable: true,
    slots: {
      default: ({ row }) => {
        if (row.status === null || row.status === '') {
          return '';
        }
        return renderDict(row.status, DictEnum.SYS_EQU_STATUS);
      }
    },
@@ -59,7 +62,7 @@
    title: '资产编号',
    field: 'assetNo',
    sortable: true,
    minWidth: 100,
    minWidth: 140,
    fixed: 'left'
  },
  {
@@ -71,6 +74,31 @@
  {
    title: '设备类型',
    field: 'equTypeName',
    minWidth: 100
  },
  {
    title: '销售商',
    field: 'seller',
    minWidth: 100
  },
  {
    title: '单位',
    field: 'unit',
    minWidth: 60
  },
  {
    title: '采购人',
    field: 'purchaseUser',
    minWidth: 100
  },
  {
    title: '经手人',
    field: 'handleUser',
    minWidth: 100
  },
  {
    title: '资料',
    field: 'profile',
    minWidth: 100
  },
  {
@@ -142,13 +170,21 @@
  {
    title: '导入状态',
    field: 'importStatus',
    slots: { default: 'importStatus' },
    slots: {
      default: ({ row }) => {
        return row.importStatus === null || row.importStatus === '' ? '' : renderDict(row.importStatus, DictEnum.EQU_IMPORT_STATU);
      }
    },
    minWidth: 100
  },
  {
    title: '盘点标志',
    field: 'inventoryFlag',
    slots: { default: 'inventoryFlag' },
    slots: {
      default: ({ row }) => {
        return row.inventoryFlag === null || row.inventoryFlag === '' ? '' : renderDict(row.inventoryFlag, DictEnum.EIMS_INVENTORY_STATU);
      }
    },
    minWidth: 100
  },
  {
@@ -209,6 +245,42 @@
    label: '资产编号'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_EQU_UNIT)
    },
    fieldName: 'unit',
    label: '单位'
  },
  {
    component: 'Input',
    fieldName: 'purchaseUserName',
    label: '采购人'
  },
  {
    component: 'Input',
    fieldName: 'purchaseUser',
    label: '采购人',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    }
  },
  {
    component: 'Input',
    fieldName: 'handleUserName',
    label: '经手人'
  },
  {
    component: 'Input',
    fieldName: 'handleUser',
    label: '经手人',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    }
  },
  {
    component: 'Input',
    fieldName: 'modelNo',
    label: '型号'
@@ -217,6 +289,11 @@
    component: 'Input',
    fieldName: 'madeIn',
    label: '制造商'
  },
  {
    component: 'Input',
    fieldName: 'seller',
    label: '销售商'
  },
  {
    component: 'Input',
@@ -246,7 +323,7 @@
      options: getDictOptions(DictEnum.SYS_EQU_STATUS),
      optionType: 'button'
    },
    defaultValue: '0',
    defaultValue: '5',
    fieldName: 'status',
    label: '状态'
  },
@@ -335,7 +412,7 @@
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_NORMAL_DISABLE),
      options: getDictOptions(DictEnum.EQU_IMPORT_STATU),
      optionType: 'button'
    },
    defaultValue: '0',
@@ -353,12 +430,12 @@
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_NORMAL_DISABLE),
      options: getDictOptions(DictEnum.EIMS_INVENTORY_STATU),
      optionType: 'button'
    },
    defaultValue: '0',
    fieldName: 'inventoryFlag',
    formItemClass: 'col-span-2 lg:col-span-1',
    formItemClass: 'col-span-2',
    label: '盘点标志'
  },
  {
eims-ui/apps/web-antd/src/views/eims/equ/equ-drawer.vue
@@ -1,14 +1,17 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, cloneDeep, getPopupContainer, listToTree } from '@vben/utils';
import { InputSearch } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { addEqu, getEqu, updateEqu } from '#/api/eims/equ';
import { getEquType, listEquType } from '#/api/eims/equ-type';
import { getDeptTree, userList } from '#/api/system/user';
import userModal from '#/views/eims/components/user-modal.vue';
import { drawerSchema } from './data';
@@ -51,10 +54,9 @@
    if (isUpdate.value && id) {
      const record = await getEqu(id);
      await formApi.setValues(record);
      if(isUpdate.value && record.deptUsed){
        await setupUserOptions(record.deptUsed)
      if (isUpdate.value && record.deptUsed) {
        await setupUserOptions(record.deptUsed);
      }
    }
    // åŠ è½½è®¾å¤‡ç±»åž‹æ ‘é€‰æ‹©
@@ -70,6 +72,38 @@
  }
});
// user modal
const [UserModal, userModalApi] = useVbenModal({
  connectedComponent: userModal,
  draggable: true,
  title: '选择成员'
});
function handleOpenModal() {
  userModalApi.setData({});
  userModalApi.open();
}
/**
 * æ‰“开选择成员
 */
const column = ref<string>();
function onOpenSelectUser(type: any) {
  column.value = type;
  handleOpenModal();
}
/**
 * æ›´æ–°é€‰æ‹©çš„æˆå‘˜
 * @param user
 */
async function selectUser(user: any) {
  if (column.value === 'purchaseUser') {
    await formApi.setValues({ 'purchaseUser': user.userId, 'purchaseUserName': user.nickName });
  } else if (column.value === 'handleUserName') {
    await formApi.setValues({ 'handleUser': user.userId, 'handleUserName': user.nickName });
  }
}
async function setupEquTypeSelect() {
  // status-0 åªæŸ¥è¯¢æœªåœç”¨è®¾å¤‡
@@ -83,8 +117,8 @@
    {
      equTypeId: 0,
      typeName: $t('menu.root'),
      children: equTree,
    },
      children: equTree
    }
  ];
  addFullName(fullEquTree, 'typeName', ' / ');
  formApi.updateSchema([
@@ -92,7 +126,7 @@
      componentProps: {
        fieldNames: {
          label: 'typeName',
          value: 'equTypeId',
          value: 'equTypeId'
        },
        getPopupContainer,
        // è®¾ç½®å¼¹çª—滚动高度 é»˜è®¤256
@@ -106,10 +140,10 @@
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'typeName',
        treeNodeLabelProp: 'fullName',
        treeNodeLabelProp: 'fullName'
      },
      fieldName: 'equTypeId',
    },
      fieldName: 'equTypeId'
    }
  ]);
}
@@ -135,7 +169,7 @@
  const placeholder = options.length > 0 ? '请选择' : '该部门下暂无用户';
  formApi.updateSchema([
    {
      componentProps: { options, placeholder ,filterOption },
      componentProps: { options, placeholder, filterOption },
      fieldName: 'respPerson'
    }
  ]);
@@ -206,6 +240,14 @@
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm />
    <BasicForm>
      <template #purchaseUserName="slotProps">
        <InputSearch :enter-button="true" placeholder="请选择" @search="onOpenSelectUser('purchaseUser')" v-bind="slotProps" />
      </template>
      <template #handleUserName="slotProps">
        <InputSearch :enter-button="true" placeholder="请选择" @search="onOpenSelectUser('handleUserName')" v-bind="slotProps" />
      </template>
    </BasicForm>
    <UserModal class="w-[1200px]" @select-user="selectUser" />
  </BasicDrawer>
</template>
eims-ui/apps/web-antd/src/views/eims/equ/equ-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, equImportData } from '#/api/eims/equ';
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 equImportData(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>
eims-ui/apps/web-antd/src/views/eims/equ/index.vue
@@ -4,7 +4,8 @@
import { ref } from 'vue';
import { useRouter } from 'vue-router';
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 { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
@@ -15,6 +16,7 @@
import { columns, querySchema } from './data';
import equDrawer from './equ-drawer.vue';
import equImportModal from './equ-import-modal.vue';
import EquTypeTree from './equ-type-tree.vue';
// å·¦è¾¹éƒ¨é—¨ç”¨
@@ -101,6 +103,17 @@
  connectedComponent: equDrawer
});
/**
 * å¯¼å…¥
 */
const [EquImportModal, equImportModalApi] = useVbenModal({
  connectedComponent: equImportModal
});
function handleImport() {
  equImportModalApi.open();
}
function handleAdd() {
  equDrawerApi.setData({});
  equDrawerApi.open();
@@ -141,11 +154,6 @@
  return importStatus ? '未导入' : '已导入';
}
function getInventoryFlag(row: any) {
  const inventoryFlag = row.inventoryFlag === null || row.inventoryFlag;
  return inventoryFlag ? '未盘点' : '已盘点';
}
const router = useRouter();
function handleDetail(record: Recordable<any>) {
  router.push(`/equ/detail/${record.equId}`);
@@ -165,6 +173,9 @@
          <Space>
            <a-button v-access:code="['eims:equ:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button v-access:code="['eims:equ:import']" @click="handleImport">
              {{ $t('pages.common.import') }}
            </a-button>
            <a-button :disabled="!vxeCheckboxChecked(tableApi)" danger type="primary" v-access:code="['eims:equ:remove']" @click="handleMultiDelete">
              {{ $t('pages.common.delete') }}
@@ -200,12 +211,9 @@
        <template #importStatus="{ row }">
          <span>{{ getImportStatus(row) }}</span>
        </template>
        <template #inventoryFlag="{ row }">
          <span>{{ getInventoryFlag(row) }}</span>
        </template>
      </BasicTable>
    </div>
    <EquDrawer @reload="tableApi.query()" />
    <EquImportModal @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/repair-req/data.tsx
@@ -108,6 +108,12 @@
    minWidth: 200
  },
  {
    title: '设备名称',
    field: 'equName',
    sortable: true,
    minWidth: 120
  },
  {
    title: '故障类别',
    field: 'faultType',
    minWidth: 100,
eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue
@@ -13,6 +13,7 @@
import { delRepairReq, listRepairReq, repairReqExport } from '#/api/eims/repair-req';
import { getDeptTree, userList } from '#/api/system/user';
import { commonDownloadExcel } from '#/utils/file/download';
import { useRoleBaseFilters } from '#/views/eims/repair-req/use-role-base-filters';
import { columns, querySchema } from './data';
import repairReqDrawer from './repair-req-drawer.vue';
@@ -50,7 +51,8 @@
        return await listRepairReq({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
          ...formValues,
          ...useRoleBaseFilters()
        });
      }
    }
eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
import { computed } from 'vue';
import { useAccess } from '@vben/access';
import { useUserStore } from '@vben/stores';
const userStore = useUserStore();
const userId = userStore.userInfo?.userId;
const { hasAccessByRoles } = useAccess();
// æ“ä½œå·¥
const operator = computed(() => hasAccessByRoles(['operator']));
// ç»´ä¿®å·¥
const repair = computed(() => hasAccessByRoles(['repair']));
export function useRoleBaseFilters() {
  const params: any = {};
  // æ“ä½œå·¥åªèƒ½æŸ¥è¯¢è‡ªå·±åˆ›å»ºçš„æ•°æ®
  if (operator.value) {
    params.createBy = userId;
  }
  // ç»´ä¿®å·¥åªèƒ½æŸ¥è¯¢æœªæŽ¥å•状态的报修单(具体状态参加字典repair_req_status)
  if (repair.value) {
    params.status = '0';
  }
  return { params };
}
eims-ui/apps/web-antd/src/views/system/user/index.vue
@@ -4,34 +4,16 @@
import { ref } from 'vue';
import { useAccess } from '@vben/access';
import {
  Page,
  useVbenDrawer,
  useVbenModal,
  type VbenFormProps,
} from '@vben/common-ui';
import { Page, useVbenDrawer, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { preferences } from '@vben/preferences';
import { getVxePopupContainer } from '@vben/utils';
import {
  Avatar,
  Dropdown,
  Menu,
  MenuItem,
  Modal,
  Popconfirm,
  Space,
} from 'ant-design-vue';
import { Avatar, Dropdown, Menu, MenuItem, Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
  userExport,
  userList,
  userRemove,
  userStatusChange,
} from '#/api/system/user';
import { userExport, userList, userRemove, userStatusChange } from '#/api/system/user';
import { TableSwitch } from '#/components/table';
import { commonDownloadExcel } from '#/utils/file/download';
@@ -46,7 +28,7 @@
 * å¯¼å…¥
 */
const [UserImpotModal, userImportModalApi] = useVbenModal({
  connectedComponent: userImportModal,
  connectedComponent: userImportModal
});
function handleImport() {
@@ -55,14 +37,17 @@
// å·¦è¾¹éƒ¨é—¨ç”¨
const selectDeptId = ref<string[]>([]);
defineExpose({
  tableSelect
});
const formOptions: VbenFormProps = {
  schema: querySchema(),
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true,
    },
      allowClear: true
    }
  },
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  handleReset: async () => {
@@ -75,13 +60,7 @@
    await reload(formValues);
  },
  // æ—¥æœŸé€‰æ‹©æ ¼å¼åŒ–
  fieldMappingTime: [
    [
      'createTime',
      ['params[beginTime]', 'params[endTime]'],
      ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
    ],
  ],
  fieldMappingTime: [['createTime', ['params[beginTime]', 'params[endTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']]]
};
const gridOptions: VxeGridProps = {
@@ -92,7 +71,7 @@
    reserve: true,
    // ç‚¹å‡»è¡Œé€‰ä¸­
    trigger: 'default',
    checkMethod: ({ row }) => row?.userId !== 1,
    checkMethod: ({ row }) => row?.userId !== 1
  },
  columns,
  height: 'auto',
@@ -111,25 +90,25 @@
        return await userList({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues,
          ...formValues
        });
      },
    },
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'userId',
    height: 48,
    height: 48
  },
  id: 'system-user-index',
  id: 'system-user-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridOptions
});
const [UserDrawer, userDrawerApi] = useVbenDrawer({
  connectedComponent: userDrawer,
  connectedComponent: userDrawer
});
function handleAdd() {
@@ -157,18 +136,18 @@
    onOk: async () => {
      await userRemove(ids);
      await tableApi.query();
    },
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(userExport, '用户管理', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime,
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
const [UserInfoModal, userInfoModalApi] = useVbenModal({
  connectedComponent: userInfoModal,
  connectedComponent: userInfoModal
});
function handleUserInfo(row: Recordable<any>) {
  userInfoModalApi.setData({ userId: row.userId });
@@ -176,12 +155,17 @@
}
const [UserResetPwdModal, userResetPwdModalApi] = useVbenModal({
  connectedComponent: userResetPwdModal,
  connectedComponent: userResetPwdModal
});
function handleResetPwd(record: Recordable<any>) {
  userResetPwdModalApi.setData({ record });
  userResetPwdModalApi.open();
}
// é€‰ä¸­æ•°æ®
function tableSelect() {
  return tableApi.grid.getCheckboxRecords();
}
const { hasAccessByCodes } = useAccess();
@@ -190,25 +174,14 @@
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <DeptTree
        v-model:select-dept-id="selectDeptId"
        class="w-[260px]"
        @reload="() => tableApi.reload()"
        @select="() => tableApi.reload()"
      />
      <DeptTree v-model:select-dept-id="selectDeptId" class="w-[260px]" @reload="() => tableApi.reload()" @select="() => tableApi.reload()" />
      <BasicTable class="flex-1 overflow-hidden" table-title="用户列表">
        <template #toolbar-tools>
          <Space>
            <a-button
              v-access:code="['system:user:export']"
              @click="handleDownloadExcel"
            >
            <a-button v-access:code="['system:user:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              v-access:code="['system:user:import']"
              @click="handleImport"
            >
            <a-button v-access:code="['system:user:import']" @click="handleImport">
              {{ $t('pages.common.import') }}
            </a-button>
            <a-button
@@ -220,11 +193,7 @@
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button
              type="primary"
              v-access:code="['system:user:add']"
              @click="handleAdd"
            >
            <a-button type="primary" v-access:code="['system:user:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
@@ -237,49 +206,28 @@
          <TableSwitch
            v-model="row.status"
            :api="() => userStatusChange(row)"
            :disabled="
              row.userId === 1 || !hasAccessByCodes(['system:user:edit'])
            "
            :disabled="row.userId === 1 || !hasAccessByCodes(['system:user:edit'])"
            :reload="() => tableApi.query()"
          />
        </template>
        <template #action="{ row }">
          <template v-if="row.userId !== 1">
            <Space>
              <ghost-button
                v-access:code="['system:user:edit']"
                @click.stop="handleEdit(row)"
              >
              <ghost-button v-access:code="['system:user:edit']" @click.stop="handleEdit(row)">
                {{ $t('pages.common.edit') }}
              </ghost-button>
              <Popconfirm
                :get-popup-container="getVxePopupContainer"
                placement="left"
                title="确认删除?"
                @confirm="handleDelete(row)"
              >
                <ghost-button
                  danger
                  v-access:code="['system:user:remove']"
                  @click.stop=""
                >
              <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
                <ghost-button danger v-access:code="['system:user:remove']" @click.stop="">
                  {{ $t('pages.common.delete') }}
                </ghost-button>
              </Popconfirm>
            </Space>
            <Dropdown
              :get-popup-container="getVxePopupContainer"
              placement="bottomRight"
            >
            <Dropdown :get-popup-container="getVxePopupContainer" placement="bottomRight">
              <template #overlay>
                <Menu>
                  <MenuItem key="1" @click="handleUserInfo(row)">
                    ç”¨æˆ·ä¿¡æ¯
                  </MenuItem>
                  <MenuItem key="1" @click="handleUserInfo(row)"> ç”¨æˆ·ä¿¡æ¯ </MenuItem>
                  <span v-access:code="['system:user:resetPwd']">
                    <MenuItem key="2" @click="handleResetPwd(row)">
                      é‡ç½®å¯†ç 
                    </MenuItem>
                    <MenuItem key="2" @click="handleResetPwd(row)"> é‡ç½®å¯†ç  </MenuItem>
                  </span>
                </Menu>
              </template>
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,8 +1,10 @@
export enum DictEnum {
  EIMS_EQU_UNIT = 'eims_equ_unit', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  REPAIR_REQ_STATUS = 'repair_req_status', // æŠ¥ä¿®çŠ¶æ€
  EQU_IMPORT_STATU = 'equ_import_status', // è®¾å¤‡å¯¼å…¥çŠ¶æ€
  REPAIR_FAULT_TYPE = 'repair_fault_type', // æŠ¥ä¿®çŠ¶æ€
  REPAIR_REQ_STATUS = 'repair_req_status', // æŠ¥ä¿®çŠ¶æ€
  REPAIR_REQ_TYPE = 'repair_req_type', // æŠ¥ä¿®ç±»åž‹
  REPAIR_URGENCY_LEVEL = 'repair_urgency_level', // æŠ¥ä¿®ç´§æ€¥ç¨‹åº¦
  SYS_COMMON_STATUS = 'sys_common_status',
eims-ui/packages/effects/request/src/request-client/request-client.ts
@@ -38,7 +38,7 @@
        'Content-Type': 'application/json;charset=utf-8',
      },
      // é»˜è®¤è¶…æ—¶æ—¶é—´
      timeout: 10_000,
      timeout: 30_000,
    };
    const { ...axiosConfig } = options;
    const requestConfig = merge(axiosConfig, defaultConfig);
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java
@@ -33,4 +33,14 @@
     */
    String EIMS_GENERATE_CODE = "eims_generate_code:";
    /**
     * ***********************字典***********************
     */
    /**
     * è®¾å¤‡å•位unit
     */
    String EIMS_EQU_UNIT = "eims_equ_unit";
}
eims/ruoyi-modules/lb-eims/pom.xml
@@ -97,6 +97,10 @@
            <groupId>org.dromara</groupId>
            <artifactId>ruoyi-common-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>ruoyi-system</artifactId>
        </dependency>
    </dependencies>
</project>
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsEquController.java
@@ -1,14 +1,19 @@
package org.dromara.eims.controller;
import java.util.ArrayList;
import java.util.List;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.eims.domain.bo.EimsEquBo;
import org.dromara.eims.domain.vo.EimsEquImportVo;
import org.dromara.eims.domain.vo.EimsEquVo;
import org.dromara.eims.listener.EimsEquImportListener;
import org.dromara.eims.service.IEimsEquService;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -23,6 +28,7 @@
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
 * ã€è®¾å¤‡å°è´¦ã€‘
@@ -104,4 +110,26 @@
                          @PathVariable Long[] equIds) {
        return toAjax(eimsEquipmentService.deleteWithValidByIds(List.of(equIds), true));
    }
    /**
     * å¯¼å…¥æ•°æ®
     *
     * @param file          å¯¼å…¥æ–‡ä»¶
     * @param updateSupport æ˜¯å¦æ›´æ–°å·²å­˜åœ¨æ•°æ®
     */
    @Log(title = "设备管理", businessType = BusinessType.IMPORT)
    @SaCheckPermission("eims:equ:import")
    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
        ExcelResult<EimsEquImportVo> result = ExcelUtil.importExcel(file.getInputStream(), EimsEquImportVo.class, new EimsEquImportListener(updateSupport));
        return R.ok(result.getAnalysis());
    }
    /**
     * èŽ·å–å¯¼å…¥æ¨¡æ¿
     */
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil.exportExcel(new ArrayList<>(), "设备数据", EimsEquVo.class, response);
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsEqu.java
@@ -1,5 +1,6 @@
package org.dromara.eims.domain;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
@@ -147,5 +148,35 @@
     */
    private Long serviceLife;
    /**
     * é”€å”®å•†
     */
    private String seller;
    /**
     * å•位
     */
    private String unit;
    /**
     * ç»æ‰‹äºº
     */
    private Long handleUser;
    /**
     * é‡‡è´­äºº
     */
    private Long purchaseUser;
    /**
     * é™„ä»¶
     */
    private String attachments;
    /**
     * èµ„æ–™
     */
    private String profile;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsEquBo.java
@@ -1,6 +1,7 @@
package org.dromara.eims.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.eims.domain.EimsEqu;
import io.github.linpeilie.annotations.AutoMapper;
@@ -142,5 +143,41 @@
     */
    private Long serviceLife;
    /**
     * é”€å”®å•†
     */
    @ExcelProperty(value = "销售商")
    private String seller;
    /**
     * å•位
     */
    @ExcelProperty(value = "单位")
    private String unit;
    /**
     * ç»æ‰‹äºº
     */
    @ExcelProperty(value = "经手人")
    private Long handleUser;
    /**
     * é‡‡è´­äºº
     */
    @ExcelProperty(value = "采购人")
    private Long purchaseUser;
    /**
     * é™„ä»¶
     */
    @ExcelProperty(value = "附件")
    private String attachments;
    /**
     * èµ„æ–™
     */
    @ExcelProperty(value = "资料")
    private String profile;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquImportVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,141 @@
package org.dromara.eims.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
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;
import java.util.Date;
/**
 * è®¾å¤‡å¯¹è±¡å¯¼å…¥VO
 *
 * @author zhuguifei
 */
@Data
@NoArgsConstructor
public class EimsEquImportVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    private Long equId;
    /**
     * è®¾å¤‡åç§°
     */
    @ExcelProperty(value = "设备名称")
    private String equName;
    /**
     * è§„格型号
     */
    @ExcelProperty(value = "型号规格")
    private String modelNo;
    /**
     * åˆ¶é€ åނ家
     */
    @ExcelProperty(value = "制造厂家")
    private String madeIn;
    /**
     * é”€å”®å•†
     */
    @ExcelProperty(value = "销售商")
    private String seller;
    /**
     * å•位
     */
    @ExcelProperty(value = "单位")
    private String unit;
    /**
     * èµ„产编号
     */
    @ExcelProperty(value = "资产编号")
    private String assetNo;
    /**
     * æ‰€åœ¨åœºæ‰€
     */
    @ExcelProperty(value = "所在场所")
    private String location;
    /**
     * ç®¡ç†è€…
     */
    @ExcelProperty(value = "管理者")
    private String respPersonName;
    /**
     * è´­ä¹°æ—¥æœŸ
     */
    @ExcelProperty(value = "购买日期")
    private String purchaseDateStr;
    private Date purchaseDate;
    /**
     * å®žé™…验收日期
     */
    @ExcelProperty(value = "验收日期")
    private String actualAcceptDateStr;
    private Date actualAcceptDate;
    /**
     * ç»æ‰‹äºº
     */
    @ExcelProperty(value = "经手人")
    private String handleUserName;
    /**
     * é‡‡è´­äºº
     */
    @ExcelProperty(value = "采购人")
    private String purchaseUserName;
    /**
     * é¢å®šåŠŸçŽ‡
     */
    @ExcelProperty(value = "功率")
    private String ratedPower;
    /**
     * è”系电话
     */
    @ExcelProperty(value = "联系电话")
    private String contactPhone;
    /**
     * ä½¿ç”¨çŠ¶æ€
     */
    @ExcelProperty(value = "使用状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "sys_equ_status")
    private String status;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
    /**
     * é™„ä»¶
     */
    @ExcelProperty(value = "附件")
    private String attachments;
    /**
     * èµ„æ–™
     */
    @ExcelProperty(value = "资料")
    private String profile;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquVo.java
@@ -1,9 +1,12 @@
package org.dromara.eims.domain.vo;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.eims.domain.EimsEqu;
@@ -25,7 +28,7 @@
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsEqu.class)
public class EimsEquVo implements Serializable {
public class EimsEquVo extends BaseEntity implements Serializable  {
    @Serial
    private static final long serialVersionUID = 1L;
@@ -33,12 +36,124 @@
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long equId;
    /**
     * è®¾å¤‡åç§°
     */
    @ExcelProperty(value = "设备名称")
    private String equName;
    /**
     * è§„格型号
     */
    @ExcelProperty(value = "规格型号")
    private String modelNo;
    /**
     * åˆ¶é€ åނ家
     */
    @ExcelProperty(value = "制造厂家")
    private String madeIn;
    /**
     * é”€å”®å•†
     */
    @ExcelProperty(value = "销售商")
    private String seller;
    /**
     * å•位
     */
    @ExcelProperty(value = "单位")
    private String unit;
    /**
     * èµ„产编号
     */
    @ExcelProperty(value = "资产编号")
    private String assetNo;
    /**
     * æ‰€åœ¨åœºæ‰€
     */
    @ExcelProperty(value = "所在场所")
    private String location;
    /**
     * ç®¡ç†è€…
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "respPerson")
    @ExcelProperty(value = "管理者")
    private String respPersonName;
    /**
     * è´­ä¹°æ—¥æœŸ
     */
    @ExcelProperty(value = "购买日期")
    @ColumnWidth(24)
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date purchaseDate;
    /**
     * å®žé™…验收日期
     */
    @ExcelProperty(value = "验收日期")
    @ColumnWidth(24)
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date actualAcceptDate;
    /**
     * ç»æ‰‹äºº
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "handleUser")
    @ExcelProperty(value = "经手人")
    private String handleUserName;
    /**
     * é‡‡è´­äºº
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "purchaseUser")
    @ExcelProperty(value = "采购人")
    private String purchaseUserName;
    /**
     * é¢å®šåŠŸçŽ‡
     */
    @ExcelProperty(value = "功率")
    private String ratedPower;
    /**
     * è”系电话
     */
    @ExcelProperty(value = "联系电话")
    private String contactPhone;
    /**
     * ä½¿ç”¨çŠ¶æ€
     */
    @ExcelProperty(value = "使用状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "sys_equ_status")
    private String status;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
    /**
     * é™„ä»¶
     */
    @ExcelProperty(value = "附件")
    private String attachments;
    /**
     * è®¾å¤‡ç¼–码
     */
    @ExcelProperty(value = "设备编码")
    //@ExcelProperty(value = "设备编码")
    private String equCode;
@@ -50,71 +165,21 @@
    /**
     * è®¾å¤‡ç±»åž‹åç§°
     */
    @ExcelProperty(value = "设备类型")
    //@ExcelProperty(value = "设备类型")
    @Translation(type = TransConstant.EQU_YPE_ID_TO_NAME, mapper = "equTypeId")
    private String equTypeName;
    /**
     * èµ„产编号
     */
    @ExcelProperty(value = "资产编号")
    private String assetNo;
    /**
     * è®¾å¤‡åç§°
     */
    @ExcelProperty(value = "设备名称")
    private String equName;
    /**
     * åž‹å·
     */
    @ExcelProperty(value = "型号")
    private String modelNo;
    /**
     * åˆ¶é€ å•†
     */
    @ExcelProperty(value = "制造商")
    private String madeIn;
    /**
     * é¢åº¦åŠŸçŽ‡
     */
    @ExcelProperty(value = "额度功率")
    private String ratedPower;
    /**
     * é“­ç‰Œä¿¡æ¯
     */
    @ExcelProperty(value = "铭牌信息")
    //@ExcelProperty(value = "铭牌信息")
    private String plateInfo;
    /**
     * é‡‡è´­æ—¥æœŸ
     */
    @ExcelProperty(value = "采购日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date purchaseDate;
    /**
     * çŠ¶æ€
     */
    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "sys_equ_status")
    private String status;
    /**
     * æ‰€åœ¨åœºæ‰€
     */
    @ExcelProperty(value = "所在场所")
    private String location;
    /**
     * ä½¿ç”¨éƒ¨é—¨ï¼ˆå…³è”id)
     */
    @ExcelProperty(value = "使用部门", converter = ExcelDictConvert.class)
    //@ExcelProperty(value = "使用部门", converter = ExcelDictConvert.class)
    @ExcelDictFormat(readConverterExp = "关=联id")
    private Long deptUsed;
    /**
@@ -126,75 +191,77 @@
    /**
     * è´£ä»»äºº(关联id)
     */
    @ExcelProperty(value = "责任人(关联id)")
    //@ExcelProperty(value = "责任人(关联id)")
    private Long respPerson;
    /**
     * éƒ¨é—¨å
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "respPerson")
    private String respPersonName;
    /**
     * è”系电话
     */
    @ExcelProperty(value = "联系电话")
    private String contactPhone;
    /**
     * æ­£å¼ä½¿ç”¨æ—¥æœŸ
     */
    @ExcelProperty(value = "正式使用日期")
    //@ExcelProperty(value = "正式使用日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date deployDate;
    /**
     * å¼€å§‹è¯•用日期
     */
    @ExcelProperty(value = "开始试用日期")
    //@ExcelProperty(value = "开始试用日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date trialDate;
    /**
     * è®¡åˆ’验收日期
     */
    @ExcelProperty(value = "计划验收日期")
    //@ExcelProperty(value = "计划验收日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date planAcceptDate;
    /**
     * å®žé™…验收日期
     */
    @ExcelProperty(value = "实际验收日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date actualAcceptDate;
    /**
     * å¯¼å…¥çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
     */
    @ExcelProperty(value = "导入状态", converter = ExcelDictConvert.class)
    //@ExcelProperty(value = "导入状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(readConverterExp = "字=典")
    private String importStatus;
    /**
     * ç›˜ç‚¹æ ‡å¿—
     */
    @ExcelProperty(value = "盘点标志")
    //@ExcelProperty(value = "盘点标志")
    private String inventoryFlag;
    /**
     * ä¸Šæ¬¡ç›˜ç‚¹æ—¥æœŸ
     */
    @ExcelProperty(value = "上次盘点日期")
    //@ExcelProperty(value = "上次盘点日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date inventoryDate;
    /**
     * ä½¿ç”¨å¹´é™
     */
    @ExcelProperty(value = "使用年限")
    //@ExcelProperty(value = "使用年限")
    private Long serviceLife;
    /**
     * ç»æ‰‹äºº
     */
    //@ExcelProperty(value = "经手人")
    private Long handleUser;
    /**
     * é‡‡è´­äºº
     */
    //@ExcelProperty(value = "采购人")
    private Long purchaseUser;
    /**
     * èµ„æ–™
     */
    @ExcelProperty(value = "资料")
    private String profile;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/listener/EimsEquImportListener.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,181 @@
package org.dromara.eims.listener;
import cn.hutool.core.bean.BeanUtil;
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 org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.excel.core.ExcelListener;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.satoken.utils.LoginHelper;
import lombok.extern.slf4j.Slf4j;
import org.dromara.eims.domain.bo.EimsEquBo;
import org.dromara.eims.domain.vo.EimsEquImportVo;
import org.dromara.eims.domain.vo.EimsEquVo;
import org.dromara.eims.service.IEimsEquService;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.service.ISysUserService;
import java.util.List;
import java.util.Map;
/**
 * è®¾å¤‡è‡ªå®šä¹‰å¯¼å…¥
 *
 * @author zhuguifei
 */
@Slf4j
public class EimsEquImportListener extends AnalysisEventListener<EimsEquImportVo> implements ExcelListener<EimsEquImportVo> {
    private final IEimsEquService equService;
    private final ISysUserService userService;
    private final DictService dictService;
    // å½“前导入用户
    private final Long operUserId;
    private final Boolean isUpdateSupport;
    //unit字典
    private final Map<String, String> unitDictMap;
    private int successNum = 0;
    private int failureNum = 0;
    private final StringBuilder successMsg = new StringBuilder();
    private final StringBuilder failureMsg = new StringBuilder();
    public EimsEquImportListener(Boolean isUpdateSupport) {
        this.equService = SpringUtils.getBean(IEimsEquService.class);
        ;
        this.userService = SpringUtils.getBean(ISysUserService.class);
        this.dictService = SpringUtils.getBean(DictService.class);
        this.isUpdateSupport = isUpdateSupport;
        this.operUserId = LoginHelper.getUserId();
        this.unitDictMap = dictService.getAllDictByDictType(CacheConstants.EIMS_EQU_UNIT);
    }
    @Override
    public void invoke(EimsEquImportVo equVo, AnalysisContext context) {
        try {
            // æ ¹æ®èµ„产编号查询设备是否已存在
            EimsEquVo eimsEquVo = equService.queryByAssetNo(equVo.getAssetNo());
            // å¤„理不规则数据
            //1.单位unit-excel导入数据中单位字段不规则,特殊处理
            normalizeUnit(equVo, unitDictMap);
            //2.购买日期、验收日期 ç‰¹æ®Šå¤„理
            if (StringUtils.isNotEmpty(equVo.getPurchaseDateStr())) {
                try {
                    equVo.setPurchaseDate(DateUtils.parseDate(equVo.getPurchaseDateStr()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (StringUtils.isNotEmpty(equVo.getActualAcceptDateStr())) {
                try {
                    equVo.setActualAcceptDate(DateUtils.parseDate(equVo.getActualAcceptDateStr()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // éªŒè¯æ˜¯å¦å­˜åœ¨è¿™ä¸ªç”¨æˆ·
            if (ObjectUtil.isNull(eimsEquVo)) {
                EimsEquBo equ = BeanUtil.toBean(equVo, EimsEquBo.class);
                // TODO æ ¡éªŒ
                //ValidatorUtils.validate(equ);
                equ.setCreateBy(operUserId);
                equService.insertByBo(equ);
                successNum++;
                successMsg.append("<br/>").append(successNum).append("、设备 ").append(equ.getEquName()).append(" å¯¼å…¥æˆåŠŸ");
            } else if (isUpdateSupport) {
                // TODO æ‰§è¡Œè¦†ç›–逻辑
                //successNum++;
                //successMsg.append("<br/>").append(successNum).append("、设备 ").append(equ.getEquName()).append(" æ›´æ–°æˆåŠŸ");
            } else {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("、设备 ").append(eimsEquVo.getEquName()).append(eimsEquVo.getAssetNo()).append(" å·²å­˜åœ¨");
            }
        } catch (Exception e) {
            failureNum++;
            String msg = "<br/>" + failureNum + "、设备 " + equVo.getEquName() + " å¯¼å…¥å¤±è´¥ï¼š";
            failureMsg.append(msg).append(e.getMessage());
            log.error(msg, e);
        }
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
    }
    @Override
    public ExcelResult<EimsEquImportVo> getExcelResult() {
        return new ExcelResult<>() {
            @Override
            public String getAnalysis() {
                if (failureNum > 0) {
                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " æ¡æ•°æ®æ ¼å¼ä¸æ­£ç¡®ï¼Œé”™è¯¯å¦‚下:");
                    throw new ServiceException(failureMsg.toString());
                } else {
                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " æ¡ï¼Œæ•°æ®å¦‚下:");
                }
                return successMsg.toString();
            }
            @Override
            public List<EimsEquImportVo> getList() {
                return null;
            }
            @Override
            public List<String> getErrorList() {
                return null;
            }
        };
    }
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
        // å¦‚果是某一个单元格的转换异常 èƒ½èŽ·å–åˆ°å…·ä½“è¡Œå·
        // å¦‚果要获取头的信息 é…åˆinvokeHeadMap使用
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
            log.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(),
                excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
        }
    }
    /**
     * ä¸ºå¯¼å…¥è®¾å¤‡åŒ¹é…å•位
     *
     * @param equVo
     * @param unitDictMap
     */
    private void normalizeUnit(EimsEquImportVo equVo, Map<String, String> unitDictMap) {
        if (equVo == null || StringUtils.isEmpty(equVo.getUnit()) || unitDictMap == null || unitDictMap.isEmpty()) {
            return;
        }
        String originalUnit = equVo.getUnit();
        //避免错误单位
        equVo.setUnit(null);
        for (Map.Entry<String, String> entry : unitDictMap.entrySet()) {
            if (originalUnit.contains(entry.getValue())) {
                equVo.setUnit(entry.getValue());
                break;
            }
        }
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsEquService.java
@@ -26,6 +26,14 @@
    EimsEquVo queryById(Long equId);
    /**
     * æŸ¥è¯¢ã€è®¾å¤‡å°è´¦ã€‘
     *
     * @param assetNo èµ„产编号
     * @return ã€è®¾å¤‡å°è´¦ã€‘
     */
    EimsEquVo queryByAssetNo(String assetNo);
    /**
     * åˆ†é¡µæŸ¥è¯¢ã€è®¾å¤‡å°è´¦ã€‘列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsEquServiceImpl.java
@@ -46,8 +46,15 @@
     * @return ã€è®¾å¤‡å°è´¦ã€‘
     */
    @Override
    public EimsEquVo queryById(Long equId){
    public EimsEquVo queryById(Long equId) {
        return baseMapper.selectVoById(equId);
    }
    @Override
    public EimsEquVo queryByAssetNo(String assetNo) {
        LambdaQueryWrapper<EimsEqu> lqw = new LambdaQueryWrapper<>();
        lqw.eq(EimsEqu::getAssetNo, assetNo);
        return baseMapper.selectVoOne(lqw);
    }
    /**
@@ -87,7 +94,7 @@
         */
        if (equTypeId != null && equTypeId > 0) {
            List<Long> allDescendantIds = getAllDescendantIds(equTypeId);
            lqw.in(EimsEqu::getEquTypeId,allDescendantIds);
            lqw.in(EimsEqu::getEquTypeId, allDescendantIds);
        }
        lqw.like(StringUtils.isNotBlank(bo.getEquName()), EimsEqu::getEquName, bo.getEquName());
@@ -117,6 +124,7 @@
    /**
     * æ ¹æ®id,获取所有后代id
     *
     * @param rootId
     * @return
     */
@@ -140,6 +148,7 @@
            }
        }
    }
    /**
     * æ–°å¢žã€è®¾å¤‡å°è´¦ã€‘
     *
@@ -173,7 +182,7 @@
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsEqu entity){
    private void validEntityBeforeSave(EimsEqu entity) {
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
@@ -186,7 +195,7 @@
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
        if (isValid) {
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java
@@ -68,19 +68,21 @@
    private QueryWrapper<EimsRepairReq> buildWrapper(EimsRepairReqBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<EimsRepairReq> qw = Wrappers.query();
        qw.eq(StringUtils.isNotBlank(bo.getCode()),"code", bo.getCode());
        qw.eq(StringUtils.isNotBlank(bo.getStatus()), "status", bo.getStatus());
        qw.eq(bo.getReqTime() != null, "req_time", bo.getReqTime());
        qw.eq(bo.getReqDept() != null, "req_dept", bo.getReqDept());
        qw.eq(bo.getReqUser() != null,"req_user", bo.getReqUser());
        qw.eq(StringUtils.isNotBlank(bo.getUrgencyLevel()), "urgency_level", bo.getUrgencyLevel());
        qw.eq(StringUtils.isNotBlank(bo.getReqType()), "req_type", bo.getReqType());
        qw.eq(bo.getEquId() != null, "equ_id", bo.getEquId());
        qw.eq(bo.getRepairDept() != null,"repair_dept", bo.getRepairDept());
        qw.eq(bo.getRepairUser() != null, "repair_user", bo.getRepairUser());
        qw.eq(StringUtils.isNotBlank(bo.getFaultType()), "fault_type", bo.getFaultType());
        qw.like(StringUtils.isNotBlank(bo.getCode()),"a.code", bo.getCode());
        qw.eq(StringUtils.isNotBlank(bo.getStatus()), "a.status", bo.getStatus());
        qw.eq(bo.getReqTime() != null, "a.req_time", bo.getReqTime());
        qw.eq(bo.getReqDept() != null, "a.req_dept", bo.getReqDept());
        qw.eq(bo.getReqUser() != null,"a.req_user", bo.getReqUser());
        qw.eq(StringUtils.isNotBlank(bo.getUrgencyLevel()), "a.urgency_level", bo.getUrgencyLevel());
        qw.eq(StringUtils.isNotBlank(bo.getReqType()), "a.req_type", bo.getReqType());
        qw.eq(bo.getEquId() != null, "a.equ_id", bo.getEquId());
        qw.eq(bo.getRepairDept() != null,"a.repair_dept", bo.getRepairDept());
        qw.eq(bo.getRepairUser() != null, "a.repair_user", bo.getRepairUser());
        qw.eq(StringUtils.isNotBlank(bo.getFaultType()), "a,fault_type", bo.getFaultType());
        qw.eq(params.containsKey("createBy"), "a.create_by", params.get("createBy"));
        qw.eq(params.containsKey("status"), "a.status", params.get("status"));
        qw.between(params.get("beginReqTime") != null && params.get("endReqTime") != null,
            "req_time", params.get("beginReqTime"), params.get("endReqTime"));
            "a.req_time", params.get("beginReqTime"), params.get("endReqTime"));
        return qw;
    }