车间能级提升-智能设备管理系统
朱桂飞
2025-02-10 34c674d503e23c0cf6d0b6dec063f3049885e5f8
新增盘点明细
已添加1个文件
已删除1个文件
已修改10个文件
850 ■■■■■ 文件已修改
eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/data.tsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/data.tsx 277 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/detail-drawer.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | 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/index.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/preferences/src/config.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInventoryDetailController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsInventoryDetailBo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInventoryDetailServiceImpl.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsInventoryDetailMapper.xml 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx
@@ -8,6 +8,7 @@
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
@@ -48,26 +49,7 @@
    sortable: true,
    slots: {
      default: ({ row }) => {
        const statu = row.beforeChange;
        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 '';
        return renderDict(row.beforeChange, DictEnum.SYS_EQU_STATUS);
      }
    },
    minWidth: 80,
@@ -79,26 +61,7 @@
    sortable: true,
    slots: {
      default: ({ row }) => {
        const statu = row.afterChange;
        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 '';
        return renderDict(row.afterChange, DictEnum.SYS_EQU_STATUS);
      }
    },
    minWidth: 80,
@@ -212,46 +175,14 @@
    field: 'beforeChange',
    label: '变更前',
    render(value) {
      switch (value) {
        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 '';
        }
      }
      return renderDict(value, DictEnum.SYS_EQU_STATUS);
    }
  },
  {
    field: 'afterChange',
    label: '变更后',
    render(value) {
      switch (value) {
        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 '';
        }
      }
      return renderDict(value, DictEnum.SYS_EQU_STATUS);
    }
  },
  {
eims-ui/apps/web-antd/src/views/eims/equ/data.tsx
@@ -7,6 +7,7 @@
import { type FormSchemaGetter, z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
@@ -50,26 +51,7 @@
    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 '';
        return renderDict(row.status, DictEnum.SYS_EQU_STATUS);
      }
    },
    minWidth: 80,
eims-ui/apps/web-antd/src/views/eims/inventory-detail/data.tsx
@@ -1,18 +1,16 @@
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 { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'equCode',
    label: '设备编码'
    label: '设备编号'
  },
  {
    component: 'Input',
@@ -36,83 +34,73 @@
    },
    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: 'status',
    sortable: true,
    minWidth: 100,
    fixed: 'left',
    slots: {
      default: ({ row }) => {
        return renderDict(row.status, DictEnum.EIMS_INVENTORY_DETAIL_STATU);
      }
    }
  },
  {
    title: '设备编号',
    field: 'equCode',
    minWidth: 120,
    fixed: 'left',
    fixed: 'left'
  },
  {
    title: '设备名称',
    field: 'equName',
    minWidth: 100,
    fixed: 'left',
    minWidth: 100
  },
  {
    title: '资产编号',
    field: 'equAssetNo',
    sortable: true,
    minWidth: 100,
  },
  {
    title: '使用部门',
    field: 'deptName',
    minWidth: 100,
  },
  {
    title: '设备类型',
    field: 'equTypeName',
    minWidth: 100,
  },
  {
    title: '设备位置',
    field: 'location',
    minWidth: 100,
    minWidth: 100
  },
  {
    title: '设备状态',
    field: 'equStatus',
    sortable: true,
    minWidth: 100,
    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 '';
        return renderDict(row.equStatus, DictEnum.SYS_EQU_STATUS);
      }
    },
    minWidth: 80,
    }
  },
  {
    title: '使用部门',
    field: 'deptName',
    minWidth: 100
  },
  {
    title: '设备类型',
    field: 'equTypeName',
    minWidth: 100
  },
  {
    title: '设备位置',
    field: 'location',
    minWidth: 100
  },
  {
    title: '盘点人',
    field: 'inventoryUser',
@@ -135,194 +123,33 @@
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    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
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'purchaseDate',
    label: '采购日期'
    fieldName: 'inventoryId'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_EQU_STATUS),
      options: getDictOptions(DictEnum.EIMS_INVENTORY_DETAIL_STATU),
      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/detail-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { addInventoryDetail, getInventoryDetail, updateInventoryDetail } from '#/api/eims/inventory-detail';
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;
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getInventoryDetail(id);
      await formApi.setValues(record);
    }
    drawerApi.drawerLoading(false);
  }
});
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    await (isUpdate.value ? updateInventoryDetail(data) : addInventoryDetail(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-drawer.vue
ÎļþÒÑɾ³ý
eims-ui/apps/web-antd/src/views/eims/inventory-detail/index.vue
@@ -1,9 +1,10 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { computed, nextTick, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { getVxePopupContainer } from '@vben/utils';
@@ -15,7 +16,7 @@
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import equDrawer from './equ-drawer.vue';
import detailDrawer from './detail-drawer.vue';
import EquTypeTree from './equ-type-tree.vue';
const route = useRoute();
@@ -23,6 +24,12 @@
// å·¦è¾¹éƒ¨é—¨ç”¨
const selectTypeId = ref<string[]>([]);
// å·²ç›˜ç‚¹
const check = ref<string>('已盘');
// æœªç›˜ç‚¹
const noCheck = ref<string>('未盘');
// æŸ¥è¯¢æ·»åŠ ç›˜ç‚¹æ ‡è®°è¿‡æ»¤
const checkFilter = ref<string>();
const formOptions: VbenFormProps = {
  commonConfig: {
@@ -35,6 +42,7 @@
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  handleReset: async () => {
    selectTypeId.value = [];
    checkFilter.value = undefined;
    // eslint-disable-next-line no-use-before-define
    const { formApi, reload } = tableApi;
    await formApi.resetForm();
@@ -58,7 +66,12 @@
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  pagerConfig: {
    // é»˜è®¤æ¡æ•°
    pageSize: 1000,
    // åˆ†é¡µå¯é€‰æ¡æ•°
    pageSizes: [1000, 2000, 3000, 4000, 5000]
  },
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
@@ -68,10 +81,36 @@
        } else {
          Reflect.deleteProperty(formValues, 'equTypeId');
        }
        // æ˜¯å¦ç›˜ç‚¹
        if (checkFilter.value === '0' || checkFilter.value === '1') {
          formValues.status = checkFilter.value;
        } else {
          Reflect.deleteProperty(formValues, 'status');
        }
        return await listInventoryDetail({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          inventoryId,
          ...formValues
        });
      },
      querySuccess: () => {
        nextTick(() => {
          // è¿‡æ»¤å·²ç›˜å’Œæœªç›˜çš„æ•°æ®
          // eslint-disable-next-line no-use-before-define
          const data = tableApi.grid.getData();
          const data0 = data.filter((item) => {
            return item.status === '' || item.status === null || item.status === '0';
          });
          if (data0 !== null && data0.length > 0) {
            noCheck.value = `未盘(${data0.length})`;
          }
          const data1 = data.filter((item) => {
            return item.status !== '' && item.status !== null && item.status === '1';
          });
          if (data1 !== null && data1.length > 0) {
            check.value = `已盘(${data1.length})`;
          }
        });
      }
    }
@@ -97,18 +136,13 @@
  }
});
const [EquDrawer, equDrawerApi] = useVbenDrawer({
  connectedComponent: equDrawer
const [DetailDrawer, detailDrawerApi] = useVbenDrawer({
  connectedComponent: detailDrawer
});
function handleAdd() {
  equDrawerApi.setData({});
  equDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  equDrawerApi.setData({ id: record.equId });
  equDrawerApi.open();
  detailDrawerApi.setData({ id: record.id });
  detailDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
@@ -129,7 +163,6 @@
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(inventoryDetailExport, '盘点明细', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
@@ -145,11 +178,12 @@
  const inventoryFlag = row.inventoryFlag === null || row.inventoryFlag;
  return inventoryFlag ? '未盘点' : '已盘点';
}
const router = useRouter();
function handleDetail(record: Recordable<any>) {
  router.push(`/equ/detail/${record.id}`);
function handleQuery(isChecked: string) {
  checkFilter.value = isChecked;
  tableApi.query();
}
const { hasAccessByRoles } = useAccess();
const isSuperAdmin = computed(() => hasAccessByRoles(['superadmin']));
</script>
<template>
@@ -159,34 +193,30 @@
      <BasicTable class="flex-1 overflow-hidden" table-title="盘点明细列表">
        <template #toolbar-tools>
          <Space>
            <a-button @click="handleQuery('0')">{{ noCheck }}</a-button>
            <a-button type="primary" @click="handleQuery('1')"> {{ check }}</a-button>
            <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">
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi) || !isSuperAdmin"
              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)">
            <ghost-button :disabled="!isSuperAdmin" 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="">
              <ghost-button :disabled="!isSuperAdmin" danger v-access:code="['eims:inventory:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
@@ -202,6 +232,6 @@
        </template>
      </BasicTable>
    </div>
    <EquDrawer @reload="tableApi.query()" />
    <DetailDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,6 +1,6 @@
export enum DictEnum {
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  SYS_COMMON_STATUS = 'sys_common_status',
  SYS_DEVICE_TYPE = 'sys_device_type', // è®¾å¤‡ç±»åž‹
  SYS_EQU_STATUS = 'sys_equ_status', // è®¾å¤‡çŠ¶æ€
@@ -8,7 +8,7 @@
  SYS_NORMAL_DISABLE = 'sys_normal_disable',
  SYS_NOTICE_STATUS = 'sys_notice_status', // é€šçŸ¥çŠ¶æ€
  SYS_NOTICE_TYPE = 'sys_notice_type', // é€šçŸ¥ç±»åž‹
  SYS_OPER_TYPE = 'sys_oper_type', // æ“ä½œç±»åž‹
  SYS_OPER_TYPE = 'sys_oper_type', // æ“ä½œç±»åž‹S
  SYS_OSS_ACCESS_POLICY = 'oss_access_policy', // oss权限桶类型
  SYS_SHOW_HIDE = 'sys_show_hide', // æ˜¾ç¤ºçŠ¶æ€
  SYS_USER_SEX = 'sys_user_sex', // æ€§åˆ«
eims-ui/packages/@core/preferences/src/config.ts
@@ -19,7 +19,7 @@
    layout: 'sidebar-nav',
    locale: 'zh-CN',
    loginExpiredMode: 'page',
    name: 'Vben Admin',
    name: 'eims',
    preferencesButtonPosition: 'auto',
    watermark: false,
  },
@@ -31,8 +31,8 @@
    styleType: 'normal',
  },
  copyright: {
    companyName: 'Vben',
    companySiteLink: 'https://www.vben.pro',
    companyName: '上海兰浦',
    companySiteLink: 'https://shlanpu.cn/',
    date: '2024',
    enable: true,
    icp: '',
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInventoryDetailController.java
@@ -39,7 +39,7 @@
    /**
     * æŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†åˆ—表
     */
    @SaCheckPermission("eims:inventoryDetail:list")
    @SaCheckPermission("eims:inventory:list")
    @GetMapping("/list")
    public TableDataInfo<EimsInventoryDetailVo> list(EimsInventoryDetailBo bo, PageQuery pageQuery) {
        //return eimsInventoryDetailService.queryPageList(bo, pageQuery);
@@ -49,7 +49,7 @@
    /**
     * å¯¼å‡ºç›˜ç‚¹æ˜Žç»†åˆ—表
     */
    @SaCheckPermission("eims:inventoryDetail:export")
    @SaCheckPermission("eims:inventory:export")
    @Log(title = "盘点明细", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsInventoryDetailBo bo, HttpServletResponse response) {
@@ -62,7 +62,7 @@
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:inventoryDetail:query")
    @SaCheckPermission("eims:inventory:query")
    @GetMapping("/{id}")
    public R<EimsInventoryDetailVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
@@ -72,7 +72,7 @@
    /**
     * æ–°å¢žç›˜ç‚¹æ˜Žç»†
     */
    @SaCheckPermission("eims:inventoryDetail:add")
    @SaCheckPermission("eims:inventory:add")
    @Log(title = "盘点明细", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
@@ -83,7 +83,7 @@
    /**
     * ä¿®æ”¹ç›˜ç‚¹æ˜Žç»†
     */
    @SaCheckPermission("eims:inventoryDetail:edit")
    @SaCheckPermission("eims:inventory:edit")
    @Log(title = "盘点明细", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
@@ -96,7 +96,7 @@
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:inventoryDetail:remove")
    @SaCheckPermission("eims:inventory:remove")
    @Log(title = "盘点明细", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsInventoryDetailBo.java
@@ -59,6 +59,8 @@
    private String deptName;
    //设备类型名称
    private String equTypeName;
    //设备类型
    private Long equTypeId;
    //设备所在位置
    private String location;
    //设备状态
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInventoryDetailServiceImpl.java
@@ -9,6 +9,10 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.eims.domain.EimsEqu;
import org.dromara.eims.domain.EimsEquType;
import org.dromara.eims.domain.vo.EimsEquTypeVo;
import org.dromara.eims.mapper.EimsEquTypeMapper;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsInventoryDetailBo;
import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
@@ -16,6 +20,7 @@
import org.dromara.eims.mapper.EimsInventoryDetailMapper;
import org.dromara.eims.service.IEimsInventoryDetailService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
@@ -31,6 +36,7 @@
public class EimsInventoryDetailServiceImpl implements IEimsInventoryDetailService {
    private final EimsInventoryDetailMapper baseMapper;
    private final EimsEquTypeMapper equTypeMapper;
    /**
     * æŸ¥è¯¢ç›˜ç‚¹æ˜Žç»†
@@ -82,10 +88,49 @@
        qw.eq(StringUtils.isNotBlank(bo.getStatus()), "a.status", bo.getStatus());
        qw.like(StringUtils.isNotBlank(bo.getEquName()), "c.equ_name", bo.getEquName());
        qw.like(StringUtils.isNotBlank(bo.getEquCode()), "c.equ_code", bo.getEquCode());
        qw.like(StringUtils.isNotBlank(bo.getEquAssetNo()), "c.asset_no", bo.getEquAssetNo());
        qw.like(StringUtils.isNotBlank(bo.getLocation()), "c.location", bo.getLocation());
        qw.like(StringUtils.isNotBlank(bo.getEquStatus()), "c.status", bo.getEquStatus());
        /**
         * equTypeId = 0 æ—¶æŸ¥è¯¢æ‰€æœ‰è®¾å¤‡ï¼ˆé»˜è®¤æ ¹ç›®å½•id为0,详见SysEquTypeServiceImpl中selectEquTypeTreeList)
         * equTypeId   ä¸ºå…¶ä»–值时只查当前设备类型id和后代设备类型id
         */
        if (bo.getEquTypeId() != null && bo.getEquTypeId() > 0) {
            List<Long> allDescendantIds = getAllDescendantIds(bo.getEquTypeId());
            qw.in("c.equ_type_id", allDescendantIds);
        }
        return qw;
    }
    /**
     * æ ¹æ®id,获取所有后代id
     * @param rootId
     * @return
     */
    public List<Long> getAllDescendantIds(Long rootId) {
        List<Long> result = new ArrayList<>();
        result.add(rootId);
        collectDescendants(rootId, result);
        return result;
    }
    private void collectDescendants(Long currentId, List<Long> collector) {
        QueryWrapper<EimsEquType> equTypeWrapper = new QueryWrapper<>();
        equTypeWrapper.lambda().eq(EimsEquType::getParentId, currentId);
        List<EimsEquTypeVo> children = equTypeMapper.selectVoList(equTypeWrapper);
        if (children != null && !children.isEmpty()) {
            for (EimsEquTypeVo child : children) {
                Long childId = child.getEquTypeId();
                collector.add(childId);
                collectDescendants(childId, collector);
            }
        }
    }
    /**
     * æ–°å¢žç›˜ç‚¹æ˜Žç»†
     *
     * @param bo ç›˜ç‚¹æ˜Žç»†
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsInventoryDetailMapper.xml
@@ -7,23 +7,24 @@
    </resultMap>
    <select id="selectInventoryDetailList" resultMap="EimsInventoryDetailResult">
        SELECT c.equ_code equCode,
        SELECT a.id id, c.equ_code equCode,
        c.equ_name equName,
        c.asset_no equAssetNo,
        e.dept_name deptName,
        d.type_name equTypeName,
        c.location location,
        a.`status` status,
        b.`status` inventoryStatus,
        c.`status` equStatus,
        d.`status` typeStatus,
        b.inventory_user inventoryUser
        f.nick_name 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
        LEFT JOIN eims_inventory b on a.inventory_id = b.inventory_id
        LEFT JOIN eims_equ c on a.equ_id = c.equ_id
        LEFT JOIN eims_equ_type d on c.equ_type_id = d.equ_type_id
        LEFT JOIN sys_dept e on e.dept_id = c.dept_used
        LEFT JOIN sys_user f on b.inventory_user = f.user_id
        ${ew.getCustomSqlSegment}
    </select>
</mapper>