车间能级提升-智能设备管理系统
朱桂飞
2025-02-08 a4e9be7205274b93571c74268855b39129145328
添加盘点模块
已添加27个文件
已修改5个文件
3108 ■■■■■ 文件已修改
eims-ui/apps/web-antd/src/api/eims/equ-trial/model.d.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/inventory-detail/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/inventory-detail/model.d.ts 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/inventory/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/inventory/model.d.ts 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/router/routes/local.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/data.tsx 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/equ-drawer.vue 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/equ-type-tree.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/index.vue 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory/data.tsx 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory/index.vue 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory/inventory-drawer.vue 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInventoryController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInventoryDetailController.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsInventory.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsInventoryDetail.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsInventoryBo.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsInventoryDetailBo.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsInventoryDetailVo.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsInventoryVo.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInventoryDetailMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInventoryMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInventoryDetailService.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInventoryService.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInventoryDetailServiceImpl.java 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInventoryServiceImpl.java 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsInventoryDetailMapper.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsInventoryMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/equ-trial/model.d.ts
@@ -35,6 +35,11 @@
  operatorId: number | string;
  /**
   * æ“ä½œäººéƒ¨é—¨
   */
  operatorDept: operatorDept | string;
  /**
   * å¼€å§‹æ—¶é—´
   */
  startTime: string;
eims-ui/apps/web-antd/src/api/eims/inventory-detail/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import type { InventoryDetailVO } from './model';
import type { ID, IDS } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  inventoryDetailExport = '/eims/inventoryDetail/export',
  inventoryDetailList = '/eims/inventoryDetail/list',
  root = '/eims/inventoryDetail'
}
/**
 * æŸ¥è¯¢ç›˜ç‚¹åˆ—表
 * @param query
 * @returns {*}
 */
export function listInventoryDetail(params?: any) {
  return requestClient.get<InventoryDetailVO[]>(Api.inventoryDetailList, { params });
}
/**
 * æŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†
 * @param inventoryDetailId
 */
export function getInventoryDetail(inventoryDetailId: ID) {
  return requestClient.get<InventoryDetailVO>(`${Api.root}/${inventoryDetailId}`);
}
/**
 * æ–°å¢žç›˜ç‚¹æ˜Žç»†
 * @param data
 */
export function addInventoryDetail(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹ç›˜ç‚¹æ˜Žç»†
 * @param data
 */
export function updateInventoryDetail(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤ç›˜ç‚¹æ˜Žç»†
 * @param inventoryId
 */
export function delInventoryDetail(inventoryDetailId: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${inventoryDetailId}`);
}
/**
 * å¯¼å‡º
 * @param
 */
export function inventoryDetailExport(data: any) {
  return commonExport(Api.inventoryDetailExport, data);
}
eims-ui/apps/web-antd/src/api/eims/inventory-detail/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
export interface InventoryDetailVO {
  /**
   * æ˜Žç»†id
   */
  id: number | string;
  /**
   * ç›˜ç‚¹id
   */
  inventoryId: number | string;
  /**
   * çŠ¶æ€
   */
  status: string;
  /**
   * è®¾å¤‡åç§°
   */
  equName: string;
  /**
   * è®¾å¤‡ç¼–码
   */
  equCode: string;
  /**
   * è®¾å¤‡èµ„产编号
   */
  equAssetNo: string;
  /**
   * éƒ¨é—¨åç§°
   */
  deptName: string;
  /**
   * è®¾å¤‡ç±»åž‹åç§°
   */
  equTypeName: string;
  /**
   * è®¾å¤‡æ‰€åœ¨ä½ç½®
   */
  location: string;
  /**
   * è®¾å¤‡çŠ¶æ€
   */
  equStatus: string;
  //
  /**
   * ç›˜ç‚¹äºº
   */
  inventoryUser: string;
}
eims-ui/apps/web-antd/src/api/eims/inventory/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import type { InventoryVO } from './model';
import type { ID, IDS } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  inventoryExport = '/eims/inventory/export',
  inventoryList = '/eims/inventory/list',
  root = '/eims/inventory'
}
/**
 * æŸ¥è¯¢ç›˜ç‚¹åˆ—表
 * @param query
 * @returns {*}
 */
export function listInventory(params?: any) {
  return requestClient.get<InventoryVO[]>(Api.inventoryList, { params });
}
/**
 * æŸ¥è¯¢ç›˜ç‚¹è¯¦ç»†
 * @param inventoryId
 */
export function getInventory(inventoryId: ID) {
  return requestClient.get<InventoryVO>(`${Api.root}/${inventoryId}`);
}
/**
 * æ–°å¢žç›˜ç‚¹
 * @param data
 */
export function addInventory(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹ç›˜ç‚¹
 * @param data
 */
export function updateInventory(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤ç›˜ç‚¹
 * @param inventoryId
 */
export function delInventory(inventoryId: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${inventoryId}`);
}
/**
 * å¯¼å‡º
 * @param
 */
export function inventoryExport(data: any) {
  return commonExport(Api.inventoryExport, data);
}
eims-ui/apps/web-antd/src/api/eims/inventory/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
export interface InventoryVO {
  /**
   * ç›˜ç‚¹id
   */
  inventoryId: number | string;
  /**
   * ç›˜ç‚¹å•号
   */
  inventoryCode: string;
  /**
   * ç›˜ç‚¹åç§°
   */
  inventoryName: string;
  /**
   * ç›˜ç‚¹äºº
   */
  inventoryUser: number;
  /**
   * ç›˜ç‚¹äººéƒ¨é—¨
   */
  userDept: number;
  /**
   * å¼€å§‹æ—¥æœŸ
   */
  startDate: string;
  /**
   * ç»“束日期
   */
  endDate: string;
  /**
   * ç›˜ç‚¹çŠ¶æ€
   */
  status: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface InventoryForm extends BaseEntity {
  /**
   * ç›˜ç‚¹id
   */
  inventoryId?: number | string;
  /**
   * ç›˜ç‚¹å•号
   */
  inventoryCode?: string;
  /**
   * ç›˜ç‚¹åç§°
   */
  inventoryName?: string;
  /**
   * ç›˜ç‚¹äºº
   */
  inventoryUser?: number;
  /**
   * å¼€å§‹æ—¥æœŸ
   */
  startDate?: string;
  /**
   * ç»“束日期
   */
  endDate?: string;
  /**
   * ç›˜ç‚¹çŠ¶æ€
   */
  status?: string;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
eims-ui/apps/web-antd/src/router/routes/local.ts
@@ -129,6 +129,30 @@
      }
    ]
  },
  {
    component: 'BasicLayout',
    meta: {
      hideChildrenInMenu: true,
      hideInMenu: true,
      title: '盘点明细'
    },
    name: 'InventoryDetail',
    path: '/',
    redirect: '/inventory/detail',
    children: [
      {
        component: '/eims/inventory-detail/index',
        meta: {
          activePath: '/equ/inventory',
          icon: 'eos-icons:role-binding-outlined',
          keepAlive: true,
          title: '盘点明细'
        },
        name: 'InventoryDetailIndex',
        path: '/inventory/detail/:inventoryId'
      }
    ]
  },
];
/**
eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue
@@ -56,6 +56,9 @@
    if (isUpdate.value && id) {
      const record = await getEquStatu(id);
      await formApi.setValues(record);
      if(isUpdate.value && record.userDept){
        await setupUserOptions(record.userDept);
      }
    }
    // è®¾å¤‡id有值时不允许编辑(1.编辑 2.设备详情页打开)
    const flag = equId !== undefined || isUpdate.value;
@@ -158,7 +161,7 @@
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
          formModel.changeUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue
@@ -54,6 +54,9 @@
    if (isUpdate.value && id) {
      const record = await getEquTrial(id);
      await formApi.setValues(record);
      if(isUpdate.value && record.operatorDept){
        await setupUserOptions(record.operatorDept);
      }
    }
    // è®¾å¤‡id有值时不允许编辑(1.编辑 2.设备详情页打开)
    const flag = equId !== undefined || isUpdate.value;
@@ -153,7 +156,7 @@
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
          formModel.operatorId = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
eims-ui/apps/web-antd/src/views/eims/inventory-detail/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,328 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { Tag } from 'ant-design-vue';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'equCode',
    label: '设备编码'
  },
  {
    component: 'Input',
    fieldName: 'equName',
    label: '设备名称'
  },
  {
    component: 'Input',
    fieldName: 'equAssetNo',
    label: '资产编号'
  },
  {
    component: 'Input',
    fieldName: 'location',
    label: '所在场所'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.SYS_EQU_STATUS)
    },
    fieldName: 'equStatus',
    label: '设备状态'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_INVENTORY_DETAIL_STATU)
    },
    fieldName: 'status',
    label: '盘点明细'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '设备编号',
    field: 'equCode',
    minWidth: 120,
    fixed: 'left',
  },
  {
    title: '设备名称',
    field: 'equName',
    minWidth: 100,
    fixed: 'left',
  },
  {
    title: '资产编号',
    field: 'equAssetNo',
    sortable: true,
    minWidth: 100,
  },
  {
    title: '使用部门',
    field: 'deptName',
    minWidth: 100,
  },
  {
    title: '设备类型',
    field: 'equTypeName',
    minWidth: 100,
  },
  {
    title: '设备位置',
    field: 'location',
    minWidth: 100,
  },
  {
    title: '设备状态',
    field: 'equStatus',
    sortable: true,
    slots: {
      default: ({ row }) => {
        const statu = row.status;
        switch (statu) {
          case '0': {
            return <Tag color="cyan">试用</Tag>;
          }
          case '1': {
            return <Tag color="green">入固</Tag>;
          }
          case '2': {
            return <Tag color="orange">迁移</Tag>;
          }
          case '3': {
            return <Tag color="red">报废</Tag>;
          }
          case null: {
            return '';
          }
          // No default
        }
        return '';
      }
    },
    minWidth: 80,
  },
  {
    title: '盘点人',
    field: 'inventoryUser',
    sortable: true,
    minWidth: 100
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'equId'
  },
  {
    component: 'TreeSelect',
    defaultValue: 0,
    fieldName: 'equTypeId',
    label: '设备类型',
    rules: 'selectRequired'
  },
  {
    component: 'Input',
    fieldName: 'equName',
    label: '设备名称',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'equCode',
    label: '设备编码',
    help: '设备唯一编码'
  },
  {
    component: 'Input',
    fieldName: 'assetNo',
    label: '资产编号'
  },
  {
    component: 'Input',
    fieldName: 'modelNo',
    label: '型号'
  },
  {
    component: 'Input',
    fieldName: 'madeIn',
    label: '制造商'
  },
  {
    component: 'Input',
    fieldName: 'ratedPower',
    label: '额定功率'
  },
  {
    component: 'Input',
    fieldName: 'plateInfo',
    label: '铭牌信息'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'purchaseDate',
    label: '采购日期'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_EQU_STATUS),
      optionType: 'button'
    },
    defaultValue: '0',
    fieldName: 'status',
    label: '状态'
  },
  {
    component: 'Input',
    fieldName: 'location',
    label: '所在场所',
    help: `设备实际摆放场所`
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'deptUsed',
    label: '使用部门'
    // rules: 'selectRequired',
  },
  {
    component: 'Select',
    componentProps: {
      allowClear: true,
      showSearch: true,
      getPopupContainer
    },
    fieldName: 'respPerson',
    label: '责任人',
    help: `设备负责人,管理人员`
  },
  {
    component: 'Input',
    fieldName: 'contactPhone',
    label: '联系电话',
    defaultValue: undefined,
    rules: z
      .string()
      .regex(/^1[3-9]\d{9}$/, '请输入正确的手机号码')
      .optional()
      .or(z.literal(''))
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'deployDate',
    label: '正式使用日期'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'trialDate',
    label: '开始试用日期'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'planAcceptDate',
    label: '计划验收日期'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'actualAcceptDate',
    label: '实际验收日期'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_NORMAL_DISABLE),
      optionType: 'button'
    },
    defaultValue: '0',
    fieldName: 'importStatus',
    formItemClass: 'col-span-2 lg:col-span-1',
    label: '导入状态'
  },
  {
    component: 'Input',
    fieldName: 'serviceLife',
    label: '使用年限'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_NORMAL_DISABLE),
      optionType: 'button'
    },
    defaultValue: '0',
    fieldName: 'inventoryFlag',
    formItemClass: 'col-span-2 lg:col-span-1',
    label: '盘点标志'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'inventoryDate',
    label: '上次盘点日期'
  }
];
eims-ui/apps/web-antd/src/views/eims/inventory-detail/equ-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,211 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, cloneDeep, getPopupContainer, listToTree } from '@vben/utils';
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 { drawerSchema } from './data';
const emit = defineEmits<{ reload: [] }>();
const typeDisabled = ref(false);
const isUpdate = ref(false);
const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
  commonConfig: {
    formItemClass: 'col-span-2',
    componentProps: {
      class: 'w-full'
    },
    labelWidth: 120
  },
  schema: drawerSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2'
});
const [BasicDrawer, drawerApi] = useVbenDrawer({
  onCancel: handleCancel,
  onConfirm: handleConfirm,
  async onOpenChange(isOpen) {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);
    const { id } = drawerApi.getData() as { id?: number | string };
    const { typeDisable } = drawerApi.getData() as { typeDisable?: boolean };
    typeDisabled.value = !!typeDisable;
    isUpdate.value = !!id;
    // åˆå§‹åŒ–
    await setupDeptSelect();
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getEqu(id);
      await formApi.setValues(record);
      if(isUpdate.value && record.deptUsed){
        await setupUserOptions(record.deptUsed)
      }
    }
    // åŠ è½½è®¾å¤‡ç±»åž‹æ ‘é€‰æ‹©
    await setupEquTypeSelect();
    if (id) {
      await formApi.setFieldValue('parentId', id);
      if (isUpdate.value && id) {
        const record = await getEquType(id);
        await formApi.setValues(record);
      }
    }
    drawerApi.drawerLoading(false);
  }
});
async function setupEquTypeSelect() {
  // status-0 åªæŸ¥è¯¢æœªåœç”¨è®¾å¤‡
  const equArray = await listEquType({ status: 0 });
  // support i18n
  equArray.forEach((item) => {
    item.typeName = $t(item.typeName);
  });
  const equTree = listToTree(equArray, { id: 'equTypeId', pid: 'parentId' });
  const fullEquTree = [
    {
      equTypeId: 0,
      typeName: $t('menu.root'),
      children: equTree,
    },
  ];
  addFullName(fullEquTree, 'typeName', ' / ');
  formApi.updateSchema([
    {
      componentProps: {
        fieldNames: {
          label: 'typeName',
          value: 'equTypeId',
        },
        getPopupContainer,
        // è®¾ç½®å¼¹çª—滚动高度 é»˜è®¤256
        listHeight: 300,
        showSearch: true,
        treeData: fullEquTree,
        disabled: typeDisabled.value,
        treeDefaultExpandAll: false,
        // é»˜è®¤å±•开的树节点
        treeDefaultExpandedKeys: [0],
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'typeName',
        treeNodeLabelProp: 'fullName',
      },
      fieldName: 'equTypeId',
    },
  ]);
}
/**
 * ç”¨æˆ·çš„加载
 */
async function setupUserOptions(deptId: any) {
  const params = { deptId };
  const userPageResult = await userList({
    pageNum: 1,
    pageSize: 500,
    ...params
  });
  const options = userPageResult.rows.map((item) => ({
    label: item.nickName || item.userName,
    value: item.userId
  }));
  // ç­›é€‰
  const filterOption = (input: string, option: any) => {
    return option.label.toLowerCase().includes(input.toLowerCase());
  };
  const placeholder = options.length > 0 ? '请选择' : '该部门下暂无用户';
  formApi.updateSchema([
    {
      componentProps: { options, placeholder ,filterOption },
      fieldName: 'respPerson'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
async function setupDeptSelect() {
  // updateSchema
  const deptTree = await getDeptTree();
  // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值 å³çˆ¶èŠ‚ç‚¹ / å­èŠ‚ç‚¹
  addFullName(deptTree, 'label', ' / ');
  formApi.updateSchema([
    {
      componentProps: (formModel) => ({
        class: 'w-full',
        fieldNames: {
          key: 'id',
          value: 'id',
          children: 'children'
        },
        getPopupContainer,
        async onSelect(deptId: number | string) {
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'deptUsed'
    }
  ]);
}
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    await (isUpdate.value ? updateEqu(data) : addEqu(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm />
  </BasicDrawer>
</template>
eims-ui/apps/web-antd/src/views/eims/inventory-detail/equ-type-tree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
<script setup lang="ts">
import type { DeptTree } from '#/api/system/user/model';
import { onMounted, type PropType, ref } from 'vue';
import { SyncOutlined } from '@ant-design/icons-vue';
import { Empty, InputSearch, Skeleton, Tree } from 'ant-design-vue';
import { getEquTypeTree } from '#/api/eims/equ-type';
defineOptions({ inheritAttrs: false });
const emit = defineEmits<{
  /**
   * ç‚¹å‡»åˆ·æ–°æŒ‰é’®çš„事件
   */
  reload: [];
  /**
   * ç‚¹å‡»èŠ‚ç‚¹çš„äº‹ä»¶
   */
  select: [];
}>();
const selectDeptId = defineModel('selectDeptId', {
  required: true,
  type: Array as PropType<string[]>,
});
const searchValue = defineModel('searchValue', {
  type: String,
  default: '',
});
/** éƒ¨é—¨æ•°æ®æº */
type DeptTreeArray = DeptTree[];
const deptTreeArray = ref<DeptTreeArray>([]);
/** éª¨æž¶å±åŠ è½½ */
const showTreeSkeleton = ref<boolean>(true);
async function loadTree() {
  showTreeSkeleton.value = true;
  searchValue.value = '';
  selectDeptId.value = [];
  const ret = await getEquTypeTree();
  deptTreeArray.value = ret;
  showTreeSkeleton.value = false;
}
async function handleReload() {
  await loadTree();
  emit('reload');
}
onMounted(loadTree);
</script>
<template>
  <div :class="$attrs.class">
    <Skeleton
      :loading="showTreeSkeleton"
      :paragraph="{ rows: 8 }"
      active
      class="p-[8px]"
    >
      <div
        class="bg-background flex h-full flex-col overflow-y-auto rounded-lg"
      >
        <!-- å›ºå®šåœ¨é¡¶éƒ¨ å¿…须加上bg-background背景色 å¦åˆ™ä¼šäº§ç”Ÿ'穿透'效果 -->
        <div class="bg-background z-100 sticky left-0 top-0 p-[8px]">
          <InputSearch
            v-model:value="searchValue"
            :placeholder="$t('pages.common.search')"
            size="small"
          >
            <template #enterButton>
              <a-button @click="handleReload">
                <SyncOutlined class="text-primary" />
              </a-button>
            </template>
          </InputSearch>
        </div>
        <div class="h-full overflow-x-hidden px-[8px]">
          <Tree
            v-bind="$attrs"
            v-if="deptTreeArray.length > 0"
            v-model:selected-keys="selectDeptId"
            :class="$attrs.class"
            :field-names="{ title: 'label', key: 'id' }"
            :show-line="{ showLeafIcon: false }"
            :tree-data="deptTreeArray"
            :virtual="false"
            default-expand-all
            @select="$emit('select')"
          >
            <template #title="{ label }">
              <span v-if="label.indexOf(searchValue) > -1">
                {{ label.substring(0, label.indexOf(searchValue)) }}
                <span style="color: #f50">{{ searchValue }}</span>
                {{
                  label.substring(
                    label.indexOf(searchValue) + searchValue.length,
                  )
                }}
              </span>
              <span v-else>{{ label }}</span>
            </template>
          </Tree>
          <!-- ä»…本人数据权限 å¯ä»¥è€ƒè™‘直接不显示 -->
          <div v-else class="mt-5">
            <Empty
              :image="Empty.PRESENTED_IMAGE_SIMPLE"
              description="无部门数据"
            />
          </div>
        </div>
      </div>
    </Skeleton>
  </div>
</template>
eims-ui/apps/web-antd/src/views/eims/inventory-detail/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,207 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { delInventoryDetail, inventoryDetailExport, listInventoryDetail } from '#/api/eims/inventory-detail';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import equDrawer from './equ-drawer.vue';
import EquTypeTree from './equ-type-tree.vue';
const route = useRoute();
const inventoryId = route.params.inventoryId as string;
// å·¦è¾¹éƒ¨é—¨ç”¨
const selectTypeId = ref<string[]>([]);
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true
    }
  },
  schema: querySchema(),
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  handleReset: async () => {
    selectTypeId.value = [];
    // eslint-disable-next-line no-use-before-define
    const { formApi, reload } = tableApi;
    await formApi.resetForm();
    const formValues = formApi.form.values;
    formApi.setLatestSubmissionValues(formValues);
    await reload(formValues);
  },
  // æ—¥æœŸé€‰æ‹©æ ¼å¼åŒ–
  fieldMappingTime: [['createTime', ['params[beginTime]', 'params[endTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']]]
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // éƒ¨é—¨æ ‘选择处理
        if (selectTypeId.value.length === 1) {
          formValues.equTypeId = selectTypeId.value[0];
        } else {
          Reflect.deleteProperty(formValues, 'equTypeId');
        }
        return await listInventoryDetail({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-inventory-detail-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [EquDrawer, equDrawerApi] = useVbenDrawer({
  connectedComponent: equDrawer
});
function handleAdd() {
  equDrawerApi.setData({});
  equDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  equDrawerApi.setData({ id: record.equId });
  equDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delInventoryDetail(row.id);
  await tableApi.query();
}
function handleMultiDelete() {
  const rows = tableApi.grid.getCheckboxRecords();
  const ids = rows.map((row: any) => row.id);
  Modal.confirm({
    title: '提示',
    okType: 'danger',
    content: `确认删除选中的${ids.length}条记录吗?`,
    onOk: async () => {
      await delInventoryDetail(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(inventoryDetailExport, '盘点明细', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
function getImportStatus(row: any) {
  const importStatus = row.importStatus === null || row.importStatus;
  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.id}`);
}
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <EquTypeTree v-model:select-dept-id="selectTypeId" 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="['eims:inventory:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button :disabled="!vxeCheckboxChecked(tableApi)" danger type="primary" v-access:code="['eims:inventory:remove']" @click="handleMultiDelete">
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:inventory:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #equName="{ row }">
          <Space>
            <a-button type="link" @click="handleDetail(row)"> {{ row.equName }}</a-button>
          </Space>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:inventory:edit']" @click.stop="handleEdit(row)">
              {{ $t('pages.common.edit') }}
            </ghost-button>
            <ghost-button v-if="row.menuType !== 'F'" class="btn-success" v-access:code="['eims:inventory:list']" @click="handleDetail(row)">
              {{ $t('pages.common.info') }}
            </ghost-button>
            <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
              <ghost-button danger v-access:code="['eims:inventory:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
        <template #importStatus="{ row }">
          <span>{{ getImportStatus(row) }}</span>
        </template>
        <template #inventoryFlag="{ row }">
          <span>{{ getInventoryFlag(row) }}</span>
        </template>
      </BasicTable>
    </div>
    <EquDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/inventory/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,211 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { Badge } from 'ant-design-vue';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'inventoryName',
    label: '盘点名称'
  },
  {
    component: 'Input',
    fieldName: 'inventoryCode',
    label: '盘点单号'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'userDept',
    label: '盘点部门',
    help: `盘点操作人员所属部门`
    // rules: 'selectRequired',
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'inventoryUser',
    label: '盘点人'
  },
  {
    component: 'RangePicker',
    fieldName: 'startDate',
    label: '盘点日期',
    help: '开始盘点日期'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '盘点名称',
    field: 'inventoryName',
    minWidth: 100
  },
  {
    title: '盘点单号',
    field: 'inventoryCode',
    minWidth: 100,
    slots: { default: 'inventoryCode' }
  },
  {
    title: '盘点状态',
    field: 'status',
    minWidth: 100,
    slots: {
      default: ({ row }) => {
        const statu = row.status;
        switch (statu) {
          case '0': {
            return <Badge status="processing" text="盘点中" />;
          }
          case '1': {
            return <Badge status="success" text="盘点结束" />;
          }
          case null: {
            return <Badge status="processing" text="盘点中" />;
          }
          // No default
        }
        return '';
      }
    }
  },
  {
    title: '开始日期',
    field: 'startDate',
    sortable: true,
    minWidth: 120
  },
  {
    title: '结束日期',
    field: 'endDate',
    sortable: true,
    minWidth: 120
  },
  {
    title: '盘点人',
    field: 'inventoryUserName',
    minWidth: 100
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'inventoryId'
  },
  {
    component: 'Input',
    fieldName: 'inventoryName',
    label: '盘点名称'
  },
  {
    component: 'Input',
    fieldName: 'inventoryCode',
    label: '盘点单号'
  },
  {
    component: 'Radio',
    dependencies: {
      show: () => false,
      triggerFields: [''],
    },
    fieldName: 'checkStrictly',
    label: '父子联动'
  },
  {
    component: 'Input',
    defaultValue: [],
    fieldName: 'equTypesList',
    label: '设备类型',
    help: `设备类型留空不勾选,系统默认盘点全部`,
    formItemClass: 'col-span-2',
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      mode: 'multiple',
      optionFilterProp: 'label',
      options: getDictOptions(DictEnum.SYS_EQU_STATUS),
    },
    fieldName: 'equStatusList',
    label: '使用状态',
    help: `使用状态留空不勾选,系统默认盘点全部`,
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.EIMS_INVENTORY_STATU),
      optionType: 'button'
    },
    defaultValue: '0',
    fieldName: 'status',
    label: '状态'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'startDate',
    label: '开始日期'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'endDate',
    label: '结束日期'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'userDept',
    label: '盘点人部门',
    help: `盘点操作人员所属部门`
    // rules: 'selectRequired',
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'inventoryUser',
    label: '盘点人'
  }
];
eims-ui/apps/web-antd/src/views/eims/inventory/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,242 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, getPopupContainer, getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { delInventory, inventoryExport, listInventory } from '#/api/eims/inventory';
import { getDeptTree, userList } from '#/api/system/user';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import inventoryDrawer from './inventory-drawer.vue';
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true
    }
  },
  schema: querySchema(),
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  // æ—¥æœŸé€‰æ‹©æ ¼å¼åŒ–
  fieldMappingTime: [['startDate', ['params[beginStartDate]', 'params[endStartDate]'], ['YYYY-MM-DD', 'YYYY-MM-DD']]]
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        return await listInventory({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'inventoryId'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-inventory-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [InventoryDrawer, inventoryDrawerApi] = useVbenDrawer({
  connectedComponent: inventoryDrawer
});
function handleAdd() {
  inventoryDrawerApi.setData({});
  inventoryDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  inventoryDrawerApi.setData({ id: record.inventoryId });
  inventoryDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delInventory(row.inventoryId);
  await tableApi.query();
}
function handleMultiDelete() {
  const rows = tableApi.grid.getCheckboxRecords();
  const ids = rows.map((row: any) => row.inventoryId);
  Modal.confirm({
    title: '提示',
    okType: 'danger',
    content: `确认删除选中的${ids.length}条记录吗?`,
    onOk: async () => {
      await delInventory(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(inventoryExport, '设备盘点记录', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
onMounted(async () => {
  await setupDeptSelect();
});
/**
 * ç”¨æˆ·çš„加载
 */
async function setupUserOptions(deptId: any) {
  const params = { deptId };
  const userPageResult = await userList({
    pageNum: 1,
    pageSize: 500,
    ...params
  });
  const options = userPageResult.rows.map((item) => ({
    label: item.nickName || item.userName,
    value: item.userId
  }));
  // ç­›é€‰
  const filterOption = (input: string, option: any) => {
    return option.label.toLowerCase().includes(input.toLowerCase());
  };
  const placeholder = options.length > 0 ? '请选择' : '该部门下暂无用户';
  tableApi.formApi.updateSchema([
    {
      componentProps: { options, placeholder, filterOption },
      fieldName: 'inventoryUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
async function setupDeptSelect() {
  // updateSchema
  const deptTree = await getDeptTree();
  // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值 å³çˆ¶èŠ‚ç‚¹ / å­èŠ‚ç‚¹
  addFullName(deptTree, 'label', ' / ');
  tableApi.formApi.updateSchema([
    {
      componentProps: (formModel) => ({
        class: 'w-full',
        fieldNames: {
          key: 'id',
          value: 'id',
          children: 'children'
        },
        getPopupContainer,
        async onSelect(deptId: number | string) {
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'userDept'
    }
  ]);
}
const router = useRouter();
function handleDetail(record: Recordable<any>) {
  router.push(`/inventory/detail/${record.inventoryId}`);
}
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <BasicTable class="flex-1 overflow-hidden" table-title="设备盘点列表">
        <template #toolbar-tools>
          <Space>
            <a-button v-access:code="['eims:inventory:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:inventory:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:inventory:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #inventoryCode="{ row }">
          <Space>
            <a-button type="link" @click="handleDetail(row)"> {{ row.inventoryCode }}</a-button>
          </Space>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:inventory: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="['eims:inventory:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <InventoryDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/inventory/inventory-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,221 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, cloneDeep, getPopupContainer, listToTree } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { listEquType } from '#/api/eims/equ-type';
import { addInventory, getInventory, updateInventory } from '#/api/eims/inventory';
import { getDeptTree, userList } from '#/api/system/user';
import { TreeSelectPanel } from '#/components/tree';
import { drawerSchema } from './data';
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
  commonConfig: {
    formItemClass: 'col-span-2',
    componentProps: {
      class: 'w-full'
    },
    labelWidth: 120
  },
  schema: drawerSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2'
});
const [BasicDrawer, drawerApi] = useVbenDrawer({
  onCancel: handleCancel,
  onConfirm: handleConfirm,
  async onOpenChange(isOpen) {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);
    const { id } = drawerApi.getData() as { id?: number | string };
    isUpdate.value = !!id;
    // åˆå§‹åŒ–
    await setupDeptSelect();
    await setupEquTypeSelect();
    formApi.updateSchema([
      {
        dependencies: {
          show: () => !isUpdate.value,
          triggerFields: ['']
        },
        fieldName: 'equTypesList'
      },
      {
        dependencies: {
          show: () => !isUpdate.value,
          triggerFields: ['']
        },
        fieldName: 'equStatusList'
      }
    ]);
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getInventory(id);
      await formApi.setValues(record);
      // æ›´æ–°æ—¶ä¸å¯ä¿®æ”¹ç›˜ç‚¹èŒƒå›´
      if (isUpdate.value && record.userDept) {
        await setupUserOptions(record.userDept);
      }
    }
    drawerApi.drawerLoading(false);
  }
});
/**
 * åŠ è½½è®¾å¤‡ç±»æ ‘
 */
const equTypeTree = ref();
async function setupEquTypeSelect() {
  const result = (await listEquType()) || [];
  // æž„建组件需要数据
  const equArray = result.map((item) => {
    return {
      ...item, // ä¿ç•™åŽŸæœ‰å¯¹è±¡çš„æ‰€æœ‰å±žæ€§
      id: item.equTypeId,
      label: item.typeName,
      weight: item.orderNum
    };
  });
  // support i18n
  equArray.forEach((item) => {
    item.typeName = $t(item.typeName);
  });
  const equTree = listToTree(equArray, { id: 'id', pid: 'parentId' });
  equTypeTree.value = equTree;
}
/**
 * ç”¨æˆ·çš„加载
 */
async function setupUserOptions(deptId: any) {
  const params = { deptId };
  const userPageResult = await userList({
    pageNum: 1,
    pageSize: 500,
    ...params
  });
  const options = userPageResult.rows.map((item) => ({
    label: item.nickName || item.userName,
    value: item.userId
  }));
  // ç­›é€‰
  const filterOption = (input: string, option: any) => {
    return option.label.toLowerCase().includes(input.toLowerCase());
  };
  const placeholder = options.length > 0 ? '请选择' : '该部门下暂无用户';
  formApi.updateSchema([
    {
      componentProps: { options, placeholder, filterOption },
      fieldName: 'inventoryUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
async function setupDeptSelect() {
  // updateSchema
  const deptTree = await getDeptTree();
  // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值 å³çˆ¶èŠ‚ç‚¹ / å­èŠ‚ç‚¹
  addFullName(deptTree, 'label', ' / ');
  formApi.updateSchema([
    {
      componentProps: (formModel) => ({
        class: 'w-full',
        fieldNames: {
          key: 'id',
          value: 'id',
          children: 'children'
        },
        getPopupContainer,
        async onSelect(deptId: number | string) {
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'userDept'
    }
  ]);
}
/**
 * é€šè¿‡å›žè°ƒæ›´æ–° æ— æ³•通过v-model
 * @param value èœå•选择是否严格模式
 */
function handleCheckStrictlyChange(value: boolean) {
  formApi.setFieldValue('checkStrictly', value);
}
const equTypeSelectRef = ref();
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    // è¿™ä¸ªç”¨äºŽæäº¤
    const equTypes = equTypeSelectRef.value?.[0]?.getCheckedKeys() ?? [];
    const data = cloneDeep(await formApi.getValues());
    data.equTypes = equTypes;
    await (isUpdate.value ? updateInventory(data) : addInventory(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm>
      <template #equTypesList="slotProps">
        <!-- check-strictly为readonly ä¸èƒ½é€šè¿‡v-model绑定 -->
        <TreeSelectPanel
          ref="equTypeSelectRef"
          :disabled="true"
          v-bind="slotProps"
          :check-strictly="formApi.form.values.checkStrictly"
          :tree-data="equTypeTree"
          @check-strictly-change="handleCheckStrictlyChange"
        />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,4 +1,6 @@
export enum DictEnum {
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  SYS_COMMON_STATUS = 'sys_common_status',
  SYS_DEVICE_TYPE = 'sys_device_type', // è®¾å¤‡ç±»åž‹
  SYS_EQU_STATUS = 'sys_equ_status', // è®¾å¤‡çŠ¶æ€
@@ -13,5 +15,5 @@
  SYS_YES_NO = 'sys_yes_no', // æ˜¯å¦
  WF_BUSINESS_STATUS = 'wf_business_status', // ä¸šåŠ¡çŠ¶æ€
  WF_FORM_TYPE = 'wf_form_type', // è¡¨å•类型
  WF_FORM_TYPE = 'wf_form_type' // è¡¨å•类型
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInventoryController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,105 @@
package org.dromara.eims.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.eims.domain.vo.EimsInventoryVo;
import org.dromara.eims.domain.bo.EimsInventoryBo;
import org.dromara.eims.service.IEimsInventoryService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * ç›˜ç‚¹
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/inventory")
public class EimsInventoryController extends BaseController {
    private final IEimsInventoryService eimsInventoryService;
    /**
     * æŸ¥è¯¢ç›˜ç‚¹åˆ—表
     */
    @SaCheckPermission("eims:inventory:list")
    @GetMapping("/list")
    public TableDataInfo<EimsInventoryVo> list(EimsInventoryBo bo, PageQuery pageQuery) {
        return eimsInventoryService.queryPageList(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºç›˜ç‚¹åˆ—表
     */
    @SaCheckPermission("eims:inventory:export")
    @Log(title = "盘点", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsInventoryBo bo, HttpServletResponse response) {
        List<EimsInventoryVo> list = eimsInventoryService.queryList(bo);
        ExcelUtil.exportExcel(list, "盘点", EimsInventoryVo.class, response);
    }
    /**
     * èŽ·å–ç›˜ç‚¹è¯¦ç»†ä¿¡æ¯
     *
     * @param inventoryId ä¸»é”®
     */
    @SaCheckPermission("eims:inventory:query")
    @GetMapping("/{inventoryId}")
    public R<EimsInventoryVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long inventoryId) {
        return R.ok(eimsInventoryService.queryById(inventoryId));
    }
    /**
     * æ–°å¢žç›˜ç‚¹
     */
    @SaCheckPermission("eims:inventory:add")
    @Log(title = "盘点", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsInventoryBo bo) {
        return toAjax(eimsInventoryService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹ç›˜ç‚¹
     */
    @SaCheckPermission("eims:inventory:edit")
    @Log(title = "盘点", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsInventoryBo bo) {
        return toAjax(eimsInventoryService.updateByBo(bo));
    }
    /**
     * åˆ é™¤ç›˜ç‚¹
     *
     * @param inventoryIds ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:inventory:remove")
    @Log(title = "盘点", businessType = BusinessType.DELETE)
    @DeleteMapping("/{inventoryIds}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] inventoryIds) {
        return toAjax(eimsInventoryService.deleteWithValidByIds(List.of(inventoryIds), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInventoryDetailController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,106 @@
package org.dromara.eims.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
import org.dromara.eims.domain.bo.EimsInventoryDetailBo;
import org.dromara.eims.service.IEimsInventoryDetailService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * ç›˜ç‚¹æ˜Žç»†
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/inventoryDetail")
public class EimsInventoryDetailController extends BaseController {
    private final IEimsInventoryDetailService eimsInventoryDetailService;
    /**
     * æŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†åˆ—表
     */
    @SaCheckPermission("eims:inventoryDetail:list")
    @GetMapping("/list")
    public TableDataInfo<EimsInventoryDetailVo> list(EimsInventoryDetailBo bo, PageQuery pageQuery) {
        //return eimsInventoryDetailService.queryPageList(bo, pageQuery);
        return eimsInventoryDetailService.queryPageListCustom(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºç›˜ç‚¹æ˜Žç»†åˆ—表
     */
    @SaCheckPermission("eims:inventoryDetail:export")
    @Log(title = "盘点明细", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsInventoryDetailBo bo, HttpServletResponse response) {
        List<EimsInventoryDetailVo> list = eimsInventoryDetailService.queryList(bo);
        ExcelUtil.exportExcel(list, "盘点明细", EimsInventoryDetailVo.class, response);
    }
    /**
     * èŽ·å–ç›˜ç‚¹æ˜Žç»†è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:inventoryDetail:query")
    @GetMapping("/{id}")
    public R<EimsInventoryDetailVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsInventoryDetailService.queryById(id));
    }
    /**
     * æ–°å¢žç›˜ç‚¹æ˜Žç»†
     */
    @SaCheckPermission("eims:inventoryDetail:add")
    @Log(title = "盘点明细", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsInventoryDetailBo bo) {
        return toAjax(eimsInventoryDetailService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹ç›˜ç‚¹æ˜Žç»†
     */
    @SaCheckPermission("eims:inventoryDetail:edit")
    @Log(title = "盘点明细", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsInventoryDetailBo bo) {
        return toAjax(eimsInventoryDetailService.updateByBo(bo));
    }
    /**
     * åˆ é™¤ç›˜ç‚¹æ˜Žç»†
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:inventoryDetail:remove")
    @Log(title = "盘点明细", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsInventoryDetailService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsInventory.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
package org.dromara.eims.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
 * ç›˜ç‚¹å¯¹è±¡ eims_inventory
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_inventory")
public class EimsInventory extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ç›˜ç‚¹id
     */
    @TableId(value = "inventory_id")
    private Long inventoryId;
    /**
     * ç›˜ç‚¹å•号
     */
    private String inventoryCode;
    /**
     * ç›˜ç‚¹åç§°
     */
    private String inventoryName;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备类型(设备类型id-逗号隔开)
     */
    private String equTypes;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备状态(设备状态-字典)
     */
    private String equStatus;
    /**
     * ç›˜ç‚¹äºº
     */
    private Long inventoryUser;
    /**
     * ç›˜ç‚¹äººéƒ¨é—¨
     */
    private Long userDept;
    /**
     * å¼€å§‹æ—¥æœŸ
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date startDate;
    /**
     * ç»“束日期
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date endDate;
    /**
     * ç›˜ç‚¹çŠ¶æ€
     */
    private String status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsInventoryDetail.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
package org.dromara.eims.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
 * ç›˜ç‚¹æ˜Žç»†å¯¹è±¡ eims_inventory_detail
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_inventory_detail")
public class EimsInventoryDetail extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @TableId(value = "id")
    private Long id;
    /**
     * ç›˜ç‚¹id
     */
    private Long inventoryId;
    /**
     * è®¾å¤‡id
     */
    private Long equId;
    /**
     * ç›˜ç‚¹ç»“æžœ
     */
    private String status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsInventoryBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
package org.dromara.eims.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import java.util.List;
import org.dromara.eims.domain.EimsInventory;
/**
 * ç›˜ç‚¹ä¸šåŠ¡å¯¹è±¡ eims_inventory
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsInventory.class, reverseConvertGenerate = false)
public class EimsInventoryBo extends BaseEntity {
    /**
     * ç›˜ç‚¹id
     */
    @NotNull(message = "盘点id不能为空", groups = { EditGroup.class })
    private Long inventoryId;
    /**
     * ç›˜ç‚¹å•号
     */
    @NotBlank(message = "盘点单号不能为空", groups = { AddGroup.class, EditGroup.class })
    private String inventoryCode;
    /**
     * ç›˜ç‚¹åç§°
     */
    @NotBlank(message = "盘点名称不能为空", groups = { AddGroup.class, EditGroup.class })
    private String inventoryName;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备类型(设备类型id-逗号隔开)
     */
    private List<String> equTypesList;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备状态(设备状态-字典)
     */
    private List<String> equStatusList;
    /**
     * ç›˜ç‚¹äºº
     */
    @NotNull(message = "盘点人不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long inventoryUser;
    /**
     * ç›˜ç‚¹äººéƒ¨é—¨
     */
    private Long userDept;
    /**
     * å¼€å§‹æ—¥æœŸ
     */
    @NotNull(message = "开始日期不能为空", groups = { AddGroup.class, EditGroup.class })
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date startDate;
    /**
     * ç»“束日期
     */
    @NotNull(message = "结束日期不能为空", groups = { AddGroup.class, EditGroup.class })
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date endDate;
    /**
     * ç›˜ç‚¹çŠ¶æ€
     */
    private String status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsInventoryDetailBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsInventoryDetail;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
 * ç›˜ç‚¹æ˜Žç»†ä¸šåŠ¡å¯¹è±¡ eims_inventory_detail
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsInventoryDetail.class, reverseConvertGenerate = false)
public class EimsInventoryDetailBo extends BaseEntity {
    /**
     *
     */
    @NotNull(message = "不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * ç›˜ç‚¹id
     */
    @NotNull(message = "盘点id不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long inventoryId;
    /**
     * è®¾å¤‡id
     */
    @NotNull(message = "设备id不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long equId;
    /**
     * ç›˜ç‚¹ç»“æžœ
     */
    @NotBlank(message = "盘点结果不能为空", groups = { AddGroup.class, EditGroup.class })
    private String status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
    //设备名称
    private String equName;
    //设备编码
    private String equCode;
    //设备资产编号
    private String equAssetNo;
    //部门名称
    private String deptName;
    //设备类型名称
    private String equTypeName;
    //设备所在位置
    private String location;
    //设备状态
    private String equStatus;
    //盘点人
    private String inventoryUser;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsInventoryDetailVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
package org.dromara.eims.domain.vo;
import org.dromara.eims.domain.EimsInventoryDetail;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
 * ç›˜ç‚¹æ˜Žç»†è§†å›¾å¯¹è±¡ eims_inventory_detail
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsInventoryDetail.class)
public class EimsInventoryDetailVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long id;
    /**
     * ç›˜ç‚¹id
     */
    @ExcelProperty(value = "盘点id")
    private Long inventoryId;
    /**
     * è®¾å¤‡id
     */
    @ExcelProperty(value = "设备id")
    private Long equId;
    /**
     * ç›˜ç‚¹ç»“æžœ
     */
    @ExcelProperty(value = "盘点结果")
    private String status;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
    //设备名称
    private String equName;
    //设备编码
    private String equCode;
    //设备资产编号
    private String equAssetNo;
    //部门名称
    private String deptName;
    //设备类型名称
    private String equTypeName;
    //设备所在位置
    private String location;
    //设备状态
    private String equStatus;
    //盘点人
    private String inventoryUser;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsInventoryVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package org.dromara.eims.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.eims.domain.EimsInventory;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
 * ç›˜ç‚¹è§†å›¾å¯¹è±¡ eims_inventory
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsInventory.class)
public class EimsInventoryVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ç›˜ç‚¹id
     */
    @ExcelProperty(value = "盘点id")
    private Long inventoryId;
    /**
     * ç›˜ç‚¹å•号
     */
    @ExcelProperty(value = "盘点单号")
    private String inventoryCode;
    /**
     * ç›˜ç‚¹åç§°
     */
    @ExcelProperty(value = "盘点名称")
    private String inventoryName;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备类型(设备类型id-逗号隔开)
     */
    @ExcelProperty(value = "盘点范围-设备类型")
    private String equTypes;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备状态(设备状态-字典)
     */
    @ExcelProperty(value = "盘点范围-设备状态")
    private String equStatus;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备类型(设备类型id-逗号隔开)
     */
    private List<Long> equTypesList;
    /**
     * ç›˜ç‚¹èŒƒå›´-设备状态(设备状态-字典)
     */
    private List<String> equStatusList;
    /**
     * ç›˜ç‚¹äºº
     */
    private Long inventoryUser;
    @ExcelProperty(value = "盘点人")
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "inventoryUser")
    private String inventoryUserName;
    /**
     * ç›˜ç‚¹äººéƒ¨é—¨
     */
    @ExcelProperty(value = "盘点人部门")
    private Long userDept;
    /**
     * å¼€å§‹æ—¥æœŸ
     */
    @ExcelProperty(value = "开始日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date startDate;
    /**
     * ç»“束日期
     */
    @ExcelProperty(value = "结束日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date endDate;
    /**
     * ç›˜ç‚¹çŠ¶æ€
     */
    @ExcelProperty(value = "盘点状态")
    private String status;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInventoryDetailMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package org.dromara.eims.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.eims.domain.EimsInventoryDetail;
import org.dromara.eims.domain.bo.EimsInventoryDetailBo;
import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
 * ç›˜ç‚¹æ˜Žç»†Mapper接口
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
public interface EimsInventoryDetailMapper extends BaseMapperPlus<EimsInventoryDetail, EimsInventoryDetailVo> {
    Page<EimsInventoryDetailVo> selectInventoryDetailList(@Param("page") Page<EimsInventoryDetailVo> page, @Param(Constants.WRAPPER) Wrapper<EimsInventoryDetail> queryWrapper);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsInventoryMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package org.dromara.eims.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.eims.domain.EimsInventory;
import org.dromara.eims.domain.vo.EimsInventoryVo;
/**
 * ç›˜ç‚¹Mapper接口
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
public interface EimsInventoryMapper extends BaseMapperPlus<EimsInventory, EimsInventoryVo> {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInventoryDetailService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
package org.dromara.eims.service;
import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
import org.dromara.eims.domain.bo.EimsInventoryDetailBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
 * ç›˜ç‚¹æ˜Žç»†Service接口
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
public interface IEimsInventoryDetailService {
    /**
     * æŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†
     *
     * @param id ä¸»é”®
     * @return ç›˜ç‚¹æ˜Žç»†
     */
    EimsInventoryDetailVo queryById(Long id);
    /**
     * åˆ†é¡µæŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†åˆ—表-多表查询
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return ç›˜ç‚¹æ˜Žç»†åˆ†é¡µåˆ—表
     */
    TableDataInfo<EimsInventoryDetailVo> queryPageListCustom(EimsInventoryDetailBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„盘点明细列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return ç›˜ç‚¹æ˜Žç»†åˆ—表
     */
    List<EimsInventoryDetailVo> queryList(EimsInventoryDetailBo bo);
    /**
     * æ–°å¢žç›˜ç‚¹æ˜Žç»†
     *
     * @param bo ç›˜ç‚¹æ˜Žç»†
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsInventoryDetailBo bo);
    /**
     * ä¿®æ”¹ç›˜ç‚¹æ˜Žç»†
     *
     * @param bo ç›˜ç‚¹æ˜Žç»†
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsInventoryDetailBo bo);
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤ç›˜ç‚¹æ˜Žç»†ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInventoryService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
package org.dromara.eims.service;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.eims.domain.bo.EimsInventoryBo;
import org.dromara.eims.domain.vo.EimsInventoryVo;
import java.util.Collection;
import java.util.List;
/**
 * ç›˜ç‚¹Service接口
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
public interface IEimsInventoryService {
    /**
     * æŸ¥è¯¢ç›˜ç‚¹
     *
     * @param inventoryId ä¸»é”®
     * @return ç›˜ç‚¹
     */
    EimsInventoryVo queryById(Long inventoryId);
    /**
     * åˆ†é¡µæŸ¥è¯¢ç›˜ç‚¹åˆ—表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return ç›˜ç‚¹åˆ†é¡µåˆ—表
     */
    TableDataInfo<EimsInventoryVo> queryPageList(EimsInventoryBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„盘点列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return ç›˜ç‚¹åˆ—表
     */
    List<EimsInventoryVo> queryList(EimsInventoryBo bo);
    /**
     * æ–°å¢žç›˜ç‚¹
     *
     * @param bo ç›˜ç‚¹
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsInventoryBo bo);
    /**
     * ä¿®æ”¹ç›˜ç‚¹
     *
     * @param bo ç›˜ç‚¹
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsInventoryBo bo);
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤ç›˜ç‚¹ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInventoryDetailServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,139 @@
package org.dromara.eims.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsInventoryDetailBo;
import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
import org.dromara.eims.domain.EimsInventoryDetail;
import org.dromara.eims.mapper.EimsInventoryDetailMapper;
import org.dromara.eims.service.IEimsInventoryDetailService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * ç›˜ç‚¹æ˜Žç»†Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-02-06
 */
@RequiredArgsConstructor
@Service
public class EimsInventoryDetailServiceImpl implements IEimsInventoryDetailService {
    private final EimsInventoryDetailMapper baseMapper;
    /**
     * æŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†
     *
     * @param id ä¸»é”®
     * @return ç›˜ç‚¹æ˜Žç»†
     */
    @Override
    public EimsInventoryDetailVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†åˆ—表-多表查询
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return ç›˜ç‚¹æ˜Žç»†åˆ†é¡µåˆ—表
     */
    @Override
    public TableDataInfo<EimsInventoryDetailVo> queryPageListCustom(EimsInventoryDetailBo bo, PageQuery pageQuery) {
        //TODO ç‰¹æ®Šå¤„理-多表同字段导致问题
        String orderByColumn = pageQuery.getOrderByColumn();
        if (StringUtils.isNotEmpty(orderByColumn) && orderByColumn.contains("status")) {
            pageQuery.setOrderByColumn(orderByColumn.replace("status", "a.status"));
        }
        Page<EimsInventoryDetailVo> page = baseMapper.selectInventoryDetailList(pageQuery.build(), buildQueryWrapper(bo));
        return TableDataInfo.build(page);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„盘点明细列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return ç›˜ç‚¹æ˜Žç»†åˆ—表
     */
    @Override
    public List<EimsInventoryDetailVo> queryList(EimsInventoryDetailBo bo) {
        QueryWrapper<EimsInventoryDetail> qw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(qw);
    }
    private QueryWrapper<EimsInventoryDetail> buildQueryWrapper(EimsInventoryDetailBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<EimsInventoryDetail> qw = Wrappers.query();
        qw.eq(bo.getInventoryId() != null, "a.inventory_id", bo.getInventoryId());
        qw.eq(bo.getEquId() != null, "a.equ_id", bo.getEquId());
        qw.eq(StringUtils.isNotBlank(bo.getStatus()), "a.status", bo.getStatus());
        qw.like(StringUtils.isNotBlank(bo.getEquName()), "c.equ_name", bo.getEquName());
        return qw;
    }
    /**
     * æ–°å¢žç›˜ç‚¹æ˜Žç»†
     *
     * @param bo ç›˜ç‚¹æ˜Žç»†
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsInventoryDetailBo bo) {
        EimsInventoryDetail add = MapstructUtils.convert(bo, EimsInventoryDetail.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹ç›˜ç‚¹æ˜Žç»†
     *
     * @param bo ç›˜ç‚¹æ˜Žç»†
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsInventoryDetailBo bo) {
        EimsInventoryDetail update = MapstructUtils.convert(bo, EimsInventoryDetail.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsInventoryDetail entity) {
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤ç›˜ç‚¹æ˜Žç»†ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInventoryServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,215 @@
package org.dromara.eims.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.eims.domain.EimsEqu;
import org.dromara.eims.domain.EimsEquType;
import org.dromara.eims.domain.EimsInventoryDetail;
import org.dromara.eims.mapper.EimsEquMapper;
import org.dromara.eims.mapper.EimsEquTypeMapper;
import org.dromara.eims.mapper.EimsInventoryDetailMapper;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsInventoryBo;
import org.dromara.eims.domain.vo.EimsInventoryVo;
import org.dromara.eims.domain.EimsInventory;
import org.dromara.eims.mapper.EimsInventoryMapper;
import org.dromara.eims.service.IEimsInventoryService;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
 * ç›˜ç‚¹Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-01-16
 */
@RequiredArgsConstructor
@Service
public class EimsInventoryServiceImpl implements IEimsInventoryService {
    private final EimsInventoryMapper baseMapper;
    private final EimsInventoryDetailMapper detailMapper;
    private final EimsEquTypeMapper equTypeMapper;
    private final EimsEquMapper equMapper;
    /**
     * æŸ¥è¯¢ç›˜ç‚¹
     *
     * @param inventoryId ä¸»é”®
     * @return ç›˜ç‚¹
     */
    @Override
    public EimsInventoryVo queryById(Long inventoryId) {
        EimsInventoryVo vo = baseMapper.selectVoById(inventoryId);
        if (StringUtils.isNotEmpty(vo.getEquTypes())) {
            List<Long> numberList = Arrays.stream(vo.getEquTypes().split(","))
                .map(Long::parseLong)
                .toList();
            vo.setEquTypesList(numberList);
        }
        if (StringUtils.isNotEmpty(vo.getEquStatus())) {
            List<String> list = Arrays.asList(vo.getEquStatus().split(","));
            vo.setEquStatusList(list);
        }
        return vo;
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢ç›˜ç‚¹åˆ—表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return ç›˜ç‚¹åˆ†é¡µåˆ—表
     */
    @Override
    public TableDataInfo<EimsInventoryVo> queryPageList(EimsInventoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsInventory> lqw = buildQueryWrapper(bo);
        Page<EimsInventoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„盘点列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return ç›˜ç‚¹åˆ—表
     */
    @Override
    public List<EimsInventoryVo> queryList(EimsInventoryBo bo) {
        LambdaQueryWrapper<EimsInventory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsInventory> buildQueryWrapper(EimsInventoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsInventory> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getInventoryCode()), EimsInventory::getInventoryCode, bo.getInventoryCode());
        lqw.like(StringUtils.isNotBlank(bo.getInventoryName()), EimsInventory::getInventoryName, bo.getInventoryName());
        lqw.eq(bo.getInventoryUser() != null, EimsInventory::getInventoryUser, bo.getInventoryUser());
        lqw.between(params.get("beginStartDate") != null && params.get("endStartDate") != null,
            EimsInventory::getStartDate, params.get("beginStartDate"), params.get("endStartDate"));
        lqw.between(params.get("beginEndDate") != null && params.get("endEndDate") != null,
            EimsInventory::getEndDate, params.get("beginEndDate"), params.get("endEndDate"));
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsInventory::getStatus, bo.getStatus());
        lqw.between(params.get("beginCreateBy") != null && params.get("endCreateBy") != null,
            EimsInventory::getCreateBy, params.get("beginCreateBy"), params.get("endCreateBy"));
        lqw.eq(bo.getUserDept() != null, EimsInventory::getUserDept, bo.getUserDept());
        lqw.eq(bo.getInventoryUser() != null, EimsInventory::getInventoryUser, bo.getInventoryUser());
        return lqw;
    }
    /**
     * æ–°å¢žç›˜ç‚¹
     *
     * @param bo ç›˜ç‚¹
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(EimsInventoryBo bo) {
        EimsInventory add = MapstructUtils.convert(bo, EimsInventory.class);
        List<String> equTypesList = bo.getEquTypesList();
        if (equTypesList != null && !equTypesList.isEmpty()) {
            String result = String.join(",", equTypesList);
            if (add != null) {
                add.setEquTypes(result);
            }
        }
        List<String> equStatusList = bo.getEquStatusList();
        if (equStatusList != null && !equStatusList.isEmpty()) {
            String result = String.join(",", equStatusList);
            if (add != null) {
                add.setEquStatus(result);
            }
        }
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setInventoryId(add.getInventoryId());
        }
        //1.查询类型下所有设备
        QueryWrapper<EimsEqu> equQueryWrapper = new QueryWrapper<>();
        equQueryWrapper.lambda().in(CollUtil.isNotEmpty(equTypesList), EimsEqu::getEquTypeId, equTypesList);
        equQueryWrapper.lambda().in(CollUtil.isNotEmpty(equStatusList), EimsEqu::getStatus, equStatusList);
        List<EimsEqu> equList = equMapper.selectList(equQueryWrapper);
        //2.新增盘点明细
        for (EimsEqu equ : equList) {
            EimsInventoryDetail detail = new EimsInventoryDetail();
            detail.setEquId(equ.getEquId());
            detail.setInventoryId(add.getInventoryId());
            //设置为未盘点
            detail.setStatus("0");
            detailMapper.insert(detail);
        }
        return flag;
    }
    /**
     * ä¿®æ”¹ç›˜ç‚¹
     *
     * @param bo ç›˜ç‚¹
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsInventoryBo bo) {
        EimsInventory update = MapstructUtils.convert(bo, EimsInventory.class);
        if (bo.getEquTypesList() != null && !bo.getEquTypesList().isEmpty()) {
            String result = String.join(",", bo.getEquTypesList());
            if (update != null) {
                update.setEquTypes(result);
            }
        }
        if (bo.getEquStatusList() != null && !bo.getEquStatusList().isEmpty()) {
            String result = String.join(",", bo.getEquStatusList());
            if (update != null) {
                update.setEquStatus(result);
            }
        }
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsInventory entity) {
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤ç›˜ç‚¹ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsInventoryDetailMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.eims.mapper.EimsInventoryDetailMapper">
    <resultMap type="org.dromara.eims.domain.vo.EimsInventoryDetailVo" id="EimsInventoryDetailResult">
    </resultMap>
    <select id="selectInventoryDetailList" resultMap="EimsInventoryDetailResult">
        SELECT c.equ_code equCode,
        c.equ_name equName,
        c.asset_no equAssetNo,
        e.dept_name deptName,
        d.type_name equTypeName,
        c.location location,
        b.`status` inventoryStatus,
        c.`status` equStatus,
        d.`status` typeStatus,
        b.inventory_user inventoryUser
        FROM eims_inventory_detail a
        JOIN eims_inventory b on a.inventory_id = b.inventory_id
        JOIN eims_equ c on a.equ_id = c.equ_id
        JOIN eims_equ_type d on c.equ_type_id = d.equ_type_id
        JOIN sys_dept e on e.dept_id = c.dept_used
        ${ew.getCustomSqlSegment}
    </select>
</mapper>
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsInventoryMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.eims.mapper.EimsInventoryMapper">
</mapper>