From f9a12ecb4ea4b7b103b50634335704140237fef7 Mon Sep 17 00:00:00 2001
From: 朱桂飞 <zhuguifei@zhuguifeideMacBook-Air.local>
Date: 星期三, 19 二月 2025 15:11:28 +0800
Subject: [PATCH] 完成工具借用、归还相关

---
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java       |    1 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixtureBorrow.java                  |   88 ++
 eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue                                      |   43 +
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureBorrowVo.java             |  127 +++
 eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx                                                  |    9 
 eims-ui/apps/web-antd/src/views/eims/fixture-borrow/fixture-borrow-drawer.vue                            |  242 ++++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBorrowBo.java             |   95 ++
 eims-ui/apps/web-antd/src/views/eims/fixture-borrow/data.tsx                                             |  234 ++++++
 eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/index.vue                                         |   17 
 eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts                                            |    4 
 eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts                                 |    2 
 eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx                                                    |   28 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureBorrowService.java         |   68 +
 eims-ui/apps/web-antd/src/views/eims/fixture/index.vue                                                   |   84 +
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/utils/DataFilterUtil.java                      |   42 +
 eims-ui/apps/web-antd/src/api/eims/fixture-borrow/model.d.ts                                             |   66 +
 eims-ui/apps/web-antd/src/views/eims/fixture-borrow/index.vue                                            |  237 ++++++
 eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFixtureBorrowMapper.xml                    |    7 
 eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/type.js                                           |    0 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureBorrowServiceImpl.java |  211 ++++++
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java                   |   13 
 eims-ui/apps/web-antd/src/api/eims/fixture-borrow/index.ts                                               |   62 +
 eims-ui/apps/web-antd/src/views/eims/components/fixture-modal.vue                                        |   49 +
 eims-ui/apps/web-antd/src/views/eims/equ-trial/index.vue                                                 |    9 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureBorrowController.java    |  105 +++
 eims-ui/apps/web-antd/src/views/eims/equ-trial/data.tsx                                                  |    9 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java                   |   13 
 eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue                                                |    5 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureBorrowMapper.java            |   15 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java                        |   10 
 eims-ui/apps/web-antd/src/views/eims/equ-statu/index.vue                                                 |    3 
 eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue                                          |    2 
 eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/data.tsx                                          |   91 ++
 eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue                                      |   49 
 eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java     |   60 +
 35 files changed, 2,043 insertions(+), 57 deletions(-)

diff --git a/eims-ui/apps/web-antd/src/api/eims/fixture-borrow/index.ts b/eims-ui/apps/web-antd/src/api/eims/fixture-borrow/index.ts
new file mode 100644
index 0000000..84042b3
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/api/eims/fixture-borrow/index.ts
@@ -0,0 +1,62 @@
+import type { IDS, PageQuery, PageResult } from '#/api/common';
+import type { FixBorrowVO } from '#/api/eims/fixture-borrow/model';
+
+import { commonExport } from '#/api/helper';
+import { requestClient } from '#/api/request';
+
+enum Api {
+  fixBorrowExport = '/eims/fixBorrow/export',
+  fixBorrowImport = '/eims/fixBorrow/importData',
+  fixBorrowList = '/eims/fixBorrow/list',
+  root = '/eims/fixBorrow'
+}
+
+/**
+ * 鏌ヨ銆愬伐鍏峰�熺敤銆戝垪琛�
+ * @param query
+ * @returns {*}
+ */
+
+export function listFixBorrow(params?: PageQuery) {
+  return requestClient.get<PageResult<FixBorrowVO>>(Api.fixBorrowList, { params });
+}
+
+/**
+ * 鏌ヨ銆愬伐鍏峰�熺敤銆戣缁�
+ * @param fixId
+ */
+export function getFixBorrow(fixId: any) {
+  return requestClient.get<FixBorrowVO>(`${Api.root}/${fixId}`);
+}
+
+/**
+ * 鏂板銆愬伐鍏峰�熺敤銆�
+ * @param data
+ */
+export function addFixBorrow(data: any) {
+  return requestClient.postWithMsg<void>(Api.root, data);
+}
+
+/**
+ * 淇敼銆愬伐鍏峰�熺敤銆�
+ * @param data
+ */
+export function updateFixBorrow(data: any) {
+  return requestClient.putWithMsg<void>(Api.root, data);
+}
+
+/**
+ * 鍒犻櫎銆愬伐鍏峰�熺敤銆�
+ * @param fixIds
+ */
+export function delFixBorrow(fixIds: IDS) {
+  return requestClient.deleteWithMsg<void>(`${Api.root}/${fixIds}`);
+}
+
+/**
+ * 瀵煎嚭銆愬伐鍏峰�熺敤銆�
+ * @param data
+ */
+export function fixBorrowExport(data: any) {
+  return commonExport(Api.fixBorrowExport, data);
+}
diff --git a/eims-ui/apps/web-antd/src/api/eims/fixture-borrow/model.d.ts b/eims-ui/apps/web-antd/src/api/eims/fixture-borrow/model.d.ts
new file mode 100644
index 0000000..1d796fe
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/api/eims/fixture-borrow/model.d.ts
@@ -0,0 +1,66 @@
+export interface FixBorrowVO {
+  /**
+   *
+   */
+  id: number | string;
+
+  /**
+   * 鍊熺敤宸ュ叿id
+   */
+  fixtureId: number | string;
+
+  /**
+   * 鍊熺敤宸ュ叿鍚嶇О
+   */
+  fixtureName: string;
+
+  /**
+   * 鍊熺敤閮ㄩ棬
+   */
+  borrowDept: number;
+
+  /**
+   * 鍊熺敤浜�
+   */
+  borrowUser: number;
+
+  /**
+   * 缁忓姙浜�
+   */
+  agentUser: number;
+
+  /**
+   * 缁忓姙浜�
+   */
+  agentUserName: string;
+
+  /**
+   * 鍊熺敤璁板綍鐘舵�侊紙瀛楀吀锛�
+   */
+  status: string;
+
+  /**
+   * 鍊熺敤鏃堕棿
+   */
+  borrowTime: string;
+
+  /**
+   * 棰勮褰掕繕鏃堕棿
+   */
+  planReturnTime: string;
+
+  /**
+   * 褰掕繕鏃堕棿
+   */
+  returnTime: string;
+
+  /**
+   * 鍊熺敤鐞嗙敱
+   */
+  borrowReason: string;
+
+  /**
+   * 澶囨敞
+   */
+  remark: string;
+}
diff --git a/eims-ui/apps/web-antd/src/views/eims/components/fixture-modal.vue b/eims-ui/apps/web-antd/src/views/eims/components/fixture-modal.vue
new file mode 100644
index 0000000..1f38600
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/components/fixture-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 InnerView from '#/views/eims/fixture/index.vue';
+
+const emit = defineEmits<{ updateSelect: [any] }>();
+
+const [BasicModal, modalApi] = useVbenModal({
+  fullscreenButton: false,
+  draggable: true,
+  onCancel: handleCancel,
+  onConfirm: handleConfirm
+});
+const innerView = ref();
+
+async function handleConfirm() {
+  try {
+    modalApi.modalLoading(true);
+    const tableSelect = innerView.value.tableSelect();
+    if (tableSelect.length > 1) {
+      message.error('鏈�澶氬彧鑳介�夋嫨涓�涓伐鍏凤紒');
+      modalApi.modalLoading(false);
+      return false;
+    }
+    emit('updateSelect', 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]">
+    <InnerView ref="innerView" />
+  </BasicModal>
+</template>
+
+<style scoped></style>
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx b/eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx
index 3f9bed4..8bb9259 100644
--- a/eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-statu/data.tsx
@@ -101,7 +101,16 @@
       allowClear: true,
       getPopupContainer
     },
+    dependencies: {
+      show: () => false,
+      triggerFields: ['']
+    },
     fieldName: 'equId',
+    label: '璁惧id'
+  },
+  {
+    component: 'Input',
+    fieldName: 'equName',
     label: '璁惧鍚嶇О'
   },
   {
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue b/eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue
index 590f7a9..a541d60 100644
--- a/eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-statu/equ-statu-drawer.vue
@@ -1,14 +1,17 @@
 <script setup lang="ts">
 import { computed, ref } from 'vue';
 
-import { useVbenDrawer } from '@vben/common-ui';
+import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
 import { $t } from '@vben/locales';
 import { addFullName, cloneDeep, getPopupContainer } from '@vben/utils';
+
+import { InputSearch } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import { listEqu } from '#/api/eims/equ';
 import { addEquStatu, getEquStatu, updateEquStatu } from '#/api/eims/equ-statu';
 import { getDeptTree, userList } from '#/api/system/user';
+import equModal from '#/views/eims/components/equ-modal.vue';
 
 import { drawerSchema } from './data';
 
@@ -46,31 +49,14 @@
     // 鍒濆鍖�
     await setupEquSelect();
     await setupDeptSelect();
-
-    // 璁惧璇︽儏椤垫墦寮�鎸囧畾璁惧id
-    const { equId } = drawerApi.getData() as { equId?: number | string };
-    if (equId) {
-      await formApi.setValues({ equId});
-    }
     // 鏇存柊 && 璧嬪��
     if (isUpdate.value && id) {
       const record = await getEquStatu(id);
       await formApi.setValues(record);
-      if(isUpdate.value && record.userDept){
+      if (isUpdate.value && record.userDept) {
         await setupUserOptions(record.userDept);
       }
     }
-    // 璁惧id鏈夊�兼椂涓嶅厑璁哥紪杈戯紙1.缂栬緫 2.璁惧璇︽儏椤垫墦寮�锛�
-    const flag = equId !== undefined || isUpdate.value;
-    formApi.updateSchema([
-      {
-        componentProps: {
-          disabled: flag
-        },
-        fieldName: 'equId'
-      }
-    ]);
-
     drawerApi.drawerLoading(false);
   }
 });
@@ -78,7 +64,7 @@
 async function setupEquSelect() {
   const equPageResult = await listEqu({
     pageNum: 1,
-    pageSize: 1000,
+    pageSize: 1000
   });
   // 浣跨敤map鏉ヨ窡韪凡缁忛亣鍒扮殑equId锛屼娇鐢╢ilter鏉ヨ繃婊ゆ帀閲嶅鐨勫厓绱犮��
   const uniqueItems = equPageResult.rows.filter((item, index, self) => index === self.findIndex((tm) => tm.equId === item.equId));
@@ -200,10 +186,31 @@
   drawerApi.close();
   await formApi.resetForm();
 }
+
+// EQU modal
+const [EquModal, equModalApi] = useVbenModal({
+  connectedComponent: equModal,
+  draggable: true,
+  title: '閫夋嫨鎴愬憳'
+});
+
+function handleEquModal() {
+  equModalApi.setData({});
+  equModalApi.open();
+}
+
+async function selectEqu(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 />
+    <BasicForm>
+      <template #equName="slotProps">
+        <InputSearch :enter-button="true" placeholder="璇烽�夋嫨" @search="handleEquModal" v-bind="slotProps" />
+      </template>
+    </BasicForm>
+    <EquModal :disabled="true" class="w-[1200px]" @update-equ="selectEqu" />
   </BasicDrawer>
 </template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-statu/index.vue b/eims-ui/apps/web-antd/src/views/eims/equ-statu/index.vue
index 6cd3155..9ec0b1d 100644
--- a/eims-ui/apps/web-antd/src/views/eims/equ-statu/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-statu/index.vue
@@ -52,6 +52,9 @@
   height: 'auto',
   keepSource: true,
   pagerConfig: {},
+  toolbarConfig: {
+    enabled: !props.equDetailFlag
+  },
   proxyConfig: {
     ajax: {
       query: async ({ page }, formValues = {}) => {
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-trial/data.tsx b/eims-ui/apps/web-antd/src/views/eims/equ-trial/data.tsx
index 087fc37..87f99a5 100644
--- a/eims-ui/apps/web-antd/src/views/eims/equ-trial/data.tsx
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-trial/data.tsx
@@ -121,7 +121,16 @@
       allowClear: true,
       getPopupContainer
     },
+    dependencies: {
+      show: () => false,
+      triggerFields: ['']
+    },
     fieldName: 'equId',
+    label: '璁惧id'
+  },
+  {
+    component: 'Input',
+    fieldName: 'equName',
     label: '璁惧鍚嶇О'
   },
   {
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue b/eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue
index 48643ce..99daa05 100644
--- a/eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-trial/equ-trial-drawer.vue
@@ -1,14 +1,17 @@
 <script setup lang="ts">
 import { computed, ref } from 'vue';
 
-import { useVbenDrawer } from '@vben/common-ui';
+import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
 import { $t } from '@vben/locales';
 import { addFullName, cloneDeep, getPopupContainer } from '@vben/utils';
+
+import { InputSearch, Modal } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import { listEqu } from '#/api/eims/equ';
 import { addEquTrial, getEquTrial, updateEquTrial } from '#/api/eims/equ-trial';
 import { getDeptTree, userList } from '#/api/system/user';
+import equModal from '#/views/eims/components/equ-modal.vue';
 
 import { drawerSchema } from './data';
 
@@ -54,7 +57,7 @@
     if (isUpdate.value && id) {
       const record = await getEquTrial(id);
       await formApi.setValues(record);
-      if(isUpdate.value && record.operatorDept){
+      if (isUpdate.value && record.operatorDept) {
         await setupUserOptions(record.operatorDept);
       }
     }
@@ -172,6 +175,7 @@
     }
   ]);
 }
+
 async function handleConfirm() {
   try {
     drawerApi.drawerLoading(true);
@@ -194,10 +198,43 @@
   drawerApi.close();
   await formApi.resetForm();
 }
+
+// EQU modal
+const [EquModal, equModalApi] = useVbenModal({
+  connectedComponent: equModal,
+  draggable: true,
+  title: '閫夋嫨鎴愬憳'
+});
+
+function handleEquModal() {
+  equModalApi.setData({});
+  equModalApi.open();
+}
+
+async function selectEqu(equ: any) {
+  // TODO 纭畾涓庡瓧鍏稿搴攕ys_equ_status
+  if (equ.status !== null && equ.status === '0') {
+    await formApi.setValues({ 'equId': equ.equId, 'equName': equ.equName });
+  } else {
+    Modal.confirm({
+      title: '鎻愮ず',
+      okType: 'danger',
+      content: `褰撳墠璁惧鐘舵�佷笉灞炰簬璇曠敤璁惧锛岀‘璁ゆ坊鍔犲悧锛焋,
+      onOk: async () => {
+        await formApi.setValues({ 'equId': equ.equId, 'equName': equ.equName });
+      }
+    });
+  }
+}
 </script>
 
 <template>
   <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
-    <BasicForm />
+    <BasicForm>
+      <template #equName="slotProps">
+        <InputSearch :enter-button="true" placeholder="璇烽�夋嫨" @search="handleEquModal" v-bind="slotProps" />
+      </template>
+    </BasicForm>
+    <EquModal :disabled="true" class="w-[1200px]" @update-equ="selectEqu" />
   </BasicDrawer>
 </template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/equ-trial/index.vue b/eims-ui/apps/web-antd/src/views/eims/equ-trial/index.vue
index 3534a0c..d914f91 100644
--- a/eims-ui/apps/web-antd/src/views/eims/equ-trial/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/equ-trial/index.vue
@@ -52,6 +52,9 @@
   height: 'auto',
   keepSource: true,
   pagerConfig: {},
+  toolbarConfig: {
+    enabled: !props.equDetailFlag
+  },
   proxyConfig: {
     ajax: {
       query: async ({ page }, formValues = {}) => {
@@ -77,7 +80,7 @@
     // 杩滅▼鎺掑簭
     remote: true,
     // 鏀寔澶氬瓧娈垫帓搴� 榛樿鍏抽棴
-    multiple: true,
+    multiple: true
   },
   id: 'eims-equ-trial-index'
 };
@@ -86,8 +89,8 @@
   formOptions,
   gridOptions,
   gridEvents: {
-    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams),
-  },
+    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
+  }
 });
 
 const [EquTrialDrawer, equTrialDrawerApi] = useVbenDrawer({
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/data.tsx b/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/data.tsx
new file mode 100644
index 0000000..8edf2c8
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/data.tsx
@@ -0,0 +1,234 @@
+import type { VxeGridProps } from '#/adapter/vxe-table';
+
+import { DictEnum } from '@vben/constants';
+import { getPopupContainer } from '@vben/utils';
+
+import { type FormSchemaGetter } from '#/adapter/form';
+import { getDictOptions } from '#/utils/dict';
+import { renderDict } from '#/utils/render';
+
+export const querySchema: FormSchemaGetter = () => [
+  {
+    component: 'Input',
+    fieldName: 'fixtureName',
+    label: '宸ュ叿鍚嶇О'
+  },
+  {
+    component: 'TreeSelect',
+    // 鍦╠rawer閲屾洿鏂� 杩欓噷涓嶉渶瑕侀粯璁ょ殑componentProps
+    defaultValue: undefined,
+    fieldName: 'borrowDept',
+    label: '鍊熺敤閮ㄩ棬'
+  },
+  {
+    component: 'Select',
+    componentProps: {
+      showSearch: true,
+      allowClear: true,
+      getPopupContainer
+    },
+    fieldName: 'borrowUser',
+    label: '鍊熺敤浜�'
+  },
+  {
+    component: 'Select',
+    componentProps: {
+      options: getDictOptions(DictEnum.FIXTURE_BORROW_RECORD_STATUS)
+    },
+    fieldName: 'status',
+    label: '鍊熺敤鐘舵��'
+  },
+  {
+    component: 'RangePicker',
+    fieldName: 'borrowTime',
+    label: '鍊熺敤鏃堕棿'
+  }
+];
+
+export const columns: VxeGridProps['columns'] = [
+  { type: 'checkbox', width: 60, fixed: 'left' },
+  {
+    title: '宸ュ叿鍚嶇О',
+    field: 'fixtureName',
+    minWidth: 100,
+    fixed: 'left',
+    slots: { default: 'fixtureName' }
+  },
+  {
+    title: '鍊熺敤鐘舵��',
+    field: 'status',
+    sortable: true,
+    slots: {
+      default: ({ row }) => {
+        if (row.status === null || row.status === '') {
+          return '';
+        }
+        return renderDict(row.status, DictEnum.FIXTURE_BORROW_RECORD_STATUS);
+      }
+    },
+    minWidth: 100,
+    fixed: 'left'
+  },
+  {
+    title: '鍊熺敤閮ㄩ棬',
+    field: 'borrowDeptName',
+    minWidth: 120
+  },
+  {
+    title: '鍊熺敤浜�',
+    field: 'borrowUserName',
+    minWidth: 100
+  },
+  {
+    title: '缁忓姙浜�',
+    field: 'agentUserName',
+    minWidth: 100
+  },
+  {
+    title: '鍊熺敤鏃堕棿',
+    field: 'borrowTime',
+    minWidth: 120
+  },
+  {
+    title: '鍊熺敤鍘熷洜',
+    field: 'borrowReason',
+    minWidth: 140
+  },
+  {
+    title: '棰勮褰掕繕鏃堕棿',
+    field: 'planReturnTime',
+    minWidth: 160
+  },
+  {
+    title: '瀹為檯褰掕繕鏃堕棿',
+    field: 'returnTime',
+    minWidth: 160
+  },
+  {
+    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: {
+      showSearch: true,
+      allowClear: true,
+      getPopupContainer
+    },
+    dependencies: {
+      show: () => false,
+      triggerFields: ['']
+    },
+    fieldName: 'fixtureId',
+    label: '宸ュ叿id',
+    rules: 'required'
+  },
+  {
+    component: 'Input',
+    fieldName: 'fixtureName',
+    label: '宸ュ叿鍚嶇О',
+    rules: 'required'
+  },
+  {
+    component: 'TreeSelect',
+    // 鍦╠rawer閲屾洿鏂� 杩欓噷涓嶉渶瑕侀粯璁ょ殑componentProps
+    defaultValue: undefined,
+    fieldName: 'borrowDept',
+    label: '鍊熺敤閮ㄩ棬',
+    rules: 'selectRequired'
+  },
+  {
+    component: 'Select',
+    componentProps: {
+      showSearch: true,
+      allowClear: true,
+      getPopupContainer
+    },
+    fieldName: 'borrowUser',
+    label: '鍊熺敤浜�',
+    rules: 'required'
+  },
+  {
+    component: 'Select',
+    componentProps: {
+      showSearch: true,
+      allowClear: true,
+      getPopupContainer
+    },
+    fieldName: 'agentUser',
+    dependencies: {
+      show: () => false,
+      triggerFields: ['']
+    },
+    label: '缁忓姙浜�'
+  },
+  {
+    component: 'Input',
+    fieldName: 'agentUserName',
+    label: '缁忓姙浜�',
+  },
+  {
+    component: 'RadioGroup',
+    componentProps: {
+      buttonStyle: 'solid',
+      options: getDictOptions(DictEnum.FIXTURE_BORROW_RECORD_STATUS),
+      optionType: 'button'
+    },
+    defaultValue: '0',
+    fieldName: 'status',
+    label: '鍊熺敤鐘舵��'
+  },
+  {
+    component: 'DatePicker',
+    componentProps: {
+      format: 'YYYY-MM-DD HH:mm:ss',
+      showTime: true,
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      getPopupContainer
+    },
+    fieldName: 'borrowTime',
+    label: '鍊熺敤鏃堕棿'
+  },
+  {
+    component: 'Textarea',
+    formItemClass: 'items-baseline',
+    fieldName: 'borrowReason',
+    label: '鍊熺敤鍘熷洜'
+  },
+  {
+    component: 'DatePicker',
+    componentProps: {
+      format: 'YYYY-MM-DD HH:mm:ss',
+      showTime: true,
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      getPopupContainer
+    },
+    fieldName: 'planReturnTime',
+    label: '棰勮褰掕繕鏃堕棿'
+  },
+  {
+    component: 'DatePicker',
+    componentProps: {
+      format: 'YYYY-MM-DD HH:mm:ss',
+      showTime: true,
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      getPopupContainer
+    },
+    fieldName: 'returnTime',
+    label: '瀹為檯褰掕繕鏃堕棿'
+  }
+];
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/fixture-borrow-drawer.vue b/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/fixture-borrow-drawer.vue
new file mode 100644
index 0000000..564077c
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/fixture-borrow-drawer.vue
@@ -0,0 +1,242 @@
+<script setup lang="ts">
+import { computed, ref } from 'vue';
+
+import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
+import { $t } from '@vben/locales';
+import { addFullName, cloneDeep, getPopupContainer } from '@vben/utils';
+
+import { InputSearch } from 'ant-design-vue';
+
+import { useVbenForm } from '#/adapter/form';
+import { addFixBorrow, getFixBorrow, updateFixBorrow } from '#/api/eims/fixture-borrow';
+import { userProfile } from '#/api/system/profile';
+import { getDeptTree, userList } from '#/api/system/user';
+import fixModal from '#/views/eims/components/fixture-modal.vue';
+import userModal from '#/views/eims/components/user-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;
+    // 鍒濆鍖�
+    await setupDeptSelect();
+
+    // 浠庡伐鍏峰彴璐﹂〉闈㈡墦寮�鐗规畩澶勭悊
+    const { fixturePage } = drawerApi.getData() as { fixturePage?: boolean };
+    if (fixturePage) {
+      formApi.updateSchema([
+        {
+          componentProps: {
+            disabled: false
+          },
+          fieldName: 'fixtureName'
+        }
+      ]);
+      await updateCustomData(drawerApi.getData());
+    }
+
+    formApi.updateSchema([
+      {
+        componentProps: {
+          disabled: isUpdate.value || fixturePage
+        },
+        fieldName: 'fixtureName'
+      }
+    ]);
+    // 鏇存柊 && 璧嬪��
+    if (isUpdate.value && id) {
+      const record = await getFixBorrow(id);
+      await formApi.setValues(record);
+      if (isUpdate.value && record.borrowDept) {
+        await setupUserOptions(record.borrowDept);
+      }
+    }
+
+    drawerApi.drawerLoading(false);
+  }
+});
+
+/**
+ * 浠庤澶囧彴璐﹂〉闈㈡墦寮�鏇存柊閮ㄥ垎鏁版嵁
+ * @param data
+ */
+async function updateCustomData(data: any) {
+  const resp = await userProfile();
+  const deptId = resp?.user?.deptId;
+  await setupUserOptions(deptId);
+  data.borrowDept = deptId;
+  await formApi.setValues(data);
+}
+
+/**
+ * 鐢ㄦ埛鐨勫姞杞�
+ */
+async function setupUserOptions(deptId: any) {
+  const params = { deptId };
+  const userPageResult = await userList({
+    pageNum: 1,
+    pageSize: 500,
+    ...params
+  });
+  const options = userPageResult.rows.map((item) => ({
+    label: item.nickName || item.userName,
+    value: item.userId
+  }));
+  // 绛涢��
+  const filterOption = (input: string, option: any) => {
+    return option.label.toLowerCase().includes(input.toLowerCase());
+  };
+
+  const placeholder = options.length > 0 ? '璇烽�夋嫨' : '璇ラ儴闂ㄤ笅鏆傛棤鐢ㄦ埛';
+  formApi.updateSchema([
+    {
+      componentProps: { options, placeholder, filterOption },
+      fieldName: 'borrowUser'
+    }
+  ]);
+}
+
+/**
+ * 鍒濆鍖栭儴闂ㄩ�夋嫨
+ */
+async function setupDeptSelect() {
+  // updateSchema
+  const deptTree = await getDeptTree();
+  // 閫変腑鍚庢樉绀哄湪杈撳叆妗嗙殑鍊� 鍗崇埗鑺傜偣 / 瀛愯妭鐐�
+  addFullName(deptTree, 'label', ' / ');
+  formApi.updateSchema([
+    {
+      componentProps: (formModel) => ({
+        class: 'w-full',
+        fieldNames: {
+          key: 'id',
+          value: 'id',
+          children: 'children'
+        },
+        getPopupContainer,
+        async onSelect(deptId: number | string) {
+          /** 鏍规嵁閮ㄩ棬ID鍔犺浇鐢ㄦ埛 */
+          await setupUserOptions(deptId);
+          /** 鍙樺寲鍚庨渶瑕侀噸鏂伴�夋嫨鐢ㄦ埛 */
+          formModel.operatorId = undefined;
+        },
+        placeholder: '璇烽�夋嫨',
+        showSearch: true,
+        treeData: deptTree,
+        treeDefaultExpandAll: true,
+        treeLine: { showLeafIcon: false },
+        // 绛涢�夌殑瀛楁
+        treeNodeFilterProp: 'label',
+        // 閫変腑鍚庢樉绀哄湪杈撳叆妗嗙殑鍊�
+        treeNodeLabelProp: 'fullName'
+      }),
+      fieldName: 'borrowDept'
+    }
+  ]);
+}
+async function handleConfirm() {
+  try {
+    drawerApi.drawerLoading(true);
+    const { valid } = await formApi.validate();
+    if (!valid) {
+      return;
+    }
+    const data = cloneDeep(await formApi.getValues());
+    await (isUpdate.value ? updateFixBorrow(data) : addFixBorrow(data));
+    emit('reload');
+    await handleCancel();
+  } catch (error) {
+    console.error(error);
+  } finally {
+    drawerApi.drawerLoading(false);
+  }
+}
+
+async function handleCancel() {
+  drawerApi.close();
+  await formApi.resetForm();
+}
+
+// user modal
+const [UserModal, userModalApi] = useVbenModal({
+  connectedComponent: userModal,
+  draggable: true,
+  title: '閫夋嫨鎴愬憳'
+});
+
+function handleUserModal() {
+  userModalApi.setData({});
+  userModalApi.open();
+}
+
+/**
+ * 鏇存柊閫夋嫨鐨勬垚鍛�
+ * @param user
+ */
+async function selectUser(user: any) {
+  await formApi.setValues({ 'agentUser': user.userId, 'agentUserName': user.nickName });
+}
+
+// user modal
+const [FixModal, fixModalApi] = useVbenModal({
+  connectedComponent: fixModal,
+  draggable: true,
+  title: '閫夋嫨宸ュ叿'
+});
+
+function handleFixModal() {
+  fixModalApi.setData({});
+  fixModalApi.open();
+}
+
+/**
+ * 鏇存柊閫夋嫨鐨勫伐鍏�
+ * @param fix
+ */
+async function selectFix(fix: any) {
+  await formApi.setValues({ 'fixtureId': fix.id, 'fixtureName': fix.fixtureName });
+}
+</script>
+
+<template>
+  <BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
+    <BasicForm>
+      <template #agentUserName="slotProps">
+        <InputSearch :enter-button="true" placeholder="璇烽�夋嫨" @search="handleUserModal" v-bind="slotProps" />
+      </template>
+      <template #fixtureName="slotProps">
+        <InputSearch :enter-button="true" placeholder="璇烽�夋嫨" @search="handleFixModal" v-bind="slotProps" />
+      </template>
+    </BasicForm>
+    <UserModal class="w-[1200px]" @select-user="selectUser" />
+    <FixModal class="w-[1200px]" @update-select="selectFix" />
+  </BasicDrawer>
+</template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/index.vue b/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/index.vue
new file mode 100644
index 0000000..92bcc07
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture-borrow/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 { delFixBorrow, fixBorrowExport, listFixBorrow } from '#/api/eims/fixture-borrow';
+import { getDeptTree, userList } from '#/api/system/user';
+import { commonDownloadExcel } from '#/utils/file/download';
+
+import { columns, querySchema } from './data';
+import fixBorrowDrawer from './fixture-borrow-drawer.vue';
+
+const formOptions: VbenFormProps = {
+  commonConfig: {
+    labelWidth: 80,
+    componentProps: {
+      allowClear: true
+    }
+  },
+  schema: querySchema(),
+  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
+  // 鏃ユ湡閫夋嫨鏍煎紡鍖�
+  fieldMappingTime: [
+    ['borrowTime', ['params[beginBorrowTime]', 'params[endBorrowTime]'], ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59']],
+    ['planReturnTime', ['params[beginPlanReturnTime]', 'params[endPlanReturnTime]'], ['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 listFixBorrow({
+          pageNum: page.currentPage,
+          pageSize: page.pageSize,
+          ...formValues
+        });
+      }
+    }
+  },
+  rowConfig: {
+    isHover: true,
+    keyField: 'id'
+  },
+  sortConfig: {
+    // 杩滅▼鎺掑簭
+    remote: true,
+    // 鏀寔澶氬瓧娈垫帓搴� 榛樿鍏抽棴
+    multiple: true
+  },
+  id: 'fixture-borrow-index'
+};
+
+const [BasicTable, tableApi] = useVbenVxeGrid({
+  formOptions,
+  gridOptions,
+  gridEvents: {
+    sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams)
+  }
+});
+
+const [FixBorrowDrawer, fixBorrowDrawerApi] = useVbenDrawer({
+  connectedComponent: fixBorrowDrawer
+});
+
+function handleAdd() {
+  fixBorrowDrawerApi.setData({});
+  fixBorrowDrawerApi.open();
+}
+
+async function handleEdit(record: Recordable<any>) {
+  fixBorrowDrawerApi.setData({ id: record.id });
+  fixBorrowDrawerApi.open();
+}
+
+async function handleDelete(row: Recordable<any>) {
+  await delFixBorrow(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 delFixBorrow(ids);
+      await tableApi.query();
+    }
+  });
+}
+
+function handleDownloadExcel() {
+  commonDownloadExcel(fixBorrowExport, '宸ュ叿鍊熺敤璁板綍', 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: 'borrowUser'
+    }
+  ]);
+}
+
+/**
+ * 鍒濆鍖栭儴闂ㄩ�夋嫨
+ */
+async function setupDeptSelect() {
+  // updateSchema
+  const deptTree = await getDeptTree();
+  // 閫変腑鍚庢樉绀哄湪杈撳叆妗嗙殑鍊� 鍗崇埗鑺傜偣 / 瀛愯妭鐐�
+  addFullName(deptTree, 'label', ' / ');
+  tableApi.formApi.updateSchema([
+    {
+      componentProps: (formModel) => ({
+        class: 'w-full',
+        fieldNames: {
+          key: 'id',
+          value: 'id',
+          children: 'children'
+        },
+        getPopupContainer,
+        async onSelect(deptId: number | string) {
+          /** 鏍规嵁閮ㄩ棬ID鍔犺浇鐢ㄦ埛 */
+          await setupUserOptions(deptId);
+          /** 鍙樺寲鍚庨渶瑕侀噸鏂伴�夋嫨鐢ㄦ埛 */
+          formModel.inventoryUser = undefined;
+        },
+        placeholder: '璇烽�夋嫨',
+        showSearch: true,
+        treeData: deptTree,
+        treeDefaultExpandAll: true,
+        treeLine: { showLeafIcon: false },
+        // 绛涢�夌殑瀛楁
+        treeNodeFilterProp: 'label',
+        // 閫変腑鍚庢樉绀哄湪杈撳叆妗嗙殑鍊�
+        treeNodeLabelProp: 'fullName'
+      }),
+      fieldName: 'borrowDept'
+    }
+  ]);
+}
+
+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:fixtureBorrow:export']" @click="handleDownloadExcel">
+              {{ $t('pages.common.export') }}
+            </a-button>
+            <a-button
+              :disabled="!vxeCheckboxChecked(tableApi)"
+              danger
+              type="primary"
+              v-access:code="['eims:fixtureBorrow:remove']"
+              @click="handleMultiDelete"
+            >
+              {{ $t('pages.common.delete') }}
+            </a-button>
+            <a-button type="primary" v-access:code="['eims:fixtureBorrow:add']" @click="handleAdd">
+              {{ $t('pages.common.add') }}
+            </a-button>
+          </Space>
+        </template>
+
+        <template #fixtureName="{ row }">
+          <Space>
+            <span>{{ row.fixtureName }}</span>
+          </Space>
+        </template>
+
+        <template #action="{ row }">
+          <Space>
+            <ghost-button v-access:code="['eims:fixtureBorrow: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:fixtureBorrow:remove']" @click.stop="">
+                {{ $t('pages.common.delete') }}
+              </ghost-button>
+            </Popconfirm>
+          </Space>
+        </template>
+      </BasicTable>
+    </div>
+    <FixBorrowDrawer @reload="tableApi.query()" />
+  </Page>
+</template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/data.tsx b/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/data.tsx
new file mode 100644
index 0000000..40bb3eb
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/data.tsx
@@ -0,0 +1,91 @@
+import type { AnalysisOverviewItem,  WorkbenchTrendItem } from '@vben/common-ui';
+
+import { SvgBellIcon, SvgCakeIcon, SvgCardIcon, SvgDownloadIcon } from '@vben/icons';
+
+export const overviewItems: AnalysisOverviewItem[] = [
+  {
+    icon: SvgCardIcon,
+    title: '宸ュ叿鎬绘暟',
+    totalTitle: '宸ュ叿鎬绘暟',
+    totalValue: 120_000,
+    value: 2000
+  },
+  {
+    icon: SvgCakeIcon,
+    title: '鍙敤宸ュ叿鏁�',
+    totalTitle: '鍙敤宸ュ叿鏁�',
+    totalValue: 500_000,
+    value: 20_000
+  },
+  {
+    icon: SvgDownloadIcon,
+    title: '鏈�杩戝�熷嚭',
+    totalTitle: '鏈�杩戝�熷嚭',
+    totalValue: 120_000,
+    value: 8000
+  },
+  {
+    icon: SvgBellIcon,
+    title: '鏈�杩戞洿鏂�',
+    totalTitle: '鏈�杩戞洿鏂�',
+    totalValue: 50_000,
+    value: 5000
+  }
+];
+
+export const trendItems: WorkbenchTrendItem[] = [
+  {
+    avatar: 'svg:avatar-1',
+    content: `鍦� <a>寮�婧愮粍</a> 鍒涘缓浜嗛」鐩� <a>Vue</a>`,
+    date: '鍒氬垰',
+    title: '濞佸粔',
+  },
+  {
+    avatar: 'svg:avatar-2',
+    content: `鍏虫敞浜� <a>濞佸粔</a> `,
+    date: '1涓皬鏃跺墠',
+    title: '鑹炬枃',
+  },
+  {
+    avatar: 'svg:avatar-3',
+    content: `鍙戝竷浜� <a>涓汉鍔ㄦ��</a> `,
+    date: '1澶╁墠',
+    title: '鍏嬮噷鏂�',
+  },
+  {
+    avatar: 'svg:avatar-4',
+    content: `鍙戣〃鏂囩珷 <a>濡備綍缂栧啓涓�涓猇ite鎻掍欢</a> `,
+    date: '2澶╁墠',
+    title: 'Vben',
+  },
+  {
+    avatar: 'svg:avatar-1',
+    content: `鍥炲浜� <a>鏉板厠</a> 鐨勯棶棰� <a>濡備綍杩涜椤圭洰浼樺寲锛�</a>`,
+    date: '3澶╁墠',
+    title: '鐨壒',
+  },
+  {
+    avatar: 'svg:avatar-2',
+    content: `鍏抽棴浜嗛棶棰� <a>濡備綍杩愯椤圭洰</a> `,
+    date: '1鍛ㄥ墠',
+    title: '鏉板厠',
+  },
+  {
+    avatar: 'svg:avatar-3',
+    content: `鍙戝竷浜� <a>涓汉鍔ㄦ��</a> `,
+    date: '1鍛ㄥ墠',
+    title: '濞佸粔',
+  },
+  {
+    avatar: 'svg:avatar-4',
+    content: `鎺ㄩ�佷簡浠g爜鍒� <a>Github</a>`,
+    date: '2021-04-01 20:00',
+    title: '濞佸粔',
+  },
+  {
+    avatar: 'svg:avatar-4',
+    content: `鍙戣〃鏂囩珷 <a>濡備綍缂栧啓浣跨敤 Admin Vben</a> `,
+    date: '2021-03-01 20:00',
+    title: 'Vben',
+  },
+];
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/index.vue b/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/index.vue
new file mode 100644
index 0000000..d114a9a
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/index.vue
@@ -0,0 +1,17 @@
+<script setup lang="ts">
+import { AnalysisOverview, Page, WorkbenchTrends } from '@vben/common-ui';
+
+import { overviewItems, trendItems } from './data';
+</script>
+
+<template>
+  <Page :auto-content-height="true">
+    <div class="h-full">
+      <AnalysisOverview :items="overviewItems" />
+      <WorkbenchTrends :items="trendItems" class="mt-5" title="鏈�鏂板姩鎬�" />
+      <div class="h-5"></div>
+    </div>
+  </Page>
+</template>
+
+<style scoped></style>
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/type.js b/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/type.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture/dashboard/type.js
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx b/eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx
index 8b58bfd..406f76e 100644
--- a/eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture/data.tsx
@@ -27,6 +27,14 @@
     label: '宸ュ叿鐘舵��'
   },
   {
+    component: 'Select',
+    componentProps: {
+      options: getDictOptions(DictEnum.FIXTURE_BORROW_STATUS)
+    },
+    fieldName: 'borrowStatus',
+    label: '鍊熺敤鐘舵��'
+  },
+  {
     component: 'Input',
     fieldName: 'assetNo',
     label: '璧勪骇缂栧彿'
@@ -101,6 +109,21 @@
     fixed: 'left'
   },
   {
+    title: '鍊熺敤鐘舵��',
+    field: 'borrowStatus',
+    sortable: true,
+    slots: {
+      default: ({ row }) => {
+        if (row.borrowStatus === null || row.borrowStatus === '') {
+          return '';
+        }
+        return renderDict(row.borrowStatus, DictEnum.FIXTURE_BORROW_STATUS);
+      }
+    },
+    minWidth: 100,
+    fixed: 'left'
+  },
+  {
     title: '绫诲瀷',
     field: 'fixtureTypeName',
     minWidth: 100
@@ -112,6 +135,11 @@
     minWidth: 140
   },
   {
+    title: '鍊熺敤浜�',
+    field: 'borrowUserName',
+    minWidth: 100
+  },
+  {
     title: '宸ュ叿缂栫爜',
     field: 'fixtureCode',
     sortable: true,
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue b/eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue
index f91f8d6..4150940 100644
--- a/eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture/fixture-drawer.vue
@@ -36,8 +36,6 @@
 
 const [BasicDrawer, drawerApi] = useVbenDrawer({
   onCancel: handleCancel,
-  closeOnPressEscape: true,
-  placement: 'left',
   onConfirm: handleConfirm,
   async onOpenChange(isOpen) {
     if (!isOpen) {
diff --git a/eims-ui/apps/web-antd/src/views/eims/fixture/index.vue b/eims-ui/apps/web-antd/src/views/eims/fixture/index.vue
index 76e3dde..022cd7f 100644
--- a/eims-ui/apps/web-antd/src/views/eims/fixture/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/fixture/index.vue
@@ -1,11 +1,12 @@
 <script setup lang="ts">
 import type { Recordable } from '@vben/types';
 
-import { onMounted, ref } from 'vue';
-import { useRouter } from 'vue-router';
+import { computed, onMounted, ref } from 'vue';
 
+import { useAccess } from '@vben/access';
 import { Page, useVbenDrawer, useVbenModal, type VbenFormProps } from '@vben/common-ui';
 import { $t } from '@vben/locales';
+import { useUserStore } from '@vben/stores';
 import { addFullName, getPopupContainer, getVxePopupContainer } from '@vben/utils';
 
 import { Modal, Popconfirm, Space } from 'ant-design-vue';
@@ -14,14 +15,21 @@
 import { delFixture, fixtureExport, listFixture } from '#/api/eims/fixture';
 import { getDeptTree, userList } from '#/api/system/user';
 import { commonDownloadExcel } from '#/utils/file/download';
+import fixtureBorrowDrawer from '#/views/eims/fixture-borrow/fixture-borrow-drawer.vue';
 
 import { columns, querySchema } from './data';
 import fixtureDrawer from './fixture-drawer.vue';
 import fixtureImportModal from './fixture-import-modal.vue';
 import FixtureTypeTree from './fixture-type-tree.vue';
 
+const userStore = useUserStore();
+const userId = userStore.userInfo?.userId;
+
 // 宸﹁竟宸ュ叿绫诲瀷
 const selectTypeId = ref<string[]>([]);
+defineExpose({
+  tableSelect
+});
 
 const formOptions: VbenFormProps = {
   commonConfig: {
@@ -104,6 +112,10 @@
   connectedComponent: fixtureDrawer
 });
 
+const [FixtureBorrowDrawer, fixtureBorrowDrawerApi] = useVbenDrawer({
+  connectedComponent: fixtureBorrowDrawer
+});
+
 /**
  * 瀵煎叆
  */
@@ -143,17 +155,29 @@
     }
   });
 }
-
+function handleBorrow(row: Recordable<any>, status: string) {
+  if (userId === null || userId === undefined || userId === '') {
+    Modal.error({
+      content: '鑾峰彇鐢ㄦ埛淇℃伅澶辫触锛岃閲嶆柊鐧诲綍鍚庨噸璇曪紒',
+      title: '鎻愮ず'
+    });
+    return false;
+  }
+  // 宸ュ叿鍙拌处鍊熺敤鐘舵�乀ODO fixture_borrow_status 0-绌洪棽 1-鍊熷嚭
+  if (status === '0') {
+    // 绌洪棽鏃跺�熷嚭锛屾柊澧炰竴鏉″�熷嚭鏁版嵁
+    fixtureBorrowDrawerApi.setData({ status, borrowUser: userId, fixtureId: row.id, fixtureName: row.fixtureName, fixturePage: true });
+    fixtureBorrowDrawerApi.open();
+  } else if (status === '1') {
+    // 鍊熷嚭鏃跺綊杩橈紝鏇存柊鍊熷嚭鏁版嵁
+    fixtureBorrowDrawerApi.setData({ id: row.curBorrowId });
+    fixtureBorrowDrawerApi.open();
+  }
+}
 function handleDownloadExcel() {
   commonDownloadExcel(fixtureExport, '宸ュ叿鍙拌处', tableApi.formApi.form.values, {
     fieldMappingTime: formOptions.fieldMappingTime
   });
-}
-
-const router = useRouter();
-
-function handleDetail(record: Recordable<any>) {
-  router.push(`/fixture/detail/${record.id}`);
 }
 
 /**
@@ -226,6 +250,30 @@
 onMounted(async () => {
   await setupDeptSelect();
 });
+
+const { hasAccessByRoles } = useAccess();
+const isSuperAdmin = computed(() => hasAccessByRoles(['superadmin']));
+/**
+ * 鍙湁鍊熺敤鐢ㄦ埛鍜岀鐞嗗憳鍙互鐐瑰嚮褰掕繕
+ */
+function isBorrowUser(row: any) {
+  return isSuperAdmin.value || row?.borrowUser === userId;
+}
+
+function isBorrow(row: any) {
+  // TODO 瀵瑰簲瀛楀吀鐘舵�乫ixture_borrow_status 0-绌洪棽 1-鍊熷嚭
+  return row.borrowStatus === '0' || row.borrowStatus === null;
+}
+
+function isReturn(row: any) {
+  // TODO 瀵瑰簲瀛楀吀鐘舵�乫ixture_borrow_status 0-绌洪棽 1-鍊熷嚭
+  return row.borrowStatus === '1';
+}
+
+// 閫変腑鏁版嵁
+function tableSelect() {
+  return tableApi.grid.getCheckboxRecords();
+}
 </script>
 
 <template>
@@ -256,19 +304,20 @@
           </Space>
         </template>
 
-        <template #equName="{ row }">
-          <Space>
-            <a-button type="link" @click="handleDetail(row)"> {{ row.equName }}</a-button>
-          </Space>
-        </template>
-
         <template #action="{ row }">
           <Space>
             <ghost-button v-access:code="['eims:fixture:edit']" @click.stop="handleEdit(row)">
               {{ $t('pages.common.edit') }}
             </ghost-button>
-            <ghost-button v-if="row.menuType !== 'F'" class="btn-success" v-access:code="['eims:fixture:list']" @click="handleDetail(row)">
-              {{ $t('pages.common.info') }}
+            <ghost-button v-if="isBorrow(row)" class="btn-success" v-access:code="['eims:fixture:borrow']" @click="handleBorrow(row, '0')">
+              鍊熺敤
+            </ghost-button>
+            <ghost-button
+              v-else-if="isReturn(row) && isBorrowUser(row)"
+              v-access:code="['eims:fixture:borrow']"
+              @click="handleBorrow(row, '1')"
+            >
+              褰掕繕
             </ghost-button>
             <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="纭鍒犻櫎锛�" @confirm="handleDelete(row)">
               <ghost-button danger v-access:code="['eims:fixture:remove']" @click.stop="">
@@ -280,6 +329,7 @@
       </BasicTable>
     </div>
     <FixtureDrawer @reload="tableApi.query()" />
+    <FixtureBorrowDrawer @reload="tableApi.query()" />
     <FixtureImportModal @reload="tableApi.query()" />
   </Page>
 </template>
diff --git a/eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue b/eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue
index d248376..52487f2 100644
--- a/eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue
+++ b/eims-ui/apps/web-antd/src/views/eims/repair-req/index.vue
@@ -13,7 +13,6 @@
 import { delRepairReq, listRepairReq, repairReqExport } from '#/api/eims/repair-req';
 import { getDeptTree, userList } from '#/api/system/user';
 import { commonDownloadExcel } from '#/utils/file/download';
-import { useRoleBaseFilters } from '#/views/eims/repair-req/use-role-base-filters';
 
 import { columns, querySchema } from './data';
 import repairReqDrawer from './repair-req-drawer.vue';
@@ -51,8 +50,8 @@
         return await listRepairReq({
           pageNum: page.currentPage,
           pageSize: page.pageSize,
-          ...formValues,
-          ...useRoleBaseFilters()
+          ...formValues
+          // ...useRoleBaseFilters()
         });
       }
     }
diff --git a/eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts b/eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts
index 80e948d..f574a24 100644
--- a/eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts
+++ b/eims-ui/apps/web-antd/src/views/eims/repair-req/use-role-base-filters.ts
@@ -22,5 +22,7 @@
   if (repair.value) {
     params.status = '0';
   }
+  console.info('useRoleBaseFilters');
+  console.info(params);
   return { params };
 }
diff --git a/eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts b/eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
index f6546a1..1c0cb60 100644
--- a/eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
+++ b/eims-ui/packages/@core/base/shared/src/constants/dict-enum.ts
@@ -1,9 +1,11 @@
 export enum DictEnum {
   EIMS_EQU_UNIT = 'eims_equ_unit', // 璁惧鐩樼偣鐘舵��
-  EIMS_FIXTURE_STATUS = 'eims_fixture_status', // 璁惧鐩樼偣鐘舵��
+  EIMS_FIXTURE_STATUS = 'eims_fixture_status', // 宸ュ叿锛堟不鍏凤級鐘舵��
   EIMS_INVENTORY_DETAIL_STATU = 'inventory_detail_statu', // 璁惧鐩樼偣鐘舵��
   EIMS_INVENTORY_STATU = 'inventory_statu', // 璁惧鐩樼偣鐘舵��
   EQU_IMPORT_STATU = 'equ_import_status', // 璁惧瀵煎叆鐘舵��
+  FIXTURE_BORROW_RECORD_STATUS = 'fixture_borrow_record_status', // 宸ュ叿锛堟不鍏凤級鍊熺敤璁板綍鐘舵��
+  FIXTURE_BORROW_STATUS = 'fixture_borrow_status', // 宸ュ叿锛堟不鍏凤級鍊熺敤鐘舵��
   REPAIR_FAULT_TYPE = 'repair_fault_type', // 鎶ヤ慨鐘舵��
   REPAIR_REQ_STATUS = 'repair_req_status', // 鎶ヤ慨鐘舵��
   REPAIR_REQ_TYPE = 'repair_req_type', // 鎶ヤ慨绫诲瀷
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureBorrowController.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureBorrowController.java
new file mode 100644
index 0000000..59f2bf9
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsFixtureBorrowController.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.EimsFixtureBorrowVo;
+import org.dromara.eims.domain.bo.EimsFixtureBorrowBo;
+import org.dromara.eims.service.IEimsFixtureBorrowService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 鍊熺敤璁板綍
+ *
+ * @author zhuguifei
+ * @date 2025-02-18
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/eims/fixBorrow")
+public class EimsFixtureBorrowController extends BaseController {
+
+    private final IEimsFixtureBorrowService eimsFixtureBorrowService;
+
+    /**
+     * 鏌ヨ鍊熺敤璁板綍鍒楄〃
+     */
+    @SaCheckPermission("eims:fixtureBorrow:list")
+    @GetMapping("/list")
+    public TableDataInfo<EimsFixtureBorrowVo> list(EimsFixtureBorrowBo bo, PageQuery pageQuery) {
+        return eimsFixtureBorrowService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭鍊熺敤璁板綍鍒楄〃
+     */
+    @SaCheckPermission("eims:fixtureBorrow:export")
+    @Log(title = "鍊熺敤璁板綍", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(EimsFixtureBorrowBo bo, HttpServletResponse response) {
+        List<EimsFixtureBorrowVo> list = eimsFixtureBorrowService.queryList(bo);
+        ExcelUtil.exportExcel(list, "鍊熺敤璁板綍", EimsFixtureBorrowVo.class, response);
+    }
+
+    /**
+     * 鑾峰彇鍊熺敤璁板綍璇︾粏淇℃伅
+     *
+     * @param id 涓婚敭
+     */
+    @SaCheckPermission("eims:fixtureBorrow:query")
+    @GetMapping("/{id}")
+    public R<EimsFixtureBorrowVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+                                     @PathVariable Long id) {
+        return R.ok(eimsFixtureBorrowService.queryById(id));
+    }
+
+    /**
+     * 鏂板鍊熺敤璁板綍
+     */
+    @SaCheckPermission("eims:fixtureBorrow:add")
+    @Log(title = "鍊熺敤璁板綍", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody EimsFixtureBorrowBo bo) {
+        return toAjax(eimsFixtureBorrowService.insertByBo(bo));
+    }
+
+    /**
+     * 淇敼鍊熺敤璁板綍
+     */
+    @SaCheckPermission("eims:fixtureBorrow:edit")
+    @Log(title = "鍊熺敤璁板綍", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody EimsFixtureBorrowBo bo) {
+        return toAjax(eimsFixtureBorrowService.updateByBo(bo));
+    }
+
+    /**
+     * 鍒犻櫎鍊熺敤璁板綍
+     *
+     * @param ids 涓婚敭涓�
+     */
+    @SaCheckPermission("eims:fixtureBorrow:remove")
+    @Log(title = "鍊熺敤璁板綍", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                          @PathVariable Long[] ids) {
+        return toAjax(eimsFixtureBorrowService.deleteWithValidByIds(List.of(ids), true));
+    }
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java
index c821e00..0dac166 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixture.java
@@ -60,6 +60,11 @@
     private Long borrowUser;
 
     /**
+     * 鍊熺敤鐘舵��
+     */
+    private String borrowStatus;
+
+    /**
      * 鐘舵�侊紙瀛楀吀锛�
      */
     private String status;
@@ -106,5 +111,10 @@
      */
     private String remark;
 
+    /**
+     * 褰撳墠鍊熺敤璁板綍id
+     */
+    private Long curBorrowId;
+
 
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixtureBorrow.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixtureBorrow.java
new file mode 100644
index 0000000..bab7347
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/EimsFixtureBorrow.java
@@ -0,0 +1,88 @@
+package org.dromara.eims.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 宸ュ叿鍊熺敤瀵硅薄 eims_fixture_borrow
+ *
+ * @author zhuguifei
+ * @date 2025-02-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("eims_fixture_borrow")
+public class EimsFixtureBorrow extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 鍊熺敤宸ュ叿id
+     */
+    private Long fixtureId;
+
+    /**
+     * 鍊熺敤宸ュ叿鍚嶇О
+     */
+    private String fixtureName;
+
+    /**
+     * 鍊熺敤閮ㄩ棬
+     */
+    private Long borrowDept;
+
+    /**
+     * 鍊熺敤浜�
+     */
+    private Long borrowUser;
+
+    /**
+     * 缁忓姙浜�
+     */
+    private Long agentUser;
+
+    /**
+     * 鍊熺敤璁板綍鐘舵�侊紙瀛楀吀锛�
+     */
+    private String status;
+
+    /**
+     * 鍊熺敤鏃堕棿
+     */
+    private Date borrowTime;
+
+    /**
+     * 棰勮褰掕繕鏃堕棿
+     */
+    private Date planReturnTime;
+
+    /**
+     * 褰掕繕鏃堕棿
+     */
+    private Date returnTime;
+
+    /**
+     * 鍊熺敤鐞嗙敱
+     */
+    private String borrowReason;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java
index 202a1fd..c15b06e 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBo.java
@@ -1,5 +1,8 @@
 package org.dromara.eims.domain.bo;
 
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
 import org.dromara.eims.domain.EimsFixture;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.common.core.validate.AddGroup;
@@ -60,6 +63,11 @@
     private Long borrowUser;
 
     /**
+     * 鍊熺敤鐘舵��
+     */
+    private String borrowStatus;
+
+    /**
      * 鐘舵�侊紙瀛楀吀锛�
      */
     private String status;
@@ -106,5 +114,10 @@
      */
     private String remark;
 
+    /**
+     * 褰撳墠鍊熺敤璁板綍id
+     */
+    private Long curBorrowId;
+
 
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBorrowBo.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBorrowBo.java
new file mode 100644
index 0000000..f22a524
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsFixtureBorrowBo.java
@@ -0,0 +1,95 @@
+package org.dromara.eims.domain.bo;
+
+import org.dromara.eims.domain.EimsFixtureBorrow;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 宸ュ叿鍊熺敤涓氬姟瀵硅薄 eims_fixture_borrow
+ *
+ * @author zhuguifei
+ * @date 2025-02-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = EimsFixtureBorrow.class, reverseConvertGenerate = false)
+public class EimsFixtureBorrowBo extends BaseEntity {
+
+    /**
+     * 
+     */
+    @NotNull(message = "涓嶈兘涓虹┖", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 鍊熺敤宸ュ叿id
+     */
+    @NotNull(message = "鍊熺敤宸ュ叿id涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
+    private Long fixtureId;
+
+    /**
+     * 鍊熺敤宸ュ叿鍚嶇О
+     */
+    @NotBlank(message = "鍊熺敤宸ュ叿鍚嶇О涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
+    private String fixtureName;
+
+    /**
+     * 鍊熺敤閮ㄩ棬
+     */
+    @NotNull(message = "鍊熺敤閮ㄩ棬涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
+    private Long borrowDept;
+
+    /**
+     * 鍊熺敤浜�
+     */
+    @NotNull(message = "鍊熺敤浜轰笉鑳戒负绌�", groups = { AddGroup.class, EditGroup.class })
+    private Long borrowUser;
+
+    /**
+     * 缁忓姙浜�
+     */
+    private Long agentUser;
+
+    /**
+     * 鍊熺敤璁板綍鐘舵�侊紙瀛楀吀锛�
+     */
+    @NotBlank(message = "鍊熺敤璁板綍鐘舵�侊紙瀛楀吀锛変笉鑳戒负绌�", groups = { AddGroup.class, EditGroup.class })
+    private String status;
+
+    /**
+     * 鍊熺敤鏃堕棿
+     */
+    @NotNull(message = "鍊熺敤鏃堕棿涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
+    private Date borrowTime;
+
+    /**
+     * 棰勮褰掕繕鏃堕棿
+     */
+    @NotNull(message = "棰勮褰掕繕鏃堕棿涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
+    private Date planReturnTime;
+
+    /**
+     * 褰掕繕鏃堕棿
+     */
+    private Date returnTime;
+
+    /**
+     * 鍊熺敤鐞嗙敱
+     */
+    @NotBlank(message = "鍊熺敤鐞嗙敱涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
+    private String borrowReason;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureBorrowVo.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureBorrowVo.java
new file mode 100644
index 0000000..7b6d7d1
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureBorrowVo.java
@@ -0,0 +1,127 @@
+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.EimsFixtureBorrow;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 宸ュ叿鍊熺敤瑙嗗浘瀵硅薄 eims_fixture_borrow
+ *
+ * @author zhuguifei
+ * @date 2025-02-18
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = EimsFixtureBorrow.class)
+public class EimsFixtureBorrowVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 鍊熺敤宸ュ叿id
+     */
+    @ExcelProperty(value = "鍊熺敤宸ュ叿id")
+    private Long fixtureId;
+
+    /**
+     * 鍊熺敤宸ュ叿鍚嶇О
+     */
+    @ExcelProperty(value = "鍊熺敤宸ュ叿鍚嶇О")
+    private String fixtureName;
+
+    /**
+     * 鍊熺敤閮ㄩ棬
+     */
+    private Long borrowDept;
+
+    /**
+     * 鍊熺敤閮ㄩ棬
+     */
+    @ExcelProperty(value = "鍊熺敤閮ㄩ棬")
+    @Translation(type = TransConstant.DEPT_ID_TO_NAME, mapper = "borrowDept")
+    private String borrowDeptName;
+
+    /**
+     * 鍊熺敤浜�
+     */
+    private Long borrowUser;
+    /**
+     * 鍊熺敤浜�
+     */
+    @ExcelProperty(value = "鍊熺敤浜�")
+    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "borrowUser")
+    private String borrowUserName;
+
+    /**
+     * 缁忓姙浜�
+     */
+    private Long agentUser;
+
+    /**
+     * 缁忓姙浜�
+     */
+    @ExcelProperty(value = "缁忓姙浜�")
+    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "agentUser")
+    private Long agentUserName;
+
+
+    /**
+     * 鍊熺敤璁板綍鐘舵�侊紙瀛楀吀锛�
+     */
+    @ExcelProperty(value = "鍊熺敤璁板綍鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "fixture_borrow_record_status")
+    private String status;
+
+    /**
+     * 鍊熺敤鏃堕棿
+     */
+    @ExcelProperty(value = "鍊熺敤鏃堕棿")
+    private Date borrowTime;
+
+    /**
+     * 棰勮褰掕繕鏃堕棿
+     */
+    @ExcelProperty(value = "棰勮褰掕繕鏃堕棿")
+    private Date planReturnTime;
+
+    /**
+     * 褰掕繕鏃堕棿
+     */
+    @ExcelProperty(value = "褰掕繕鏃堕棿")
+    private Date returnTime;
+
+    /**
+     * 鍊熺敤鐞嗙敱
+     */
+    @ExcelProperty(value = "鍊熺敤鐞嗙敱")
+    private String borrowReason;
+
+    /**
+     * 澶囨敞
+     */
+    @ExcelProperty(value = "澶囨敞")
+    private String remark;
+
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java
index 86f6a85..7ca4dae 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/vo/EimsFixtureVo.java
@@ -85,8 +85,16 @@
     private Long borrowUser;
 
     /**
+     * 鍊熺敤鐘舵��
+     */
+    @ExcelProperty(value = "鍊熺敤鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "fixture_borrow_status")
+    private String borrowStatus;
+
+    /**
      * 鍊熺敤浜�
      */
+    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "borrowUser")
     private String borrowUserName;
 
     /**
@@ -146,5 +154,10 @@
     @ExcelProperty(value = "澶囨敞")
     private String remark;
 
+    /**
+     * 褰撳墠鍊熺敤璁板綍id
+     */
+    private Long curBorrowId;
+
 
 }
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureBorrowMapper.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureBorrowMapper.java
new file mode 100644
index 0000000..368b3e5
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/mapper/EimsFixtureBorrowMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.eims.mapper;
+
+import org.dromara.eims.domain.EimsFixtureBorrow;
+import org.dromara.eims.domain.vo.EimsFixtureBorrowVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 宸ュ叿鍊熺敤Mapper鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2025-02-18
+ */
+public interface EimsFixtureBorrowMapper extends BaseMapperPlus<EimsFixtureBorrow, EimsFixtureBorrowVo> {
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureBorrowService.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureBorrowService.java
new file mode 100644
index 0000000..c0c27f5
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsFixtureBorrowService.java
@@ -0,0 +1,68 @@
+package org.dromara.eims.service;
+
+import org.dromara.eims.domain.vo.EimsFixtureBorrowVo;
+import org.dromara.eims.domain.bo.EimsFixtureBorrowBo;
+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-18
+ */
+public interface IEimsFixtureBorrowService {
+
+    /**
+     * 鏌ヨ宸ュ叿鍊熺敤
+     *
+     * @param id 涓婚敭
+     * @return 宸ュ叿鍊熺敤
+     */
+    EimsFixtureBorrowVo queryById(Long id);
+
+    /**
+     * 鍒嗛〉鏌ヨ宸ュ叿鍊熺敤鍒楄〃
+     *
+     * @param bo        鏌ヨ鏉′欢
+     * @param pageQuery 鍒嗛〉鍙傛暟
+     * @return 宸ュ叿鍊熺敤鍒嗛〉鍒楄〃
+     */
+    TableDataInfo<EimsFixtureBorrowVo> queryPageList(EimsFixtureBorrowBo bo, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ绗﹀悎鏉′欢鐨勫伐鍏峰�熺敤鍒楄〃
+     *
+     * @param bo 鏌ヨ鏉′欢
+     * @return 宸ュ叿鍊熺敤鍒楄〃
+     */
+    List<EimsFixtureBorrowVo> queryList(EimsFixtureBorrowBo bo);
+
+    /**
+     * 鏂板宸ュ叿鍊熺敤
+     *
+     * @param bo 宸ュ叿鍊熺敤
+     * @return 鏄惁鏂板鎴愬姛
+     */
+    Boolean insertByBo(EimsFixtureBorrowBo bo);
+
+    /**
+     * 淇敼宸ュ叿鍊熺敤
+     *
+     * @param bo 宸ュ叿鍊熺敤
+     * @return 鏄惁淇敼鎴愬姛
+     */
+    Boolean updateByBo(EimsFixtureBorrowBo bo);
+
+    /**
+     * 鏍¢獙骞舵壒閲忓垹闄ゅ伐鍏峰�熺敤淇℃伅
+     *
+     * @param ids     寰呭垹闄ょ殑涓婚敭闆嗗悎
+     * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+     * @return 鏄惁鍒犻櫎鎴愬姛
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureBorrowServiceImpl.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureBorrowServiceImpl.java
new file mode 100644
index 0000000..8c191a9
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureBorrowServiceImpl.java
@@ -0,0 +1,211 @@
+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.common.satoken.utils.LoginHelper;
+import org.dromara.eims.domain.EimsEquType;
+import org.dromara.eims.domain.EimsFixture;
+import org.dromara.eims.domain.vo.EimsEquTypeVo;
+import org.dromara.eims.domain.vo.EimsFixtureVo;
+import org.dromara.eims.mapper.EimsFixtureMapper;
+import org.dromara.system.domain.SysDept;
+import org.dromara.system.domain.vo.SysDeptVo;
+import org.dromara.system.mapper.SysDeptMapper;
+import org.dromara.system.service.ISysDeptService;
+import org.springframework.stereotype.Service;
+import org.dromara.eims.domain.bo.EimsFixtureBorrowBo;
+import org.dromara.eims.domain.vo.EimsFixtureBorrowVo;
+import org.dromara.eims.domain.EimsFixtureBorrow;
+import org.dromara.eims.mapper.EimsFixtureBorrowMapper;
+import org.dromara.eims.service.IEimsFixtureBorrowService;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 宸ュ叿鍊熺敤Service涓氬姟灞傚鐞�
+ *
+ * @author zhuguifei
+ * @date 2025-02-18
+ */
+@RequiredArgsConstructor
+@Service
+public class EimsFixtureBorrowServiceImpl implements IEimsFixtureBorrowService {
+
+    private final EimsFixtureBorrowMapper baseMapper;
+    private final EimsFixtureMapper fixtureMapper;
+    private final SysDeptMapper sysDeptMapper;
+
+    /**
+     * 鏌ヨ宸ュ叿鍊熺敤
+     *
+     * @param id 涓婚敭
+     * @return 宸ュ叿鍊熺敤
+     */
+    @Override
+    public EimsFixtureBorrowVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ宸ュ叿鍊熺敤鍒楄〃
+     *
+     * @param bo        鏌ヨ鏉′欢
+     * @param pageQuery 鍒嗛〉鍙傛暟
+     * @return 宸ュ叿鍊熺敤鍒嗛〉鍒楄〃
+     */
+    @Override
+    public TableDataInfo<EimsFixtureBorrowVo> queryPageList(EimsFixtureBorrowBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<EimsFixtureBorrow> lqw = buildQueryWrapper(bo);
+        Page<EimsFixtureBorrowVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 鏌ヨ绗﹀悎鏉′欢鐨勫伐鍏峰�熺敤鍒楄〃
+     *
+     * @param bo 鏌ヨ鏉′欢
+     * @return 宸ュ叿鍊熺敤鍒楄〃
+     */
+    @Override
+    public List<EimsFixtureBorrowVo> queryList(EimsFixtureBorrowBo bo) {
+        LambdaQueryWrapper<EimsFixtureBorrow> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<EimsFixtureBorrow> buildQueryWrapper(EimsFixtureBorrowBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<EimsFixtureBorrow> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getFixtureId() != null, EimsFixtureBorrow::getFixtureId, bo.getFixtureId());
+        lqw.like(StringUtils.isNotBlank(bo.getFixtureName()), EimsFixtureBorrow::getFixtureName, bo.getFixtureName());
+
+        lqw.eq(bo.getBorrowUser() != null, EimsFixtureBorrow::getBorrowUser, bo.getBorrowUser());
+        lqw.eq(bo.getAgentUser() != null, EimsFixtureBorrow::getAgentUser, bo.getAgentUser());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsFixtureBorrow::getStatus, bo.getStatus());
+        lqw.between(params.get("beginBorrowTime") != null && params.get("endBorrowTime") != null,
+            EimsFixtureBorrow::getBorrowTime ,params.get("beginBorrowTime"), params.get("endBorrowTime"));
+        lqw.between(params.get("beginPlanReturnTime") != null && params.get("endPlanReturnTime") != null,
+            EimsFixtureBorrow::getPlanReturnTime ,params.get("beginPlanReturnTime"), params.get("endPlanReturnTime"));
+        lqw.eq(bo.getReturnTime() != null, EimsFixtureBorrow::getReturnTime, bo.getReturnTime());
+        lqw.eq(StringUtils.isNotBlank(bo.getBorrowReason()), EimsFixtureBorrow::getBorrowReason, bo.getBorrowReason());
+
+        /**
+         * 鏌ヨ閮ㄩ棬涓嬫墍鏈夊瓙閮ㄩ棬
+         */
+        if (bo.getBorrowDept() != null ) {
+            List<Long> allDescendantIds = getAllDescendantIds(bo.getBorrowDept());
+            lqw.in(bo.getBorrowDept() != null ,EimsFixtureBorrow::getBorrowDept, allDescendantIds);
+        }
+
+
+        return lqw;
+    }
+
+    /**
+     * 鏍规嵁id锛岃幏鍙栨墍鏈夊悗浠d
+     * @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<SysDept> sysDeptWrapper = new QueryWrapper<>();
+        sysDeptWrapper.lambda().eq(SysDept::getParentId, currentId);
+
+        List<SysDeptVo> children = sysDeptMapper.selectVoList(sysDeptWrapper);
+        if (children != null && !children.isEmpty()) {
+            for (SysDeptVo child : children) {
+                Long childId = child.getDeptId();
+                collector.add(childId);
+                collectDescendants(childId, collector);
+            }
+        }
+    }
+
+    /**
+     * 鏂板宸ュ叿鍊熺敤
+     *
+     * @param bo 宸ュ叿鍊熺敤
+     * @return 鏄惁鏂板鎴愬姛
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean insertByBo(EimsFixtureBorrowBo bo) {
+        EimsFixtureBorrow add = MapstructUtils.convert(bo, EimsFixtureBorrow.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+            //鍚屾椂鏇存柊宸ュ叿鍙拌处琛ㄤ腑鍊熺敤浜�
+            EimsFixtureVo eimsFixtureVo = fixtureMapper.selectVoById(bo.getFixtureId());
+            eimsFixtureVo.setBorrowUser(LoginHelper.getUserId());
+            //璁剧疆宸ュ叿鍙拌处鐘舵�佷负鍊熺敤
+            eimsFixtureVo.setBorrowStatus("1");//TODO 淇濇寔瀛楀吀鏁版嵁涓�鑷磃ixture_borrow_status
+            //鏇存柊宸ュ叿鍙拌处褰撳墠鍊熺敤璁板綍id
+            eimsFixtureVo.setCurBorrowId(add.getId());
+            eimsFixtureVo.setBorrowDept(LoginHelper.getDeptId());
+            EimsFixture fixture = MapstructUtils.convert(eimsFixtureVo, EimsFixture.class);
+            fixtureMapper.updateById(fixture);
+        }
+        return flag;
+    }
+
+    /**
+     * 淇敼宸ュ叿鍊熺敤
+     *
+     * @param bo 宸ュ叿鍊熺敤
+     * @return 鏄惁淇敼鎴愬姛
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean updateByBo(EimsFixtureBorrowBo bo) {
+        EimsFixtureBorrow update = MapstructUtils.convert(bo, EimsFixtureBorrow.class);
+        validEntityBeforeSave(update);
+        //璁剧疆宸ュ叿鍙拌处鐘舵�佷负褰掕繕 TODO 淇濇寔瀛楀吀鏁版嵁涓�鑷磃ixture_borrow_record_status
+        if(bo.getStatus().equals("1")){
+            EimsFixtureVo eimsFixtureVo = fixtureMapper.selectVoById(bo.getFixtureId());
+            //璁剧疆宸ュ叿鍙拌处鐘舵�佷负褰掕繕
+            eimsFixtureVo.setBorrowStatus("0"); //TODO 淇濇寔瀛楀吀鏁版嵁涓�鑷磃ixture_borrow_status
+            EimsFixture fixture = MapstructUtils.convert(eimsFixtureVo, EimsFixture.class);
+            fixtureMapper.updateById(fixture);
+        }
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+     */
+    private void validEntityBeforeSave(EimsFixtureBorrow entity){
+        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+    }
+
+    /**
+     * 鏍¢獙骞舵壒閲忓垹闄ゅ伐鍏峰�熺敤淇℃伅
+     *
+     * @param ids     寰呭垹闄ょ殑涓婚敭闆嗗悎
+     * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+     * @return 鏄惁鍒犻櫎鎴愬姛
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java
index e6cf528..41a18a0 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsFixtureServiceImpl.java
@@ -100,6 +100,7 @@
         lqw.eq(StringUtils.isNotBlank(bo.getFixtureDesc()), EimsFixture::getFixtureDesc, bo.getFixtureDesc());
         lqw.eq(bo.getBorrowDept()!=null, EimsFixture::getBorrowDept, bo.getBorrowDept());
         lqw.eq(bo.getBorrowUser()!=null, EimsFixture::getBorrowUser, bo.getBorrowUser());
+        lqw.eq(StringUtils.isNotEmpty(bo.getBorrowStatus()), EimsFixture::getBorrowStatus, bo.getBorrowStatus());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), EimsFixture::getStatus, bo.getStatus());
         lqw.like(StringUtils.isNotBlank(bo.getAssetNo()), EimsFixture::getAssetNo, bo.getAssetNo());
         lqw.like(StringUtils.isNotBlank(bo.getModelNo()), EimsFixture::getModelNo, bo.getModelNo());
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java
index 6ef4ace..b191443 100644
--- a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairReqServiceImpl.java
@@ -10,7 +10,12 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import org.dromara.eims.domain.EimsEqu;
+import org.dromara.eims.domain.EimsFixtureBorrow;
 import org.dromara.eims.domain.vo.EimsInventoryDetailVo;
+import org.dromara.eims.utils.DataFilterUtil;
+import org.dromara.system.domain.SysDept;
+import org.dromara.system.domain.vo.SysDeptVo;
+import org.dromara.system.mapper.SysDeptMapper;
 import org.springframework.stereotype.Service;
 import org.dromara.eims.domain.bo.EimsRepairReqBo;
 import org.dromara.eims.domain.vo.EimsRepairReqVo;
@@ -18,6 +23,7 @@
 import org.dromara.eims.mapper.EimsRepairReqMapper;
 import org.dromara.eims.service.IEimsRepairReqService;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Collection;
@@ -33,6 +39,7 @@
 public class EimsRepairReqServiceImpl implements IEimsRepairReqService {
 
     private final EimsRepairReqMapper baseMapper;
+    private final SysDeptMapper sysDeptMapper;
 
     /**
      * 鏌ヨ鏁呴殰鎶ヤ慨
@@ -41,7 +48,7 @@
      * @return 鏁呴殰鎶ヤ慨
      */
     @Override
-    public EimsRepairReqVo queryById(Long id){
+    public EimsRepairReqVo queryById(Long id) {
         return baseMapper.selectVoById(id);
     }
 
@@ -61,6 +68,7 @@
 
     @Override
     public TableDataInfo<EimsRepairReqVo> queryPageListCustom(EimsRepairReqBo bo, PageQuery pageQuery) {
+        DataFilterUtil.getInstance().filterRepairReq(bo);
         Page<EimsRepairReqVo> page = baseMapper.selectRepairReqList(pageQuery.build(), buildWrapper(bo));
         return TableDataInfo.build(page);
     }
@@ -68,24 +76,62 @@
     private QueryWrapper<EimsRepairReq> buildWrapper(EimsRepairReqBo bo) {
         Map<String, Object> params = bo.getParams();
         QueryWrapper<EimsRepairReq> qw = Wrappers.query();
-        qw.like(StringUtils.isNotBlank(bo.getCode()),"a.code", bo.getCode());
+        qw.like(StringUtils.isNotBlank(bo.getCode()), "a.code", bo.getCode());
         qw.eq(StringUtils.isNotBlank(bo.getStatus()), "a.status", bo.getStatus());
         qw.eq(bo.getReqTime() != null, "a.req_time", bo.getReqTime());
-        qw.eq(bo.getReqDept() != null, "a.req_dept", bo.getReqDept());
-        qw.eq(bo.getReqUser() != null,"a.req_user", bo.getReqUser());
+        qw.eq(bo.getReqUser() != null, "a.req_user", bo.getReqUser());
         qw.eq(StringUtils.isNotBlank(bo.getUrgencyLevel()), "a.urgency_level", bo.getUrgencyLevel());
         qw.eq(StringUtils.isNotBlank(bo.getReqType()), "a.req_type", bo.getReqType());
         qw.eq(bo.getEquId() != null, "a.equ_id", bo.getEquId());
-        qw.eq(bo.getRepairDept() != null,"a.repair_dept", bo.getRepairDept());
+        qw.eq(bo.getRepairDept() != null, "a.repair_dept", bo.getRepairDept());
         qw.eq(bo.getRepairUser() != null, "a.repair_user", bo.getRepairUser());
         qw.eq(StringUtils.isNotBlank(bo.getFaultType()), "a,fault_type", bo.getFaultType());
         qw.eq(params.containsKey("createBy"), "a.create_by", params.get("createBy"));
         qw.eq(params.containsKey("status"), "a.status", params.get("status"));
         qw.between(params.get("beginReqTime") != null && params.get("endReqTime") != null,
             "a.req_time", params.get("beginReqTime"), params.get("endReqTime"));
+
+
+        qw.eq(bo.getCreateBy()!=null, "a.create_by", bo.getCreateBy());
+        qw.eq(StringUtils.isNotEmpty(bo.getStatus()), "a.status", bo.getStatus());
+
+        /**
+         * 鏌ヨ閮ㄩ棬涓嬫墍鏈夊瓙閮ㄩ棬
+         */
+        if (bo.getReqDept() != null) {
+            List<Long> allDescendantIds = getAllDescendantIds(bo.getReqDept());
+            qw.in(bo.getReqDept() != null, "a.req_dept", allDescendantIds);
+        }
+
         return qw;
     }
 
+    /**
+     * 鏍规嵁id锛岃幏鍙栨墍鏈夊悗浠d
+     *
+     * @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<SysDept> sysDeptWrapper = new QueryWrapper<>();
+        sysDeptWrapper.lambda().eq(SysDept::getParentId, currentId);
+
+        List<SysDeptVo> children = sysDeptMapper.selectVoList(sysDeptWrapper);
+        if (children != null && !children.isEmpty()) {
+            for (SysDeptVo child : children) {
+                Long childId = child.getDeptId();
+                collector.add(childId);
+                collectDescendants(childId, collector);
+            }
+        }
+    }
 
     /**
      * 鏌ヨ绗﹀悎鏉′欢鐨勬晠闅滄姤淇垪琛�
@@ -149,7 +195,7 @@
     /**
      * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
      */
-    private void validEntityBeforeSave(EimsRepairReq entity){
+    private void validEntityBeforeSave(EimsRepairReq entity) {
         //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
     }
 
@@ -162,7 +208,7 @@
      */
     @Override
     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if(isValid){
+        if (isValid) {
             //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
         }
         return baseMapper.deleteByIds(ids) > 0;
diff --git a/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/utils/DataFilterUtil.java b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/utils/DataFilterUtil.java
new file mode 100644
index 0000000..bee36a7
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/utils/DataFilterUtil.java
@@ -0,0 +1,42 @@
+package org.dromara.eims.utils;
+
+import org.dromara.common.core.domain.model.LoginUser;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.eims.domain.bo.EimsRepairReqBo;
+
+import java.util.Set;
+
+/**
+ * 鑷畾涔夋暟鎹殧绂�
+ */
+public class DataFilterUtil {
+
+    //TODO 淇濇寔涓庢暟鎹簱涓�鐩� 瀹氫箟瑙掕壊绫诲瀷 operator-鎿嶄綔宸� repair-缁翠慨宸�
+    private  enum Role {
+        operator, repair
+    }
+
+    private static final DataFilterUtil INSTANCE = new DataFilterUtil();
+
+    private DataFilterUtil() {
+    }
+    public static DataFilterUtil getInstance() {
+        return INSTANCE;
+    }
+    //鎶ヤ慨鍗�
+    public void filterRepairReq(EimsRepairReqBo bo){
+        LoginUser loginUser = LoginHelper.getLoginUser();
+        if (loginUser == null)  return;
+        Set<String> rolePermission = loginUser.getRolePermission();
+        if (rolePermission == null)  return;
+        if (rolePermission.contains(Role.operator.name())) {
+            //缁翠慨宸ュ彧鑳芥煡璇㈣嚜宸辩殑鏁版嵁
+            bo.setCreateBy(loginUser.getUserId());
+        }else if (rolePermission.contains(Role.repair.name())) {
+            //TODO 缁翠慨宸ュ彧鑳芥煡璇㈡湭鎺ュ崟鐘舵�佺殑鎶ヤ慨鍗曪紙鍏蜂綋鐘舵�佸弬鑰冨瓧鍏竢epair_req_status锛�
+            bo.setStatus("0");
+        }
+        System.err.println(loginUser);
+    }
+
+}
diff --git a/eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFixtureBorrowMapper.xml b/eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFixtureBorrowMapper.xml
new file mode 100644
index 0000000..413d14f
--- /dev/null
+++ b/eims/ruoyi-modules/lb-eims/src/main/resources/mapper/eims/EimsFixtureBorrowMapper.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.EimsFixtureBorrowMapper">
+
+</mapper>

--
Gitblit v1.9.3