车间能级提升-智能设备管理系统
朱桂飞
2025-02-12 3f476e9dc149c89df5fff1513a690ff05ec545c9
新增故障报修
已添加17个文件
已修改9个文件
2063 ■■■■■ 文件已修改
eims-ui/apps/web-antd/src/api/eims/repair-req/index.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/repair-req/model.d.ts 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/utils/index.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/components/code-input.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/components/equ-modal.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/data.tsx 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/equ/index.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory-detail/data.tsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/inventory/inventory-drawer.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/repair-req/data.tsx 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/views/eims/repair-req/repair-req-drawer.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsRepairReqController.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/GenerateCodeController.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsRepairReq.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsRepairReqBo.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsRepairReqVo.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsRepairReqMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsRepairReqService.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsRepairReqMapper.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui/apps/web-antd/src/api/eims/repair-req/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
import type { RepairReqVO } from './model';
import type { ID, IDS } from '#/api/common';
import { commonExport } from '#/api/helper';
import { requestClient } from '#/api/request';
enum Api {
  repairReqExport = '/eims/repairReq/export',
  repairReqList = '/eims/repairReq/list',
  root = '/eims/repairReq'
}
/**
 * æŸ¥è¯¢æ•…障报修列表
 * @param query
 * @returns {*}
 */
export function listRepairReq(params?: any) {
  return requestClient.get<RepairReqVO[]>(Api.repairReqList, { params });
}
/**
 * æŸ¥è¯¢æ•…障报修详细
 * @param repairReqId
 */
export function getRepairReq(repairReqId: ID) {
  return requestClient.get<RepairReqVO>(`${Api.root}/${repairReqId}`);
}
/**
 * æ–°å¢žæ•…障报修
 * @param data
 */
export function addRepairReq(data: any) {
  return requestClient.postWithMsg<void>(Api.root, data);
}
/**
 * ä¿®æ”¹æ•…障报修
 * @param data
 */
export function updateRepairReq(data: any) {
  return requestClient.putWithMsg<void>(Api.root, data);
}
/**
 * åˆ é™¤æ•…障报修
 * @param repairReqId
 */
export function delRepairReq(repairReqId: IDS) {
  return requestClient.deleteWithMsg<void>(`${Api.root}/${repairReqId}`);
}
/**
 * å¯¼å‡º
 * @param
 */
export function repairReqExport(data: any) {
  return commonExport(Api.repairReqExport, data);
}
eims-ui/apps/web-antd/src/api/eims/repair-req/model.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,235 @@
export interface RepairReqVO {
  /**
   * æŠ¥ä¿®id
   */
  id: number | string;
  /**
   * æŠ¥ä¿®å•号
   */
  code: string;
  /**
   * æŠ¥ä¿®çŠ¶æ€
   */
  status: string;
  /**
   * å‘生事件
   */
  occTime: string;
  /**
   * æŠ¥ä¿®æ—¶é—´
   */
  reqTime: string;
  /**
   * æŠ¥ä¿®äººéƒ¨é—¨
   */
  reqDept: number;
  /**
   * æŠ¥ä¿®äºº
   */
  reqUser: number;
  /**
   * æŠ¥ä¿®æè¿°
   */
  reqDesc: string;
  /**
   * ç´§æ€¥ç¨‹åº¦
   */
  urgencyLevel: string;
  /**
   * æ•…障图片
   */
  faultPicture: string;
  /**
   * æŠ¥ä¿®ç±»åž‹
   */
  reqType: string;
  /**
   * è®¾å¤‡id
   */
  equId: number | string;
  /**
   * ç»´ä¿®å•id
   */
  repairId: number | string;
  /**
   * ç»´ä¿®äººéƒ¨é—¨
   */
  repairDept: number;
  /**
   * ç»´ä¿®äºº
   */
  repairUser: number;
  /**
   * æ•…障类别
   */
  faultType: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface RepairReqForm extends BaseEntity {
  /**
   * æŠ¥ä¿®id
   */
  id?: number | string;
  /**
   * æŠ¥ä¿®å•号
   */
  code?: string;
  /**
   * æŠ¥ä¿®çŠ¶æ€
   */
  status?: string;
  /**
   * å‘生事件
   */
  occTime?: string;
  /**
   * æŠ¥ä¿®æ—¶é—´
   */
  reqTime?: string;
  /**
   * æŠ¥ä¿®äººéƒ¨é—¨
   */
  reqDept?: number;
  /**
   * æŠ¥ä¿®äºº
   */
  reqUser?: number;
  /**
   * æŠ¥ä¿®æè¿°
   */
  reqDesc?: string;
  /**
   * ç´§æ€¥ç¨‹åº¦
   */
  urgencyLevel?: string;
  /**
   * æ•…障图片
   */
  faultPicture?: string;
  /**
   * æŠ¥ä¿®ç±»åž‹
   */
  reqType?: string;
  /**
   * è®¾å¤‡id
   */
  equId?: number | string;
  /**
   * ç»´ä¿®å•id
   */
  repairId?: number | string;
  /**
   * ç»´ä¿®äººéƒ¨é—¨
   */
  repairDept?: number;
  /**
   * ç»´ä¿®äºº
   */
  repairUser?: number;
  /**
   * æ•…障类别
   */
  faultType?: string;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface RepairReqQuery extends PageQuery {
  /**
   * æŠ¥ä¿®å•号
   */
  code?: string;
  /**
   * æŠ¥ä¿®çŠ¶æ€
   */
  status?: string;
  /**
   * æŠ¥ä¿®æ—¶é—´
   */
  reqTime?: string;
  /**
   * æŠ¥ä¿®äººéƒ¨é—¨
   */
  reqDept?: number;
  /**
   * æŠ¥ä¿®äºº
   */
  reqUser?: number;
  /**
   * ç´§æ€¥ç¨‹åº¦
   */
  urgencyLevel?: string;
  /**
   * æŠ¥ä¿®ç±»åž‹
   */
  reqType?: string;
  /**
   * è®¾å¤‡id
   */
  equId?: number | string;
  /**
   * ç»´ä¿®äººéƒ¨é—¨
   */
  repairDept?: number;
  /**
   * ç»´ä¿®äºº
   */
  repairUser?: number;
  /**
   * æ•…障类别
   */
  faultType?: string;
  /**
   * æ—¥æœŸèŒƒå›´å‚æ•°
   */
  params?: any;
}
eims-ui/apps/web-antd/src/api/eims/utils/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
import { requestClient } from '#/api/request';
enum Api {
  generateCode = '/eims/generate/'
}
/**
 * ç”Ÿæˆå„种单号
 * @param prefix å•号前缀
 */
export function generateCode(prefix: string) {
  return requestClient.get<string>(`${Api.generateCode}/${prefix}`);
}
eims-ui/apps/web-antd/src/views/eims/components/code-input.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
<script setup lang="ts">
import { IconifyIcon } from '@vben/icons';
import { Input } from 'ant-design-vue';
import { generateCode } from '#/api/eims/utils';
defineOptions({ name: 'CodeInput' });
/**
 * ç‰¹åˆ«æ³¨æ„ï¼Œå•号根据前缀生成
 * BXD-报修单
 */
const props = defineProps({
  disabled: {
    default: false,
    type: Boolean
  },
  prefix: {
    default: null,
    type: String
  },
  placeholder: {
    default: '自动生成',
    type: String
  }
});
const value = defineModel<string>('value', {
  required: false,
  type: String
});
async function refreshCode() {
  // æ ¹æ®
  // value.value = buildUUID();
  const code = await generateCode(props.prefix);
  value.value = code;
}
/**
 * ä¸‡ä¸€è¦åœ¨æ¯æ¬¡æ–°å¢žæ—¶æ‰“å¼€Drawer刷新
 * éœ€è¦è°ƒç”¨å®žä¾‹æ–¹æ³•
 */
defineExpose({ refreshCode });
</script>
<template>
  <Input v-model:value="value" :disabled="disabled" :placeholder="placeholder">
    <template v-if="!disabled" #addonAfter>
      <a-button type="primary" @click="refreshCode">
        <div class="flex items-center gap-[4px]">
          <IconifyIcon icon="charm:refresh" />
          <span>自动生成</span>
        </div>
      </a-button>
    </template>
  </Input>
</template>
<style lang="scss" scoped>
:deep(.ant-input-group-addon) {
  padding: 0;
  border: none;
}
:deep(.ant-btn-primary) {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
</style>
eims-ui/apps/web-antd/src/views/eims/components/equ-modal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import EquView from '#/views/eims/equ/index.vue';
const emit = defineEmits<{ updateEqu: [any] }>();
const [BasicModal, modalApi] = useVbenModal({
  fullscreenButton: false,
  draggable: true,
  onCancel: handleCancel,
  onConfirm: handleConfirm
});
const equView = ref();
async function handleConfirm() {
  try {
    modalApi.modalLoading(true);
    const tableSelect = equView.value.tableSelect();
    if (tableSelect.length > 1) {
      message.error('最多只能选择一台设备!');
      modalApi.modalLoading(false);
      return false;
    }
    emit('updateEqu', tableSelect[0]);
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    modalApi.modalLoading(false);
  }
}
async function handleCancel() {
  modalApi.close();
}
</script>
<template>
  <BasicModal :fullscreen-button="true" class="w-[800px]">
    <EquView ref="equView" />
  </BasicModal>
</template>
<style scoped></style>
eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx
@@ -4,8 +4,6 @@
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { Tag } from 'ant-design-vue';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
eims-ui/apps/web-antd/src/views/eims/equ/data.tsx
@@ -3,8 +3,6 @@
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { Tag } from 'ant-design-vue';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
@@ -65,7 +63,7 @@
    fixed: 'left'
  },
  {
    title: '设备编号',
    title: '设备编码',
    field: 'equCode',
    sortable: true,
    minWidth: 100
eims-ui/apps/web-antd/src/views/eims/equ/index.vue
@@ -20,6 +20,10 @@
// å·¦è¾¹éƒ¨é—¨ç”¨
const selectDeptId = ref<string[]>([]);
defineExpose({
  tableSelect
});
const formOptions: VbenFormProps = {
  commonConfig: {
    labelWidth: 80,
@@ -80,7 +84,7 @@
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true,
    multiple: true
  },
  id: 'eims-equ-index'
};
@@ -89,8 +93,8 @@
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams),
  },
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [EquDrawer, equDrawerApi] = useVbenDrawer({
@@ -146,6 +150,10 @@
function handleDetail(record: Recordable<any>) {
  router.push(`/equ/detail/${record.equId}`);
}
// é€‰ä¸­æ•°æ®
function tableSelect() {
  return tableApi.grid.getCheckboxRecords();
}
</script>
<template>
eims-ui/apps/web-antd/src/views/eims/inventory-detail/data.tsx
@@ -10,7 +10,7 @@
  {
    component: 'Input',
    fieldName: 'equCode',
    label: '设备编号'
    label: '设备编码'
  },
  {
    component: 'Input',
@@ -60,7 +60,7 @@
    }
  },
  {
    title: '设备编号',
    title: '设备编码',
    field: 'equCode',
    minWidth: 120,
    fixed: 'left'
eims-ui/apps/web-antd/src/views/eims/inventory/index.vue
@@ -169,7 +169,7 @@
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
          formModel.inventoryUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
eims-ui/apps/web-antd/src/views/eims/inventory/inventory-drawer.vue
@@ -150,7 +150,7 @@
          /** æ ¹æ®éƒ¨é—¨ID加载用户 */
          await setupUserOptions(deptId);
          /** å˜åŒ–后需要重新选择用户 */
          formModel.respPerson = undefined;
          formModel.inventoryUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
eims-ui/apps/web-antd/src/views/eims/repair-req/data.tsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,259 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    fieldName: 'code',
    label: '报修单号'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.REPAIR_REQ_STATUS)
    },
    fieldName: 'status',
    label: '报修状态'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'reqDept',
    label: '报修部门',
    // rules: 'selectRequired',
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'reqUser',
    label: '报修人'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.REPAIR_REQ_TYPE)
    },
    fieldName: 'reqType',
    label: '报修类型'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.REPAIR_FAULT_TYPE)
    },
    fieldName: 'faultType',
    label: '故障类别'
  },
  {
    component: 'Select',
    componentProps: {
      options: getDictOptions(DictEnum.REPAIR_URGENCY_LEVEL)
    },
    fieldName: 'urgencyLevel',
    label: '紧急程度'
  },
  {
    component: 'RangePicker',
    fieldName: 'reqTime',
    label: '报修时间'
  }
];
export const columns: VxeGridProps['columns'] = [
  { type: 'checkbox', width: 60, fixed: 'left' },
  {
    title: '报修单号',
    field: 'code',
    minWidth: 160,
    fixed: 'left'
  },
  {
    title: '处理状态',
    field: 'status',
    minWidth: 100,
    fixed: 'left',
    slots: {
      default: ({ row }) => {
        return renderDict(row.status, DictEnum.REPAIR_REQ_STATUS);
      }
    }
  },
  {
    title: '报修类型',
    field: 'reqType',
    sortable: true,
    minWidth: 100,
    slots: {
      default: ({ row }) => {
        return renderDict(row.reqType, DictEnum.REPAIR_REQ_TYPE);
      }
    }
  },
  {
    title: '报修时间',
    field: 'reqTime',
    sortable: true,
    minWidth: 200
  },
  {
    title: '故障类别',
    field: 'faultType',
    minWidth: 100,
    slots: {
      default: ({ row }) => {
        return renderDict(row.faultType, DictEnum.REPAIR_FAULT_TYPE);
      }
    }
  },
  {
    title: '报修部门',
    field: 'reqDeptName',
    minWidth: 100
  },
  {
    title: '报修人',
    field: 'reqUserName',
    minWidth: 100
  },
  {
    title: '故障描述',
    field: 'reqDesc',
    minWidth: 120
  },
  {
    field: 'action',
    fixed: 'right',
    slots: { default: 'action' },
    title: '操作',
    width: 130
  }
];
export const drawerSchema: FormSchemaGetter = () => [
  {
    component: 'Input',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    },
    fieldName: 'id'
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
    },
    fieldName: 'reqType',
    label: '报修类型',
    help: `报修类型,如设备故障、工具(治具)故障等`
  },
  {
    component: 'Input',
    fieldName: 'code',
    label: '报修单号'
  },
  {
    component: 'Input',
    fieldName: 'equName',
    label: '设备名称',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    }
  },
  {
    component: 'Input',
    fieldName: 'equId',
    label: '设备id',
    dependencies: {
      show: () => false,
      triggerFields: ['']
    }
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.REPAIR_REQ_STATUS)
    },
    fieldName: 'status',
    label: '处理状态'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD HH:mm:ss',
      showTime: true,
      valueFormat: 'YYYY-MM-DD HH:mm:ss',
      getPopupContainer
    },
    fieldName: 'reqTime',
    label: '报修时间'
  },
  {
    component: 'DatePicker',
    componentProps: {
      format: 'YYYY-MM-DD HH:mm:ss',
      showTime: true,
      valueFormat: 'YYYY-MM-DD HH:mm:ss',
      getPopupContainer
    },
    fieldName: 'occTime',
    label: '发生时间'
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.REPAIR_FAULT_TYPE)
    },
    fieldName: 'faultType',
    label: '故障类别'
  },
  {
    component: 'Select',
    componentProps: {
      getPopupContainer,
      options: getDictOptions(DictEnum.REPAIR_URGENCY_LEVEL)
    },
    fieldName: 'urgencyLevel',
    label: '紧急程度'
  },
  {
    component: 'Textarea',
    formItemClass: 'items-baseline',
    fieldName: 'reqDesc',
    label: '故障描述'
  },
  {
    component: 'TreeSelect',
    // åœ¨drawer里更新 è¿™é‡Œä¸éœ€è¦é»˜è®¤çš„componentProps
    defaultValue: undefined,
    fieldName: 'reqDept',
    label: '报修部门',
    help: `报修人员所属部门`
    // rules: 'selectRequired',
  },
  {
    component: 'Select',
    componentProps: {
      showSearch: true,
      allowClear: true,
      getPopupContainer
    },
    fieldName: 'reqUser',
    label: '报修人'
  }
];
eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,230 @@
<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 { delRepairReq, listRepairReq, repairReqExport } from '#/api/eims/repair-req';
import { getDeptTree, userList } from '#/api/system/user';
import { commonDownloadExcel } from '#/utils/file/download';
import { columns, querySchema } from './data';
import repairReqDrawer from './repair-req-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: [['reqTime', ['params[beginReqTime]', 'params[endReqTime]'], ['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 = {}) => {
        return await listRepairReq({
          pageNum: page.currentPage,
          pageSize: page.pageSize,
          ...formValues
        });
      }
    }
  },
  rowConfig: {
    isHover: true,
    keyField: 'id'
  },
  sortConfig: {
    // è¿œç¨‹æŽ’序
    remote: true,
    // æ”¯æŒå¤šå­—段排序 é»˜è®¤å…³é—­
    multiple: true
  },
  id: 'eims-repair-req-index'
};
const [BasicTable, tableApi] = useVbenVxeGrid({
  formOptions,
  gridOptions,
  gridEvents: {
    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
  }
});
const [RepairReqDrawer, repairReqDrawerApi] = useVbenDrawer({
  connectedComponent: repairReqDrawer
});
function handleAdd() {
  repairReqDrawerApi.setData({});
  repairReqDrawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
  repairReqDrawerApi.setData({ id: record.id });
  repairReqDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
  await delRepairReq(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 delRepairReq(ids);
      await tableApi.query();
    }
  });
}
function handleDownloadExcel() {
  commonDownloadExcel(repairReqExport, '故障报修记录', tableApi.formApi.form.values, {
    fieldMappingTime: formOptions.fieldMappingTime
  });
}
onMounted(async () => {
  await setupDeptSelect();
});
/**
 * ç”¨æˆ·çš„加载
 */
async function setupUserOptions(deptId: any) {
  const params = { deptId };
  const userPageResult = await userList({
    pageNum: 1,
    pageSize: 500,
    ...params
  });
  const options = userPageResult.rows.map((item) => ({
    label: item.nickName || item.userName,
    value: item.userId
  }));
  // ç­›é€‰
  const filterOption = (input: string, option: any) => {
    return option.label.toLowerCase().includes(input.toLowerCase());
  };
  const placeholder = options.length > 0 ? '请选择' : '该部门下暂无用户';
  tableApi.formApi.updateSchema([
    {
      componentProps: { options, placeholder, filterOption },
      fieldName: 'reqUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.reqUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'reqDept'
    }
  ]);
}
</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:repairReq:export']" @click="handleDownloadExcel">
              {{ $t('pages.common.export') }}
            </a-button>
            <a-button
              :disabled="!vxeCheckboxChecked(tableApi)"
              danger
              type="primary"
              v-access:code="['eims:repairReq:remove']"
              @click="handleMultiDelete"
            >
              {{ $t('pages.common.delete') }}
            </a-button>
            <a-button type="primary" v-access:code="['eims:repairReq:add']" @click="handleAdd">
              {{ $t('pages.common.add') }}
            </a-button>
          </Space>
        </template>
        <template #action="{ row }">
          <Space>
            <ghost-button v-access:code="['eims:repairReq: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:repairReq:remove']" @click.stop="">
                {{ $t('pages.common.delete') }}
              </ghost-button>
            </Popconfirm>
          </Space>
        </template>
      </BasicTable>
    </div>
    <RepairReqDrawer @reload="tableApi.query()" />
  </Page>
</template>
eims-ui/apps/web-antd/src/views/eims/repair-req/repair-req-drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,262 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { DictEnum } from '@vben/constants';
import { $t } from '@vben/locales';
import { addFullName, cloneDeep, getPopupContainer, listToTree } from '@vben/utils';
import { InputSearch } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { listEquType } from '#/api/eims/equ-type';
import { addRepairReq, getRepairReq, updateRepairReq } from '#/api/eims/repair-req';
import { getDeptTree, userList } from '#/api/system/user';
import { getDictOptions } from '#/utils/dict';
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;
    }
    // åŠ¨æ€åˆ‡æ¢è¡¨å•
    formApi.updateSchema([
      {
        componentProps: () => ({
          disabled: isUpdate.value,
          options: getDictOptions(DictEnum.REPAIR_REQ_TYPE),
          async onSelect(reqType: string) {
            // ç±»åž‹è§å­—å…¸-REPAIR_REQ_TYPE
            formApi.updateSchema([
              {
                dependencies: {
                  show: () => reqType === '1',
                  triggerFields: ['']
                },
                fieldName: 'equName'
              }
            ]);
          }
        }),
        fieldName: 'reqType'
      },
      {
        dependencies: {
          show: () => false,
          triggerFields: ['']
        },
        fieldName: 'equName'
      }
    ]);
    drawerApi.drawerLoading(true);
    const { id } = drawerApi.getData() as { id?: number | string };
    isUpdate.value = !!id;
    // åˆå§‹åŒ–
    await setupDeptSelect();
    await setupEquTypeSelect();
    // æ›´æ–° && èµ‹å€¼
    if (isUpdate.value && id) {
      const record = await getRepairReq(id);
      const reqType = record.reqType;
      await formApi.setValues(record);
      // æ›´æ–°æ—¶ä¸å¯ä¿®æ”¹ç›˜ç‚¹èŒƒå›´
      if (isUpdate.value && record.reqDept) {
        await setupUserOptions(record.reqDept);
      }
      formApi.updateSchema([
        {
          dependencies: {
            show: () => reqType === '1',
            triggerFields: ['']
          },
          fieldName: 'equName'
        }
      ]);
    }
    drawerApi.drawerLoading(false);
  }
});
const [EquModal, equModalApi] = useVbenModal({
  connectedComponent: equModal,
  draggable: true,
  title: '选择设备'
});
function handleOpenModal() {
  equModalApi.setData({});
  equModalApi.open();
}
/**
 * åŠ è½½è®¾å¤‡ç±»æ ‘
 */
const equTypeTree = ref();
async function setupEquTypeSelect() {
  const result = (await listEquType()) || [];
  // æž„建组件需要数据
  const equArray = result.map((item) => {
    return {
      ...item, // ä¿ç•™åŽŸæœ‰å¯¹è±¡çš„æ‰€æœ‰å±žæ€§
      id: item.equTypeId,
      label: item.typeName,
      weight: item.orderNum
    };
  });
  // support i18n
  equArray.forEach((item) => {
    item.typeName = $t(item.typeName);
  });
  const equTree = listToTree(equArray, { id: 'id', pid: 'parentId' });
  equTypeTree.value = equTree;
}
/**
 * ç”¨æˆ·çš„加载
 */
async function setupUserOptions(deptId: any) {
  const params = { deptId };
  const userPageResult = await userList({
    pageNum: 1,
    pageSize: 500,
    ...params
  });
  const options = userPageResult.rows.map((item) => ({
    label: item.nickName || item.userName,
    value: item.userId
  }));
  // ç­›é€‰
  const filterOption = (input: string, option: any) => {
    return option.label.toLowerCase().includes(input.toLowerCase());
  };
  const placeholder = options.length > 0 ? '请选择' : '该部门下暂无用户';
  formApi.updateSchema([
    {
      componentProps: { options, placeholder, filterOption },
      fieldName: 'reqUser'
    }
  ]);
}
/**
 * åˆå§‹åŒ–部门选择
 */
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.reqUser = undefined;
        },
        placeholder: '请选择',
        showSearch: true,
        treeData: deptTree,
        treeDefaultExpandAll: true,
        treeLine: { showLeafIcon: false },
        // ç­›é€‰çš„字段
        treeNodeFilterProp: 'label',
        // é€‰ä¸­åŽæ˜¾ç¤ºåœ¨è¾“入框的值
        treeNodeLabelProp: 'fullName'
      }),
      fieldName: 'reqDept'
    }
  ]);
}
async function handleConfirm() {
  try {
    drawerApi.drawerLoading(true);
    const { valid } = await formApi.validate();
    if (!valid) {
      return;
    }
    const data = cloneDeep(await formApi.getValues());
    await (isUpdate.value ? updateRepairReq(data) : addRepairReq(data));
    emit('reload');
    await handleCancel();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.drawerLoading(false);
  }
}
async function handleCancel() {
  drawerApi.close();
  await formApi.resetForm();
}
/**
 * æ‰“开查询设备
 */
function onSearchEqu() {
  handleOpenModal();
}
/**
 * æ›´æ–°é€‰æ‹©çš„设备
 * @param equ
 */
async function updateEqu(equ: any) {
  await formApi.setValues({ 'equId': equ.equId, 'equName': equ.equName });
}
</script>
<template>
  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
    <BasicForm>
      <template #code="slotProps">
        <CodeInput v-bind="slotProps" :disabled="isUpdate" prefix="BXD" />
      </template>
      <template #equName="slotProps">
        <InputSearch :enter-button="true" placeholder="请选择设备" @search="onSearchEqu" v-bind="slotProps"
                     :disabled="isUpdate" />
      </template>
    </BasicForm>
    <EquModal class="w-[1200px]" @update-equ="updateEqu" />
  </BasicDrawer>
</template>
eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,6 +1,10 @@
export enum DictEnum {
  EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  EIMS_INVENTORY_STATU = 'inventory_statu', // è®¾å¤‡ç›˜ç‚¹çŠ¶æ€
  REPAIR_REQ_STATUS = 'repair_req_status', // æŠ¥ä¿®çŠ¶æ€
  REPAIR_FAULT_TYPE = 'repair_fault_type', // æŠ¥ä¿®çŠ¶æ€
  REPAIR_REQ_TYPE = 'repair_req_type', // æŠ¥ä¿®ç±»åž‹
  REPAIR_URGENCY_LEVEL = 'repair_urgency_level', // æŠ¥ä¿®ç´§æ€¥ç¨‹åº¦
  SYS_COMMON_STATUS = 'sys_common_status',
  SYS_DEVICE_TYPE = 'sys_device_type', // è®¾å¤‡ç±»åž‹
  SYS_EQU_STATUS = 'sys_equ_status', // è®¾å¤‡çŠ¶æ€
eims/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheConstants.java
@@ -27,4 +27,10 @@
     */
    String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
    /**
     * ç”Ÿæˆå•号  redis key
     * code组成规则 prefix + å¹´æœˆæ—¥ + åºå·
     */
    String EIMS_GENERATE_CODE = "eims_generate_code:";
}
eims/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml
@@ -2,9 +2,9 @@
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    url: jdbc:mysql://localhost:3306/eims?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: root
    password: root
    password: 123456
    hikari:
      connection-timeout: 30000
      validation-timeout: 5000
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsRepairReqController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,106 @@
package org.dromara.eims.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.eims.domain.vo.EimsRepairReqVo;
import org.dromara.eims.domain.bo.EimsRepairReqBo;
import org.dromara.eims.service.IEimsRepairReqService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
 * æ•…障报修
 *
 * @author zhuguifei
 * @date 2025-02-10
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/repairReq")
public class EimsRepairReqController extends BaseController {
    private final IEimsRepairReqService eimsRepairReqService;
    /**
     * æŸ¥è¯¢æ•…障报修列表
     */
    @SaCheckPermission("eims:repairReq:list")
    @GetMapping("/list")
    public TableDataInfo<EimsRepairReqVo> list(EimsRepairReqBo bo, PageQuery pageQuery) {
        //return eimsRepairReqService.queryPageList(bo, pageQuery);
        return eimsRepairReqService.queryPageListCustom(bo, pageQuery);
    }
    /**
     * å¯¼å‡ºæ•…障报修列表
     */
    @SaCheckPermission("eims:repairReq:export")
    @Log(title = "故障报修", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(EimsRepairReqBo bo, HttpServletResponse response) {
        List<EimsRepairReqVo> list = eimsRepairReqService.queryList(bo);
        ExcelUtil.exportExcel(list, "故障报修", EimsRepairReqVo.class, response);
    }
    /**
     * èŽ·å–æ•…éšœæŠ¥ä¿®è¯¦ç»†ä¿¡æ¯
     *
     * @param id ä¸»é”®
     */
    @SaCheckPermission("eims:repairReq:query")
    @GetMapping("/{id}")
    public R<EimsRepairReqVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable Long id) {
        return R.ok(eimsRepairReqService.queryById(id));
    }
    /**
     * æ–°å¢žæ•…障报修
     */
    @SaCheckPermission("eims:repairReq:add")
    @Log(title = "故障报修", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsRepairReqBo bo) {
        return toAjax(eimsRepairReqService.insertByBo(bo));
    }
    /**
     * ä¿®æ”¹æ•…障报修
     */
    @SaCheckPermission("eims:repairReq:edit")
    @Log(title = "故障报修", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsRepairReqBo bo) {
        return toAjax(eimsRepairReqService.updateByBo(bo));
    }
    /**
     * åˆ é™¤æ•…障报修
     *
     * @param ids ä¸»é”®ä¸²
     */
    @SaCheckPermission("eims:repairReq:remove")
    @Log(title = "故障报修", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(eimsRepairReqService.deleteWithValidByIds(List.of(ids), true));
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/GenerateCodeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package org.dromara.eims.controller;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.RedisUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
 * ã€ç”Ÿæˆç¼–码】
 *
 * @author zhuguifei
 * @date 2025-02-11
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/eims/generate")
public class GenerateCodeController {
    /**
     * æ ¹æ®å‰ç¼€ç”Ÿæˆå„种编码
     *
     * @param prefix å‰ç¼€
     * @return
     */
    @GetMapping("/{prefix}")
    public R<String> generateCode(@NotNull(message = "类型不能为空")
                                      @PathVariable String prefix) {
        String todayStr = DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now());
        String key = CacheConstants.EIMS_GENERATE_CODE + ":" + prefix;
        String code;
        // ä½¿ç”¨Redis的原子性操作避免并发问题
        String oldCode = RedisUtils.getCacheObject(key);
        if (oldCode != null && oldCode.contains(todayStr)) {
            int no = Integer.parseInt(oldCode.substring(oldCode.length() - 4));
            code = String.format("%s%s%04d", prefix, todayStr, no + 1);
        } else {
            code = String.format("%s%s%04d", prefix, todayStr, 1);
        }
        // æ›´æ–°ç¼“å­˜
        try {
            RedisUtils.setCacheObject(key, code);
        } catch (Exception e) {
            return R.fail("生成编码失败,请稍后重试!");
        }
        return R.ok("生成成功!", code);
    }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsRepairReq.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
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_repair_req
 *
 * @author zhuguifei
 * @date 2025-02-10
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("eims_repair_req")
public class EimsRepairReq extends BaseEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æŠ¥ä¿®id
     */
    @TableId(value = "id")
    private Long id;
    /**
     * æŠ¥ä¿®å•号
     */
    private String code;
    /**
     * æŠ¥ä¿®çŠ¶æ€
     */
    private String status;
    /**
     * å‘生事件
     */
    private Date occTime;
    /**
     * æŠ¥ä¿®æ—¶é—´
     */
    private Date reqTime;
    /**
     * æŠ¥ä¿®äººéƒ¨é—¨
     */
    private Long reqDept;
    /**
     * æŠ¥ä¿®äºº
     */
    private Long reqUser;
    /**
     * æŠ¥ä¿®æè¿°
     */
    private String reqDesc;
    /**
     * ç´§æ€¥ç¨‹åº¦
     */
    private String urgencyLevel;
    /**
     * æ•…障图片
     */
    private String faultPicture;
    /**
     * æŠ¥ä¿®ç±»åž‹
     */
    private String reqType;
    /**
     * è®¾å¤‡id
     */
    private Long equId;
    /**
     * ç»´ä¿®å•id
     */
    private Long repairId;
    /**
     * ç»´ä¿®äººéƒ¨é—¨
     */
    private Long repairDept;
    /**
     * ç»´ä¿®äºº
     */
    private Long repairUser;
    /**
     * æ•…障类别
     */
    private String faultType;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsRepairReqBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
package org.dromara.eims.domain.bo;
import org.dromara.eims.domain.EimsRepairReq;
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_repair_req
 *
 * @author zhuguifei
 * @date 2025-02-10
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = EimsRepairReq.class, reverseConvertGenerate = false)
public class EimsRepairReqBo extends BaseEntity {
    /**
     * æŠ¥ä¿®id
     */
    @NotNull(message = "报修id不能为空", groups = { EditGroup.class })
    private Long id;
    /**
     * æŠ¥ä¿®å•号
     */
    @NotBlank(message = "报修单号不能为空", groups = { AddGroup.class, EditGroup.class })
    private String code;
    /**
     * æŠ¥ä¿®çŠ¶æ€
     */
    @NotBlank(message = "报修状态不能为空", groups = { AddGroup.class, EditGroup.class })
    private String status;
    /**
     * å‘生时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date occTime;
    /**
     * æŠ¥ä¿®æ—¶é—´
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date reqTime;
    /**
     * æŠ¥ä¿®äººéƒ¨é—¨
     */
    @NotNull(message = "报修人部门不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long reqDept;
    /**
     * æŠ¥ä¿®äºº
     */
    @NotNull(message = "报修人不能为空", groups = { AddGroup.class, EditGroup.class })
    private Long reqUser;
    /**
     * æŠ¥ä¿®æè¿°
     */
    @NotBlank(message = "报修描述不能为空", groups = { AddGroup.class, EditGroup.class })
    private String reqDesc;
    /**
     * ç´§æ€¥ç¨‹åº¦
     */
    @NotBlank(message = "紧急程度不能为空", groups = { AddGroup.class, EditGroup.class })
    private String urgencyLevel;
    /**
     * æ•…障图片
     */
    private String faultPicture;
    /**
     * æŠ¥ä¿®ç±»åž‹
     */
    @NotBlank(message = "报修类型不能为空", groups = { AddGroup.class, EditGroup.class })
    private String reqType;
    /**
     * è®¾å¤‡id
     */
    private Long equId;
    /**
     * ç»´ä¿®å•id
     */
    private Long repairId;
    /**
     * ç»´ä¿®äººéƒ¨é—¨
     */
    private Long repairDept;
    /**
     * ç»´ä¿®äºº
     */
    private Long repairUser;
    /**
     * æ•…障类别
     */
    @NotBlank(message = "故障类别不能为空", groups = { AddGroup.class, EditGroup.class })
    private String faultType;
    /**
     * å¤‡æ³¨
     */
    private String remark;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsRepairReqVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
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.EimsRepairReq;
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_repair_req
 *
 * @author zhuguifei
 * @date 2025-02-10
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = EimsRepairReq.class)
public class EimsRepairReqVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æŠ¥ä¿®id
     */
    @ExcelProperty(value = "报修id")
    private Long id;
    /**
     * æŠ¥ä¿®å•号
     */
    @ExcelProperty(value = "报修单号")
    private String code;
    /**
     * æŠ¥ä¿®çŠ¶æ€
     */
    @ExcelProperty(value = "报修状态")
    private String status;
    /**
     * å‘生事件
     */
    @ExcelProperty(value = "发生时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date occTime;
    /**
     * æŠ¥ä¿®æ—¶é—´
     */
    @ExcelProperty(value = "报修时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date reqTime;
    /**
     * æŠ¥ä¿®äººéƒ¨é—¨
     */
    @ExcelProperty(value = "报修人部门")
    private Long reqDept;
    @Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "reqDept")
    private String reqDeptName;
    /**
     * æŠ¥ä¿®äºº
     */
    @ExcelProperty(value = "报修人")
    private Long reqUser;
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "reqUser")
    private String reqUserName;
    /**
     * æŠ¥ä¿®æè¿°
     */
    @ExcelProperty(value = "报修描述")
    private String reqDesc;
    /**
     * ç´§æ€¥ç¨‹åº¦
     */
    @ExcelProperty(value = "紧急程度")
    private String urgencyLevel;
    /**
     * æ•…障图片
     */
    @ExcelProperty(value = "故障图片")
    private String faultPicture;
    /**
     * æŠ¥ä¿®ç±»åž‹
     */
    @ExcelProperty(value = "报修类型")
    private String reqType;
    /**
     * è®¾å¤‡id
     */
    @ExcelProperty(value = "设备id")
    private Long equId;
    /**
     * ç»´ä¿®å•id
     */
    @ExcelProperty(value = "维修单id")
    private Long repairId;
    /**
     * ç»´ä¿®äººéƒ¨é—¨
     */
    @ExcelProperty(value = "维修人部门")
    private Long repairDept;
    /**
     * ç»´ä¿®äºº
     */
    @ExcelProperty(value = "维修人")
    private Long repairUser;
    /**
     * æ•…障类别
     */
    @ExcelProperty(value = "故障类别")
    private String faultType;
    /**
     * å¤‡æ³¨
     */
    @ExcelProperty(value = "备注")
    private String remark;
    private String equCode;
    private String assetNo;
    @Translation(type = TransConstant.EQU_ID_TO_NAME, mapper = "equId")
    private String equName;
    private String equLocation;
    private String equTypeName;
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsRepairReqMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
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.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.eims.domain.EimsRepairReq;
import org.dromara.eims.domain.vo.EimsRepairReqVo;
/**
 * æ•…障报修Mapper接口
 *
 * @author zhuguifei
 * @date 2025-02-11
 */
public interface EimsRepairReqMapper extends BaseMapperPlus<EimsRepairReq, EimsRepairReqVo> {
    Page<EimsRepairReqVo> selectRepairReqList(@Param("page") Page<EimsRepairReqVo> page, @Param(Constants.WRAPPER) Wrapper<EimsRepairReq> queryWrapper);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsRepairReqService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,78 @@
package org.dromara.eims.service;
import org.dromara.eims.domain.vo.EimsRepairReqVo;
import org.dromara.eims.domain.bo.EimsRepairReqBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
 * æ•…障报修Service接口
 *
 * @author zhuguifei
 * @date 2025-02-10
 */
public interface IEimsRepairReqService {
    /**
     * æŸ¥è¯¢æ•…障报修
     *
     * @param id ä¸»é”®
     * @return æ•…障报修
     */
    EimsRepairReqVo queryById(Long id);
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•…障报修列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return æ•…障报修分页列表
     */
    TableDataInfo<EimsRepairReqVo> queryPageList(EimsRepairReqBo bo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„æ•…障报修列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return æ•…障报修列表
     */
    List<EimsRepairReqVo> queryList(EimsRepairReqBo bo);
    /**
     * æ–°å¢žæ•…障报修
     *
     * @param bo æ•…障报修
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    Boolean insertByBo(EimsRepairReqBo bo);
    /**
     * ä¿®æ”¹æ•…障报修
     *
     * @param bo æ•…障报修
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    Boolean updateByBo(EimsRepairReqBo bo);
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤æ•…障报修信息
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•…障报修列表-多表查询
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return æ•…障报修分页列表
     */
    TableDataInfo<EimsRepairReqVo> queryPageListCustom(EimsRepairReqBo bo, PageQuery pageQuery);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
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.EimsEqu;
import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsRepairReqBo;
import org.dromara.eims.domain.vo.EimsRepairReqVo;
import org.dromara.eims.domain.EimsRepairReq;
import org.dromara.eims.mapper.EimsRepairReqMapper;
import org.dromara.eims.service.IEimsRepairReqService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
 * æ•…障报修Service业务层处理
 *
 * @author zhuguifei
 * @date 2025-02-10
 */
@RequiredArgsConstructor
@Service
public class EimsRepairReqServiceImpl implements IEimsRepairReqService {
    private final EimsRepairReqMapper baseMapper;
    /**
     * æŸ¥è¯¢æ•…障报修
     *
     * @param id ä¸»é”®
     * @return æ•…障报修
     */
    @Override
    public EimsRepairReqVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•…障报修列表
     *
     * @param bo        æŸ¥è¯¢æ¡ä»¶
     * @param pageQuery åˆ†é¡µå‚æ•°
     * @return æ•…障报修分页列表
     */
    @Override
    public TableDataInfo<EimsRepairReqVo> queryPageList(EimsRepairReqBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<EimsRepairReq> lqw = buildQueryWrapper(bo);
        Page<EimsRepairReqVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    @Override
    public TableDataInfo<EimsRepairReqVo> queryPageListCustom(EimsRepairReqBo bo, PageQuery pageQuery) {
        Page<EimsRepairReqVo> page = baseMapper.selectRepairReqList(pageQuery.build(), buildWrapper(bo));
        return TableDataInfo.build(page);
    }
    private QueryWrapper<EimsRepairReq> buildWrapper(EimsRepairReqBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<EimsRepairReq> qw = Wrappers.query();
        qw.eq(StringUtils.isNotBlank(bo.getCode()),"code", bo.getCode());
        qw.eq(StringUtils.isNotBlank(bo.getStatus()), "status", bo.getStatus());
        qw.eq(bo.getReqTime() != null, "req_time", bo.getReqTime());
        qw.eq(bo.getReqDept() != null, "req_dept", bo.getReqDept());
        qw.eq(bo.getReqUser() != null,"req_user", bo.getReqUser());
        qw.eq(StringUtils.isNotBlank(bo.getUrgencyLevel()), "urgency_level", bo.getUrgencyLevel());
        qw.eq(StringUtils.isNotBlank(bo.getReqType()), "req_type", bo.getReqType());
        qw.eq(bo.getEquId() != null, "equ_id", bo.getEquId());
        qw.eq(bo.getRepairDept() != null,"repair_dept", bo.getRepairDept());
        qw.eq(bo.getRepairUser() != null, "repair_user", bo.getRepairUser());
        qw.eq(StringUtils.isNotBlank(bo.getFaultType()), "fault_type", bo.getFaultType());
        qw.between(params.get("beginReqTime") != null && params.get("endReqTime") != null,
            "req_time", params.get("beginReqTime"), params.get("endReqTime"));
        return qw;
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„æ•…障报修列表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return æ•…障报修列表
     */
    @Override
    public List<EimsRepairReqVo> queryList(EimsRepairReqBo bo) {
        LambdaQueryWrapper<EimsRepairReq> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    private LambdaQueryWrapper<EimsRepairReq> buildQueryWrapper(EimsRepairReqBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<EimsRepairReq> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), EimsRepairReq::getCode, bo.getCode());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsRepairReq::getStatus, bo.getStatus());
        lqw.eq(bo.getReqTime() != null, EimsRepairReq::getReqTime, bo.getReqTime());
        lqw.eq(bo.getReqDept() != null, EimsRepairReq::getReqDept, bo.getReqDept());
        lqw.eq(bo.getReqUser() != null, EimsRepairReq::getReqUser, bo.getReqUser());
        lqw.eq(StringUtils.isNotBlank(bo.getUrgencyLevel()), EimsRepairReq::getUrgencyLevel, bo.getUrgencyLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getReqType()), EimsRepairReq::getReqType, bo.getReqType());
        lqw.eq(bo.getEquId() != null, EimsRepairReq::getEquId, bo.getEquId());
        lqw.eq(bo.getRepairDept() != null, EimsRepairReq::getRepairDept, bo.getRepairDept());
        lqw.eq(bo.getRepairUser() != null, EimsRepairReq::getRepairUser, bo.getRepairUser());
        lqw.eq(StringUtils.isNotBlank(bo.getFaultType()), EimsRepairReq::getFaultType, bo.getFaultType());
        return lqw;
    }
    /**
     * æ–°å¢žæ•…障报修
     *
     * @param bo æ•…障报修
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public Boolean insertByBo(EimsRepairReqBo bo) {
        EimsRepairReq add = MapstructUtils.convert(bo, EimsRepairReq.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }
    /**
     * ä¿®æ”¹æ•…障报修
     *
     * @param bo æ•…障报修
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @Override
    public Boolean updateByBo(EimsRepairReqBo bo) {
        EimsRepairReq update = MapstructUtils.convert(bo, EimsRepairReq.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
    /**
     * ä¿å­˜å‰çš„æ•°æ®æ ¡éªŒ
     */
    private void validEntityBeforeSave(EimsRepairReq entity){
        //TODO åšä¸€äº›æ•°æ®æ ¡éªŒ,如唯一约束
    }
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤æ•…障报修信息
     *
     * @param ids     å¾…删除的主键集合
     * @param isValid æ˜¯å¦è¿›è¡Œæœ‰æ•ˆæ€§æ ¡éªŒ
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO åšä¸€äº›ä¸šåŠ¡ä¸Šçš„æ ¡éªŒ,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsRepairReqMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?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.EimsRepairReqMapper">
    <resultMap type="org.dromara.eims.domain.vo.EimsRepairReqVo" id="EimsRepairReqResult">
    </resultMap>
    <select id="selectRepairReqList" resultMap="EimsRepairReqResult">
        SELECT a.*,
               b.equ_code  equCode,
               b.asset_no  assetNo,
               b.equ_name  equName,
               b.location  equLocation,
               c.type_name equTypeName
        FROM eims_repair_req a
                 LEFT JOIN eims_equ b on a.equ_id = b.equ_id
                 LEFT JOIN eims_equ_type c on b.equ_type_id = c.equ_type_id
            ${ew.getCustomSqlSegment}
    </select>
</mapper>