车间能级提升-智能设备管理系统
朱桂飞
2025-02-17 2c3d6ae9d456ad2cf0b3047d6421ef6f36d216d0
新增工具治具模块
已添加29个文件
已修改8个文件
3298 ■■■■■ 文件已修改
eims-ui/apps/web-antd/src/api/eims/fixture-type/index.ts 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/fixture-type/model.d.ts 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/fixture/index.ts 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/fixture/model.d.ts 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ-type/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/equ-type-tree.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture-type/data.tsx 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture-type/fixture-type-drawer.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture-type/index.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-import-modal.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-type-tree.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/index.vue 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/FixtureTypeService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/FixtureTypeNameTranslationImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureTypeController.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixtureType.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureTypeBo.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquTypeVo.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureTypeVo.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureTypeMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureTypeService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsEquTypeServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureTypeServiceImpl.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFixtureMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/fixture-type/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
import type { FixtureTypeTree, FixtureTypeVO } from './model';
import type { ID, IDS } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  fixtureTypeExport = '/eims/fixtureType/export',
  fixtureTypeList = '/eims/fixtureType/list',
  fixtureTypeTree = '/eims/fixtureType/tree',
  root = '/eims/fixtureType'
}
/**
 * æŸ¥è¯¢å·¥å…·ç±»åž‹åˆ—表
 * @param query
 * @returns {*}
 */
export function listFixtureType(params?: any) {
  return requestClient.get<FixtureTypeVO[]>(Api.fixtureTypeList, { params });
}
/**
 * èŽ·å–å·¥å…·ç±»åž‹æ ‘
 * @returns å·¥å…·æ ‘数组
 */
export function getFixtureTypeTree() {
  return requestClient.get<FixtureTypeTree[]>(Api.fixtureTypeTree);
}
/**
 * æŸ¥è¯¢å·¥å…·ç±»åž‹è¯¦ç»†
 * @param fixTypeId
 */
export function getFixtureType(fixTypeId: ID) {
  return requestClient.get<FixtureTypeVO>(`${Api.root}/${fixTypeId}`);
}
/**
 * æ–°å¢žå·¥å…·ç±»åž‹
 * @param data
 */
export function addFixtureType(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹å·¥å…·ç±»åž‹
 * @param data
 */
export function updateFixtureType(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤å·¥å…·ç±»åž‹
 * @param fixTypeId
 */
export function delFixtureType(fixTypeId: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${fixTypeId}`);
}
/**
 * å¯¼å‡º
 * @param
 */
export function fixtureTypeExport(data: any) {
  return commonExport(Api.fixtureTypeExport, data);
}
eims-ui/apps/web-antd/src/api/eims/fixture-type/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
export interface FixtureTypeVO {
  /**
   * ç±»åž‹id
   */
  id: number | string;
  /**
   * ç±»åž‹åç§°
   */
  typeName: string;
  /**
   * ç±»åž‹ç¼–码
   */
  typeCode: string;
  /**
   * çˆ¶id
   */
  parentId: number | string;
  /**
   * æ˜¾ç¤ºé¡ºåº
   */
  orderNum: number;
  /**
   * èœå•类型(M目录 C菜单 F按钮)
   */
  menuType: string;
  /**
   * èœå•图标
   */
  icon: string;
  /**
   * èœå•状态(0正常 1停用)
   */
  status: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
  /**
   * å­å¯¹è±¡
   */
  children: FixtureTypeVO[];
}
/**
 * @description: è®¾å¤‡ç±»åž‹æ ‘
 */
export interface FixtureTypeTree {
  id: number;
  /**
   * antd组件必须要这个属性 å®žé™…是没有这个属性的
   */
  key: string;
  parentId: number;
  label: string;
  weight: number;
  children?: FixtureTypeTree[];
}
eims-ui/apps/web-antd/src/api/eims/fixture/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
import type { IDS, PageQuery, PageResult } from '#/api/common';
import type { FixtureImportParam, FixtureVO } from '#/api/eims/fixture/model';
import { commonExport, ContentTypeEnum } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  fixtureExport = '/eims/fixture/export',
  fixtureImport = '/eims/fixture/importData',
  fixtureImportTemplate = '/eims/fixture/importTemplate',
  fixtureList = '/eims/fixture/list',
  root = '/eims/fixture'
}
/**
 * æŸ¥è¯¢ã€å·¥å…·å°è´¦ã€‘列表
 * @param query
 * @returns {*}
 */
export function listFixture(params?: PageQuery) {
  return requestClient.get<PageResult<FixtureVO>>(Api.fixtureList, { params });
}
/**
 * æŸ¥è¯¢ã€å·¥å…·å°è´¦ã€‘详细
 * @param fixId
 */
export function getFixture(fixId: any) {
  return requestClient.get<FixtureVO>(`${Api.root}/${fixId}`);
}
/**
 * æ–°å¢žã€å·¥å…·å°è´¦ã€‘
 * @param data
 */
export function addFixture(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹ã€å·¥å…·å°è´¦ã€‘
 * @param data
 */
export function updateFixture(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤ã€å·¥å…·å°è´¦ã€‘
 * @param fixIds
 */
export function delFixture(fixIds: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${fixIds}`);
}
/**
 * å¯¼å‡ºã€å·¥å…·å°è´¦ã€‘
 * @param data
 */
export function fixtureExport(data: any) {
  return commonExport(Api.fixtureExport, data);
}
/**
 * ä»Žexcel导入设备
 * @param data
 * @returns void
 */
export function fixtureImportData(data: FixtureImportParam) {
  return requestClient.post<{ code: number; msg: string }>(Api.fixtureImport, data, {
    headers: {
      'Content-Type': ContentTypeEnum.FORM_DATA
    },
    isTransformResponse: false
  });
}
/**
 * ä¸‹è½½å¯¼å…¥æ¨¡æ¿
 * @returns blob
 */
export function downloadImportTemplate() {
  return requestClient.post<Blob>(
    Api.fixtureImportTemplate,
    {},
    {
      isTransformResponse: false,
      responseType: 'blob'
    }
  );
}
eims-ui/apps/web-antd/src/api/eims/fixture/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,172 @@
export interface FixtureVO {
  /**
   *
   */
  id: number | string;
  /**
   * æ²»å…·ç¼–码
   */
  fixtureCode: string;
  /**
   * æ²»å…·åç§°
   */
  fixtureName: string;
  /**
   * æ²»å…·ï¼ˆå·¥å…·ï¼‰ç±»åž‹
   */
  fixtureType: number;
  /**
   * æ²»å…·æè¿°
   */
  fixtureDesc: string;
  /**
   * å€Ÿç”¨éƒ¨é—¨
   */
  borrowDept: number | string;
  /**
   * å€Ÿç”¨éƒ¨é—¨
   */
  borrowDeptName: string;
  /**
   * å€Ÿç”¨äºº
   */
  borrowUser: number | string;
  /**
   * å€Ÿç”¨äºº
   */
  borrowUserName: string;
  /**
   * çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
   */
  status: string;
  /**
   * èµ„产编号
   */
  assetNo: string;
  /**
   * åž‹å·
   */
  modelNo: string;
  /**
   * è§„æ ¼
   */
  specNo: string;
  /**
   * åˆ¶é€ å•†
   */
  madeIn: string;
  /**
   * é‡‡è´­æ—¥æœŸ
   */
  purchaseDate: string;
  /**
   * ä½¿ç”¨æ—¥æœŸ
   */
  deployDate: string;
  /**
   * ä½¿ç”¨å¹´é™
   */
  serviceLife: number;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface FixtureForm extends BaseEntity {
  /**
   *
   */
  id?: number | string;
  /**
   * æ²»å…·ç¼–码
   */
  fixtureCode?: string;
  /**
   * æ²»å…·åç§°
   */
  fixtureName?: string;
  /**
   * æ²»å…·ï¼ˆå·¥å…·ï¼‰ç±»åž‹
   */
  fixtureType?: number;
  /**
   * æ²»å…·æè¿°
   */
  fixtureDesc?: string;
  /**
   * çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
   */
  status?: string;
  /**
   * èµ„产编号
   */
  assetNo?: string;
  /**
   * åž‹å·
   */
  modelNo?: string;
  /**
   * è§„æ ¼
   */
  specNo?: string;
  /**
   * åˆ¶é€ å•†
   */
  madeIn?: string;
  /**
   * é‡‡è´­æ—¥æœŸ
   */
  purchaseDate?: string;
  /**
   * ä½¿ç”¨æ—¥æœŸ
   */
  deployDate?: string;
  /**
   * ä½¿ç”¨å¹´é™
   */
  serviceLife?: number;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
/**
 * @description: è®¾å¤‡å¯¼å…¥
 * @param updateSupport æ˜¯å¦è¦†ç›–数据
 * @param file excel文件
 */
export interface FixtureImportParam {
  updateSupport: boolean;
  file: Blob | File;
}
eims-ui/apps/web-antd/src/views/eims/equ-type/index.vue
@@ -130,7 +130,7 @@
<template>
  <Page :auto-content-height="true">
    <BasicTable table-title="菜单列表" table-title-help="双击展开/收起子菜单">
    <BasicTable table-title="设备类型列表" table-title-help="双击展开/收起子菜单">
      <template #toolbar-tools>
        <Space>
          <a-button @click="setExpandOrCollapse(false)">
eims-ui/apps/web-antd/src/views/eims/equ/equ-type-tree.vue
@@ -111,7 +111,7 @@
          <div v-else class="mt-5">
            <Empty
              :image="Empty.PRESENTED_IMAGE_SIMPLE"
              description="无部门数据"
              description="无设备类型数据"
            />
          </div>
        </div>
eims-ui/apps/web-antd/src/views/eims/equ/index.vue
@@ -149,10 +149,6 @@
  });
}
function getImportStatus(row: any) {
  const importStatus = row.importStatus === null || row.importStatus;
  return importStatus ? '未导入' : '已导入';
}
const router = useRouter();
function handleDetail(record: Recordable<any>) {
@@ -206,10 +202,6 @@
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
        <template #importStatus="{ row }">
          <span>{{ getImportStatus(row) }}</span>
        </template>
      </BasicTable>
    </div>
eims-ui/apps/web-antd/src/views/eims/fixture-type/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,196 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { h } from 'vue';
import { DictEnum } from '@vben/constants';
import { FolderIcon, MenuIcon, VbenIcon } from '@vben/icons';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'typeName',
    label: '类型名称 '
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.SYS_NORMAL_DISABLE)
    },
    fieldName: 'status',
    label: '类型状态 '
  }
];
// èœå•类型(M目录 C菜单 F按钮)
export const fixtureTypeOptions = [
  { label: '目录', value: 'M' },
  { label: '类型', value: 'C' }
];
export const yesNoOptions = [
  { label: '是', value: '0' },
  { label: '否', value: '1' }
];
// ï¼ˆM目录 C菜单)
const menuTypes = {
  M: { icon: FolderIcon, value: '目录' },
  C: { icon: MenuIcon, value: '类型' }
};
export const columns: VxeGridProps['columns'] = [
  {
    title: '类型名称',
    field: 'typeName',
    treeNode: true,
    width: 200
  },
  {
    title: '类型编码',
    field: 'typeCode',
    width: 200
  },
  {
    title: '图标',
    field: 'icon',
    width: 80,
    slots: {
      default: ({ row }) => {
        if (row?.icon === '#') {
          return '';
        }
        return (
          <span class={'flex justify-center'}>
            <VbenIcon icon={row.icon} />
          </span>
        );
      }
    }
  },
  {
    title: '排序',
    field: 'orderNum',
    width: 120
  },
  {
    title: '节点类型',
    field: 'menuType',
    width: 150,
    slots: {
      default: ({ row }) => {
        const current = menuTypes[row.menuType as 'C' | 'M'];
        if (!current) {
          return '未知';
        }
        return (
          <span class="flex items-center justify-center gap-1">
            {h(current.icon, { class: 'size-[18px]' })}
            <span>{current.value}</span>
          </span>
        );
      }
    }
  },
  {
    title: '状态',
    field: 'status',
    width: 100,
    slots: {
      default: ({ row }) => {
        return renderDict(row.status, DictEnum.SYS_NORMAL_DISABLE);
      }
    }
  },
  {
    title: '创建时间',
    field: 'createTime'
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    component: 'TreeSelect',
    defaultValue: 0,
    fieldName: 'parentId',
    label: '上级菜单',
    rules: 'selectRequired'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: fixtureTypeOptions,
      optionType: 'button'
    },
    defaultValue: 'M',
    dependencies: {
      componentProps: (_, api) => {
        // åˆ‡æ¢æ—¶æ¸…空校验
        // ç›´æŽ¥æŠ„的源码 æ²¡æœ‰æ¸…空校验的方法
        Object.keys(api.errors.value).forEach((key) => {
          api.setFieldError(key, undefined);
        });
        return {};
      },
      triggerFields: ['menuType']
    },
    fieldName: 'menuType',
    label: '节点类型'
  },
  {
    component: 'Input',
    fieldName: 'typeName',
    label: '类型名称',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'typeCode',
    label: '类型编码',
    rules: 'required'
  },
  {
    component: 'InputNumber',
    fieldName: 'orderNum',
    help: '排序, æ•°å­—越小越靠前',
    label: '显示排序',
    rules: 'required'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.SYS_NORMAL_DISABLE),
      optionType: 'button'
    },
    defaultValue: '0',
    dependencies: {
      // ç±»åž‹ä¸ä¸ºæŒ‰é’®æ—¶æ˜¾ç¤º
      show: (values) => values.menuType !== 'F',
      triggerFields: ['menuType']
    },
    fieldName: 'status',
    help: '停用后不会出现在列表',
    label: '类型状态'
  }
];
eims-ui/apps/web-antd/src/views/eims/fixture-type/fixture-type-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,132 @@
<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 { addFixtureType, getFixtureType, listFixtureType, updateFixtureType } from '#/api/eims/fixture-type';
import { drawerSchema } from './data';
interface ModalProps {
  id?: number | string;
  update: boolean;
}
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: {
    componentProps: {
      class: 'w-full'
    },
    formItemClass: 'col-span-2',
    labelWidth: 90
  },
  schema: drawerSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2'
});
async function setupFixtureTypeSelect() {
  // menu
  const menuArray = await listFixtureType({ status: '0' });
  // support i18n
  menuArray.forEach((item) => {
    item.typeName = $t(item.typeName);
  });
  // const folderArray = menuArray.filter((item) => item.menuType === 'M');
  const menuTree = listToTree(menuArray, { id: 'id', pid: 'parentId' });
  const fullMenuTree = [
    {
      id: 0,
      typeName: $t('menu.root'),
      children: menuTree
    }
  ];
  addFullName(fullMenuTree, 'typeName', ' / ');
  formApi.updateSchema([
    {
      componentProps: {
        fieldNames: {
          label: 'typeName',
          value: 'id'
        },
        getPopupContainer,
        // è®¾ç½®å¼¹çª—滚动高度 é»˜è®¤256
        listHeight: 300,
        showSearch: true,
        treeData: fullMenuTree,
        treeDefaultExpandAll: false,
        // é»˜è®¤å±•开的树节点
        treeDefaultExpandedKeys: [0],
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'typeName',
        treeNodeLabelProp: 'fullName'
      },
      fieldName: 'parentId'
    }
  ]);
}
const [BasicDrawer, drawerApi] = useVbenDrawer({
  onCancel: handleCancel,
  onConfirm: handleConfirm,
  async onOpenChange(isOpen) {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);
    const { id, update } = drawerApi.getData() as ModalProps;
    isUpdate.value = update;
    // åŠ è½½è®¾å¤‡ç±»åž‹æ ‘é€‰æ‹©
    await setupFixtureTypeSelect();
    if (id) {
      await formApi.setFieldValue('parentId', id);
      if (update) {
        const record = await getFixtureType(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 ? updateFixtureType(data) : addFixtureType(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/fixture-type/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { eachTree, getVxePopupContainer } from '@vben/utils';
import { Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { delFixtureType, fixtureTypeExport, listFixtureType } from '#/api/eims/fixture-type';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import fixtureTypeDrawer from './fixture-type-drawer.vue';
/**
 * ä¸è¦é—®ä¸ºä»€ä¹ˆæœ‰ä¸¤ä¸ªæ ¹èŠ‚ç‚¹ v-if会控制只会渲染一个
 */
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'
};
const gridOptions: VxeGridProps = {
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {
    enabled: false
  },
  proxyConfig: {
    ajax: {
      query: async (_, formValues = {}) => {
        const resp = await listFixtureType({
          ...formValues
        });
        return { rows: resp };
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  /**
   * å¼€å¯è™šæ‹Ÿæ»šåЍ
   * æ•°æ®é‡å°å¯ä»¥é€‰æ‹©å…³é—­
   * å¦‚果遇到样式问题(空白、错位 æ»šåŠ¨ç­‰)可以选择关闭虚拟滚动
   */
  scrollY: {
    enabled: true,
    gt: 0
  },
  treeConfig: {
    parentField: 'parentId',
    rowField: 'id',
    // è‡ªåŠ¨è½¬æ¢ä¸ºtree ç”±vxe处理 æ— éœ€æ‰‹åŠ¨è½¬æ¢
    transform: true
  },
  id: 'fixture-type-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    cellDblclick: (e: any) => {
      const { row = {} } = e;
      if (!row?.children) {
        return;
      }
      const isExpanded = row?.expand;
      tableApi.grid.setTreeExpand(row, !isExpanded);
      row.expand = !isExpanded;
    },
    // éœ€è¦ç›‘听使用箭头展开的情况 å¦åˆ™å±•å¼€/折叠的数据不一致
    toggleTreeExpand: (e: any) => {
      const { row = {}, expanded } = e;
      row.expand = expanded;
    }
  }
});
const [FixtureTypeDrawer, drawerApi] = useVbenDrawer({
  connectedComponent: fixtureTypeDrawer
});
function handleAdd() {
  drawerApi.setData({});
  drawerApi.open();
}
function handleSubAdd(row: Recordable<any>) {
  const { id } = row;
  drawerApi.setData({ id, update: false });
  drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  drawerApi.setData({ id: record.id, update: true });
  drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delFixtureType(row.id);
  await tableApi.query();
}
function handleDownloadExcel() {
  commonDownloadExcel(fixtureTypeExport, '工具类型', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
/**
 * å…¨éƒ¨å±•å¼€/折叠
 * @param expand æ˜¯å¦å±•å¼€
 */
function setExpandOrCollapse(expand: boolean) {
  eachTree(tableApi.grid.getData(), (item) => (item.expand = expand));
  tableApi.grid?.setAllTreeExpand(expand);
}
</script>
<template>
  <Page :auto-content-height="true">
    <BasicTable table-title="工具类型列表" table-title-help="双击展开/收起子菜单">
      <template #toolbar-tools>
        <Space>
          <a-button @click="setExpandOrCollapse(false)">
            {{ $t('pages.common.collapse') }}
          </a-button>
          <a-button @click="setExpandOrCollapse(true)">
            {{ $t('pages.common.expand') }}
          </a-button>
          <a-button v-access:code="['eims:fixtureType:export']" @click="handleDownloadExcel">
            {{ $t('pages.common.export') }}
          </a-button>
          <a-button type="primary" v-access:code="['eims:fixtureType:add']" @click="handleAdd">
            {{ $t('pages.common.add') }}
          </a-button>
        </Space>
      </template>
      <template #action="{ row }">
        <Space>
          <ghost-button v-access:code="['eims:fixtureType:edit']" @click="handleEdit(row)">
            {{ $t('pages.common.edit') }}
          </ghost-button>
          <!-- '按钮类型'无法再添加子菜单 -->
          <ghost-button v-if="row.menuType !== 'F'" class="btn-success" v-access:code="['eims:fixtureType:add']" @click="handleSubAdd(row)">
            {{ $t('pages.common.add') }}
          </ghost-button>
          <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
            <ghost-button danger v-access:code="['eims:fixtureType:remove']" @click.stop="">
              {{ $t('pages.common.delete') }}
            </ghost-button>
          </Popconfirm>
        </Space>
      </template>
    </BasicTable>
    <FixtureTypeDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,245 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'fixtureName',
    label: '工具名称'
  },
  {
    component: 'Input',
    fieldName: 'fixtureCode',
    label: '工具编码'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_FIXTURE_STATUS)
    },
    fieldName: 'status',
    label: '工具状态'
  },
  {
    component: 'Input',
    fieldName: 'assetNo',
    label: '资产编号'
  },
  {
    component: 'Input',
    fieldName: 'modelNo',
    label: '工具型号'
  },
  {
    component: 'Input',
    fieldName: 'specNo',
    label: '工具规格'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'borrowDept',
    label: '借用部门',
    // rules: 'selectRequired',
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'borrowUser',
    label: '借用人'
  },
  {
    component: 'Input',
    fieldName: 'madeIn',
    label: '制造商'
  },
  {
    component: 'RangePicker',
    fieldName: 'purchaseDate',
    label: '采购日期'
  },
  {
    component: 'RangePicker',
    fieldName: 'deployDate',
    label: '使用日期'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '工具(治具)名称',
    field: 'fixtureName',
    minWidth: 140,
    fixed: 'left'
  },
  {
    title: '状态',
    field: 'status',
    sortable: true,
    slots: {
      default: ({ row }) => {
        if (row.status === null || row.status === '') {
          return '';
        }
        return renderDict(row.status, DictEnum.EIMS_FIXTURE_STATUS);
      }
    },
    minWidth: 80,
    fixed: 'left'
  },
  {
    title: '类型',
    field: 'fixtureTypeName',
    minWidth: 100
  },
  {
    title: '资产编号',
    field: 'assetNo',
    sortable: true,
    minWidth: 140
  },
  {
    title: '工具编码',
    field: 'fixtureCode',
    sortable: true,
    minWidth: 100
  },
  {
    title: '型号',
    field: 'modelNo',
    minWidth: 100
  },
  {
    title: '规格',
    field: 'specNo',
    minWidth: 100
  },
  {
    title: '制造商',
    field: 'madeIn',
    minWidth: 140
  },
  {
    title: '采购日期',
    field: 'purchaseDate',
    minWidth: 140
  },
  {
    title: '使用日期',
    field: 'deployDate',
    minWidth: 140
  },
  {
    title: '使用年限',
    field: 'serviceLife',
    minWidth: 100
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    component: 'TreeSelect',
    defaultValue: 0,
    fieldName: 'fixtureType',
    label: '工具类型',
    rules: 'selectRequired'
  },
  {
    component: 'Input',
    fieldName: 'fixtureName',
    label: '工具名称',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'fixtureCode',
    label: '工具编码',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'assetNo',
    label: '资产编号'
  },
  {
    component: 'Input',
    fieldName: 'modelNo',
    label: '型号'
  },
  {
    component: 'Input',
    fieldName: 'specNo',
    label: '规格'
  },
  {
    component: 'Input',
    fieldName: 'madeIn',
    label: '制造商'
  },
  {
    component: 'RadioGroup',
    componentProps: {
      buttonStyle: 'solid',
      options: getDictOptions(DictEnum.EIMS_FIXTURE_STATUS),
      optionType: 'button'
    },
    defaultValue: '0',
    fieldName: 'status',
    label: '状态'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'purchaseDate',
    label: '采购日期'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD',
      showTime: false,
      valueFormat: 'YYYY-MM-DD',
      getPopupContainer
    },
    fieldName: 'deployDate',
    label: '使用日期'
  },
  {
    component: 'Input',
    fieldName: 'serviceLife',
    label: '使用年限'
  }
];
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,212 @@
<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 { addFixture, getFixture, updateFixture } from '#/api/eims/fixture';
import { getFixtureType, listFixtureType } from '#/api/eims/fixture-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,
  closeOnPressEscape: true,
  placement: 'left',
  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 getFixture(id);
      await formApi.setValues(record);
      if (isUpdate.value && record.borrowDept) {
        await setupUserOptions(record.borrowDept);
      }
    }
    // åŠ è½½å·¥å…·ç±»åž‹æ ‘é€‰æ‹©
    await setupFixtureTypeSelect();
    if (id) {
      await formApi.setFieldValue('parentId', id);
      if (isUpdate.value && id) {
        const record = await getFixtureType(id);
        await formApi.setValues(record);
      }
    }
    drawerApi.drawerLoading(false);
  }
});
async function setupFixtureTypeSelect() {
  // status-0 åªæŸ¥è¯¢æœªåœç”¨å·¥å…·
  const fixArray = await listFixtureType({ status: 0 });
  // support i18n
  fixArray.forEach((item) => {
    item.typeName = $t(item.typeName);
  });
  const fixTree = listToTree(fixArray, { id: 'id', pid: 'parentId' });
  const fullTree = [
    {
      id: 0,
      typeName: $t('menu.root'),
      children: fixTree
    }
  ];
  addFullName(fullTree, 'typeName', ' / ');
  formApi.updateSchema([
    {
      componentProps: {
        fieldNames: {
          label: 'typeName',
          value: 'id'
        },
        getPopupContainer,
        // è®¾ç½®å¼¹çª—滚动高度 é»˜è®¤256
        listHeight: 300,
        showSearch: true,
        treeData: fullTree,
        disabled: typeDisabled.value,
        treeDefaultExpandAll: false,
        // é»˜è®¤å±•开的树节点
        treeDefaultExpandedKeys: [0],
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'typeName',
        treeNodeLabelProp: 'fullName'
      },
      fieldName: 'fixtureType'
    }
  ]);
}
/**
 * ç”¨æˆ·çš„加载
 */
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: 'borrowUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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: 'borrowDept'
    }
  ]);
}
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    await (isUpdate.value ? updateFixture(data) : addFixture(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/fixture/fixture-import-modal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,112 @@
<script setup lang="ts">
import type { UploadFile } from 'ant-design-vue/es/upload/interface';
import { h, ref, unref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { ExcelIcon, InBoxIcon } from '@vben/icons';
import { Modal, Switch, Upload } from 'ant-design-vue';
import { downloadImportTemplate, equImportData } from '#/api/eims/equ';
import { commonDownloadExcel } from '#/utils/file/download';
const emit = defineEmits<{ reload: [] }>();
const UploadDragger = Upload.Dragger;
const [BasicModal, modalApi] = useVbenModal({
  onCancel: handleCancel,
  onConfirm: handleSubmit,
});
const fileList = ref<UploadFile[]>([]);
const checked = ref(false);
async function handleSubmit() {
  try {
    modalApi.modalLoading(true);
    if (fileList.value.length !== 1) {
      handleCancel();
      return;
    }
    const data = {
      file: fileList.value[0]!.originFileObj as Blob,
      updateSupport: unref(checked),
    };
    const { code, msg } = await equImportData(data);
    let modal = Modal.success;
    if (code === 200) {
      emit('reload');
    } else {
      emit('reload');
      modal = Modal.error;
    }
    handleCancel();
    modal({
      content: h('div', {
        class: 'max-h-[260px] overflow-y-auto',
        innerHTML: msg, // åŽå°å·²ç»å¤„理xss问题
      }),
      title: '提示',
    });
  } catch (error) {
    console.warn(error);
    modalApi.close();
  } finally {
    modalApi.modalLoading(false);
  }
}
function handleCancel() {
  modalApi.close();
  fileList.value = [];
  checked.value = false;
}
</script>
<template>
  <BasicModal
    :close-on-click-modal="false"
    :fullscreen-button="false"
    title="设备导入"
  >
    <!-- z-index不设置会遮挡模板下载loading -->
    <!-- æ‰‹åŠ¨å¤„ç† è€Œä¸æ˜¯æ”¾å…¥æ–‡ä»¶å°±ä¸Šä¼  -->
    <UploadDragger
      v-model:file-list="fileList"
      :before-upload="() => false"
      :max-count="1"
      :show-upload-list="true"
      accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
    >
      <p class="ant-upload-drag-icon flex items-center justify-center">
        <InBoxIcon class="text-primary size-[48px]" />
      </p>
      <p class="ant-upload-text">点击或者拖拽到此处上传文件</p>
    </UploadDragger>
    <div class="mt-2 flex flex-col gap-2">
      <div class="flex items-center gap-2">
        <span>允许导入xlsx, xls文件</span>
        <a-button
          type="link"
          @click="commonDownloadExcel(downloadImportTemplate, '设备导入模板')"
        >
          <div class="flex items-center gap-[4px]">
            <ExcelIcon />
            <span>下载模板</span>
          </div>
        </a-button>
      </div>
      <div class="flex items-center gap-2">
        <span class="text-red-500">⚠️特别注意⚠️:请下载模版保持导入文件表头和模版一致后导入</span>
      </div>
      <div class="flex items-center gap-2">
        <span :class="{ 'text-red-500': checked }">
          æ˜¯å¦æ›´æ–°/覆盖已存在的用户数据
        </span>
        <Switch v-model:checked="checked" />
      </div>
    </div>
  </BasicModal>
</template>
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-type-tree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
<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 { getFixtureTypeTree } from '#/api/eims/fixture-type';
defineOptions({ inheritAttrs: false });
const emit = defineEmits<{
  /**
   * ç‚¹å‡»åˆ·æ–°æŒ‰é’®çš„事件
   */
  reload: [];
  /**
   * ç‚¹å‡»èŠ‚ç‚¹çš„äº‹ä»¶
   */
  select: [];
}>();
const selectTypeId = defineModel('selectTypeId', {
  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 = '';
  selectTypeId.value = [];
  const ret = await getFixtureTypeTree();
  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="selectTypeId"
            :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/fixture/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,285 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenDrawer, useVbenModal, 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 { delFixture, fixtureExport, listFixture } from '#/api/eims/fixture';
import { getDeptTree, userList } from '#/api/system/user';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import fixtureDrawer from './fixture-drawer.vue';
import fixtureImportModal from './fixture-import-modal.vue';
import FixtureTypeTree from './fixture-type-tree.vue';
// å·¦è¾¹å·¥å…·ç±»åž‹
const selectTypeId = ref<string[]>([]);
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true
    }
  },
  collapsed: 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: [
    ['purchaseDate', ['params[beginPurchaseDate]', 'params[endPurchaseDate]'], ['YYYY-MM-DD', 'YYYY-MM-DD']],
    ['deployDate', ['params[beginDeployDate]', 'params[endDeployDate]'], ['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 = {}) => {
        // éƒ¨é—¨æ ‘选择处理
        if (selectTypeId.value.length === 1) {
          formValues.fixtureType = selectTypeId.value[0];
        } else {
          Reflect.deleteProperty(formValues, 'fixtureType');
        }
        return await listFixture({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'fixtureId'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-fixture-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [FixtureDrawer, fixtureDrawerApi] = useVbenDrawer({
  connectedComponent: fixtureDrawer
});
/**
 * å¯¼å…¥
 */
const [FixtureImportModal, fixtureImportModalApi] = useVbenModal({
  connectedComponent: fixtureImportModal
});
function handleImport() {
  fixtureImportModalApi.open();
}
function handleAdd() {
  fixtureDrawerApi.setData({});
  fixtureDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  fixtureDrawerApi.setData({ id: record.id });
  fixtureDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delFixture(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 delFixture(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(fixtureExport, '工具台账', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
const router = useRouter();
function handleDetail(record: Recordable<any>) {
  router.push(`/fixture/detail/${record.id}`);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.inventoryUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'borrowDept'
    }
  ]);
}
/**
 * ç”¨æˆ·çš„加载
 */
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: 'borrowUser'
    }
  ]);
}
onMounted(async () => {
  await setupDeptSelect();
});
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <FixtureTypeTree v-model:select-type-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:fixture:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button v-access:code="['eims:fixture:import']" @click="handleImport">
              {{ $t('pages.common.import') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:fixture:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:fixture: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:fixture: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:fixture: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:fixture:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <FixtureDrawer @reload="tableApi.query()" />
    <FixtureImportModal @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,5 +1,6 @@
export enum DictEnum {
  EIMS_EQU_UNIT = 'eims_equ_unit', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_FIXTURE_STATUS = 'eims_fixture_status', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EQU_IMPORT_STATU = 'equ_import_status', // è®¾å¤‡å¯¼å…¥çŠ¶æ€
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/FixtureTypeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package org.dromara.common.core.service;
public interface FixtureTypeService {
    /**
     * é€šè¿‡å·¥å…·ç±»åž‹ID查询工具名称
     *
     * @param fixIds å·¥å…·ID串逗号分隔
     * @return å·¥å…·ç±»åž‹åç§°ä¸²é€—号分隔
     */
    String selectFixtureTypeNameByIds(String fixIds);
}
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java
@@ -40,5 +40,9 @@
     * è®¾å¤‡åç§°id转名称
     */
    String EQU_ID_TO_NAME = "equ_id_to_name";
    /**
     * å·¥å…·ç±»åž‹(治具)id转名称
     */
    String FIXTURE_TYPE_ID_TO_NAME = "fixture_type_id_to_name";
}
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/FixtureTypeNameTranslationImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package org.dromara.common.translation.core.impl;
import lombok.AllArgsConstructor;
import org.dromara.common.core.service.FixtureTypeService;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.common.translation.core.TranslationInterface;
/**
 * å·¥å…·åç§°ç¿»è¯‘实现
 *
 * @author zhuguifei
 */
@AllArgsConstructor
@TranslationType(type = TransConstant.FIXTURE_TYPE_ID_TO_NAME)
public class FixtureTypeNameTranslationImpl implements TranslationInterface<String> {
    private final FixtureTypeService fixtureTypeService;
    @Override
    public String translation(Object key, String other) {
        if (key instanceof String ids) {
            return fixtureTypeService.selectFixtureTypeNameByIds(ids);
        } else if (key instanceof Long id) {
            return fixtureTypeService.selectFixtureTypeNameByIds(id.toString());
        }
        return null;
    }
}
eims/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -6,3 +6,4 @@
org.dromara.common.translation.core.impl.NicknameTranslationImpl
org.dromara.common.translation.core.impl.EquTypeNameTranslationImpl
org.dromara.common.translation.core.impl.EquNameTranslationImpl
org.dromara.common.translation.core.impl.FixtureTypeNameTranslationImpl
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureController.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.EimsFixtureVo;
import org.dromara.eims.domain.bo.EimsFixtureBo;
import org.dromara.eims.service.IEimsFixtureService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * å·¥å…·(治具)台账
 *
 * @author zhuguifei
 * @date 2025-02-14
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/fixture")
public class EimsFixtureController extends BaseController {
    private final IEimsFixtureService eimsFixtureService;
    /**
     * æŸ¥è¯¢å·¥å…·(治具)台账列表
     */
    @SaCheckPermission("eims:fixture:list")
    @GetMapping("/list")
    public TableDataInfo<EimsFixtureVo> list(EimsFixtureBo bo, PageQuery pageQuery) {
        return eimsFixtureService.queryPageList(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºå·¥å…·(治具)台账列表
     */
    @SaCheckPermission("eims:fixture:export")
    @Log(title = "工具(治具)台账", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsFixtureBo bo, HttpServletResponse response) {
        List<EimsFixtureVo> list = eimsFixtureService.queryList(bo);
        ExcelUtil.exportExcel(list, "工具(治具)台账", EimsFixtureVo.class, response);
    }
    /**
     * èŽ·å–å·¥å…·(治具)台账详细信息
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:fixture:query")
    @GetMapping("/{id}")
    public R<EimsFixtureVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsFixtureService.queryById(id));
    }
    /**
     * æ–°å¢žå·¥å…·(治具)台账
     */
    @SaCheckPermission("eims:fixture:add")
    @Log(title = "工具(治具)台账", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsFixtureBo bo) {
        return toAjax(eimsFixtureService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹å·¥å…·(治具)台账
     */
    @SaCheckPermission("eims:fixture:edit")
    @Log(title = "工具(治具)台账", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsFixtureBo bo) {
        return toAjax(eimsFixtureService.updateByBo(bo));
    }
    /**
     * åˆ é™¤å·¥å…·(治具)台账
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:fixture:remove")
    @Log(title = "工具(治具)台账", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsFixtureService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureTypeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
package org.dromara.eims.controller;
import java.util.List;
import cn.hutool.core.lang.tree.Tree;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.eims.domain.bo.EimsEquTypeBo;
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.EimsFixtureTypeVo;
import org.dromara.eims.domain.bo.EimsFixtureTypeBo;
import org.dromara.eims.service.IEimsFixtureTypeService;
/**
 * å·¥å…·ç±»åž‹
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/fixtureType")
public class EimsFixtureTypeController extends BaseController {
    private final IEimsFixtureTypeService eimsFixtureTypeService;
    /**
     * æŸ¥è¯¢å·¥å…·ç±»åž‹åˆ—表
     */
    @SaCheckPermission("eims:fixtureType:list")
    @GetMapping("/list")
    public R<List<EimsFixtureTypeVo>> list(EimsFixtureTypeBo bo) {
        List<EimsFixtureTypeVo> list = eimsFixtureTypeService.queryList(bo);
        return R.ok(list);
    }
    /**
     * èŽ·å–è®¾å¤‡ç±»åž‹æ ‘åˆ—è¡¨
     */
    @SaCheckPermission("eims:fixtureType:list")
    @GetMapping("/tree")
    public R<List<Tree<Long>>> fixtureTypeTree(EimsFixtureTypeBo bo) {
        return R.ok(eimsFixtureTypeService.selectFixtureTypeTreeList(bo));
    }
    /**
     * å¯¼å‡ºå·¥å…·ç±»åž‹åˆ—表
     */
    @SaCheckPermission("eims:fixtureType:export")
    @Log(title = "工具类型", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public  void export(EimsFixtureTypeBo bo, HttpServletResponse response) {
        List<EimsFixtureTypeVo> list = eimsFixtureTypeService.queryList(bo);
        ExcelUtil.exportExcel(list, "工具类型", EimsFixtureTypeVo.class, response);
    }
    /**
     * èŽ·å–å·¥å…·ç±»åž‹è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:fixtureType:query")
    @GetMapping("/{id}")
    public R<EimsFixtureTypeVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsFixtureTypeService.queryById(id));
    }
    /**
     * æ–°å¢žå·¥å…·ç±»åž‹
     */
    @SaCheckPermission("eims:fixtureType:add")
    @Log(title = "工具类型", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsFixtureTypeBo bo) {
        return toAjax(eimsFixtureTypeService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹å·¥å…·ç±»åž‹
     */
    @SaCheckPermission("eims:fixtureType:edit")
    @Log(title = "工具类型", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsFixtureTypeBo bo) {
        return toAjax(eimsFixtureTypeService.updateByBo(bo));
    }
    /**
     * åˆ é™¤å·¥å…·ç±»åž‹
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:fixtureType:remove")
    @Log(title = "工具类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsFixtureTypeService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
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_fixture
 *
 * @author zhuguifei
 * @date 2025-02-14
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_fixture")
public class EimsFixture extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @TableId(value = "id")
    private Long id;
    /**
     * æ²»å…·ç¼–码
     */
    private String fixtureCode;
    /**
     * æ²»å…·åç§°
     */
    private String fixtureName;
    /**
     * æ²»å…·ï¼ˆå·¥å…·ï¼‰ç±»åž‹
     */
    private Long fixtureType;
    /**
     * æ²»å…·æè¿°
     */
    private String fixtureDesc;
    /**
     * å€Ÿç”¨éƒ¨é—¨
     */
    private Long borrowDept;
    /**
     * å€Ÿç”¨äºº
     */
    private Long borrowUser;
    /**
     * çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
     */
    private String status;
    /**
     * èµ„产编号
     */
    private String assetNo;
    /**
     * åž‹å·
     */
    private String modelNo;
    /**
     * è§„æ ¼
     */
    private String specNo;
    /**
     * åˆ¶é€ å•†
     */
    private String madeIn;
    /**
     * é‡‡è´­æ—¥æœŸ
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date purchaseDate;
    /**
     * ä½¿ç”¨æ—¥æœŸ
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date deployDate;
    /**
     * ä½¿ç”¨å¹´é™
     */
    private Long serviceLife;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixtureType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
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_fixture_type
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_fixture_type")
public class EimsFixtureType extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @TableId(value = "id")
    private Long id;
    /**
     * ç±»åž‹åç§°
     */
    private String typeName;
    /**
     * ç±»åž‹ç¼–码
     */
    private String typeCode;
    /**
     * çˆ¶id
     */
    private Long parentId;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    private Long orderNum;
    /**
     * èœå•类型(M目录 C菜单 F按钮)
     */
    private String menuType;
    /**
     * èœå•图标
     */
    private String icon;
    /**
     * èœå•状态(0正常 1停用)
     */
    private String status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsFixture;
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 com.fasterxml.jackson.annotation.JsonFormat;
/**
 * å·¥å…·(治具)台账业务对象 eims_fixture
 *
 * @author zhuguifei
 * @date 2025-02-14
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsFixture.class, reverseConvertGenerate = false)
public class EimsFixtureBo extends BaseEntity {
    /**
     *
     */
    @NotNull(message = "不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * æ²»å…·ç¼–码
     */
    private String fixtureCode;
    /**
     * æ²»å…·åç§°
     */
    @NotBlank(message = "治具名称不能为空", groups = { AddGroup.class, EditGroup.class })
    private String fixtureName;
    /**
     * æ²»å…·ï¼ˆå·¥å…·ï¼‰ç±»åž‹
     */
    private Long fixtureType;
    /**
     * æ²»å…·æè¿°
     */
    private String fixtureDesc;
    /**
     * å€Ÿç”¨éƒ¨é—¨
     */
    private Long borrowDept;
    /**
     * å€Ÿç”¨äºº
     */
    private Long borrowUser;
    /**
     * çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
     */
    private String status;
    /**
     * èµ„产编号
     */
    private String assetNo;
    /**
     * åž‹å·
     */
    private String modelNo;
    /**
     * è§„æ ¼
     */
    private String specNo;
    /**
     * åˆ¶é€ å•†
     */
    private String madeIn;
    /**
     * é‡‡è´­æ—¥æœŸ
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date purchaseDate;
    /**
     * ä½¿ç”¨æ—¥æœŸ
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date deployDate;
    /**
     * ä½¿ç”¨å¹´é™
     */
    private Long serviceLife;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureTypeBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsFixtureType;
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_fixture_type
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsFixtureType.class, reverseConvertGenerate = false)
public class EimsFixtureTypeBo extends BaseEntity {
    /**
     *
     */
    @NotNull(message = "不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * ç±»åž‹åç§°
     */
    @NotBlank(message = "类型名称不能为空", groups = { AddGroup.class, EditGroup.class })
    private String typeName;
    /**
     * ç±»åž‹ç¼–码
     */
    @NotBlank(message = "类型编码不能为空", groups = { AddGroup.class, EditGroup.class })
    private String typeCode;
    /**
     * çˆ¶id
     */
    @NotNull(message = "父id不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long parentId;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    @NotNull(message = "显示顺序不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long orderNum;
    /**
     * èœå•类型(M目录 C菜单 F按钮)
     */
    @NotBlank(message = "菜单类型(M目录 C菜单 F按钮)不能为空", groups = { AddGroup.class, EditGroup.class })
    private String menuType;
    /**
     * èœå•图标
     */
    private String icon;
    /**
     * èœå•状态(0正常 1停用)
     */
    @NotBlank(message = "菜单状态(0正常 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
    private String status;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquTypeVo.java
@@ -1,5 +1,6 @@
package org.dromara.eims.domain.vo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.eims.domain.EimsEquType;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
@@ -22,7 +23,7 @@
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsEquType.class)
public class EimsEquTypeVo implements Serializable {
public class EimsEquTypeVo extends BaseEntity implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureTypeVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
package org.dromara.eims.domain.vo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.eims.domain.EimsFixtureType;
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_fixture_type
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsFixtureType.class)
public class EimsFixtureTypeVo extends BaseEntity implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long id;
    /**
     * ç±»åž‹åç§°
     */
    @ExcelProperty(value = "类型名称")
    private String typeName;
    /**
     * ç±»åž‹ç¼–码
     */
    @ExcelProperty(value = "类型编码")
    private String typeCode;
    /**
     * çˆ¶id
     */
    @ExcelProperty(value = "父id")
    private Long parentId;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    @ExcelProperty(value = "显示顺序")
    private Long orderNum;
    /**
     * èœå•类型(M目录 C菜单 F按钮)
     */
    @ExcelProperty(value = "菜单类型", converter = ExcelDictConvert.class)
    @ExcelDictFormat(readConverterExp = "M=目录,C=菜单,F=按钮")
    private String menuType;
    /**
     * èœå•图标
     */
    @ExcelProperty(value = "菜单图标")
    private String icon;
    /**
     * èœå•状态(0正常 1停用)
     */
    @ExcelProperty(value = "菜单状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "sys_show_hide")
    private String status;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,150 @@
package org.dromara.eims.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.eims.domain.EimsFixture;
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_fixture
 *
 * @author zhuguifei
 * @date 2025-02-14
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsFixture.class)
public class EimsFixtureVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long id;
    /**
     * æ²»å…·ç¼–码
     */
    @ExcelProperty(value = "治具编码")
    private String fixtureCode;
    /**
     * æ²»å…·åç§°
     */
    @ExcelProperty(value = "治具名称")
    private String fixtureName;
    /**
     * æ²»å…·ï¼ˆå·¥å…·ï¼‰ç±»åž‹
     */
    private Long fixtureType;
    /**
     * æ²»å…·ï¼ˆå·¥å…·ï¼‰ç±»åž‹
     */
    @ExcelProperty(value = "治具类型")
    @Translation(type = TransConstant.FIXTURE_TYPE_ID_TO_NAME, mapper = "fixtureType")
    private String fixtureTypeName;
    /**
     * æ²»å…·æè¿°
     */
    @ExcelProperty(value = "治具描述")
    private String fixtureDesc;
    /**
     * å€Ÿç”¨éƒ¨é—¨
     */
    private Long borrowDept;
    /**
     * å€Ÿç”¨éƒ¨é—¨
     */
    private String borrowDeptName;
    /**
     * å€Ÿç”¨äºº
     */
    private Long borrowUser;
    /**
     * å€Ÿç”¨äºº
     */
    private String borrowUserName;
    /**
     * çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
     */
    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "eims_fixture_status")
    private String status;
    /**
     * èµ„产编号
     */
    @ExcelProperty(value = "资产编号")
    private String assetNo;
    /**
     * åž‹å·
     */
    @ExcelProperty(value = "型号")
    private String modelNo;
    /**
     * è§„æ ¼
     */
    @ExcelProperty(value = "规格")
    private String specNo;
    /**
     * åˆ¶é€ å•†
     */
    @ExcelProperty(value = "制造商")
    private String madeIn;
    /**
     * é‡‡è´­æ—¥æœŸ
     */
    @ExcelProperty(value = "采购日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date purchaseDate;
    /**
     * ä½¿ç”¨æ—¥æœŸ
     */
    @ExcelProperty(value = "使用日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date deployDate;
    /**
     * ä½¿ç”¨å¹´é™
     */
    @ExcelProperty(value = "使用年限")
    private Long serviceLife;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package org.dromara.eims.mapper;
import org.dromara.eims.domain.EimsFixture;
import org.dromara.eims.domain.vo.EimsFixtureVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
 * å·¥å…·(治具)台账Mapper接口
 *
 * @author zhuguifei
 * @date 2025-02-14
 */
public interface EimsFixtureMapper extends BaseMapperPlus<EimsFixture, EimsFixtureVo> {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureTypeMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package org.dromara.eims.mapper;
import org.dromara.eims.domain.EimsFixtureType;
import org.dromara.eims.domain.vo.EimsFixtureTypeVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
 * å·¥å…·ç±»åž‹Mapper接口
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
public interface EimsFixtureTypeMapper extends BaseMapperPlus<EimsFixtureType, EimsFixtureTypeVo> {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package org.dromara.eims.service;
import org.dromara.eims.domain.vo.EimsFixtureVo;
import org.dromara.eims.domain.bo.EimsFixtureBo;
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-14
 */
public interface IEimsFixtureService {
    /**
     * æŸ¥è¯¢å·¥å…·(治具)台账
     *
     * @param id ä¸»é”®
     * @return å·¥å…·(治具)台账
     */
    EimsFixtureVo queryById(Long id);
    /**
     * åˆ†é¡µæŸ¥è¯¢å·¥å…·(治具)台账列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return å·¥å…·(治具)台账分页列表
     */
    TableDataInfo<EimsFixtureVo> queryPageList(EimsFixtureBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„工具(治具)台账列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å·¥å…·(治具)台账列表
     */
    List<EimsFixtureVo> queryList(EimsFixtureBo bo);
    /**
     * æ–°å¢žå·¥å…·(治具)台账
     *
     * @param bo å·¥å…·(治具)台账
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsFixtureBo bo);
    /**
     * ä¿®æ”¹å·¥å…·(治具)台账
     *
     * @param bo å·¥å…·(治具)台账
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsFixtureBo 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/IEimsFixtureTypeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package org.dromara.eims.service;
import cn.hutool.core.lang.tree.Tree;
import org.dromara.eims.domain.bo.EimsEquTypeBo;
import org.dromara.eims.domain.vo.EimsFixtureTypeVo;
import org.dromara.eims.domain.bo.EimsFixtureTypeBo;
import java.util.Collection;
import java.util.List;
/**
 * å·¥å…·ç±»åž‹Service接口
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
public interface IEimsFixtureTypeService {
    /**
     * æŸ¥è¯¢å·¥å…·ç±»åž‹
     *
     * @param id ä¸»é”®
     * @return å·¥å…·ç±»åž‹
     */
    EimsFixtureTypeVo queryById(Long id);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„工具类型列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å·¥å…·ç±»åž‹åˆ—表
     */
    List<EimsFixtureTypeVo> queryList(EimsFixtureTypeBo bo);
    /**
     * æ–°å¢žå·¥å…·ç±»åž‹
     *
     * @param bo å·¥å…·ç±»åž‹
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsFixtureTypeBo bo);
    /**
     * ä¿®æ”¹å·¥å…·ç±»åž‹
     *
     * @param bo å·¥å…·ç±»åž‹
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsFixtureTypeBo bo);
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤å·¥å…·ç±»åž‹ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
    /**
     * èŽ·å–å·¥å…·ç±»åž‹æ ‘åˆ—è¡¨
     *
     * @param bo
     * @return æ ‘列表
     */
    List<Tree<Long>> selectFixtureTypeTreeList(EimsFixtureTypeBo bo);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsEquTypeServiceImpl.java
@@ -143,7 +143,7 @@
     */
    @Override
    public List<Tree<Long>> selectEquTypeTreeList(EimsEquTypeBo bo) {
        // åªæŸ¥è¯¢æœªç¦ç”¨éƒ¨é—¨
        // åªæŸ¥è¯¢æœªç¦ç”¨ç±»åž‹
        bo.setStatus(UserConstants.DEPT_NORMAL);
        LambdaQueryWrapper<EimsEquType> lqw = buildQueryWrapper(bo);
        List<EimsEquTypeVo> equTypeVoList = baseMapper.selectVoList(lqw);
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,196 @@
package org.dromara.eims.service.impl;
import cn.hutool.core.convert.Convert;
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.SpringUtils;
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.eims.domain.EimsEqu;
import org.dromara.eims.domain.EimsEquType;
import org.dromara.eims.domain.EimsFixtureType;
import org.dromara.eims.domain.vo.EimsEquTypeVo;
import org.dromara.eims.domain.vo.EimsEquVo;
import org.dromara.eims.domain.vo.EimsFixtureTypeVo;
import org.dromara.eims.mapper.EimsFixtureTypeMapper;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsFixtureBo;
import org.dromara.eims.domain.vo.EimsFixtureVo;
import org.dromara.eims.domain.EimsFixture;
import org.dromara.eims.mapper.EimsFixtureMapper;
import org.dromara.eims.service.IEimsFixtureService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * å·¥å…·(治具)台账Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-02-14
 */
@RequiredArgsConstructor
@Service
public class EimsFixtureServiceImpl implements IEimsFixtureService {
    private final EimsFixtureMapper baseMapper;
    private final EimsFixtureTypeMapper fixtureTypeMapper;
    /**
     * æŸ¥è¯¢å·¥å…·(治具)台账
     *
     * @param id ä¸»é”®
     * @return å·¥å…·(治具)台账
     */
    @Override
    public EimsFixtureVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢å·¥å…·(治具)台账列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return å·¥å…·(治具)台账分页列表
     */
    @Override
    public TableDataInfo<EimsFixtureVo> queryPageList(EimsFixtureBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsFixture> lqw = buildQueryWrapper(bo);
        Page<EimsFixtureVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„工具(治具)台账列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å·¥å…·(治具)台账列表
     */
    @Override
    public List<EimsFixtureVo> queryList(EimsFixtureBo bo) {
        LambdaQueryWrapper<EimsFixture> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsFixture> buildQueryWrapper(EimsFixtureBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsFixture> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getFixtureCode()), EimsFixture::getFixtureCode, bo.getFixtureCode());
        lqw.like(StringUtils.isNotBlank(bo.getFixtureName()), EimsFixture::getFixtureName, bo.getFixtureName());
        Long fixtureType = bo.getFixtureType();
        /**
         * equTypeId = 0 æ—¶æŸ¥è¯¢æ‰€æœ‰è®¾å¤‡ï¼ˆé»˜è®¤æ ¹ç›®å½•id为0,详见SysEquTypeServiceImpl中selectEquTypeTreeList)
         * equTypeId   ä¸ºå…¶ä»–值时只查当前设备类型id和后代设备类型id
         */
        if (fixtureType != null && fixtureType > 0) {
            List<Long> allDescendantIds = getAllDescendantIds(fixtureType);
            lqw.in(EimsFixture::getFixtureType, allDescendantIds);
        }
        lqw.eq(StringUtils.isNotBlank(bo.getFixtureDesc()), EimsFixture::getFixtureDesc, bo.getFixtureDesc());
        lqw.eq(bo.getBorrowDept()!=null, EimsFixture::getBorrowDept, bo.getBorrowDept());
        lqw.eq(bo.getBorrowUser()!=null, EimsFixture::getBorrowUser, bo.getBorrowUser());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsFixture::getStatus, bo.getStatus());
        lqw.like(StringUtils.isNotBlank(bo.getAssetNo()), EimsFixture::getAssetNo, bo.getAssetNo());
        lqw.like(StringUtils.isNotBlank(bo.getModelNo()), EimsFixture::getModelNo, bo.getModelNo());
        lqw.like(StringUtils.isNotBlank(bo.getSpecNo()), EimsFixture::getSpecNo, bo.getSpecNo());
        lqw.like(StringUtils.isNotBlank(bo.getMadeIn()), EimsFixture::getMadeIn, bo.getMadeIn());
        lqw.between(params.get("beginPurchaseDate") != null && params.get("endPurchaseDate") != null,
            EimsFixture::getPurchaseDate ,params.get("beginPurchaseDate"), params.get("endPurchaseDate"));
        lqw.between(params.get("beginDeployDate") != null && params.get("endDeployDate") != null,
            EimsFixture::getDeployDate ,params.get("beginDeployDate"), params.get("endDeployDate"));
        lqw.eq(bo.getServiceLife() != null, EimsFixture::getServiceLife, bo.getServiceLife());
        return lqw;
    }
    /**
     * æ ¹æ®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<EimsFixtureType> fixTypeWrapper = new QueryWrapper<>();
        fixTypeWrapper.lambda().eq(EimsFixtureType::getParentId, currentId);
        List<EimsFixtureTypeVo> children = fixtureTypeMapper.selectVoList(fixTypeWrapper);
        if (children != null && !children.isEmpty()) {
            for (EimsFixtureTypeVo child : children) {
                Long childId = child.getId();
                collector.add(childId);
                collectDescendants(childId, collector);
            }
        }
    }
    /**
     * æ–°å¢žå·¥å…·(治具)台账
     *
     * @param bo å·¥å…·(治具)台账
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsFixtureBo bo) {
        EimsFixture add = MapstructUtils.convert(bo, EimsFixture.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹å·¥å…·(治具)台账
     *
     * @param bo å·¥å…·(治具)台账
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsFixtureBo bo) {
        EimsFixture update = MapstructUtils.convert(bo, EimsFixture.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsFixture 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/EimsFixtureTypeServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,183 @@
package org.dromara.eims.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.service.FixtureTypeService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.TreeBuildUtils;
import org.dromara.eims.domain.EimsEquType;
import org.dromara.eims.domain.bo.EimsEquTypeBo;
import org.dromara.eims.domain.vo.EimsEquTypeVo;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsFixtureTypeBo;
import org.dromara.eims.domain.vo.EimsFixtureTypeVo;
import org.dromara.eims.domain.EimsFixtureType;
import org.dromara.eims.mapper.EimsFixtureTypeMapper;
import org.dromara.eims.service.IEimsFixtureTypeService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * å·¥å…·ç±»åž‹Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-02-17
 */
@RequiredArgsConstructor
@Service
public class EimsFixtureTypeServiceImpl implements IEimsFixtureTypeService, FixtureTypeService {
    private final EimsFixtureTypeMapper baseMapper;
    /**
     * æŸ¥è¯¢å·¥å…·ç±»åž‹
     *
     * @param id ä¸»é”®
     * @return å·¥å…·ç±»åž‹
     */
    @Override
    public EimsFixtureTypeVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„工具类型列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å·¥å…·ç±»åž‹åˆ—表
     */
    @Override
    public List<EimsFixtureTypeVo> queryList(EimsFixtureTypeBo bo) {
        LambdaQueryWrapper<EimsFixtureType> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsFixtureType> buildQueryWrapper(EimsFixtureTypeBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsFixtureType> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTypeName()), EimsFixtureType::getTypeName, bo.getTypeName());
        lqw.like(StringUtils.isNotBlank(bo.getTypeCode()), EimsFixtureType::getTypeCode, bo.getTypeCode());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsFixtureType::getStatus, bo.getStatus());
        return lqw;
    }
    /**
     * æ–°å¢žå·¥å…·ç±»åž‹
     *
     * @param bo å·¥å…·ç±»åž‹
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsFixtureTypeBo bo) {
        EimsFixtureType add = MapstructUtils.convert(bo, EimsFixtureType.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹å·¥å…·ç±»åž‹
     *
     * @param bo å·¥å…·ç±»åž‹
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsFixtureTypeBo bo) {
        EimsFixtureType update = MapstructUtils.convert(bo, EimsFixtureType.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsFixtureType entity){
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤å·¥å…·ç±»åž‹ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
    @Override
    public List<Tree<Long>> selectFixtureTypeTreeList(EimsFixtureTypeBo bo) {
        // åªæŸ¥è¯¢æœªç¦ç”¨ç±»åž‹
        bo.setStatus(UserConstants.DEPT_NORMAL);
        LambdaQueryWrapper<EimsFixtureType> lqw = buildQueryWrapper(bo);
        List<EimsFixtureTypeVo> fixtureTypeVoList = baseMapper.selectVoList(lqw);
        for (int i = 0; i < fixtureTypeVoList.size(); i++) {
            EimsFixtureTypeVo fixtureTypeVo = fixtureTypeVoList.get(i);
            if(fixtureTypeVo.getParentId() == null){
                fixtureTypeVoList.get(i).setParentId(0L);
            }
        }
        //加根目录
        EimsFixtureTypeVo root = new EimsFixtureTypeVo();
        root.setId(0L);
        root.setMenuType("M");
        root.setTypeName("所有工具");
        root.setStatus("0");
        root.setTypeCode("0");
        root.setOrderNum(0L);
        root.setIcon("#");
        fixtureTypeVoList.add(root);
        fixtureTypeVoList.sort((o1, o2) -> o1.getId().compareTo(o2.getId()));
        return buildEquTypeTreeSelect(fixtureTypeVoList);
    }
    /**
     * æž„建前端所需要下拉树结构
     *
     * @param fixtureTypeVoList å·¥å…·ç±»åž‹åˆ—表
     * @return ä¸‹æ‹‰æ ‘结构列表
     */
    public List<Tree<Long>> buildEquTypeTreeSelect(List<EimsFixtureTypeVo> fixtureTypeVoList) {
        if (CollUtil.isEmpty(fixtureTypeVoList)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(fixtureTypeVoList, (dept, tree) ->
            tree.setId(dept.getId())
                .setParentId(dept.getParentId())
                .setName(dept.getTypeName())
                .setWeight(dept.getOrderNum()));
    }
    @Override
    public String selectFixtureTypeNameByIds(String fixIds) {
        List<String> list = new ArrayList<>();
        for (Long id : StringUtils.splitTo(fixIds, Convert::toLong)) {
            EimsFixtureTypeVo vo = SpringUtils.getAopProxy(this).queryById(id);
            if (ObjectUtil.isNotNull(vo)) {
                list.add(vo.getTypeName());
            }
        }
        return String.join(StringUtils.SEPARATOR, list);
    }
}
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFixtureMapper.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.EimsFixtureMapper">
</mapper>