车间能级提升-智能设备管理系统
zhuguifei
2025-04-08 c6e203d8e80c9cd8f74c79498662fa20d223ff56
知识库,备件
已添加60个文件
已修改11个文件
6322 ■■■■■ 文件已修改
eims-ui/apps/web-antd/src/api/eims/fault-know/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/fault-know/model.d.ts 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/spare-inout/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/spare-inout/model.d.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/spare-type/index.ts 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/spare-type/model.d.ts 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/spare/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/spare/model.d.ts 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fault-know/data.tsx 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fault-know/equ-type-tree.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fault-know/fault-know-drawer.vue 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fault-know/index.vue 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-import-modal.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/fixture/index.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-in/data.tsx 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-in/index.vue 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-in/spare-in-drawer.vue 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-out/data.tsx 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-out/index.vue 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-out/spare-out-drawer.vue 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-type/data.tsx 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-type/index.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare-type/spare-type-drawer.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare/data.tsx 282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare/index.vue 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare/spare-drawer.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/spare/spare-type-tree.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/DictConstants.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SpareTypeService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/EquTypeNameTranslationImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/SpareTypeNameTranslationImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | 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/EimsFaultKnowController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsSpareController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsSpareInoutController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsSpareTypeController.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFaultKnow.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsSpare.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsSpareInout.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsSpareType.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFaultKnowBo.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsSpareBo.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsSpareInoutBo.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsSpareTypeBo.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsEquVo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFaultKnowVo.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsSpareInoutVo.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsSpareTypeVo.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsSpareVo.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFaultKnowMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsSpareInoutMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsSpareMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsSpareTypeMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFaultKnowService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsSpareInoutService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsSpareService.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsSpareTypeService.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFaultKnowServiceImpl.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsSpareInoutServiceImpl.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsSpareServiceImpl.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsSpareTypeServiceImpl.java 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFaultKnowMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsSpareInoutMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsSpareMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsSpareTypeMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/fault-know/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import type { FaultKnowVO } from './model';
import type { ID, IDS } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  faultKnowExport = '/eims/faultKnow/export',
  faultKnowList = '/eims/faultKnow/list',
  root = '/eims/faultKnow'
}
/**
 * æŸ¥è¯¢æ•…障知识列表
 * @param params
 * @returns {*}
 */
export function listFaultKnow(params?: any) {
  return requestClient.get<FaultKnowVO[]>(Api.faultKnowList, { params });
}
/**
 * æŸ¥è¯¢æ•…障知识详细
 * @param faultKnowId
 */
export function getFaultKnow(faultKnowId: ID) {
  return requestClient.get<FaultKnowVO>(`${Api.root}/${faultKnowId}`);
}
/**
 * æ–°å¢žæ•…障知识
 * @param data
 */
export function addFaultKnow(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹æ•…障知识
 * @param data
 */
export function updateFaultKnow(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤æ•…障知识
 * @param faultKnowId
 */
export function delFaultKnow(faultKnowId: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${faultKnowId}`);
}
/**
 * å¯¼å‡º
 * @param
 */
export function faultKnowExport(data: any) {
  return commonExport(Api.faultKnowExport, data);
}
eims-ui/apps/web-antd/src/api/eims/fault-know/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
export interface FaultKnowVO {
  /**
   *
   */
  id: number | string;
  /**
   * è®¾å¤‡id
   */
  equId: number | string;
  /**
   * è®¾å¤‡ç±»åž‹
   */
  equType: number;
  /**
   * è®¾å¤‡éƒ¨ä½(字典)
   */
  equPart: string;
  /**
   * çŸ¥è¯†ç¼–码
   */
  faultCode: string;
  /**
   * æ•…障类别(字典)
   */
  faultType: string;
  /**
   * æ•…障原因(字典)
   */
  faultReason: string;
  /**
   * æŠ¥ä¿®æè¿°
   */
  reqDesc: string;
  /**
   * å¤„理措施
   */
  resHandle: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
eims-ui/apps/web-antd/src/api/eims/spare-inout/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import type { IDS, PageQuery, PageResult } from '#/api/common';
import type { SpareInoutVO } from '#/api/eims/spare-inout/model';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  root = '/eims/spareInout',
  spareInoutExport = '/eims/spareInout/export',
  spareInoutList = '/eims/spareInout/list'
}
/**
 * æŸ¥è¯¢ã€å¤‡ä»¶å°è´¦ã€‘列表
 * @param query
 * @returns {*}
 */
export function listSpareInout(params?: PageQuery) {
  return requestClient.get<PageResult<SpareInoutVO>>(Api.spareInoutList, { params });
}
/**
 * æŸ¥è¯¢ã€å¤‡ä»¶å°è´¦ã€‘详细
 * @param spareInoutId
 */
export function getSpareInout(spareInoutId: any) {
  return requestClient.get<SpareInoutVO>(`${Api.root}/${spareInoutId}`);
}
/**
 * æ–°å¢žã€å¤‡ä»¶å°è´¦ã€‘
 * @param data
 */
export function addSpareInout(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹ã€å¤‡ä»¶å°è´¦ã€‘
 * @param data
 */
export function updateSpareInout(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤ã€å¤‡ä»¶å°è´¦ã€‘
 * @param spareInoutIds
 */
export function delSpareInout(spareInoutIds: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${spareInoutIds}`);
}
/**
 * å¯¼å‡ºã€å¤‡ä»¶å°è´¦ã€‘
 * @param data
 */
export function spareInoutExport(data: any) {
  return commonExport(Api.spareInoutExport, data);
}
eims-ui/apps/web-antd/src/api/eims/spare-inout/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
export interface SpareInoutVO {
  /**
   *
   */
  id: number | string;
  /**
   * å•号
   */
  orderCode: string;
  /**
   * å•号日期
   */
  orderDate: string;
  /**
   * ç»åŠžäºº
   */
  chargeUser: number;
  /**
   * å·¥å•类型(1-入库单  2-出库单) å­—å…¸
   */
  type: string;
  /**
   * å‡ºåº“客户名称或入库供应商
   */
  partnerName: string;
  /**
   * å…³è”单号(如-维修单)
   */
  associatedOrder: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
eims-ui/apps/web-antd/src/api/eims/spare-type/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
import type { SpareTypeTree, SpareTypeVO } from './model';
import type { ID, IDS } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  root = '/eims/spareType',
  spareTypeExport = '/eims/spareType/export',
  spareTypeList = '/eims/spareType/list',
  spareTypeTree = '/eims/spareType/tree'
}
/**
 * æŸ¥è¯¢å¤‡ä»¶ç±»åž‹åˆ—表
 * @param query
 * @returns {*}
 */
export function listSpareType(params?: any) {
  return requestClient.get<SpareTypeVO[]>(Api.spareTypeList, { params });
}
/**
 * èŽ·å–å¤‡ä»¶ç±»åž‹æ ‘
 * @returns éƒ¨é—¨æ ‘数组
 */
export function getSpareTypeTree() {
  return requestClient.get<SpareTypeTree[]>(Api.spareTypeTree);
}
/**
 * æŸ¥è¯¢å¤‡ä»¶ç±»åž‹è¯¦ç»†
 * @param spareTypeId
 */
export function getSpareType(spareTypeId: ID) {
  return requestClient.get<SpareTypeVO>(`${Api.root}/${spareTypeId}`);
}
/**
 * æ–°å¢žå¤‡ä»¶ç±»åž‹
 * @param data
 */
export function addSpareType(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹å¤‡ä»¶ç±»åž‹
 * @param data
 */
export function updateSpareType(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤å¤‡ä»¶ç±»åž‹
 * @param spareTypeId
 */
export function delSpareType(spareTypeId: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${spareTypeId}`);
}
/**
 * å¯¼å‡º
 * @param
 */
export function spareTypeExport(data: any) {
  return commonExport(Api.spareTypeExport, data);
}
eims-ui/apps/web-antd/src/api/eims/spare-type/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
export interface SpareTypeVO {
  /**
   *
   */
  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: SpareTypeVO[];
}
/**
 * @description: å¤‡ä»¶ç±»åž‹æ ‘
 */
export interface SpareTypeTree {
  id: number;
  /**
   * antd组件必须要这个属性 å®žé™…是没有这个属性的
   */
  key: string;
  parentId: number;
  label: string;
  weight: number;
  children?: SpareTypeTree[];
}
eims-ui/apps/web-antd/src/api/eims/spare/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import type { IDS, PageQuery, PageResult } from '#/api/common';
import type { SpareVO } from '#/api/eims/spare/model';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  root = '/eims/spare',
  spareExport = '/eims/spare/export',
  spareList = '/eims/spare/list'
}
/**
 * æŸ¥è¯¢ã€å¤‡ä»¶å°è´¦ã€‘列表
 * @param query
 * @returns {*}
 */
export function listSpare(params?: PageQuery) {
  return requestClient.get<PageResult<SpareVO>>(Api.spareList, { params });
}
/**
 * æŸ¥è¯¢ã€å¤‡ä»¶å°è´¦ã€‘详细
 * @param spareId
 */
export function getSpare(spareId: any) {
  return requestClient.get<SpareVO>(`${Api.root}/${spareId}`);
}
/**
 * æ–°å¢žã€å¤‡ä»¶å°è´¦ã€‘
 * @param data
 */
export function addSpare(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹ã€å¤‡ä»¶å°è´¦ã€‘
 * @param data
 */
export function updateSpare(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤ã€å¤‡ä»¶å°è´¦ã€‘
 * @param spareIds
 */
export function delSpare(spareIds: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${spareIds}`);
}
/**
 * å¯¼å‡ºã€å¤‡ä»¶å°è´¦ã€‘
 * @param data
 */
export function spareExport(data: any) {
  return commonExport(Api.spareExport, data);
}
eims-ui/apps/web-antd/src/api/eims/spare/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,90 @@
export interface SpareVO {
  /**
   *
   */
  id: number | string;
  /**
   * ç±»åž‹
   */
  type: number;
  /**
   * å¤‡ä»¶åç§°
   */
  name: string;
  /**
   * å¤‡ä»¶ç¼–码
   */
  code: string;
  /**
   * å¤‡ä»¶å›¾ç‰‡
   */
  img: number;
  /**
   * å¤‡ä»¶å›¾ç‰‡Url
   */
  imgUrl: string;
  /**
   * åž‹å·
   */
  modelNo: string;
  /**
   * åˆ¶é€ å•†
   */
  madeIn: string;
  /**
   * ä¾›åº”商
   */
  supplier: string;
  /**
   * è®¡é‡å•位(字典)
   */
  unit: string;
  /**
   * å‚考价格
   */
  referPrice: number;
  /**
   * åº“存上限
   */
  upperStock: number;
  /**
   * åº“存下限
   */
  lowerStock: number;
  /**
   * å®žé™…库存
   */
  actualStock: number;
  /**
   * åº“存金额
   */
  stockAmount: number;
  /**
   * æ›´æ¢å‘¨æœŸ
   */
  replaceCycle: number;
  /**
   * æ›´æ¢å‘¨æœŸå•位(字典)
   */
  cycleUnit: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
eims-ui/apps/web-antd/src/views/eims/fault-know/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,205 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'faultCode',
    label: '知识编号'
  },
  {
    component: 'Input',
    fieldName: 'equName',
    label: '设备名称'
  },
  {
    component: 'Input',
    fieldName: 'assetNo',
    label: '资产编号'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_EQU_PART)
    },
    fieldName: 'equPart',
    label: '设备部位'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.REPAIR_FAULT_TYPE)
    },
    fieldName: 'faultType',
    label: '故障类别'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_FAULT_REASON)
    },
    fieldName: 'faultReason',
    label: '故障原因'
  },
  {
    component: 'Input',
    fieldName: 'reqDesc',
    label: '故障描述'
  },
  {
    component: 'Input',
    fieldName: 'resHandle',
    label: '处理措施'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '知识编码',
    field: 'faultCode',
    minWidth: 200
  },
  {
    title: '设备名称',
    field: 'equName',
    minWidth: 140,
    fixed: 'left',
    slots: { default: 'equName' }
  },
  {
    title: '资产编号',
    field: 'assetNo',
    sortable: true,
    minWidth: 140,
    fixed: 'left'
  },
  {
    title: '设备类型',
    field: 'equTypeName',
    minWidth: 140
  },
  {
    title: '设备部位',
    field: 'equPart',
    sortable: true,
    slots: {
      default: ({ row }) => {
        if (row.equPart === null || row.equPart === '') {
          return '';
        }
        return renderDict(row.equPart, DictEnum.EIMS_EQU_PART);
      }
    },
    minWidth: 120
  },
  {
    title: '故障类别',
    field: 'faultType',
    sortable: true,
    slots: {
      default: ({ row }) => {
        if (row.faultType === null || row.faultType === '') {
          return '';
        }
        return renderDict(row.faultType, DictEnum.REPAIR_FAULT_TYPE);
      }
    },
    minWidth: 120
  },
  {
    title: '故障原因',
    field: 'faultReason',
    sortable: true,
    slots: {
      default: ({ row }) => {
        if (row.faultReason === null || row.faultReason === '') {
          return '';
        }
        return renderDict(row.faultReason, DictEnum.EIMS_FAULT_REASON);
      }
    },
    minWidth: 120
  },
  {
    title: '报修描述',
    field: 'reqDesc',
    minWidth: 300
  },
  {
    title: '处理措施',
    field: 'resHandle',
    minWidth: 300
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'equId'
  },
  {
    component: 'Input',
    fieldName: 'faultCode',
    label: '知识编码',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'equName',
    label: '设备名称',
    rules: 'required'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_EQU_PART)
    },
    fieldName: 'equPart',
    label: '设备部位'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.REPAIR_FAULT_TYPE)
    },
    fieldName: 'faultType',
    label: '故障类别'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.EIMS_FAULT_REASON)
    },
    fieldName: 'faultReason',
    label: '故障原因'
  },
  {
    component: 'Textarea',
    formItemClass: 'items-baseline',
    fieldName: 'reqDesc',
    label: '报修描述'
  },
  {
    component: 'Textarea',
    formItemClass: 'items-baseline',
    fieldName: 'resHandle',
    label: '处理措施'
  }
];
eims-ui/apps/web-antd/src/views/eims/fault-know/equ-type-tree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
<script setup lang="ts">
import type { DeptTree } from '#/api/system/user/model';
import { onMounted, type PropType, ref } from 'vue';
import { SyncOutlined } from '@ant-design/icons-vue';
import { Empty, InputSearch, Skeleton, Tree } from 'ant-design-vue';
import { getEquTypeTree } from '#/api/eims/equ-type';
defineOptions({ inheritAttrs: false });
const emit = defineEmits<{
  /**
   * ç‚¹å‡»åˆ·æ–°æŒ‰é’®çš„事件
   */
  reload: [];
  /**
   * ç‚¹å‡»èŠ‚ç‚¹çš„äº‹ä»¶
   */
  select: [];
}>();
const selectDeptId = defineModel('selectDeptId', {
  required: true,
  type: Array as PropType<string[]>,
});
const searchValue = defineModel('searchValue', {
  type: String,
  default: '',
});
/** éƒ¨é—¨æ•°æ®æº */
type DeptTreeArray = DeptTree[];
const deptTreeArray = ref<DeptTreeArray>([]);
/** éª¨æž¶å±åŠ è½½ */
const showTreeSkeleton = ref<boolean>(true);
async function loadTree() {
  showTreeSkeleton.value = true;
  searchValue.value = '';
  selectDeptId.value = [];
  const ret = await getEquTypeTree();
  deptTreeArray.value = ret;
  showTreeSkeleton.value = false;
}
async function handleReload() {
  await loadTree();
  emit('reload');
}
onMounted(loadTree);
</script>
<template>
  <div :class="$attrs.class">
    <Skeleton
      :loading="showTreeSkeleton"
      :paragraph="{ rows: 8 }"
      active
      class="p-[8px]"
    >
      <div
        class="bg-background flex h-full flex-col overflow-y-auto rounded-lg"
      >
        <!-- å›ºå®šåœ¨é¡¶éƒ¨ å¿…须加上bg-background背景色 å¦åˆ™ä¼šäº§ç”Ÿ'穿透'效果 -->
        <div class="bg-background z-100 sticky left-0 top-0 p-[8px]">
          <InputSearch
            v-model:value="searchValue"
            :placeholder="$t('pages.common.search')"
            size="small"
          >
            <template #enterButton>
              <a-button @click="handleReload">
                <SyncOutlined class="text-primary" />
              </a-button>
            </template>
          </InputSearch>
        </div>
        <div class="h-full overflow-x-hidden px-[8px]">
          <Tree
            v-bind="$attrs"
            v-if="deptTreeArray.length > 0"
            v-model:selected-keys="selectDeptId"
            :class="$attrs.class"
            :field-names="{ title: 'label', key: 'id' }"
            :show-line="{ showLeafIcon: false }"
            :tree-data="deptTreeArray"
            :virtual="false"
            default-expand-all
            @select="$emit('select')"
          >
            <template #title="{ label }">
              <span v-if="label.indexOf(searchValue) > -1">
                {{ label.substring(0, label.indexOf(searchValue)) }}
                <span style="color: #f50">{{ searchValue }}</span>
                {{
                  label.substring(
                    label.indexOf(searchValue) + searchValue.length,
                  )
                }}
              </span>
              <span v-else>{{ label }}</span>
            </template>
          </Tree>
          <!-- ä»…本人数据权限 å¯ä»¥è€ƒè™‘直接不显示 -->
          <div v-else class="mt-5">
            <Empty
              :image="Empty.PRESENTED_IMAGE_SIMPLE"
              description="无设备类型数据"
            />
          </div>
        </div>
      </div>
    </Skeleton>
  </div>
</template>
eims-ui/apps/web-antd/src/views/eims/fault-know/fault-know-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,114 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { InputSearch } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { addFaultKnow, getFaultKnow, updateFaultKnow } from '#/api/eims/fault-know';
import CodeInput from '#/views/eims/components/code-input.vue';
import equModal from '#/views/eims/components/equ-modal.vue';
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 getFaultKnow(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 ? updateFaultKnow(data) : addFaultKnow(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
// EQU modal
const [EquModal, equModalApi] = useVbenModal({
  connectedComponent: equModal,
  draggable: true,
  title: '选择设备'
});
function handleEquModal() {
  equModalApi.setData({});
  equModalApi.open();
}
/**
 * æ›´æ–°é€‰æ‹©çš„设备
 * @param equ
 */
async function updateEqu(equ: any) {
  await formApi.setValues({ 'equId': equ.equId, 'equName': equ.equName, 'equTypeId': equ.equTypeId });
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm>
      <template #faultCode="slotProps">
        <CodeInput v-bind="slotProps" :disabled="isUpdate" prefix="GZZS" />
      </template>
      <template #equName="slotProps">
        <InputSearch :enter-button="true" placeholder="请选择设备" @search="handleEquModal" v-bind="slotProps" :disabled="isUpdate" />
      </template>
    </BasicForm>
    <EquModal class="w-[1200px]" @update-equ="updateEqu" />
  </BasicDrawer>
</template>
eims-ui/apps/web-antd/src/views/eims/fault-know/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,194 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { delFaultKnow, faultKnowExport, listFaultKnow } from '#/api/eims/fault-know';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import EquTypeTree from './equ-type-tree.vue';
import faultKnowDrawer from './fault-know-drawer.vue';
// å·¦è¾¹éƒ¨é—¨ç”¨
const selectDeptId = ref<string[]>([]);
defineExpose({
  tableSelect
});
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true
    }
  },
  schema: querySchema(),
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  handleReset: async () => {
    selectDeptId.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: [['deployDate', ['params[beginTime]', 'params[endTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']]]
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // éƒ¨é—¨æ ‘选择处理
        if (selectDeptId.value.length === 1 && selectDeptId.value[0] !== '0') {
          formValues.equTypeId = selectDeptId.value[0];
        } else {
          Reflect.deleteProperty(formValues, 'equTypeId');
        }
        return await listFaultKnow({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-fault-know-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [FaultKnowDrawer, faultKnowDrawerApi] = useVbenDrawer({
  connectedComponent: faultKnowDrawer
});
function handleAdd() {
  faultKnowDrawerApi.setData({});
  faultKnowDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  faultKnowDrawerApi.setData({ id: record.id });
  faultKnowDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delFaultKnow(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 delFaultKnow(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(faultKnowExport, '故障知识', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
// é€‰ä¸­æ•°æ®
function tableSelect() {
  return tableApi.grid.getCheckboxRecords();
}
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <EquTypeTree v-model:select-dept-id="selectDeptId" class="w-[260px]" @reload="() => tableApi.reload()" @select="() => tableApi.reload()" />
      <BasicTable class="flex-1 overflow-hidden" table-title="设备列表">
        <template #toolbar-tools>
          <Space>
            <a-button v-access:code="['eims:faultKnow:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:faultKnow:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:faultKnow:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #equName="{ row }">
          <Space>
            <a-button type="link"> {{ row.equName }}</a-button>
          </Space>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:faultKnow:edit']" @click.stop="handleEdit(row)">
              {{ $t('pages.common.edit') }}
            </ghost-button>
            <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
              <ghost-button danger v-access:code="['eims:faultKnow:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <FaultKnowDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/fixture/fixture-import-modal.vue
@@ -90,7 +90,7 @@
        <span>允许导入xlsx, xls文件</span>
        <a-button
          type="link"
          @click="commonDownloadExcel(downloadImportTemplate, '设备导入模板')"
          @click="commonDownloadExcel(downloadImportTemplate, '工具导入模板')"
        >
          <div class="flex items-center gap-[4px]">
            <ExcelIcon />
eims-ui/apps/web-antd/src/views/eims/fixture/index.vue
@@ -18,8 +18,8 @@
import fixtureBorrowDrawer from '#/views/eims/fixture-borrow/fixture-borrow-drawer.vue';
import { columns, querySchema } from './data';
import fixtureDrawer from './fixture-drawer.vue';
import fixtureBorrowListDrawer from './fixture-borrow-list-drawer.vue';
import fixtureDrawer from './fixture-drawer.vue';
import fixtureImportModal from './fixture-import-modal.vue';
import FixtureTypeTree from './fixture-type-tree.vue';
@@ -108,7 +108,7 @@
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams),
    cellClick: (e: any) => {
      const { row } = e;
      handleBorroeList(row)
      handleBorroeList(row);
    }
  }
});
@@ -300,9 +300,9 @@
            <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">
            <!-- <a-button v-access:code="['eims:fixture:import']" @click="handleImport">
              {{ $t('pages.common.import') }}
            </a-button>
            </a-button>-->
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
eims-ui/apps/web-antd/src/views/eims/insp-plan/data.tsx
@@ -258,7 +258,7 @@
      getPopupContainer
    },
    fieldName: 'inspFirstTime',
    label: '首次保养时间'
    label: '首次点检时间'
  },
  {
    component: 'DatePicker',
@@ -269,7 +269,7 @@
      getPopupContainer
    },
    fieldName: 'inspLastTime',
    label: '上次保养时间'
    label: '上次点检时间'
  },
  {
    component: 'DatePicker',
@@ -280,7 +280,7 @@
      getPopupContainer
    },
    fieldName: 'inspNextTime',
    label: '下次保养时间',
    label: '下次点检时间',
  },
  {
    component: 'Textarea',
eims-ui/apps/web-antd/src/views/eims/spare-in/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,156 @@
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';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'orderCode',
    label: '入库单号'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'chargeDept',
    label: '经办部门'
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'chargeUser',
    label: '经办人'
  },
  {
    component: 'Input',
    fieldName: 'partnerName',
    label: '供应商'
  },
  {
    component: 'RangePicker',
    fieldName: 'orderTime',
    label: '工单时间'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '入库单号',
    field: 'orderCode',
    minWidth: 100,
    fixed: 'left',
    slots: { default: 'orderCode' }
  },
  {
    title: '日期',
    field: 'orderTime',
    minWidth: 120
  },
  {
    title: '供应商',
    field: 'partnerName',
    minWidth: 100
  },
  {
    title: '经办人',
    field: 'chargeUserName',
    minWidth: 100
  },
  {
    title: '关联单号',
    field: 'associatedOrder',
    minWidth: 120
  },
  {
    title: '备注',
    field: 'remark',
    minWidth: 140
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.SPARE_INOUT_TYPE)
    },
    dependencies: {
      show: () => true,
      triggerFields: ['']
    },
    fieldName: 'type',
    defaultValue: '1',
    label: '类型'
  },
  {
    component: 'Input',
    fieldName: 'orderCode',
    label: '入库单号'
  },
  {
    component: 'Input',
    fieldName: 'partnerName',
    label: '供应商'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'chargeDept',
    label: '经办部门',
    rules: 'selectRequired'
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'chargeUser',
    label: '经办人',
    rules: 'required'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD HH:mm:ss',
      showTime: true,
      valueFormat: 'YYYY-MM-DD HH:mm:ss',
      getPopupContainer
    },
    fieldName: 'orderTime',
    label: '入库时间'
  },
  {
    component: 'Textarea',
    formItemClass: 'items-baseline',
    fieldName: 'remark',
    label: '备注'
  }
];
eims-ui/apps/web-antd/src/views/eims/spare-in/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,237 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { onMounted } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, getPopupContainer, getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { delSpareInout, listSpareInout, spareInoutExport } from '#/api/eims/spare-inout';
import { getDeptTree, userList } from '#/api/system/user';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import drawer from './spare-in-drawer.vue';
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true
    }
  },
  schema: querySchema(),
  collapsed: true,
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  // æ—¥æœŸé€‰æ‹©æ ¼å¼åŒ–
  fieldMappingTime: [['orderTime', ['params[beginOrderTime]', 'params[endOrderTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']]]
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // 1-入库单 2-出库单
        formValues.type = '1';
        return await listSpareInout({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'spre-inout-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [Drawer, drawerApi] = useVbenDrawer({
  connectedComponent: drawer
});
function handleAdd() {
  drawerApi.setData({});
  drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  drawerApi.setData({ id: record.id });
  drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delSpareInout(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 delSpareInout(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(spareInoutExport, '备件入库单记录', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
/**
 * ç”¨æˆ·çš„加载
 */
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: 'chargeUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.chargeUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'chargeDept'
    }
  ]);
}
onMounted(async () => {
  await setupDeptSelect();
});
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <BasicTable class="flex-1 overflow-hidden" table-title="备件入库单列表">
        <template #toolbar-tools>
          <Space>
            <a-button v-access:code="['eims:spareInout:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:spareInout:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:spareInout:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #orderCode="{ row }">
          <Space>
            <a-button type="link"> {{ row.orderCode }}</a-button>
          </Space>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:spareInout:edit']" @click.stop="handleEdit(row)">
              {{ $t('pages.common.edit') }}
            </ghost-button>
            <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
              <ghost-button danger v-access:code="['eims:spareInout:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <Drawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/spare-in/spare-in-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, cloneDeep, getPopupContainer } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { addSpareInout, getSpareInout, updateSpareInout } from '#/api/eims/spare-inout';
import { getDeptTree, userList } from '#/api/system/user';
import { drawerSchema } from './data';
import CodeInput from '#/views/eims/components/code-input.vue';
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
  commonConfig: {
    formItemClass: 'col-span-2',
    componentProps: {
      class: 'w-full'
    },
    labelWidth: 120
  },
  schema: drawerSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2'
});
const [BasicDrawer, drawerApi] = useVbenDrawer({
  onCancel: handleCancel,
  onConfirm: handleConfirm,
  async onOpenChange(isOpen) {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);
    const { id } = drawerApi.getData() as { id?: number | string };
    isUpdate.value = !!id;
    // åˆå§‹åŒ–
    await setupDeptSelect();
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getSpareInout(id);
      await formApi.setValues(record);
    }
    drawerApi.drawerLoading(false);
  }
});
/**
 * ç”¨æˆ·çš„加载
 */
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: 'chargeUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.operatorId = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'chargeDept'
    }
  ]);
}
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    await (isUpdate.value ? updateSpareInout(data) : addSpareInout(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm>
      <template #orderCode="slotProps">
        <CodeInput v-bind="slotProps" :disabled="isUpdate" prefix="RK" />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
eims-ui/apps/web-antd/src/views/eims/spare-out/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,156 @@
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';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'orderCode',
    label: '出库单号'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'chargeDept',
    label: '经办部门'
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'chargeUser',
    label: '经办人'
  },
  {
    component: 'Input',
    fieldName: 'partnerName',
    label: '客户'
  },
  {
    component: 'RangePicker',
    fieldName: 'orderTime',
    label: '工单时间'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '出库单号',
    field: 'orderCode',
    minWidth: 100,
    fixed: 'left',
    slots: { default: 'orderCode' }
  },
  {
    title: '日期',
    field: 'orderTime',
    minWidth: 120
  },
  {
    title: '客户',
    field: 'partnerName',
    minWidth: 100
  },
  {
    title: '经办人',
    field: 'chargeUserName',
    minWidth: 100
  },
  {
    title: '关联单号',
    field: 'associatedOrder',
    minWidth: 120
  },
  {
    title: '备注',
    field: 'remark',
    minWidth: 140
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 200
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.SPARE_INOUT_TYPE)
    },
    dependencies: {
      show: () => true,
      triggerFields: ['']
    },
    fieldName: 'type',
    defaultValue: '2',
    label: '类型'
  },
  {
    component: 'Input',
    fieldName: 'orderCode',
    label: '出库单号'
  },
  {
    component: 'Input',
    fieldName: 'partnerName',
    label: '客户'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'chargeDept',
    label: '经办部门',
    rules: 'selectRequired'
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'chargeUser',
    label: '经办人',
    rules: 'required'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD HH:mm:ss',
      showTime: true,
      valueFormat: 'YYYY-MM-DD HH:mm:ss',
      getPopupContainer
    },
    fieldName: 'orderTime',
    label: '出库时间'
  },
  {
    component: 'Textarea',
    formItemClass: 'items-baseline',
    fieldName: 'remark',
    label: '备注'
  }
];
eims-ui/apps/web-antd/src/views/eims/spare-out/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,237 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { onMounted } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, getPopupContainer, getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { delSpareInout, listSpareInout, spareInoutExport } from '#/api/eims/spare-inout';
import { getDeptTree, userList } from '#/api/system/user';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import drawer from './spare-out-drawer.vue';
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
    componentProps: {
      allowClear: true
    }
  },
  schema: querySchema(),
  collapsed: true,
  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
  // æ—¥æœŸé€‰æ‹©æ ¼å¼åŒ–
  fieldMappingTime: [['orderTime', ['params[beginOrderTime]', 'params[endOrderTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']]]
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // 1-入库单 2-出库单
        formValues.type = '2';
        return await listSpareInout({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'spre-inout-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [Drawer, drawerApi] = useVbenDrawer({
  connectedComponent: drawer
});
function handleAdd() {
  drawerApi.setData({});
  drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  drawerApi.setData({ id: record.id });
  drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delSpareInout(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 delSpareInout(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(spareInoutExport, '备件出库单记录', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
/**
 * ç”¨æˆ·çš„加载
 */
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: 'chargeUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.chargeUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'chargeDept'
    }
  ]);
}
onMounted(async () => {
  await setupDeptSelect();
});
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <BasicTable class="flex-1 overflow-hidden" table-title="备件出库单列表">
        <template #toolbar-tools>
          <Space>
            <a-button v-access:code="['eims:spareInout:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:spareInout:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:spareInout:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #orderCode="{ row }">
          <Space>
            <a-button type="link"> {{ row.orderCode }}</a-button>
          </Space>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:spareInout:edit']" @click.stop="handleEdit(row)">
              {{ $t('pages.common.edit') }}
            </ghost-button>
            <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
              <ghost-button danger v-access:code="['eims:spareInout:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <Drawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/spare-out/spare-out-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { addFullName, cloneDeep, getPopupContainer } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { addSpareInout, getSpareInout, updateSpareInout } from '#/api/eims/spare-inout';
import { getDeptTree, userList } from '#/api/system/user';
import { drawerSchema } from './data';
import CodeInput from '#/views/eims/components/code-input.vue';
const emit = defineEmits<{ reload: [] }>();
const isUpdate = ref(false);
const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const [BasicForm, formApi] = useVbenForm({
  commonConfig: {
    formItemClass: 'col-span-2',
    componentProps: {
      class: 'w-full'
    },
    labelWidth: 120
  },
  schema: drawerSchema(),
  showDefaultActions: false,
  wrapperClass: 'grid-cols-2'
});
const [BasicDrawer, drawerApi] = useVbenDrawer({
  onCancel: handleCancel,
  onConfirm: handleConfirm,
  async onOpenChange(isOpen) {
    if (!isOpen) {
      return null;
    }
    drawerApi.drawerLoading(true);
    const { id } = drawerApi.getData() as { id?: number | string };
    isUpdate.value = !!id;
    // åˆå§‹åŒ–
    await setupDeptSelect();
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getSpareInout(id);
      await formApi.setValues(record);
    }
    drawerApi.drawerLoading(false);
  }
});
/**
 * ç”¨æˆ·çš„加载
 */
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: 'chargeUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.operatorId = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'chargeDept'
    }
  ]);
}
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    await (isUpdate.value ? updateSpareInout(data) : addSpareInout(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm>
      <template #orderCode="slotProps">
        <CodeInput v-bind="slotProps" :disabled="isUpdate" prefix="CK" />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
eims-ui/apps/web-antd/src/views/eims/spare-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 spareTypeOptions = [
  { 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: spareTypeOptions,
      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/spare-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 { eachTree, getVxePopupContainer } from '@vben/utils';
import { Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { delSpareType, spareTypeExport, listSpareType } from '#/api/eims/spare-type';
import { $t } from '@vben/locales';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import spareTypeDrawer from './spare-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 listSpareType({
          ...formValues
        });
        return { rows: resp };
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  /**
   * å¼€å¯è™šæ‹Ÿæ»šåЍ
   * æ•°æ®é‡å°å¯ä»¥é€‰æ‹©å…³é—­
   * å¦‚果遇到样式问题(空白、错位 æ»šåŠ¨ç­‰)可以选择关闭虚拟滚动
   */
  scrollY: {
    enabled: true,
    gt: 0
  },
  treeConfig: {
    parentField: 'parentId',
    rowField: 'id',
    // è‡ªåŠ¨è½¬æ¢ä¸ºtree ç”±vxe处理 æ— éœ€æ‰‹åŠ¨è½¬æ¢
    transform: true
  },
  id: 'spare-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 [SpareTypeDrawer, drawerApi] = useVbenDrawer({
  connectedComponent: spareTypeDrawer
});
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 delSpareType(row.id);
  await tableApi.query();
}
function handleDownloadExcel() {
  commonDownloadExcel(spareTypeExport, '备件类型', 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:spareType:export']" @click="handleDownloadExcel">
            {{ $t('pages.common.export') }}
          </a-button>
          <a-button type="primary" v-access:code="['eims:spareType:add']" @click="handleAdd">
            {{ $t('pages.common.add') }}
          </a-button>
        </Space>
      </template>
      <template #action="{ row }">
        <Space>
          <ghost-button v-access:code="['eims:spareType:edit']" @click="handleEdit(row)">
            {{ $t('pages.common.edit') }}
          </ghost-button>
          <!-- '按钮类型'无法再添加子菜单 -->
          <ghost-button v-if="row.menuType !== 'F'" class="btn-success" v-access:code="['eims:spareType: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:spareType:remove']" @click.stop="">
              {{ $t('pages.common.delete') }}
            </ghost-button>
          </Popconfirm>
        </Space>
      </template>
    </BasicTable>
    <SpareTypeDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/spare-type/spare-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 { addSpareType, getSpareType, listSpareType, updateSpareType } from '#/api/eims/spare-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 setupSpareTypeSelect() {
  // menu
  const menuArray = await listSpareType({ 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 setupSpareTypeSelect();
    if (id) {
      await formApi.setFieldValue('parentId', id);
      if (update) {
        const record = await getSpareType(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 ? updateSpareType(data) : addSpareType(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/spare/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,282 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
import { getPopupContainer } from '@vben/utils';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'name',
    label: '备件名称'
  },
  {
    component: 'Input',
    fieldName: 'code',
    label: '备件编码'
  },
  {
    component: 'Input',
    fieldName: 'modelNo',
    label: '备件型号'
  },
  {
    component: 'Input',
    fieldName: 'madeIn',
    label: '生产产商'
  },
  {
    component: 'Input',
    fieldName: 'supplier',
    label: '供应商'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '备件预览',
    field: 'imgUrl',
    showOverflow: true,
    width: 100,
    fixed: 'left',
    align: 'center',
    slots: { default: 'imgUrl' }
  },
  {
    title: '备件名称',
    field: 'name',
    fixed: 'left',
    align: 'center',
    width: 200
  },
  {
    title: '备件编码',
    field: 'code',
    width: 140
  },
  {
    title: '备件型号',
    field: 'modelNo',
    width: 100
  },
  {
    title: '备件类型',
    field: 'typeName',
    width: 100
  },
  {
    title: '生产产商',
    field: 'madeIn',
    width: 140
  },
  {
    title: '供应商',
    field: 'supplier',
    width: 140
  },
  {
    title: '计量单位',
    field: 'unit',
    sortable: true,
    slots: {
      default: ({ row }) => {
        if (row.unit === null || row.unit === '') {
          return '';
        }
        return renderDict(row.unit, DictEnum.EIMS_SPARE_UNIT);
      }
    },
    width: 100
  },
  {
    title: '参考价',
    field: 'referPrice',
    sortable: true,
    width: 120
  },
  {
    title: '库存上限',
    field: 'upperStock',
    sortable: true,
    width: 120
  },
  {
    title: '库存下限',
    field: 'lowerStock',
    width: 120
  },
  {
    title: '实际库存',
    field: 'actualStock',
    width: 120
  },
  {
    title: '库存金额',
    field: 'stockAmount',
    width: 120
  },
  {
    title: '更换周期',
    field: 'replaceCycle',
    width: 120
  },
  {
    title: '备注',
    field: 'remark',
    width: 120
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 180
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    component: 'TreeSelect',
    defaultValue: 0,
    fieldName: 'type',
    label: '备件类型',
    rules: 'selectRequired'
  },
  {
    component: 'Input',
    fieldName: 'name',
    label: '备件名称',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'code',
    label: '备件编码',
    rules: 'required'
  },
  {
    component: 'Input',
    fieldName: 'img',
    dependencies: {
      show: () => false,
      triggerFields: ['imgUrl']
    },
    label: '备件预览',
  },
  {
    component: 'Input',
    fieldName: 'imgUrl',
    label: '备件预览'
  },
  {
    component: 'Input',
    fieldName: 'modelNo',
    label: '型号'
  },
  {
    component: 'Input',
    fieldName: 'madeIn',
    label: '生产产商'
  },
  {
    component: 'Input',
    fieldName: 'supplier',
    label: '供应商'
  },
  {
    component: 'InputNumber',
    fieldName: 'referPrice',
    label: '参考价格',
    componentProps: {
      min: 0,
      precision: 2,
      addonAfter: 'ï¿¥',
      placeholder: '请输入'
    }
  },
  {
    component: 'InputNumber',
    fieldName: 'upperStock',
    label: '库存上限',
    componentProps: {
      min: 0
    }
  },
  {
    component: 'InputNumber',
    fieldName: 'lowerStock',
    label: '库存下限',
    componentProps: {
      min: 0
    }
  },
  {
    component: 'InputNumber',
    fieldName: 'actualStock',
    formItemClass: 'col-span-1',
    label: '实际库存',
    componentProps: {
      min: 0
    }
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.EIMS_SPARE_UNIT)
    },
    fieldName: 'unit',
    formItemClass: 'col-span-1 w-[80px]',
    labelWidth: 0,
    label: ''
  },
  {
    component: 'InputNumber',
    fieldName: 'stockAmount',
    label: '库存金额',
    componentProps: {
      min: 0,
      precision: 2,
      addonAfter: 'ï¿¥',
      placeholder: '请输入'
    }
  },
  {
    component: 'InputNumber',
    fieldName: 'replaceCycle',
    formItemClass: 'col-span-1',
    label: '更换周期',
    componentProps: {
      min: 0
    }
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.MAINT_CYCLE_UNIT)
    },
    fieldName: 'cycleUnit',
    formItemClass: 'col-span-1 w-[80px]',
    labelWidth: 0,
    label: ''
  },
  {
    component: 'Textarea',
    formItemClass: 'items-baseline',
    fieldName: 'remark',
    label: '备注'
  }
];
eims-ui/apps/web-antd/src/views/eims/spare/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,217 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import { onMounted, ref } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { getVxePopupContainer } from '@vben/utils';
import { Image, Modal, Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, vxeCheckboxChecked, type VxeGridProps, vxeSortEvent } from '#/adapter/vxe-table';
import { delSpare, listSpare, spareExport } from '#/api/eims/spare';
import { configInfoByKey } from '#/api/system/config';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import spareDrawer from './spare-drawer.vue';
import SpareTypeTree from './spare-type-tree.vue';
// å·¦è¾¹éƒ¨é—¨ç”¨
const selectTypeId = ref<any[]>([]);
defineExpose({
  tableSelect
});
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);
  }
};
const gridOptions: VxeGridProps = {
  checkboxConfig: {
    // é«˜äº®
    highlight: true,
    // ç¿»é¡µæ—¶ä¿ç•™é€‰ä¸­çŠ¶æ€
    reserve: true
    // ç‚¹å‡»è¡Œé€‰ä¸­
    // trigger: 'row'
  },
  columns,
  height: 'auto',
  keepSource: true,
  pagerConfig: {
    enabled: false,
  },
  proxyConfig: {
    enabled: true,
    ajax: {
      query: async ({ page }, formValues = {}) => {
        // éƒ¨é—¨æ ‘选择处理
        if (selectTypeId.value.length === 1 && selectTypeId.value[0] !== 0) {
          formValues.type = selectTypeId.value[0];
        } else {
          Reflect.deleteProperty(formValues, 'type');
        }
        return await listSpare({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  columnConfig: {
    resizable: true,
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-spare-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [SpareDrawer, spareDrawerApi] = useVbenDrawer({
  connectedComponent: spareDrawer
});
function handleAdd() {
  spareDrawerApi.setData({});
  spareDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  spareDrawerApi.setData({ id: record.id });
  spareDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delSpare(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 delSpare(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(spareExport, '备件台账', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
const preview = ref(false);
onMounted(async () => {
  const resp = await configInfoByKey('sys.oss.previewListResource');
  preview.value = Boolean(resp);
});
function isImageFile(ext: string) {
  const supportList = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
  return supportList.some((item) => ext.toLocaleLowerCase().includes(item));
}
// é€‰ä¸­æ•°æ®
function tableSelect() {
  return tableApi.grid.getCheckboxRecords();
}
</script>
<template>
  <Page :auto-content-height="true">
    <div class="flex h-full gap-[8px]">
      <SpareTypeTree 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:spare:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:spare:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:spare:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #imgUrl="{ row }">
          <Image v-if="preview && isImageFile(row.imgUrl)" :src="row.imgUrl" height="38px" />
          <span v-else>{{ row.imgUrl }}</span>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:spare:edit']" @click.stop="handleEdit(row)">
              {{ $t('pages.common.edit') }}
            </ghost-button>
            <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认删除?" @confirm="handleDelete(row)">
              <ghost-button danger v-access:code="['eims:spare:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <SpareDrawer @reload="tableApi.query()" />
  </Page>
</template>
<style>
/* ç»Ÿä¸€æ‰€æœ‰åˆ—的边框和行高 */
.vxe-table--body .vxe-body--row .vxe-body--column {
  height: 56px !important;
  box-sizing: border-box !important;
  padding-top: 1px !important; /* ä¿æŒå’Œæ™®é€šåˆ—一致的padding */
}
</style>
eims-ui/apps/web-antd/src/views/eims/spare/spare-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,149 @@
<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 { addSpare, getSpare, updateSpare } from '#/api/eims/spare';
import { listSpareType } from '#/api/eims/spare-type';
import { ImageUpload } from '#/components/upload';
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 };
    await setupSpareTypeSelect();
    onImageChange();
    isUpdate.value = !!id;
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getSpare(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 ? updateSpare(data) : addSpare(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
async function setupSpareTypeSelect() {
  // status-0 åªæŸ¥è¯¢æœªåœç”¨
  const equArray = await listSpareType({ status: 0 });
  // support i18n
  equArray.forEach((item) => {
    item.typeName = $t(item.typeName);
  });
  const equTree = listToTree(equArray, { id: 'id', pid: 'parentId' });
  const fullEquTree = [
    {
      id: 0,
      typeName: $t('menu.root'),
      children: equTree
    }
  ];
  addFullName(fullEquTree, 'typeName', ' / ');
  formApi.updateSchema([
    {
      componentProps: {
        fieldNames: {
          label: 'typeName',
          value: 'id'
        },
        getPopupContainer,
        // è®¾ç½®å¼¹çª—滚动高度 é»˜è®¤256
        listHeight: 300,
        showSearch: true,
        treeData: fullEquTree,
        treeDefaultExpandAll: false,
        // é»˜è®¤å±•开的树节点
        treeDefaultExpandedKeys: [0],
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'typeName',
        treeNodeLabelProp: 'fullName'
      },
      fieldName: 'type'
    }
  ]);
}
const accept = ref(['jpg', 'jpeg', 'png', 'gif', 'webp']);
const maxNumber = ref(1);
function onImageChange() {
  formApi.updateSchema([
    {
      componentProps: () => ({
        async onChange(value: any) {
          await formApi.setValues({ 'img': value });
        }
      }),
      fieldName: 'imgUrl'
    }
  ]);
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm>
      <template #imgUrl="slotProps">
        <!--注意:上传成功后返回ossid-->
        <ImageUpload v-bind="slotProps" :accept="accept" :max-number="maxNumber"
                     result-field="ossId" />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
eims-ui/apps/web-antd/src/views/eims/spare/spare-type-tree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
<script setup lang="ts">
import type { SpareTypeTree } from '#/api/eims/spare-type/model.d.ts';
import { onMounted, type PropType, ref } from 'vue';
import { SyncOutlined } from '@ant-design/icons-vue';
import { Empty, InputSearch, Skeleton, Tree } from 'ant-design-vue';
import { getSpareTypeTree } from '#/api/eims/spare-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 TypeTreeArray = SpareTypeTree[];
const spareTypeTreeArray = ref<TypeTreeArray>([]);
/** éª¨æž¶å±åŠ è½½ */
const showTreeSkeleton = ref<boolean>(true);
async function loadTree() {
  showTreeSkeleton.value = true;
  searchValue.value = '';
  selectTypeId.value = [];
  const ret = await getSpareTypeTree();
  spareTypeTreeArray.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="spareTypeTreeArray.length > 0"
            v-model:selected-keys="selectTypeId"
            :class="$attrs.class"
            :field-names="{ title: 'label', key: 'id' }"
            :show-line="{ showLeafIcon: false }"
            :tree-data="spareTypeTreeArray"
            :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/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,11 +1,15 @@
export enum DictEnum {
  EIMS_EQU_PART = 'eims_equ_part', // è®¾å¤‡éƒ¨ä½
  EIMS_SPARE_UNIT = 'eims_spare_unit', // å¤‡ä»¶è®¡é‡å•位
  EIMS_EQU_UNIT = 'eims_equ_unit', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_FAULT_REASON = 'eims_fault_reason', // æ•…障原因
  EIMS_FIXTURE_STATUS = 'eims_fixture_status', // å·¥å…·ï¼ˆæ²»å…·ï¼‰çŠ¶æ€
  EIMS_INSPECT_RESULT = 'eims_inspect_result', // ç‚¹æ£€ç»“æžœ
  EIMS_INSPECT_STATUS = 'eims_inspect_status', // ç‚¹æ£€çŠ¶æ€
  EIMS_INSPECT_TYPE = 'eims_inspect_type', // ç‚¹æ£€ç±»åž‹
  EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_MAINT_TYPE = 'eims_maint_type', // ä¿å…»ç±»åž‹
  EIMS_INSPECT_RESULT = 'eims_inspect_result', // ç‚¹æ£€ç»“æžœ
  EIMS_ORDITM_STATUS = 'eims_orditm_status', // ä¿å…»å·¥å•明细完成状态
  EQU_IMPORT_STATU = 'equ_import_status', // è®¾å¤‡å¯¼å…¥çŠ¶æ€
  FIXTURE_BORROW_RECORD_STATUS = 'fixture_borrow_record_status', // å·¥å…·ï¼ˆæ²»å…·ï¼‰å€Ÿç”¨è®°å½•状态
@@ -13,11 +17,11 @@
  MAINT_CYCLE_UNIT = 'maint_cycle_unit', // ä¿å…»å‘¨æœŸå•位
  MAINT_ORDER_ST_STATUS = 'maint_order_st_status', // ä¿å…»å·¥å•汇总稽查状态
  MAINT_ORDER_STATUS = 'maint_order_status', // ä¿å…»å·¥å•状态
  EIMS_INSPECT_STATUS = 'eims_inspect_status', // ç‚¹æ£€çŠ¶æ€
  MAINT_TIME_RULE = 'maint_time_rule', // ä¿å…»è§„则
  REPAIR_FAULT_TYPE = 'repair_fault_type', // æŠ¥ä¿®çŠ¶æ€
  REPAIR_FAULT_TYPE = 'repair_fault_type', // æ•…障类别
  REPAIR_RECORD_HANDLE = 'repair_record_handle', // ç»´ä¿®è®°å½•操作
  REPAIR_REQ_STATUS = 'repair_req_status', // æŠ¥ä¿®çŠ¶æ€
  SPARE_INOUT_TYPE = 'spare_inout_type', // å¤‡ä»¶å‡ºå…¥åº“类型 1-入库单 2-出库单
  REPAIR_REQ_TYPE = 'repair_req_type', // æŠ¥ä¿®ç±»åž‹
  REPAIR_RES_STATUS = 'repair_res_status', // ç»´ä¿®çŠ¶æ€
  REPAIR_URGENCY_LEVEL = 'repair_urgency_level', // æŠ¥ä¿®ç´§æ€¥ç¨‹åº¦
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/DictConstants.java
@@ -151,5 +151,14 @@
        String Y = "1"; // å·²å®Œæˆ
    }
    /**
     *点检记录状态
     */
    String EIMS_INSPECT_STATUS = "eims_inspect_status";
    interface EIMS_INSPECT_STATUS_DETAIL {
        String N = "0";// æœªç‚¹æ£€
        String Y = "1"; // å·²ç‚¹æ£€
    }
}
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/SpareTypeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package org.dromara.common.core.service;
public interface SpareTypeService {
    /**
     * é€šè¿‡å¤‡ä»¶ç±»åž‹ID查询备件类型名称
     *
     * @param spareTypeIds å¤‡ä»¶ç±»åž‹ID串逗号分隔
     * @return å¤‡ä»¶ç±»åž‹åç§°ä¸²é€—号分隔
     */
    String selectSpareTypeNameByIds(String spareTypeIds);
}
eims/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java
@@ -345,6 +345,17 @@
    }
    /**
     * å¼€å¯äº†ç‰ˆæœ¬æŽ§åˆ¶ï¼Œminio中保留原文件名
     * @param data
     * @param suffix
     * @param fileName
     * @return
     */
    public UploadResult uploadSuffix(byte[] data, String suffix,String fileName) {
        return upload(new ByteArrayInputStream(data), getDatePath(fileName), Long.valueOf(data.length), FileUtils.getMimeType(suffix));
    }
    /**
     * ä¸Šä¼  InputStream åˆ° Amazon S3,使用指定的后缀构造对象键。
     *
     * @param inputStream è¦ä¸Šä¼ çš„输入流
@@ -477,6 +488,15 @@
        return path + suffix;
    }
    public String getDatePath(String fileName) {
        // ç”Ÿæˆæ—¥æœŸè·¯å¾„
        String datePath = DateUtils.datePath();
        String timestamp  = DateUtils.dateTimeNow();
        String suffix = StringUtils.substring(fileName, fileName.lastIndexOf("."), fileName.length());
        String file = StringUtils.substring(fileName,0, fileName.lastIndexOf("."));
        return datePath + StringUtils.SLASH + file +  "_" + timestamp +   suffix;
    }
    /**
     * ç§»é™¤è·¯å¾„中的基础URL部分,得到相对路径
     *
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java
@@ -35,7 +35,7 @@
    /**
     * è®¾å¤‡ç±»åž‹åç§°id转名称
     */
    String EQU_YPE_ID_TO_NAME = "equ_type_id_to_name";
    String EQU_TYPE_ID_TO_NAME = "equ_type_id_to_name";
    /**
     * è®¾å¤‡åç§°id转名称
     */
@@ -65,4 +65,10 @@
     */
    String MAINT_ORDER_ID_TO_CODE = "maint_order_id_to_code";
    /**
     * å¤‡ä»¶ç±»åž‹id转name
     */
    String SPARE_TYPE_ID_TO_NAME = "spare_type_id_to_name";
}
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/EquTypeNameTranslationImpl.java
@@ -1,7 +1,6 @@
package org.dromara.common.translation.core.impl;
import lombok.AllArgsConstructor;
import org.dromara.common.core.service.DeptService;
import org.dromara.common.core.service.EquTypeService;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.constant.TransConstant;
@@ -13,7 +12,7 @@
 * @author zhuguifei
 */
@AllArgsConstructor
@TranslationType(type = TransConstant.EQU_YPE_ID_TO_NAME)
@TranslationType(type = TransConstant.EQU_TYPE_ID_TO_NAME)
public class EquTypeNameTranslationImpl implements TranslationInterface<String> {
    private final EquTypeService equTypeService;
eims/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/SpareTypeNameTranslationImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package org.dromara.common.translation.core.impl;
import lombok.AllArgsConstructor;
import org.dromara.common.core.service.EquTypeService;
import org.dromara.common.core.service.SpareTypeService;
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.SPARE_TYPE_ID_TO_NAME)
public class SpareTypeNameTranslationImpl implements TranslationInterface<String> {
    private final SpareTypeService spareTypeService;
    @Override
    public String translation(Object key, String other) {
        if (key instanceof String ids) {
            return spareTypeService.selectSpareTypeNameByIds(ids);
        } else if (key instanceof Long id) {
            return spareTypeService.selectSpareTypeNameByIds(id.toString());
        }
        return null;
    }
}
eims/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -11,3 +11,4 @@
org.dromara.common.translation.core.impl.RepairReqCodeTranslationImpl
org.dromara.common.translation.core.impl.RepairResCodeTranslationImpl
org.dromara.common.translation.core.impl.MaintOrderCodeTranslationImpl
org.dromara.common.translation.core.impl.SpareTypeNameTranslationImpl
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFaultKnowController.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.EimsFaultKnowVo;
import org.dromara.eims.domain.bo.EimsFaultKnowBo;
import org.dromara.eims.service.IEimsFaultKnowService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * æ•…障知识
 *
 * @author zhuguifei
 * @date 2025-03-18
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/faultKnow")
public class EimsFaultKnowController extends BaseController {
    private final IEimsFaultKnowService eimsFaultKnowService;
    /**
     * æŸ¥è¯¢æ•…障知识列表
     */
    @SaCheckPermission("eims:faultKnow:list")
    @GetMapping("/list")
    public TableDataInfo<EimsFaultKnowVo> list(EimsFaultKnowBo bo, PageQuery pageQuery) {
        return eimsFaultKnowService.queryPageList(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºæ•…障知识列表
     */
    @SaCheckPermission("eims:faultKnow:export")
    @Log(title = "故障知识", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsFaultKnowBo bo, HttpServletResponse response) {
        List<EimsFaultKnowVo> list = eimsFaultKnowService.queryList(bo);
        ExcelUtil.exportExcel(list, "故障知识", EimsFaultKnowVo.class, response);
    }
    /**
     * èŽ·å–æ•…éšœçŸ¥è¯†è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:faultKnow:query")
    @GetMapping("/{id}")
    public R<EimsFaultKnowVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsFaultKnowService.queryById(id));
    }
    /**
     * æ–°å¢žæ•…障知识
     */
    @SaCheckPermission("eims:faultKnow:add")
    @Log(title = "故障知识", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsFaultKnowBo bo) {
        return toAjax(eimsFaultKnowService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹æ•…障知识
     */
    @SaCheckPermission("eims:faultKnow:edit")
    @Log(title = "故障知识", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsFaultKnowBo bo) {
        return toAjax(eimsFaultKnowService.updateByBo(bo));
    }
    /**
     * åˆ é™¤æ•…障知识
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:faultKnow:remove")
    @Log(title = "故障知识", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsFaultKnowService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsSpareController.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.EimsSpareVo;
import org.dromara.eims.domain.bo.EimsSpareBo;
import org.dromara.eims.service.IEimsSpareService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * å¤‡ä»¶å°è´¦
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/spare")
public class EimsSpareController extends BaseController {
    private final IEimsSpareService eimsSpareService;
    /**
     * æŸ¥è¯¢å¤‡ä»¶å°è´¦åˆ—表
     */
    @SaCheckPermission("eims:spare:list")
    @GetMapping("/list")
    public TableDataInfo<EimsSpareVo> list(EimsSpareBo bo, PageQuery pageQuery) {
        return eimsSpareService.queryPageList(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºå¤‡ä»¶å°è´¦åˆ—表
     */
    @SaCheckPermission("eims:spare:export")
    @Log(title = "备件台账", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsSpareBo bo, HttpServletResponse response) {
        List<EimsSpareVo> list = eimsSpareService.queryList(bo);
        ExcelUtil.exportExcel(list, "备件台账", EimsSpareVo.class, response);
    }
    /**
     * èŽ·å–å¤‡ä»¶å°è´¦è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:spare:query")
    @GetMapping("/{id}")
    public R<EimsSpareVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsSpareService.queryById(id));
    }
    /**
     * æ–°å¢žå¤‡ä»¶å°è´¦
     */
    @SaCheckPermission("eims:spare:add")
    @Log(title = "备件台账", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsSpareBo bo) {
        return toAjax(eimsSpareService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹å¤‡ä»¶å°è´¦
     */
    @SaCheckPermission("eims:spare:edit")
    @Log(title = "备件台账", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsSpareBo bo) {
        return toAjax(eimsSpareService.updateByBo(bo));
    }
    /**
     * åˆ é™¤å¤‡ä»¶å°è´¦
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:spare:remove")
    @Log(title = "备件台账", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsSpareService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsSpareInoutController.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.EimsSpareInoutVo;
import org.dromara.eims.domain.bo.EimsSpareInoutBo;
import org.dromara.eims.service.IEimsSpareInoutService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * å¤‡ä»¶å‡ºå…¥åº“
 *
 * @author zhuguifei
 * @date 2025-03-26
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/spareInout")
public class EimsSpareInoutController extends BaseController {
    private final IEimsSpareInoutService eimsSpareInoutService;
    /**
     * æŸ¥è¯¢å¤‡ä»¶å‡ºå…¥åº“列表
     */
    @SaCheckPermission("eims:spareInout:list")
    @GetMapping("/list")
    public TableDataInfo<EimsSpareInoutVo> list(EimsSpareInoutBo bo, PageQuery pageQuery) {
        return eimsSpareInoutService.queryPageList(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºå¤‡ä»¶å‡ºå…¥åº“列表
     */
    @SaCheckPermission("eims:spareInout:export")
    @Log(title = "备件出入库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsSpareInoutBo bo, HttpServletResponse response) {
        List<EimsSpareInoutVo> list = eimsSpareInoutService.queryList(bo);
        ExcelUtil.exportExcel(list, "备件出入库", EimsSpareInoutVo.class, response);
    }
    /**
     * èŽ·å–å¤‡ä»¶å‡ºå…¥åº“è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:spareInout:query")
    @GetMapping("/{id}")
    public R<EimsSpareInoutVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsSpareInoutService.queryById(id));
    }
    /**
     * æ–°å¢žå¤‡ä»¶å‡ºå…¥åº“
     */
    @SaCheckPermission("eims:spareInout:add")
    @Log(title = "备件出入库", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsSpareInoutBo bo) {
        return toAjax(eimsSpareInoutService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹å¤‡ä»¶å‡ºå…¥åº“
     */
    @SaCheckPermission("eims:spareInout:edit")
    @Log(title = "备件出入库", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsSpareInoutBo bo) {
        return toAjax(eimsSpareInoutService.updateByBo(bo));
    }
    /**
     * åˆ é™¤å¤‡ä»¶å‡ºå…¥åº“
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:spareInout:remove")
    @Log(title = "备件出入库", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsSpareInoutService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsSpareTypeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
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.EimsSpareTypeVo;
import org.dromara.eims.domain.bo.EimsSpareTypeBo;
import org.dromara.eims.service.IEimsSpareTypeService;
/**
 * å¤‡ä»¶ç±»åž‹
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/spareType")
public class EimsSpareTypeController extends BaseController {
    private final IEimsSpareTypeService eimsSpareTypeService;
    /**
     * æŸ¥è¯¢å¤‡ä»¶ç±»åž‹åˆ—表
     */
    @SaCheckPermission("eims:spareType:list")
    @GetMapping("/list")
    public R<List<EimsSpareTypeVo>> list(EimsSpareTypeBo bo) {
        List<EimsSpareTypeVo> list = eimsSpareTypeService.queryList(bo);
        return R.ok(list);
    }
    /**
     * èŽ·å–è®¾å¤‡ç±»åž‹æ ‘åˆ—è¡¨
     */
    @SaCheckPermission("eims:spareType:list")
    @GetMapping("/tree")
    public R<List<Tree<Long>>> spareTypeTree(EimsSpareTypeBo bo) {
        return R.ok(eimsSpareTypeService.selectSpareTypeTreeList(bo));
    }
    /**
     * å¯¼å‡ºå¤‡ä»¶ç±»åž‹åˆ—表
     */
    @SaCheckPermission("eims:spareType:export")
    @Log(title = "备件类型", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsSpareTypeBo bo, HttpServletResponse response) {
        List<EimsSpareTypeVo> list = eimsSpareTypeService.queryList(bo);
        ExcelUtil.exportExcel(list, "备件类型", EimsSpareTypeVo.class, response);
    }
    /**
     * èŽ·å–å¤‡ä»¶ç±»åž‹è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:spareType:query")
    @GetMapping("/{id}")
    public R<EimsSpareTypeVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(eimsSpareTypeService.queryById(id));
    }
    /**
     * æ–°å¢žå¤‡ä»¶ç±»åž‹
     */
    @SaCheckPermission("eims:spareType:add")
    @Log(title = "备件类型", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsSpareTypeBo bo) {
        return toAjax(eimsSpareTypeService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹å¤‡ä»¶ç±»åž‹
     */
    @SaCheckPermission("eims:spareType:edit")
    @Log(title = "备件类型", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsSpareTypeBo bo) {
        return toAjax(eimsSpareTypeService.updateByBo(bo));
    }
    /**
     * åˆ é™¤å¤‡ä»¶ç±»åž‹
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:spareType:remove")
    @Log(title = "备件类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        if (ids == null || ids.length == 0) {
            return R.warn("请选择需要删除的数据");
        }
        for (int i = 0; i < ids.length; i++) {
            if (eimsSpareTypeService.hasChildBySpareTypeId(ids[i])) {
                return R.warn("存在子菜单,不允许删除");
            }
        }
        return toAjax(eimsSpareTypeService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFaultKnow.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
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_fault_know
 *
 * @author zhuguifei
 * @date 2025-03-18
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_fault_know")
public class EimsFaultKnow extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @TableId(value = "id")
    private Long id;
    /**
     * è®¾å¤‡id
     */
    private Long equId;
    /**
     * è®¾å¤‡ç±»åž‹
     */
    private Long equType;
    /**
     * è®¾å¤‡éƒ¨ä½(字典)
     */
    private String equPart;
    /**
     * çŸ¥è¯†ç¼–码
     */
    private String faultCode;
    /**
     * æ•…障类别(字典)
     */
    private String faultType;
    /**
     * æ•…障原因(字典)
     */
    private String faultReason;
    /**
     * æŠ¥ä¿®æè¿°
     */
    private String reqDesc;
    /**
     * å¤„理措施
     */
    private String resHandle;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsSpare.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,114 @@
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 org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import java.io.Serial;
import java.math.BigDecimal;
/**
 * å¤‡ä»¶å°è´¦å¯¹è±¡ eims_spare
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_spare")
public class EimsSpare extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @TableId(value = "id")
    private Long id;
    /**
     * ç±»åž‹
     */
    private Long type;
    /**
     * å¤‡ä»¶åç§°
     */
    private String name;
    /**
     * å¤‡ä»¶ç¼–码
     */
    private String code;
    /**
     * å¤‡ä»¶å›¾ç‰‡
     */
    private Long img;
    /**
     * åž‹å·
     */
    private String modelNo;
    /**
     * åˆ¶é€ å•†
     */
    private String madeIn;
    /**
     * ä¾›åº”商
     */
    private String supplier;
    /**
     * è®¡é‡å•位(字典)
     */
    private String unit;
    /**
     * å‚考价格
     */
    private BigDecimal referPrice;
    /**
     * åº“存上限
     */
    private Long upperStock;
    /**
     * åº“存下限
     */
    private Long lowerStock;
    /**
     * å®žé™…库存
     */
    private Long actualStock;
    /**
     * åº“存金额
     */
    private BigDecimal stockAmount;
    /**
     * æ›´æ¢å‘¨æœŸ
     */
    private Long replaceCycle;
    /**
     * æ›´æ¢å‘¨æœŸå•位(字典)
     */
    private String cycleUnit;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsSpareInout.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
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_spare_inout
 *
 * @author zhuguifei
 * @date 2025-03-26
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_spare_inout")
public class EimsSpareInout extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @TableId(value = "id")
    private Long id;
    /**
     * å•号
     */
    private String orderCode;
    /**
     * å•号日期
     */
    private Date orderTime;
    /**
     * ç»åŠžäºº
     */
    private Long chargeUser;
    private Long chargeDept;
    /**
     * å·¥å•类型(1-入库单  2-出库单) å­—å…¸
     */
    private String type;
    /**
     * å‡ºåº“客户名称或入库供应商
     */
    private String partnerName;
    /**
     * å…³è”单号(如-维修单)
     */
    private String associatedOrder;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsSpareType.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_spare_type
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_spare_type")
public class EimsSpareType 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/EimsFaultKnowBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsFaultKnow;
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_fault_know
 *
 * @author zhuguifei
 * @date 2025-03-18
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsFaultKnow.class, reverseConvertGenerate = false)
public class EimsFaultKnowBo extends BaseEntity {
    /**
     *
     */
    @NotNull(message = "不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * è®¾å¤‡id
     */
    @NotNull(message = "设备id不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long equId;
    /**
     * è®¾å¤‡ç±»åž‹
     */
    private Long equType;
    /**
     * è®¾å¤‡éƒ¨ä½(字典)
     */
    private String equPart;
    /**
     * çŸ¥è¯†ç¼–码
     */
    @NotBlank(message = "知识编码不能为空", groups = { AddGroup.class, EditGroup.class })
    private String faultCode;
    /**
     * æ•…障类别(字典)
     */
    private String faultType;
    /**
     * æ•…障原因(字典)
     */
    private String faultReason;
    /**
     * æŠ¥ä¿®æè¿°
     */
    private String reqDesc;
    /**
     * å¤„理措施
     */
    private String resHandle;
    /**
     * å¤‡æ³¨
     */
    private String remark;
    //关联表字段
    /**
     * è®¾å¤‡åç§°
     */
    private String equName;
    /**
     * è®¾å¤‡èµ„产编号
     */
    private String assetNo;
    /**
     * è®¾å¤‡ç±»åž‹id
     */
    private Long equTypeId;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsSpareBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsSpare;
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 org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import java.math.BigDecimal;
/**
 * å¤‡ä»¶å°è´¦ä¸šåŠ¡å¯¹è±¡ eims_spare
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsSpare.class, reverseConvertGenerate = false)
public class EimsSpareBo extends BaseEntity {
    /**
     *
     */
    @NotNull(message = "不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * ç±»åž‹
     */
    @NotNull(message = "类型不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long type;
    /**
     * å¤‡ä»¶åç§°
     */
    @NotBlank(message = "备件名称不能为空", groups = { AddGroup.class, EditGroup.class })
    private String name;
    /**
     * å¤‡ä»¶ç¼–码
     */
    @NotBlank(message = "备件编码不能为空", groups = { AddGroup.class, EditGroup.class })
    private String code;
    /**
     * å¤‡ä»¶å›¾ç‰‡
     */
    private Long img;
    /**
     * åž‹å·
     */
    private String modelNo;
    /**
     * åˆ¶é€ å•†
     */
    private String madeIn;
    /**
     * ä¾›åº”商
     */
    private String supplier;
    /**
     * è®¡é‡å•位(字典)
     */
    private String unit;
    /**
     * å‚考价格
     */
    private BigDecimal referPrice;
    /**
     * åº“存上限
     */
    private Long upperStock;
    /**
     * åº“存下限
     */
    private Long lowerStock;
    /**
     * å®žé™…库存
     */
    private Long actualStock;
    /**
     * åº“存金额
     */
    private BigDecimal stockAmount;
    /**
     * æ›´æ¢å‘¨æœŸ
     */
    private Long replaceCycle;
    /**
     * æ›´æ¢å‘¨æœŸå•位(字典)
     */
    private String cycleUnit;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsSpareInoutBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsSpareInout;
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_spare_inout
 *
 * @author zhuguifei
 * @date 2025-03-26
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsSpareInout.class, reverseConvertGenerate = false)
public class EimsSpareInoutBo extends BaseEntity {
    /**
     *
     */
    @NotNull(message = "不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * å•号
     */
    @NotBlank(message = "单号不能为空", groups = { AddGroup.class, EditGroup.class })
    private String orderCode;
    /**
     * å•号日期
     */
    @NotNull(message = "单号日期不能为空", groups = { AddGroup.class, EditGroup.class })
    private Date orderTime;
    /**
     * ç»åŠžäºº
     */
    @NotNull(message = "经办人不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long chargeUser;
    private Long chargeDept;
    /**
     * å·¥å•类型(1-入库单  2-出库单) å­—å…¸
     */
    @NotBlank(message = "工单类型(1-入库单  2-出库单) å­—典不能为空", groups = { AddGroup.class, EditGroup.class })
    private String type;
    /**
     * å‡ºåº“客户名称或入库供应商
     */
    @NotBlank(message = "出库客户名称或入库供应商不能为空", groups = { AddGroup.class, EditGroup.class })
    private String partnerName;
    /**
     * å…³è”单号(如-维修单)
     */
    private String associatedOrder;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsSpareTypeBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsSpareType;
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_spare_type
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsSpareType.class, reverseConvertGenerate = false)
public class EimsSpareTypeBo 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
     */
    private Long parentId;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    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/EimsEquVo.java
@@ -166,7 +166,7 @@
     * è®¾å¤‡ç±»åž‹åç§°
     */
    //@ExcelProperty(value = "设备类型")
    @Translation(type = TransConstant.EQU_YPE_ID_TO_NAME, mapper = "equTypeId")
    @Translation(type = TransConstant.EQU_TYPE_ID_TO_NAME, mapper = "equTypeId")
    private String equTypeName;
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFaultKnowVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,100 @@
package org.dromara.eims.domain.vo;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.eims.domain.EimsFaultKnow;
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_fault_know
 *
 * @author zhuguifei
 * @date 2025-03-18
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsFaultKnow.class)
public class EimsFaultKnowVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long id;
    /**
     * è®¾å¤‡id
     */
    @ExcelProperty(value = "设备id")
    private Long equId;
    @Translation(type = TransConstant.EQU_ID_TO_NAME, mapper = "equId")
    private String equName;
    private String assetNo;
    /**
     * è®¾å¤‡ç±»åž‹
     */
    @ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class)
    private Long equType;
    private String equTypeName;
    /**
     * è®¾å¤‡éƒ¨ä½(字典)
     */
    @ExcelProperty(value = "设备部位(字典)")
    private String equPart;
    /**
     * çŸ¥è¯†ç¼–码
     */
    @ExcelProperty(value = "知识编码")
    private String faultCode;
    /**
     * æ•…障类别(字典)
     */
    @ExcelProperty(value = "故障类别(字典)", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "repair_fault_type")
    private String faultType;
    /**
     * æ•…障原因(字典)
     */
    @ExcelProperty(value = "故障原因(字典)")
    private String faultReason;
    /**
     * æŠ¥ä¿®æè¿°
     */
    @ExcelProperty(value = "报修描述")
    private String reqDesc;
    /**
     * å¤„理措施
     */
    @ExcelProperty(value = "处理措施")
    private String resHandle;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsSpareInoutVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
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.EimsSpareInout;
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_spare_inout
 *
 * @author zhuguifei
 * @date 2025-03-26
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsSpareInout.class)
public class EimsSpareInoutVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long id;
    /**
     * å•号
     */
    @ExcelProperty(value = "单号")
    private String orderCode;
    /**
     * å•号日期
     */
    @ExcelProperty(value = "单号日期")
    private Date orderTime;
    /**
     * ç»åŠžäºº
     */
    @ExcelProperty(value = "经办人")
    private Long chargeUser;
    private Long chargeDept;
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "chargeUser")
    private String chargeUserName;
    @Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "chargeDept")
    private String chargeDeptName;
    /**
     * å·¥å•类型(1-入库单  2-出库单) å­—å…¸
     */
    @ExcelProperty(value = "工单类型", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "spare_inout_type")
    private String type;
    /**
     * å‡ºåº“客户名称或入库供应商
     */
    @ExcelProperty(value = "出库客户名称或入库供应商")
    private String partnerName;
    /**
     * å…³è”单号(如-维修单)
     */
    @ExcelProperty(value = "关联单号", converter = ExcelDictConvert.class)
    @ExcelDictFormat(readConverterExp = "如=-维修单")
    private String associatedOrder;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsSpareTypeVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,88 @@
package org.dromara.eims.domain.vo;
import org.dromara.eims.domain.EimsSpareType;
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_spare_type
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsSpareType.class)
public class EimsSpareTypeVo 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(readConverterExp = "0=正常,1=停用")
    private String status;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsSpareVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
package org.dromara.eims.domain.vo;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.eims.domain.EimsSpare;
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.math.BigDecimal;
import java.util.Date;
/**
 * å¤‡ä»¶å°è´¦è§†å›¾å¯¹è±¡ eims_spare
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsSpare.class)
public class EimsSpareVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     *
     */
    @ExcelProperty(value = "")
    private Long id;
    /**
     * ç±»åž‹
     */
    @ExcelProperty(value = "类型")
    private Long type;
    @Translation(type = TransConstant.SPARE_TYPE_ID_TO_NAME, mapper = "type")
    private String typeName;
    /**
     * å¤‡ä»¶åç§°
     */
    @ExcelProperty(value = "备件名称")
    private String name;
    /**
     * å¤‡ä»¶ç¼–码
     */
    @ExcelProperty(value = "备件编码")
    private String code;
    /**
     * å¤‡ä»¶å›¾ç‰‡
     */
    @ExcelProperty(value = "备件图片")
    private Long img;
    /**
     * å¤‡ä»¶å›¾ç‰‡Url
     */
    @Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "img")
    private String imgUrl;
    /**
     * åž‹å·
     */
    @ExcelProperty(value = "型号")
    private String modelNo;
    /**
     * åˆ¶é€ å•†
     */
    @ExcelProperty(value = "制造商")
    private String madeIn;
    /**
     * ä¾›åº”商
     */
    @ExcelProperty(value = "供应商")
    private String supplier;
    /**
     * è®¡é‡å•位(字典)
     */
    @ExcelProperty(value = "计量单位", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "eims_spare_unit")
    private String unit;
    /**
     * å‚考价格
     */
    @ExcelProperty(value = "参考价格")
    private BigDecimal referPrice;
    /**
     * åº“存上限
     */
    @ExcelProperty(value = "库存上限")
    private Long upperStock;
    /**
     * åº“存下限
     */
    @ExcelProperty(value = "库存下限")
    private Long lowerStock;
    /**
     * å®žé™…库存
     */
    @ExcelProperty(value = "实际库存")
    private Long actualStock;
    /**
     * åº“存金额
     */
    @ExcelProperty(value = "库存金额")
    private BigDecimal stockAmount;
    /**
     * æ›´æ¢å‘¨æœŸ
     */
    @ExcelProperty(value = "更换周期")
    private Long replaceCycle;
    /**
     * æ›´æ¢å‘¨æœŸå•位(字典)
     */
    @ExcelProperty(value = "更换周期单位", converter = ExcelDictConvert.class)
    @ExcelDictFormat(dictType = "maint_cycle_unit")
    private String cycleUnit;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/job/InspectPlanToRecordJob.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,124 @@
package org.dromara.eims.job;
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
import com.aizuda.snailjob.client.model.ExecuteResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.dromara.common.core.constant.DictConstants;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.eims.domain.EimsInspectPlan;
import org.dromara.eims.domain.EimsInspectRecord;
import org.dromara.eims.domain.EimsMaintOrder;
import org.dromara.eims.domain.EimsMaintPlan;
import org.dromara.eims.domain.vo.EimsInspectPlanVo;
import org.dromara.eims.domain.vo.EimsMaintPlanVo;
import org.dromara.eims.mapper.EimsInspectPlanMapper;
import org.dromara.eims.mapper.EimsInspectRecordMapper;
import org.dromara.eims.mapper.EimsMaintOrderMapper;
import org.dromara.eims.mapper.EimsMaintPlanMapper;
import org.dromara.eims.service.IGenerateCodeService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Component
@RequiredArgsConstructor
@JobExecutor(name = "inspectPlanToRecordJob")
public class InspectPlanToRecordJob {
    private final EimsInspectRecordMapper recordMapper;
    private final EimsInspectPlanMapper planMapper;
    private final IGenerateCodeService codeService;
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public ExecuteResult jobExecute(JobArgs jobArgs) {
        // èŽ·å–ä»Šå¤©æ—¥æœŸ
        Date today = new Date();
        LambdaQueryWrapper<EimsInspectPlan> planBoQueryWrapper = Wrappers.lambdaQuery();
        // æŸ¥è¯¢å¯ç”¨çš„点检计划
        planBoQueryWrapper.eq(EimsInspectPlan::getStatus, DictConstants.SYS_NORMAL_DISABLE_DETAIL.NORMAL);
        // è¿‡æ»¤æ²¡æœ‰ä¸‹æ¬¡è¿è¡Œæ—¶é—´
        planBoQueryWrapper.isNotNull(EimsInspectPlan::getInspNextTime);
        // è¿‡æ»¤æ²¡æœ‰ç‚¹æ£€å‘¨æœŸçš„æ•°æ®
        planBoQueryWrapper.isNotNull(EimsInspectPlan::getInspCycle);
        planBoQueryWrapper.isNotNull(EimsInspectPlan::getInspCycleUnit);
        List<EimsInspectPlanVo> planVoList = planMapper.selectVoList(planBoQueryWrapper);
        for (int i = 0; i < planVoList.size(); i++) {
            EimsInspectPlanVo planVo = planVoList.get(i);
            // ç‚¹æ£€è®¡åˆ’add的时候会自动生成下次运行时间
            Date oldNext = planVo.getInspNextTime();
            int day = DateUtils.differentDays(today, oldNext);
            // å¦‚果计划生成点检日期大于今天则不生成点检记录
            if (day >= 1) {
                continue;
            }
            // è®¡ç®—生成点检记录时间
            Long inspCycle = planVo.getInspCycle();
            Date newNext = null;
            String inspCycleUnit = planVo.getInspCycleUnit();
            switch (inspCycleUnit) {
                case DictConstants.MAINT_CYCLE_UNIT_DETAIL.DAY:
                    newNext = DateUtils.addDays(oldNext, inspCycle.intValue());
                    break;
                case DictConstants.MAINT_CYCLE_UNIT_DETAIL.WEEK:
                    newNext = DateUtils.addWeeks(oldNext, inspCycle.intValue());
                    break;
                case DictConstants.MAINT_CYCLE_UNIT_DETAIL.MONTH:
                    newNext = DateUtils.addMonths(oldNext, inspCycle.intValue());
                    break;
                case DictConstants.MAINT_CYCLE_UNIT_DETAIL.SEASON:
                    newNext = DateUtils.addMonths(oldNext, inspCycle.intValue() * 3);
                    break;
                case DictConstants.MAINT_CYCLE_UNIT_DETAIL.YEAR:
                    newNext = DateUtils.addYears(oldNext, inspCycle.intValue());
                    break;
            }
            EimsInspectRecord record = new EimsInspectRecord();
            record.setEquId(planVo.getEquId());
            record.setInspDesc(planVo.getInspDesc());
            record.setInspType(planVo.getInspType());
            record.setInspUser(planVo.getInspUser());
            record.setInspDept(planVo.getInspDept());
            record.setStatus(DictConstants.EIMS_INSPECT_STATUS_DETAIL.N);
            record.setPlanTime(oldNext);
            record.setPlanId(planVo.getId());
            //点检项名称
            record.setInspName(planVo.getInspName());
            record.setInspCode(codeService.generateCode("DJZD"));
            EimsInspectPlan plan = MapstructUtils.convert(planVo, EimsInspectPlan.class);
            assert plan != null;
            plan.setInspLastTime(oldNext);
            plan.setInspNextTime(newNext);
            if(plan.getInspFirstTime()==null)plan.setInspFirstTime(oldNext);
            boolean flag = recordMapper.insert(record) > 0;
            //TODO ç”Ÿæˆå¤±è´¥ï¼Œæ·»åŠ å¼‚å¸¸è®°å½•
            if (!flag) continue;
            planMapper.updateById(plan);
        }
        return ExecuteResult.success("点检计划生成点检记录成功");
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFaultKnowMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package org.dromara.eims.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.eims.domain.EimsFaultKnow;
import org.dromara.eims.domain.EimsInspectSt;
import org.dromara.eims.domain.vo.EimsFaultKnowVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.eims.domain.vo.EimsInspectStVo;
/**
 * æ•…障知识Mapper接口
 *
 * @author zhuguifei
 * @date 2025-03-18
 */
public interface EimsFaultKnowMapper extends BaseMapperPlus<EimsFaultKnow, EimsFaultKnowVo> {
    Page<EimsFaultKnowVo> selectFaultKnowList(@Param("page") Page<EimsFaultKnowVo> page, @Param(Constants.WRAPPER) Wrapper<EimsFaultKnow> queryWrapper);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsSpareInoutMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package org.dromara.eims.mapper;
import org.dromara.eims.domain.EimsSpareInout;
import org.dromara.eims.domain.vo.EimsSpareInoutVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
 * å¤‡ä»¶å‡ºå…¥åº“Mapper接口
 *
 * @author zhuguifei
 * @date 2025-03-26
 */
public interface EimsSpareInoutMapper extends BaseMapperPlus<EimsSpareInout, EimsSpareInoutVo> {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsSpareMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package org.dromara.eims.mapper;
import org.dromara.eims.domain.EimsSpare;
import org.dromara.eims.domain.vo.EimsSpareVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
 * å¤‡ä»¶å°è´¦Mapper接口
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
public interface EimsSpareMapper extends BaseMapperPlus<EimsSpare, EimsSpareVo> {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsSpareTypeMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package org.dromara.eims.mapper;
import org.dromara.eims.domain.EimsSpareType;
import org.dromara.eims.domain.vo.EimsSpareTypeVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
 * å¤‡ä»¶ç±»åž‹Mapper接口
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
public interface EimsSpareTypeMapper extends BaseMapperPlus<EimsSpareType, EimsSpareTypeVo> {
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFaultKnowService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package org.dromara.eims.service;
import org.dromara.eims.domain.vo.EimsFaultKnowVo;
import org.dromara.eims.domain.bo.EimsFaultKnowBo;
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-03-18
 */
public interface IEimsFaultKnowService {
    /**
     * æŸ¥è¯¢æ•…障知识
     *
     * @param id ä¸»é”®
     * @return æ•…障知识
     */
    EimsFaultKnowVo queryById(Long id);
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•…障知识列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return æ•…障知识分页列表
     */
    TableDataInfo<EimsFaultKnowVo> queryPageList(EimsFaultKnowBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„æ•…障知识列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return æ•…障知识列表
     */
    List<EimsFaultKnowVo> queryList(EimsFaultKnowBo bo);
    /**
     * æ–°å¢žæ•…障知识
     *
     * @param bo æ•…障知识
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsFaultKnowBo bo);
    /**
     * ä¿®æ”¹æ•…障知识
     *
     * @param bo æ•…障知识
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsFaultKnowBo 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/IEimsSpareInoutService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package org.dromara.eims.service;
import org.dromara.eims.domain.vo.EimsSpareInoutVo;
import org.dromara.eims.domain.bo.EimsSpareInoutBo;
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-03-26
 */
public interface IEimsSpareInoutService {
    /**
     * æŸ¥è¯¢å¤‡ä»¶å‡ºå…¥åº“
     *
     * @param id ä¸»é”®
     * @return å¤‡ä»¶å‡ºå…¥åº“
     */
    EimsSpareInoutVo queryById(Long id);
    /**
     * åˆ†é¡µæŸ¥è¯¢å¤‡ä»¶å‡ºå…¥åº“列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return å¤‡ä»¶å‡ºå…¥åº“分页列表
     */
    TableDataInfo<EimsSpareInoutVo> queryPageList(EimsSpareInoutBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„备件出入库列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å¤‡ä»¶å‡ºå…¥åº“列表
     */
    List<EimsSpareInoutVo> queryList(EimsSpareInoutBo bo);
    /**
     * æ–°å¢žå¤‡ä»¶å‡ºå…¥åº“
     *
     * @param bo å¤‡ä»¶å‡ºå…¥åº“
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsSpareInoutBo bo);
    /**
     * ä¿®æ”¹å¤‡ä»¶å‡ºå…¥åº“
     *
     * @param bo å¤‡ä»¶å‡ºå…¥åº“
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsSpareInoutBo 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/IEimsSpareService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
package org.dromara.eims.service;
import org.dromara.eims.domain.vo.EimsSpareVo;
import org.dromara.eims.domain.bo.EimsSpareBo;
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-03-20
 */
public interface IEimsSpareService {
    /**
     * æŸ¥è¯¢å¤‡ä»¶å°è´¦
     *
     * @param id ä¸»é”®
     * @return å¤‡ä»¶å°è´¦
     */
    EimsSpareVo queryById(Long id);
    /**
     * åˆ†é¡µæŸ¥è¯¢å¤‡ä»¶å°è´¦åˆ—表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return å¤‡ä»¶å°è´¦åˆ†é¡µåˆ—表
     */
    TableDataInfo<EimsSpareVo> queryPageList(EimsSpareBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„备件台账列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å¤‡ä»¶å°è´¦åˆ—表
     */
    List<EimsSpareVo> queryList(EimsSpareBo bo);
    /**
     * æ–°å¢žå¤‡ä»¶å°è´¦
     *
     * @param bo å¤‡ä»¶å°è´¦
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsSpareBo bo);
    /**
     * ä¿®æ”¹å¤‡ä»¶å°è´¦
     *
     * @param bo å¤‡ä»¶å°è´¦
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsSpareBo 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/IEimsSpareTypeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package org.dromara.eims.service;
import cn.hutool.core.lang.tree.Tree;
import jakarta.validation.constraints.NotEmpty;
import org.dromara.eims.domain.vo.EimsSpareTypeVo;
import org.dromara.eims.domain.bo.EimsSpareTypeBo;
import java.util.Collection;
import java.util.List;
/**
 * å¤‡ä»¶ç±»åž‹Service接口
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
public interface IEimsSpareTypeService {
    /**
     * æŸ¥è¯¢å¤‡ä»¶ç±»åž‹
     *
     * @param id ä¸»é”®
     * @return å¤‡ä»¶ç±»åž‹
     */
    EimsSpareTypeVo queryById(Long id);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„备件类型列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å¤‡ä»¶ç±»åž‹åˆ—表
     */
    List<EimsSpareTypeVo> queryList(EimsSpareTypeBo bo);
    /**
     * æ–°å¢žå¤‡ä»¶ç±»åž‹
     *
     * @param bo å¤‡ä»¶ç±»åž‹
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsSpareTypeBo bo);
    /**
     * ä¿®æ”¹å¤‡ä»¶ç±»åž‹
     *
     * @param bo å¤‡ä»¶ç±»åž‹
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsSpareTypeBo bo);
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤å¤‡ä»¶ç±»åž‹ä¿¡æ¯
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
    /**
     * æ£€æŸ¥æ˜¯å¦å­˜åœ¨å­é¡¹
     * @param id
     * @return
     */
    boolean hasChildBySpareTypeId(@NotEmpty(message = "主键不能为空") Long id);
    /**
     * èŽ·å–å¤‡ä»¶ç±»åž‹æ ‘åˆ—è¡¨
     *
     * @param bo
     * @return æ ‘列表
     */
    List<Tree<Long>> selectSpareTypeTreeList(EimsSpareTypeBo bo);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFaultKnowServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,191 @@
package org.dromara.eims.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.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.EimsFaultKnowBo;
import org.dromara.eims.domain.vo.EimsFaultKnowVo;
import org.dromara.eims.domain.EimsFaultKnow;
import org.dromara.eims.mapper.EimsFaultKnowMapper;
import org.dromara.eims.service.IEimsFaultKnowService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * æ•…障知识Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-03-18
 */
@RequiredArgsConstructor
@Service
public class EimsFaultKnowServiceImpl implements IEimsFaultKnowService {
    private final EimsFaultKnowMapper baseMapper;
    private final EimsEquTypeMapper equTypeMapper;
    /**
     * æŸ¥è¯¢æ•…障知识
     *
     * @param id ä¸»é”®
     * @return æ•…障知识
     */
    @Override
    public EimsFaultKnowVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•…障知识列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return æ•…障知识分页列表
     */
    @Override
    public TableDataInfo<EimsFaultKnowVo> queryPageList(EimsFaultKnowBo bo, PageQuery pageQuery) {
        QueryWrapper<EimsFaultKnow> qw = buildWrapper(bo);
        Page<EimsFaultKnowVo> result = baseMapper.selectFaultKnowList(pageQuery.build(), qw);
        return TableDataInfo.build(result);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„æ•…障知识列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return æ•…障知识列表
     */
    @Override
    public List<EimsFaultKnowVo> queryList(EimsFaultKnowBo bo) {
        LambdaQueryWrapper<EimsFaultKnow> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsFaultKnow> buildQueryWrapper(EimsFaultKnowBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsFaultKnow> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getEquId() != null, EimsFaultKnow::getEquId, bo.getEquId());
        lqw.eq(bo.getEquType() != null, EimsFaultKnow::getEquType, bo.getEquType());
        lqw.eq(StringUtils.isNotBlank(bo.getEquPart()), EimsFaultKnow::getEquPart, bo.getEquPart());
        lqw.eq(StringUtils.isNotBlank(bo.getFaultCode()), EimsFaultKnow::getFaultCode, bo.getFaultCode());
        lqw.eq(StringUtils.isNotBlank(bo.getFaultType()), EimsFaultKnow::getFaultType, bo.getFaultType());
        lqw.eq(StringUtils.isNotBlank(bo.getFaultReason()), EimsFaultKnow::getFaultReason, bo.getFaultReason());
        lqw.eq(StringUtils.isNotBlank(bo.getReqDesc()), EimsFaultKnow::getReqDesc, bo.getReqDesc());
        lqw.eq(StringUtils.isNotBlank(bo.getResHandle()), EimsFaultKnow::getResHandle, bo.getResHandle());
        return lqw;
    }
    private QueryWrapper<EimsFaultKnow> buildWrapper(EimsFaultKnowBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<EimsFaultKnow> qw = Wrappers.query();
        qw.eq(bo.getEquId() != null, "fk.equ_id", bo.getEquId());
        qw.eq(bo.getEquType() != null,"fk.equ_type", bo.getEquType());
        qw.like(bo.getEquName() != null,"eu.equ_name", bo.getEquName());
        qw.like(bo.getAssetNo() != null,"eu.asset_no", bo.getAssetNo());
        qw.eq(StringUtils.isNotBlank(bo.getEquPart()), "fk.equ_part", bo.getEquPart());
        qw.like(StringUtils.isNotBlank(bo.getFaultCode()), "fk.fault_code", bo.getFaultCode());
        qw.eq(StringUtils.isNotBlank(bo.getFaultType()), "fk.fault_type", bo.getFaultType());
        qw.eq(StringUtils.isNotBlank(bo.getFaultReason()), "fk.fault_reason", bo.getFaultReason());
        qw.like(StringUtils.isNotBlank(bo.getReqDesc()),"fk.req_desc", bo.getReqDesc());
        qw.like(StringUtils.isNotBlank(bo.getResHandle()), "fk.res_handle", bo.getResHandle());
        if (bo.getEquTypeId() != null && bo.getEquTypeId() > 0) {
            List<Long> allDescendantIds = getAllDescendantIds(bo.getEquTypeId());
            qw.in("et.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 æ•…障知识
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsFaultKnowBo bo) {
        EimsFaultKnow add = MapstructUtils.convert(bo, EimsFaultKnow.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹æ•…障知识
     *
     * @param bo æ•…障知识
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsFaultKnowBo bo) {
        EimsFaultKnow update = MapstructUtils.convert(bo, EimsFaultKnow.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsFaultKnow 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/EimsSpareInoutServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,135 @@
package org.dromara.eims.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsSpareInoutBo;
import org.dromara.eims.domain.vo.EimsSpareInoutVo;
import org.dromara.eims.domain.EimsSpareInout;
import org.dromara.eims.mapper.EimsSpareInoutMapper;
import org.dromara.eims.service.IEimsSpareInoutService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * å¤‡ä»¶å‡ºå…¥åº“Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-03-26
 */
@RequiredArgsConstructor
@Service
public class EimsSpareInoutServiceImpl implements IEimsSpareInoutService {
    private final EimsSpareInoutMapper baseMapper;
    /**
     * æŸ¥è¯¢å¤‡ä»¶å‡ºå…¥åº“
     *
     * @param id ä¸»é”®
     * @return å¤‡ä»¶å‡ºå…¥åº“
     */
    @Override
    public EimsSpareInoutVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢å¤‡ä»¶å‡ºå…¥åº“列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return å¤‡ä»¶å‡ºå…¥åº“分页列表
     */
    @Override
    public TableDataInfo<EimsSpareInoutVo> queryPageList(EimsSpareInoutBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsSpareInout> lqw = buildQueryWrapper(bo);
        Page<EimsSpareInoutVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„备件出入库列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å¤‡ä»¶å‡ºå…¥åº“列表
     */
    @Override
    public List<EimsSpareInoutVo> queryList(EimsSpareInoutBo bo) {
        LambdaQueryWrapper<EimsSpareInout> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsSpareInout> buildQueryWrapper(EimsSpareInoutBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsSpareInout> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getOrderCode()), EimsSpareInout::getOrderCode, bo.getOrderCode());
        lqw.between(params.get("beginOrderTime") != null && params.get("endOrderTime") != null,
            EimsSpareInout::getOrderTime ,params.get("beginOrderTime"), params.get("endOrderTime"));
        lqw.eq(bo.getChargeUser() != null, EimsSpareInout::getChargeUser, bo.getChargeUser());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), EimsSpareInout::getType, bo.getType());
        lqw.like(StringUtils.isNotBlank(bo.getPartnerName()), EimsSpareInout::getPartnerName, bo.getPartnerName());
        lqw.eq(StringUtils.isNotBlank(bo.getAssociatedOrder()), EimsSpareInout::getAssociatedOrder, bo.getAssociatedOrder());
        return lqw;
    }
    /**
     * æ–°å¢žå¤‡ä»¶å‡ºå…¥åº“
     *
     * @param bo å¤‡ä»¶å‡ºå…¥åº“
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsSpareInoutBo bo) {
        EimsSpareInout add = MapstructUtils.convert(bo, EimsSpareInout.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹å¤‡ä»¶å‡ºå…¥åº“
     *
     * @param bo å¤‡ä»¶å‡ºå…¥åº“
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsSpareInoutBo bo) {
        EimsSpareInout update = MapstructUtils.convert(bo, EimsSpareInout.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsSpareInout 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/EimsSpareServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,135 @@
package org.dromara.eims.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsSpareBo;
import org.dromara.eims.domain.vo.EimsSpareVo;
import org.dromara.eims.domain.EimsSpare;
import org.dromara.eims.mapper.EimsSpareMapper;
import org.dromara.eims.service.IEimsSpareService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * å¤‡ä»¶å°è´¦Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@RequiredArgsConstructor
@Service
public class EimsSpareServiceImpl implements IEimsSpareService {
    private final EimsSpareMapper baseMapper;
    /**
     * æŸ¥è¯¢å¤‡ä»¶å°è´¦
     *
     * @param id ä¸»é”®
     * @return å¤‡ä»¶å°è´¦
     */
    @Override
    public EimsSpareVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢å¤‡ä»¶å°è´¦åˆ—表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return å¤‡ä»¶å°è´¦åˆ†é¡µåˆ—表
     */
    @Override
    public TableDataInfo<EimsSpareVo> queryPageList(EimsSpareBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsSpare> lqw = buildQueryWrapper(bo);
        Page<EimsSpareVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„备件台账列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å¤‡ä»¶å°è´¦åˆ—表
     */
    @Override
    public List<EimsSpareVo> queryList(EimsSpareBo bo) {
        LambdaQueryWrapper<EimsSpare> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsSpare> buildQueryWrapper(EimsSpareBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsSpare> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getType() != null, EimsSpare::getType, bo.getType());
        lqw.like(StringUtils.isNotBlank(bo.getName()), EimsSpare::getName, bo.getName());
        lqw.like(StringUtils.isNotBlank(bo.getCode()), EimsSpare::getCode, bo.getCode());
        lqw.like(StringUtils.isNotBlank(bo.getModelNo()), EimsSpare::getModelNo, bo.getModelNo());
        lqw.like(StringUtils.isNotBlank(bo.getMadeIn()), EimsSpare::getMadeIn, bo.getMadeIn());
        lqw.like(StringUtils.isNotBlank(bo.getSupplier()), EimsSpare::getSupplier, bo.getSupplier());
        lqw.eq(StringUtils.isNotBlank(bo.getUnit()), EimsSpare::getUnit, bo.getUnit());
        return lqw;
    }
    /**
     * æ–°å¢žå¤‡ä»¶å°è´¦
     *
     * @param bo å¤‡ä»¶å°è´¦
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsSpareBo bo) {
        EimsSpare add = MapstructUtils.convert(bo, EimsSpare.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹å¤‡ä»¶å°è´¦
     *
     * @param bo å¤‡ä»¶å°è´¦
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsSpareBo bo) {
        EimsSpare update = MapstructUtils.convert(bo, EimsSpare.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsSpare 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/EimsSpareTypeServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,188 @@
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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.service.SpareTypeService;
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.core.utils.TreeBuildUtils;
import org.dromara.eims.domain.EimsEquType;
import org.dromara.eims.domain.EimsSpareType;
import org.dromara.eims.domain.bo.EimsSpareTypeBo;
import org.dromara.eims.domain.vo.EimsEquTypeVo;
import org.dromara.eims.domain.vo.EimsSpareTypeVo;
import org.dromara.eims.mapper.EimsSpareTypeMapper;
import org.dromara.eims.service.IEimsSpareTypeService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
 * å¤‡ä»¶ç±»åž‹Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-03-20
 */
@RequiredArgsConstructor
@Service
public class EimsSpareTypeServiceImpl implements IEimsSpareTypeService, SpareTypeService {
    private final EimsSpareTypeMapper baseMapper;
    /**
     * æŸ¥è¯¢å¤‡ä»¶ç±»åž‹
     *
     * @param id ä¸»é”®
     * @return å¤‡ä»¶ç±»åž‹
     */
    @Override
    public EimsSpareTypeVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„备件类型列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return å¤‡ä»¶ç±»åž‹åˆ—表
     */
    @Override
    public List<EimsSpareTypeVo> queryList(EimsSpareTypeBo bo) {
        LambdaQueryWrapper<EimsSpareType> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsSpareType> buildQueryWrapper(EimsSpareTypeBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsSpareType> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTypeName()), EimsSpareType::getTypeName, bo.getTypeName());
        lqw.eq(StringUtils.isNotBlank(bo.getTypeCode()), EimsSpareType::getTypeCode, bo.getTypeCode());
        lqw.eq(StringUtils.isNotBlank(bo.getMenuType()), EimsSpareType::getMenuType, bo.getMenuType());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsSpareType::getStatus, bo.getStatus());
        return lqw;
    }
    /**
     * æ–°å¢žå¤‡ä»¶ç±»åž‹
     *
     * @param bo å¤‡ä»¶ç±»åž‹
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsSpareTypeBo bo) {
        EimsSpareType add = MapstructUtils.convert(bo, EimsSpareType.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹å¤‡ä»¶ç±»åž‹
     *
     * @param bo å¤‡ä»¶ç±»åž‹
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsSpareTypeBo bo) {
        EimsSpareType update = MapstructUtils.convert(bo, EimsSpareType.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsSpareType 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 boolean hasChildBySpareTypeId(Long id) {
        return baseMapper.exists(new LambdaQueryWrapper<EimsSpareType>().eq(EimsSpareType::getParentId, id));
    }
    @Override
    public List<Tree<Long>> selectSpareTypeTreeList(EimsSpareTypeBo bo) {
        // åªæŸ¥è¯¢æœªç¦ç”¨ç±»åž‹
        bo.setStatus(UserConstants.DEPT_NORMAL);
        LambdaQueryWrapper<EimsSpareType> lqw = buildQueryWrapper(bo);
        List<EimsSpareTypeVo> typeVoList = baseMapper.selectVoList(lqw);
        for (int i = 0; i < typeVoList.size(); i++) {
            EimsSpareTypeVo typeVo = typeVoList.get(i);
            if(typeVo.getParentId() == null){
                typeVoList.get(i).setParentId(0L);
            }
        }
        //加根目录
        EimsSpareTypeVo root = new EimsSpareTypeVo();
        root.setId(0L);
        root.setMenuType("M");
        root.setTypeName("所有备件");
        root.setStatus("0");
        root.setTypeCode("0");
        root.setOrderNum(0L);
        root.setIcon("#");
        typeVoList.add(root);
        typeVoList.sort((o1, o2) -> o1.getId().compareTo(o2.getId()));
        return buildEquTypeTreeSelect(typeVoList);
    }
    /**
     * æž„建前端所需要下拉树结构
     *
     * @param typeVoList ç±»åž‹åˆ—表
     * @return ä¸‹æ‹‰æ ‘结构列表
     */
    public List<Tree<Long>> buildEquTypeTreeSelect(List<EimsSpareTypeVo> typeVoList) {
        if (CollUtil.isEmpty(typeVoList)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(typeVoList, (dept, tree) ->
            tree.setId(dept.getId())
                .setParentId(dept.getParentId())
                .setName(dept.getTypeName())
                .setWeight(dept.getOrderNum()));
    }
    @Override
    public String selectSpareTypeNameByIds(String spareTypeIds) {
        List<String> list = new ArrayList<>();
        for (Long id : StringUtils.splitTo(spareTypeIds, Convert::toLong)) {
            EimsSpareTypeVo 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/EimsFaultKnowMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
<?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.EimsFaultKnowMapper">
    <resultMap type="org.dromara.eims.domain.vo.EimsFaultKnowVo" id="EimsFaultKnowVoResult">
    </resultMap>
    <select id="selectFaultKnowList" resultMap="EimsFaultKnowVoResult">
        SELECT fk.*, eu.equ_name equName, eu.asset_no assetNo, et.type_name equTypeName
        FROM eims_fault_know fk
                 LEFT JOIN eims_equ eu ON fk.equ_id = eu.equ_id
                 LEFT JOIN eims_equ_type et ON eu.equ_type_id = et.equ_type_id
            ${ew.getCustomSqlSegment}
    </select>
</mapper>
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsSpareInoutMapper.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.EimsSpareInoutMapper">
</mapper>
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsSpareMapper.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.EimsSpareMapper">
</mapper>
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsSpareTypeMapper.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.EimsSpareTypeMapper">
</mapper>
eims/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java
@@ -195,7 +195,7 @@
        OssClient storage = OssFactory.instance();
        UploadResult uploadResult;
        try {
            uploadResult = storage.uploadSuffix(file.getBytes(), suffix);
            uploadResult = storage.uploadSuffix(file.getBytes(), suffix,originalfileName);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        }