Quellcode durchsuchen

feature:增加仪器巡检任务和故障报修

liuzhenlin vor 5 Monaten
Ursprung
Commit
2b2226213a

+ 2 - 0
.env.production

@@ -23,6 +23,8 @@ VITE_WORKFLOW = dashoo.labsop.workflow-34000
 VITE_INSTR_ADMIN = dashoo.labsop.apparatus-34000
 VITE_LEARNING = dashoo.labsop.learning-34000
 VITE_PLATFORM_API = dashoo.labsop.platform-34000
+VITE_LABORATORY: dashoo.labsop.laboratory-34000
+
 
 #公共配置
 VITE_UPLOAD = /weedfs/upload

+ 2 - 2
components.d.ts

@@ -7,7 +7,6 @@ export {}
 
 declare module 'vue' {
   export interface GlobalComponents {
-    copy: typeof import('./src/components/select-inst copy.vue')['default']
     CustomForm: typeof import('./src/components/CustomForm.vue')['default']
     FlowTable: typeof import('./src/components/FlowTable.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
@@ -19,12 +18,13 @@ declare module 'vue' {
     VanActionBarIcon: typeof import('vant/es')['ActionBarIcon']
     VanBackTop: typeof import('vant/es')['BackTop']
     VanButton: typeof import('vant/es')['Button']
+    VanCalendar: typeof import('vant/es')['Calendar']
     VanCell: typeof import('vant/es')['Cell']
     VanCellGroup: typeof import('vant/es')['CellGroup']
     VanCheckbox: typeof import('vant/es')['Checkbox']
     VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
+    VanCol: typeof import('vant/es')['Col']
     VanDatePicker: typeof import('vant/es')['DatePicker']
-    VanDatetimePicker: typeof import('vant/es')['DatetimePicker']
     VanEmpty: typeof import('vant/es')['Empty']
     VanField: typeof import('vant/es')['Field']
     VanFloatingBubble: typeof import('vant/es')['FloatingBubble']

+ 4 - 4
pnpm-lock.yaml

@@ -1,5 +1,9 @@
 lockfileVersion: '6.0'
 
+settings:
+  autoInstallPeers: false
+  excludeLinksFromLockfile: false
+
 dependencies:
   '@element-plus/icons-vue':
     specifier: ^2.3.1
@@ -1494,7 +1498,3 @@ packages:
   /weixin-js-sdk@1.6.5:
     resolution: {integrity: sha512-Gph1WAWB2YN/lMOFB/ymb+hbU/wYazzJgu6PMMktCy9cSCeW5wA6Zwt0dpahJbJ+RJEwtTv2x9iIu0U4enuVSQ==}
     dev: false
-
-settings:
-  autoInstallPeers: true
-  excludeLinksFromLockfile: false

+ 25 - 0
src/api/laboratory/inspection.ts

@@ -0,0 +1,25 @@
+import request from '/@/utils/micro_request.js';
+
+const basePath = import.meta.env.VITE_LABORATORY;
+
+// 证书管理
+export function useRectificationNewApi() {
+  return {
+    // 列表
+    getList(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'GetList', query);
+    },
+    onCreate(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'CreateRectificationNoticeDetail', query);
+    },
+    onUpdated(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'UpdateRectificationNoticeDetail', query);
+    },
+    getDetail(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'GetRectificationNoticeById', query);
+    },
+    onDelete(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'DelNotice', query);
+    }
+  }
+}

+ 93 - 0
src/api/laboratory/lab/index.ts

@@ -0,0 +1,93 @@
+/*
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-07-14 17:15:49
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-08-17 16:29:09
+ * @Description: file content
+ * @FilePath: \frontend\packages\vue-next-admin-sub\src\api\Lab\index.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_LABORATORY;
+const instrPath = import.meta.env.VITE_INSTR_ADMIN;
+
+// 参数设置
+export function useLabApi() {
+  return {
+    // 新增实验室
+    addLab(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'Create', query);
+    },
+    // 新增实验室 (仅预约)
+    addLabOnlyAppoint(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'CreateBasic', query);
+    },
+    // 设备详情
+    getLabDetail(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'GetEntityById', query);
+    },
+    // 更新实验室(仅预约)
+    updateLabDetailOnlyAppoint(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'UpdateByIdBasic', query);
+    },
+    // 更新实验室
+    updateLabDetail(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'UpdateById', query);
+    },
+    // 删除实验室
+    delLab(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'DeleteByIds', query);
+    },
+    // 实验室列表
+    getList(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'GetList', query);
+    },
+    // 实验室列表
+    getAllList(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'GetAllList', query);
+    },
+    // 审批
+    approve(query?: object) {
+      return request.postRequest(basePath, 'workflow', 'Approve', query);
+    },
+    // 生成二维码 
+    generateQrcode(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'Qrcode', query);
+    },
+    // 绑定实验室危险源
+    addLabDanger(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'CreateLaboratoryDanger', query);
+    },
+    // 更新绑定的实验室危险源
+    updateLabDanger(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'UpdateLaboratoryDanger', query);
+    },
+    // 删除实验室危险源
+    delLbaDanger(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'DeleteLaboratoryDangerById', query);
+    },
+    // 查询实验室危险源列表
+    getDangerByLab(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'GetLaboratoryDangerById', query);
+    },
+    // 查询实验室危险源详情
+    getDangerByLabAndId(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'GetLaboratoryDangerEntityById', query);
+    },
+    // 实验室绑定人员
+    addLabUser(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'CreateLaboratoryMember', query);
+    },
+    // 获取实验室绑定人员
+    getLabUser(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'GetLaboratoryMemberById', query);
+    },
+    // 删除实验室绑定人员
+    delLbaUser(query?: object) {
+      return request.postRequest(basePath, 'laboratory', 'DeleteLaboratoryMemberById', query);
+    },
+    // 按实验室查询
+    getInstrByLab(query?: object) {
+      return request.postRequest(instrPath, 'TusInstrument', 'GetListByLaboratory', query);
+    },
+  };
+}

+ 32 - 0
src/api/laboratory/lab/labLeave.ts

@@ -0,0 +1,32 @@
+/*
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-07-14 17:15:49
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-08-17 16:29:09
+ * @Description: file content
+ * @FilePath: \frontend\packages\vue-next-admin-sub\src\api\Lab\index.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_LABORATORY;
+
+// 实验室人员请假
+export function useLabUserLeaveApi() {
+  return {
+    // 新增
+    add(query?: object) {
+      return request.postRequest(basePath, 'LabUserLeave', 'Create', query);
+    },
+    del(query?: object) {
+      return request.postRequest(basePath, 'LabUserLeave', 'DeleteByIds', query);
+    },
+    getDetails(query?: object) {
+      return request.postRequest(basePath, 'LabUserLeave', 'GetEntityById', query);
+    },
+    getList(query?: object) {
+      return request.postRequest(basePath, 'LabUserLeave', 'GetList', query);
+    },
+    update(query?: object) {
+      return request.postRequest(basePath, 'LabUserLeave', 'UpdateById', query);
+    },
+  };
+}

+ 35 - 0
src/api/laboratory/lab/labUser.ts

@@ -0,0 +1,35 @@
+/*
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-07-14 17:15:49
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-08-17 16:29:09
+ * @Description: file content
+ * @FilePath: \frontend\packages\vue-next-admin-sub\src\api\Lab\index.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_LABORATORY;
+
+// 实验室人员
+export function useLabUserApi() {
+  return {
+    // 新增
+    add(query?: object) {
+      return request.postRequest(basePath, 'LabUser', 'Create', query);
+    },
+    del(query?: object) {
+      return request.postRequest(basePath, 'LabUser', 'DeleteByIds', query);
+    },
+    getDetails(query?: object) {
+      return request.postRequest(basePath, 'LabUser', 'GetEntityById', query);
+    },
+    getList(query?: object) {
+      return request.postRequest(basePath, 'LabUser', 'GetList', query);
+    },
+    update(query?: object) {
+      return request.postRequest(basePath, 'LabUser', 'UpdateById', query);
+    },
+    getListUseDuration(query?: object) {
+      return request.postRequest(basePath, 'LabUser', 'GetListUseDuration', query);
+    },
+  };
+}

+ 39 - 0
src/api/laboratory/lab/setting.ts

@@ -0,0 +1,39 @@
+/*
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-08-10 18:20:32
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-08-11 16:35:49
+ * @Description: file content
+ * @FilePath: \frontend\packages\vue-next-admin-sub\src\api\instr\setting.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_LABORATORY;
+// 参数设置
+export function useSetApi() {
+  return {
+    // 获取设置详情
+    getSettingDetail(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'GetConfig', query);
+    },
+    // 预约间隔
+    timeSplit(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'TimeSplit', query);
+    },
+    // 送样设置
+    setSampleDelivery(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'PutInstCfgSample', query);
+    },
+    // 预约设置
+    setAppint(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'PutInstCfgAppoint', query);
+    },
+    // 使用设置
+    useSetting(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'PutInstCfgUse', query);
+    },
+    // 计费设置 
+    chargeSetting(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'PutInstCfgCharge', query);
+    },
+  };
+}

+ 51 - 0
src/api/laboratory/lab/useAppoint.ts

@@ -0,0 +1,51 @@
+/*
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-08-10 18:20:32
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-08-25 17:14:47
+ * @Description: file content
+ * @FilePath: \frontend\packages\vue-next-admin-sub\src\api\inst\useAppoint.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_LABORATORY;
+// 参数设置
+export function useUseAppointApi() {
+  return {
+    //预约列表
+    list(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'GetList', query);
+    },
+    // 预约
+    add(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'Create', query);
+    },
+    // 预约
+    update(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'UpdateById', query);
+    },
+    // 取消预约
+    cancelAppoint(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'AdminCancel', query);
+    },
+    // 取消预约
+    userCancelAppoint(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'UserCancel', query);
+    },
+    // 获取全部预约情况
+    getAppointInfo(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'AppointInfo', query);
+    },
+    // 获取设备预约情况
+    getInstrAppointInfo(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'GetEntityById', query);
+    },
+    // 获取用户信息
+    getUserId(query?: object) {
+      return request.postRequest(basePath, 'LabAppointConfig', 'UserInfo', query);
+    },
+    //按权限查预约列表
+    getListByPermission(query?: object) {
+      return request.postRequest(basePath, 'LabAppointment', 'GetListByInst', query);
+    },
+  };
+}

+ 55 - 0
src/api/laboratory/lab/usedRecord.ts

@@ -0,0 +1,55 @@
+/*
+ * @Author: liuzhenlin 461480418@qq.ocm
+ * @Date: 2023-08-10 18:20:32
+ * @LastEditors: liuzhenlin
+ * @LastEditTime: 2023-08-25 15:54:57
+ * @Description: file content
+ * @FilePath: \frontend\packages\vue-next-admin-sub\src\api\inst\usedRecord.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_LABORATORY;
+// 参数设置
+export function useUsedRecordApi() {
+  return {
+    //预约列表 
+    list(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'GetListByInst', query);
+    },
+    // 预约
+    create(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'CreateFromAppoint', query);
+    },
+    // 删除
+    del(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'DeleteByIds', query);
+    },
+    // 更新
+    update(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'UpdateById', query);
+    },
+    // 统计信息
+    getStatisticsInfo(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'StatisticByInst', query);
+    },
+    // 导出
+    exportFile(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'ExportExcelByInst', query);
+    },
+    // 按课题查询
+    getListByCurrentProj(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'GetListByCurrentProj', query);
+    },
+    // 按课题查询导出
+    exportByCurrentProj(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'ExportByCurrentProj', query);
+    },
+    // 查询使用记录
+    getUsedList(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'GetList', query);
+    },
+    // 查询导出
+    exportUsedRecord(query?: object) {
+      return request.postRequest(basePath, 'LabUsedRecord', 'ExportExcel', query);
+    },
+  };
+}

+ 52 - 0
src/api/laboratory/rectification/index.ts

@@ -0,0 +1,52 @@
+import request from '/@/utils/micro_request.js';
+
+const basePath = import.meta.env.VITE_LABORATORY;
+
+// 证书管理
+export function useRectificationApi() {
+    return {
+        // 列表
+        getList(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'GetList', query);
+        },
+        // 根据Id查询实验室整改通知的隐患
+        getRectificationNoticeById(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'GetRectificationNoticeById', query);
+        },
+         // 根据Id查询实验室整改通知的隐患
+         getRectificationNoticeDangerById(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'GetRectificationNoticeDangerById', query);
+        },
+        // 创建整改通知
+        createRectificationNotice(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'CreateRectificationNotice', query);
+        },
+        // 修改整改通知的状态
+        updateRectificationNoticeStatusById(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'UpdateRectificationNoticeStatusById', query);
+        },
+        // 完成整改
+        completeRectificationById(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'CompleteRectificationById', query);
+        },
+        // 根据隐患Id创建通知详情
+        createRectificationNoticeDetail(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'CreateRectificationNoticeDetail', query);
+        },
+        // 根据Id修改通知详情
+        updateRectificationNoticeDetail(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'UpdateRectificationNoticeDetail', query);
+        },
+        // 根据隐患Id查询对应详情
+        getRectificationNoticeDetailByDangerId(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'GetRectificationNoticeDetailByDangerId', query);
+        },
+        // 根据主Id查询对应详情
+        getRectificationNoticeDetailByMainId(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'GetRectificationNoticeDetailByMainId', query);
+        },
+        getRectificationNoticeDetailByTaskId(query?: object) {
+            return request.postRequest(basePath, 'rectification', 'GetRectificationNoticeDetailByTaskId', query);
+        },
+    }
+}

+ 25 - 0
src/api/laboratory/rectification/indexNew.ts

@@ -0,0 +1,25 @@
+import request from '/@/utils/micro_request.js';
+
+const basePath = import.meta.env.VITE_LABORATORY;
+
+// 证书管理
+export function useRectificationNewApi() {
+  return {
+    // 列表
+    getList(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'GetList', query);
+    },
+    onCreate(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'CreateRectificationNoticeDetail', query);
+    },
+    onUpdated(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'UpdateRectificationNoticeDetail', query);
+    },
+    getDetail(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'GetRectificationNoticeById', query);
+    },
+    onDelete(query?: object) {
+      return request.postRequest(basePath, 'rectificationnew', 'DelNotice', query);
+    }
+  }
+}

+ 59 - 0
src/api/laboratory/system/dict.ts

@@ -0,0 +1,59 @@
+/*
+ * @Author: wanglj 471442253@qq.com
+ * @Date: 2023-07-19 13:42:40
+ * @LastEditors: wanglj
+ * @LastEditTime: 2023-07-21 10:16:53
+ * @Description: file content
+ * @FilePath: \labsop_meno\frontend\packages\vue-next-admin\src\api\system\dict.ts
+ */
+import request from '/@/utils/micro_request.js'
+const basePath = import.meta.env.VITE_ADMIN
+// 参数设置
+export function useDictApi() {
+  return {
+    // 字典分类创建
+    createDictType(query?: object) {
+      return request.postRequest(basePath,'Dict','CreateDictType', query)
+    },
+    // 字典分类列表
+    getDictTypeList(query?: object) {
+      return request.postRequest(basePath,'Dict','GetDictTypeList', query)
+    },
+    // 删除字典分类
+    delDictType(query?: object) {
+      return request.postRequest(basePath,'Dict','DeleteDictTypeByIds', query)
+    },
+    // 字典分类详情
+    getDictTypeEntity(query?: object) {
+      return request.postRequest(basePath,'Dict','GetDictTypeEntity', query)
+    },
+    // 字典分类更新
+    updateDictType(query?: object) {
+      return request.postRequest(basePath,'Dict','UpdateDictType', query)
+    },
+    // 字典明细创建
+    createDictData(query?: object) {
+      return request.postRequest(basePath,'Dict','CreateDictData', query)
+    },
+    // 字典明细列表
+    getDictDataList(query?: object) {
+      return request.postRequest(basePath,'Dict','GetDictDataList', query)
+    },
+    // 字典明细删除
+    delDictData(query?: object) {
+      return request.postRequest(basePath,'Dict','DeleteDictDataByIds', query)
+    },
+     // 字典明细详情
+     getDictDataEntity(query?: object) {
+      return request.postRequest(basePath,'Dict','GetDictDataEntity', query)
+    },
+     // 字典明细更新
+     updateDictData(query?: object) {
+      return request.postRequest(basePath,'Dict','UpdateDictData', query)
+    },
+    // 根据字典类型获取字典项明细
+    getDictDataByType(str: string) {
+      return request.postRequest(basePath,'Dict','GetDictDataByType', { dictType: str })
+    },
+  }
+}

+ 39 - 0
src/api/laboratory/system/index.ts

@@ -0,0 +1,39 @@
+/*
+ * @Author: wanglj 471442253@qq.com
+ * @Date: 2023-07-19 13:42:40
+ * @LastEditors: wanglj
+ * @LastEditTime: 2023-07-21 10:16:53
+ * @Description: file content
+ * @FilePath: \labsop_meno\frontend\packages\vue-next-admin\src\api\system\dict.ts
+ */
+import request from '/@/utils/micro_request.js';
+const basePath = import.meta.env.VITE_ADMIN;
+// 参数设置
+export function useSystemApi() {
+  return {
+    // 根据字典类型获取字典项明细
+    getDictDataByType(str: string) {
+      return request.postRequest(basePath, 'Dict', 'GetDictDataByType', { dictType: str });
+    },
+    // 获取用户列表
+    getUserList(query?: object) {
+      return request.postRequest(basePath, 'User', 'GetList', query);
+    },
+    // 获取用户字典
+    getUserDict(query?: object) {
+      return request.postRequest(basePath, 'User', 'GetDictList', query);
+    },
+    // 获取仪器责任人角色用户列表
+    getInstUserList(query?: object) {
+      return request.postRequest(basePath, 'User', 'GetUserByRoleCode', query);
+    },
+    // 部门树
+    getDeptTree(query?: object) {
+      return request.postRequest(basePath, 'Dept', 'GetDeptTree', query);
+    },
+    // 部门列表
+    getDeptList(query?: object) {
+      return request.postRequest(basePath, 'Dept', 'GetList', query);
+    },
+  };
+}

+ 33 - 1
src/router.ts

@@ -114,7 +114,39 @@ const routes = [
       title: '新增故障报修'
     }
   },
-   {
+  {
+    name: 'inspectionHome',
+    path: '/lab/inspection/home',
+    component: () => import('/@/view/laboratory/inspection/index.vue'),
+    meta: {
+      title: '巡检信息'
+    }
+  },
+  {
+    name: 'inspectionDetails',
+    path: '/lab/inspection/details',
+    component: () => import('/@/view/laboratory/inspection/details.vue'),
+    meta: {
+      title: '巡检信息详情'
+    }
+  },
+  {
+    name: 'addInspTask',
+    path: '/lab/inspection/addInspTask',
+    component: () => import('/@/view/laboratory/inspection/addInspTask.vue'),
+    meta: {
+      title: '巡检任务创建'
+    }
+  },
+  {
+    name: 'inspectionFeedback',
+    path: '/lab/inspection/feedback',
+    component: () => import('/@/view/laboratory/inspection/feedback.vue'),
+    meta: {
+      title: '隐患整改'
+    }
+  },
+  {
     name: 'repairReportConfirm',
     path: '/inst/repairReport/confirm',
     component: () => import('/@/view/instr/repairReport/confirm.vue'),

+ 1 - 1
src/view/animal/application/components/Application.vue

@@ -280,7 +280,7 @@
   import { UploadFile } from 'element-plus/es/components'
   import dayjs from 'dayjs'
   import { storeToRefs } from 'pinia'
-
+  import { UploadFileType } from '/@/constants/pageConstants'
   import { usePlatAnimalCageApplicationApi } from '/@/api/platform/animal'
   import { LeavelList } from '/@/constants/pageConstants'
   import { deepClone } from '/@/utils/other'

+ 4 - 0
src/view/home/index.vue

@@ -59,6 +59,10 @@
           <img src="../../assets/img/更多应用.png" alt="" />
           <p>故障报修</p>
         </li>
+        <li @click="onRouterPush('/lab/inspection/home')">
+          <img src="../../assets/img/更多应用.png" alt="" />
+          <p>巡检任务</p>
+        </li>
       </ul>
     </div>
     <div class="swipe-con flex justify-between mt10">

+ 282 - 0
src/view/laboratory/inspection/addInspTask.vue

@@ -0,0 +1,282 @@
+<!--
+ * @Author: wanglj wanglijie@dashoo.cn
+ * @Date: 2025-03-18 20:02:42
+ * @LastEditors: wanglj wanglijie@dashoo.cn
+ * @LastEditTime: 2025-03-21 09:46:32
+ * @FilePath: \labsop_h5\src\view\training\enroll.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div class="app-container">
+    <van-form ref="formRef" @submit="onSubmit" class="mt10" required="auto">
+      <h4 class="mb8 mt8">巡检信息</h4>
+      <van-field v-model="state.form.taskTitle" label="任务名称" placeholder="任务名称" :rules="[{ required: true, message: '请输入任务名称' }]" />
+      <van-cell-group>
+        <van-field
+          v-model="state.form.labName"
+          label="实验室"
+          placeholder="实验室"
+          readonly
+          @click="state.shwoLab = true"
+          :rules="[{ required: true, message: '请选择实验室' }]"
+        />
+        <van-field
+          v-model="state.form.frcnPmName"
+          label="负责人"
+          placeholder="负责人"
+          readonly
+          @click="state.shwoUser = true"
+          :rules="[{ required: true, message: '请选择负责人' }]"
+        />
+        <van-field
+          v-model="state.form.date"
+          label="限定整改时间"
+          placeholder="限定整改时间"
+          :rules="[{ required: true, message: '限定整改时间' }]"
+          @click="showAddDatePicker = true"
+          readonly
+        />
+        <van-field
+          v-model="state.form.troubleDesc"
+          rows="3"
+          autosize
+          type="textarea"
+          maxlength="200"
+          show-word-limit
+          label="隐患说明"
+          placeholder="隐患说明"
+          :rules="[{ required: true, message: '请输入隐患说明' }]"
+        />
+        <van-field name="uploader" label="隐患照片" :rules="[{ required: true, message: '请上传隐患照片' }]">
+          <template #input>
+            <van-uploader v-model="state.form.photos" :after-read="afterRead" preview-size="60" :preview-full-image="true" :max-count="6" />
+          </template>
+        </van-field>
+      </van-cell-group>
+      <van-action-bar placeholder>
+        <van-action-bar-icon icon="wap-home-o" text="首页" @click="router.push('/home')" />
+        <van-action-bar-icon icon="revoke" text="返回" @click="router.push('/lab/inspection/home')" />
+        <van-action-bar-button type="primary" text="立即提交" :loading="loading" native-type="submit" />
+      </van-action-bar>
+    </van-form>
+  </div>
+  <!-- 实验室 -->
+  <van-popup v-model:show="state.shwoLab" position="bottom">
+    <van-picker :columns="labList" :columns-field-names="{ text: 'labName', value: 'id' }" @confirm="pickLab" @cancel="state.shwoLab = false" />
+  </van-popup>
+  <!-- 负责人 -->
+  <van-popup v-model:show="state.shwoUser" position="bottom">
+    <van-picker :columns="userList" :columns-field-names="{ text: 'name', value: 'id' }" @confirm="pickUser" @cancel="state.shwoUser = false" />
+  </van-popup>
+  <!-- 所在时间 -->
+  <van-popup v-model:show="showAddDatePicker" position="bottom">
+    <van-calendar v-model:show="showAddDatePicker" @confirm="onConfirmDate" @cancel="showAddDatePicker = false" type="range" />
+  </van-popup>
+</template>
+
+<script name="repairReportConfirm" lang="ts" setup>
+  import to from 'await-to-js'
+  import { onMounted, reactive, ref } from 'vue'
+  import { storeToRefs } from 'pinia'
+  import { useUserInfo } from '/@/stores/userInfo'
+  import { showNotify } from 'vant'
+  import { formatDate } from '/@/utils/formatTime'
+  import { useRouter } from 'vue-router'
+  import { handleUpload } from '/@/utils/upload'
+  import { useRectificationNewApi } from '/@/api/laboratory/rectification/indexNew'
+  import { useLabApi } from '/@/api/laboratory/lab'
+  import { useSystemApi } from '/@/api/laboratory/system'
+
+  const LabApi = useLabApi()
+  const rectificationApi = useRectificationNewApi()
+  const systemApi = useSystemApi()
+
+  const labList = ref([])
+  const userList = ref([])
+
+  const storesUseUserInfo = useUserInfo()
+  const router = useRouter()
+
+  const { userInfos } = storeToRefs(storesUseUserInfo)
+
+  const formRef = ref()
+  const state = reactive({
+    form: {
+      taskTitle: '',
+      labId: null,
+      frcnPmId: null,
+      date: '',
+      photos: [] as any,
+      frcnStartDate: '',
+      frcnEndDate: '',
+      labName: '',
+      troubleDesc: '',
+      frcnPmName: ''
+    },
+    shwoLab: false,
+    shwoUser: false
+  })
+  const loading = ref(false) // 加载状态
+
+  const initForm = async () => {
+    state.form = {
+      taskTitle: '',
+      labId: null,
+      frcnPmId: null,
+      date: '',
+      photos: [] as any,
+      frcnStartDate: '',
+      frcnEndDate: '',
+      labName: '',
+      troubleDesc: '',
+      frcnPmName: ''
+    }
+  }
+
+  const date = ref([]) // 选择的日期
+  const maxDate = ref(new Date()) // 最大日期
+
+  const showAddDatePicker = ref(false) // 是否显示选择日期的弹窗
+
+  const getLabList = async () => {
+    const [err, res]: ToResponse = await to(LabApi.getList())
+    if (err) return
+    labList.value = res?.data.list
+  }
+
+  const getUserList = async () => {
+    systemApi.getInstUserList({ roleCode: 'laboratory_manager' }).then((user) => {
+      userList.value = user.data.map((item: any) => ({ id: item.id, name: item.nickName }))
+    })
+  }
+  const onSubmit = async () => {
+    console.log('提交表单')
+    const [errValid] = await to(formRef.value.validate())
+    if (errValid) return
+    let params = JSON.parse(JSON.stringify(state.form))
+    console.log(params)
+    const files = params.photos.map((item: any) => {
+      return {
+        name: item.name,
+        url: item.url
+      }
+    })
+    loading.value = true
+    const [err, res]: ToResponse = await to(rectificationApi.onCreate(params))
+    loading.value = false
+    if (err) return
+    showNotify({
+      type: 'success',
+      message: '巡检隐患信息已提交,请耐心等待处理'
+    })
+    setTimeout(() => {
+      router.push('/lab/inspection/home')
+    }, 1000)
+  }
+
+  const onConfirmDate = (values) => {
+    const [start, end] = values
+    showAddDatePicker.value = false
+    state.form.frcnStartDate = formatDate(new Date(start), 'YYYY-mm-dd')
+    state.form.frcnEndDate = formatDate(new Date(end), 'YYYY-mm-dd')
+    state.form.date = state.form.frcnStartDate + '-' + state.form.frcnEndDate
+  }
+
+  const pickLab = ({ selectedOptions }: { selectedOptions: any[] }) => {
+    state.shwoLab = false
+    state.form.labId = selectedOptions[selectedOptions.length - 1].id
+    state.form.labName = selectedOptions[selectedOptions.length - 1].labName
+  }
+
+  const pickUser = ({ selectedOptions }: { selectedOptions: any[] }) => {
+    state.shwoUser = false
+    state.form.frcnPmId = selectedOptions[selectedOptions.length - 1].id
+    state.form.frcnPmName = selectedOptions[selectedOptions.length - 1].name
+  }
+
+  const afterRead = async (files: any) => {
+    if (files.length) {
+      for (const file of files) {
+        file.status = 'uploading'
+        const [err, res]: ToResponse = await to(handleUpload(file.file))
+        if (err) {
+          file.status = 'failed'
+          return
+        }
+        file.status = 'success'
+        file.url = res
+        file.name = file.file.name
+      }
+    } else {
+      const file = files
+      file.status = 'uploading'
+      const [err, res]: ToResponse = await to(handleUpload(file.file))
+      if (err) {
+        file.status = 'failed'
+        return
+      }
+      file.status = 'success'
+      file.url = res
+      file.name = file.file.name
+    }
+  }
+
+  onMounted(async () => {
+    getLabList()
+    getUserList()
+    initForm()
+  })
+</script>
+
+<style lang="scss" scoped>
+  .app-container {
+    header {
+      padding: 14px;
+      background-color: #f9ffff;
+      border-radius: 4px;
+      margin-top: 10px;
+    }
+    h4 {
+      margin: 10px 0;
+      height: 20px;
+      line-height: 20px;
+      &::before {
+        display: inline-block;
+        content: '';
+        background-color: #3c78e3;
+        width: 4px;
+        height: 20px;
+        margin-right: 4px;
+        vertical-align: top;
+      }
+    }
+    :deep(.flow-cell) {
+      margin-left: 22px;
+      display: flex;
+      justify-content: space-between;
+      color: #333;
+    }
+  }
+  .ck-editor {
+    height: calc(100vh - 100px);
+    overflow-y: auto;
+    padding: 0 10px;
+  }
+  .need-to-know {
+    height: calc(100% - 20px);
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    padding: 10px 20px;
+    white-space: pre-wrap;
+    p {
+      flex: 1;
+      overflow-y: auto;
+    }
+    footer {
+      flex: 0 0 45px;
+      margin-top: 4px;
+      border-top: 1px solid #f7f8fa;
+    }
+  }
+</style>

+ 173 - 0
src/view/laboratory/inspection/details.vue

@@ -0,0 +1,173 @@
+<!--
+ * @Author: wanglj wanglijie@dashoo.cn
+ * @Date: 2025-03-18 20:02:42
+ * @LastEditors: wanglj wanglijie@dashoo.cn
+ * @LastEditTime: 2025-03-21 09:46:32
+ * @FilePath: \labsop_h5\src\view\training\enroll.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div class="app-container">
+    <van-form ref="formRef" class="mt10" required="auto">
+      <h4 class="mb8 mt8">隐患信息</h4>
+      <van-field v-model="state.form.taskTitle" label="任务名称" readonly />
+      <van-cell-group>
+        <van-field v-model="state.form.labName" label="实验室" placeholder="实验室" readonly />
+        <van-field v-model="state.form.frcnPmName" label="负责人" placeholder="负责人" readonly />
+        <van-field v-model="state.form.date" label="限定整改时间" placeholder="限定整改时间" readonly>
+          <template #input>
+            {{ formatDate(new Date(state.form.frcnStartDate), 'YYYY-mm-dd') }} ~
+            {{ formatDate(new Date(state.form.frcnEndDate), 'YYYY-mm-dd') }}
+          </template>
+        </van-field>
+        <van-field v-model="state.form.troubleDesc" autosize type="textarea" label="隐患说明" placeholder="隐患说明" readonly />
+        <van-field name="uploader" label="隐患照片">
+          <template #input>
+            <div>
+              <van-image
+                class="mr10 mb10"
+                v-for="(v, i) in state.form.photos"
+                width="100"
+                height="100"
+                :src="v.url"
+                @click="showPreviewImg(state.form.photos, i)"
+              />
+            </div>
+          </template>
+        </van-field>
+      </van-cell-group>
+      <h4 class="mb8 mt8">整改信息</h4>
+      <div v-if="state.form.frcnStatus == '10'">暂未进行整改</div>
+      <van-cell-group v-else>
+        <van-field v-model="state.form.frcnCompleteDate" label="整改时间" placeholder="整改时间" readonly>
+          <template #input>
+            {{ formatDate(new Date(state.form.frcnCompleteDate), 'YYYY-mm-dd') }}
+          </template>
+        </van-field>
+        <van-field v-model="state.form.alterDesc" autosize type="textarea" label="整改说明" placeholder="整改说明" />
+        <van-field name="uploader" label="整改照片" :rules="[{ required: true, message: '请上传整改照片' }]">
+          <template #input>
+            <div>
+              <van-image
+                class="mr10 mb10"
+                v-for="(v, i) in state.form.alterPhotos"
+                width="100"
+                height="100"
+                :src="v.url"
+                @click="showPreviewImg(state.form.alterPhotos, i)"
+              />
+            </div>
+          </template>
+        </van-field>
+      </van-cell-group>
+    </van-form>
+  </div>
+</template>
+
+<script name="repairReportConfirm" lang="ts" setup>
+  import to from 'await-to-js'
+  import { onMounted, reactive, ref } from 'vue'
+  import { showNotify, showImagePreview } from 'vant'
+  import { formatDate } from '/@/utils/formatTime'
+  import { useRouter } from 'vue-router'
+  import { useRectificationNewApi } from '/@/api/laboratory/rectification/indexNew'
+
+  const rectificationApi = useRectificationNewApi()
+
+  const router = useRouter()
+
+  const formRef = ref()
+  const state = reactive({
+    form: {
+      taskTitle: '',
+      labId: null,
+      frcnPmId: null,
+      date: '',
+      photos: [] as any,
+      frcnStartDate: '',
+      frcnEndDate: '',
+      labName: '',
+      troubleDesc: '',
+      frcnPmName: '',
+      alterDesc: '',
+      frcnCompleteDate: '',
+      alterPhotos: [] as any,
+      frcnStatus: '10'
+    }
+  })
+  const initForm = async () => {
+    const id = Number(router.currentRoute.value.query.id) || null
+    if (!id)
+      return showNotify({
+        type: 'warning',
+        message: '未指定巡检信息'
+      })
+    const [err, res]: ToResponse = await to(rectificationApi.getDetail({ id }))
+    if (err) return
+    state.form = res?.data
+  }
+
+  const showPreviewImg = (photos: string, index: number) => {
+    const images = JSON.parse(photos).map((item: any) => item.url)
+    showImagePreview({
+      images,
+      startPosition: index
+    })
+  }
+  onMounted(async () => {
+    initForm()
+  })
+</script>
+
+<style lang="scss" scoped>
+  .app-container {
+    header {
+      padding: 14px;
+      background-color: #f9ffff;
+      border-radius: 4px;
+      margin-top: 10px;
+    }
+    h4 {
+      margin: 10px 0;
+      height: 20px;
+      line-height: 20px;
+      &::before {
+        display: inline-block;
+        content: '';
+        background-color: #3c78e3;
+        width: 4px;
+        height: 20px;
+        margin-right: 4px;
+        vertical-align: top;
+      }
+    }
+    :deep(.flow-cell) {
+      margin-left: 22px;
+      display: flex;
+      justify-content: space-between;
+      color: #333;
+    }
+  }
+  .ck-editor {
+    height: calc(100vh - 100px);
+    overflow-y: auto;
+    padding: 0 10px;
+  }
+  .need-to-know {
+    height: calc(100% - 20px);
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    padding: 10px 20px;
+    white-space: pre-wrap;
+    p {
+      flex: 1;
+      overflow-y: auto;
+    }
+    footer {
+      flex: 0 0 45px;
+      margin-top: 4px;
+      border-top: 1px solid #f7f8fa;
+    }
+  }
+</style>

+ 247 - 0
src/view/laboratory/inspection/feedback.vue

@@ -0,0 +1,247 @@
+<!--
+ * @Author: wanglj wanglijie@dashoo.cn
+ * @Date: 2025-03-18 20:02:42
+ * @LastEditors: wanglj wanglijie@dashoo.cn
+ * @LastEditTime: 2025-03-21 09:46:32
+ * @FilePath: \labsop_h5\src\view\training\enroll.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div class="app-container">
+    <van-form ref="formRef" @submit="onSubmit" class="mt10" required="auto">
+      <h4 class="mb8 mt8">隐患信息</h4>
+      <van-field v-model="state.form.taskTitle" label="任务名称" readonly />
+      <van-cell-group>
+        <van-field v-model="state.form.labName" label="实验室" placeholder="实验室" readonly />
+        <van-field v-model="state.form.frcnPmName" label="负责人" placeholder="负责人" readonly />
+        <van-field v-model="state.form.date" label="限定整改时间" placeholder="限定整改时间" readonly>
+          <template #input>
+            {{ formatDate(new Date(state.form.frcnStartDate), 'YYYY-mm-dd') }} ~
+            {{ formatDate(new Date(state.form.frcnEndDate), 'YYYY-mm-dd') }}
+          </template>
+        </van-field>
+        <van-field v-model="state.form.troubleDesc" autosize type="textarea" label="隐患说明" placeholder="隐患说明" readonly />
+        <van-field name="uploader" label="隐患照片">
+          <template #input>
+            <div>
+              <van-image
+                class="mr10 mb10"
+                v-for="(v, i) in state.form.photos"
+                width="100"
+                height="100"
+                :src="v.url"
+                @click="showPreviewImg(state.form.photos, i)"
+              />
+            </div>
+          </template>
+        </van-field>
+      </van-cell-group>
+      <h4 class="mb8 mt8">整改信息</h4>
+      <van-cell-group>
+        <van-field
+          v-model="state.alterForm.frcnCompleteDate"
+          label="整改时间"
+          placeholder="整改时间"
+          :rules="[{ required: true, message: '整改时间' }]"
+          @click="showAddDatePicker = true"
+          readonly
+        />
+        <van-field
+          v-model="state.alterForm.alterDesc"
+          rows="3"
+          autosize
+          type="textarea"
+          maxlength="200"
+          show-word-limit
+          label="整改说明"
+          placeholder="整改说明"
+          :rules="[{ required: true, message: '请输入整改说明' }]"
+        />
+        <van-field name="uploader" label="整改照片" :rules="[{ required: true, message: '请上传整改照片' }]">
+          <template #input>
+            <van-uploader v-model="state.alterForm.alterPhotos" :after-read="afterRead" preview-size="60" :preview-full-image="true" :max-count="6" />
+          </template>
+        </van-field>
+      </van-cell-group>
+      <van-action-bar placeholder>
+        <van-action-bar-icon icon="wap-home-o" text="首页" @click="router.push('/home')" />
+        <van-action-bar-icon icon="revoke" text="返回" @click="router.push('/lab/inspection/home')" />
+        <van-action-bar-button type="primary" text="立即提交" :loading="loading" native-type="submit" />
+      </van-action-bar>
+    </van-form>
+  </div>
+  <!-- 所在时间 -->
+  <van-popup v-model:show="showAddDatePicker" position="bottom">
+    <van-date-picker v-model="date" title="选择日期" @confirm="onConfirmDate" @cancel="showAddDatePicker = false" />
+  </van-popup>
+</template>
+
+<script name="repairReportConfirm" lang="ts" setup>
+  import to from 'await-to-js'
+  import { onMounted, reactive, ref } from 'vue'
+  import { showNotify, showImagePreview } from 'vant'
+  import { formatDate } from '/@/utils/formatTime'
+  import { useRouter } from 'vue-router'
+  import { handleUpload } from '/@/utils/upload'
+  import { useRectificationNewApi } from '/@/api/laboratory/rectification/indexNew'
+
+  const rectificationApi = useRectificationNewApi()
+
+  const router = useRouter()
+
+  const formRef = ref()
+  const state = reactive({
+    form: {
+      taskTitle: '',
+      labId: null,
+      frcnPmId: null,
+      date: '',
+      photos: [] as any,
+      frcnStartDate: '',
+      frcnEndDate: '',
+      labName: '',
+      troubleDesc: '',
+      frcnPmName: ''
+    },
+    alterForm: {
+      alterDesc: '',
+      frcnCompleteDate: '',
+      alterPhotos: [] as any
+    },
+    shwoLab: false,
+    shwoUser: false
+  })
+  const loading = ref(false) // 加载状态
+  const date = ref([])
+  const initForm = async () => {
+    const id = Number(router.currentRoute.value.query.id) || null
+    if (!id)
+      return showNotify({
+        type: 'warning',
+        message: '未指定巡检信息'
+      })
+    const [err, res]: ToResponse = await to(rectificationApi.getDetail({ id }))
+    if (err) return
+    state.form = res?.data
+  }
+  date.value = [new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]
+  const showAddDatePicker = ref(false) // 是否显示选择日期的弹窗
+
+  const onSubmit = async () => {
+    console.log('提交表单')
+    const [errValid] = await to(formRef.value.validate())
+    if (errValid) return
+    let params = { ...state.alterForm, id: Number(router.currentRoute.value.query.id), frcnStatus: '40' }
+    console.log(params)
+    loading.value = true
+    const [err, res]: ToResponse = await to(rectificationApi.onUpdated(params))
+    loading.value = false
+    if (err) return
+    showNotify({
+      type: 'success',
+      message: '整改信息提交成功'
+    })
+    setTimeout(() => {
+      router.push('/lab/inspection/home')
+    }, 1000)
+  }
+
+  const onConfirmDate = (values) => {
+    showAddDatePicker.value = false
+    state.alterForm.frcnCompleteDate = `${date.value[0]}-${date.value[1]}-${date.value[2]}`
+    console.log(values)
+    // state.form.frcnStartDate = formatDate(new Date(start), 'YYYY-mm-dd')
+    // state.form.frcnEndDate = formatDate(new Date(end), 'YYYY-mm-dd')
+    // state.form.date = state.form.frcnStartDate + '-' + state.form.frcnEndDate
+  }
+
+  const afterRead = async (files: any) => {
+    if (files.length) {
+      for (const file of files) {
+        file.status = 'uploading'
+        const [err, res]: ToResponse = await to(handleUpload(file.file))
+        if (err) {
+          file.status = 'failed'
+          return
+        }
+        file.status = 'success'
+        file.url = res
+        file.name = file.file.name
+      }
+    } else {
+      const file = files
+      file.status = 'uploading'
+      const [err, res]: ToResponse = await to(handleUpload(file.file))
+      if (err) {
+        file.status = 'failed'
+        return
+      }
+      file.status = 'success'
+      file.url = res
+      file.name = file.file.name
+    }
+  }
+  const showPreviewImg = (photos: string, index: number) => {
+    const images = JSON.parse(photos).map((item: any) => item.url)
+    showImagePreview({
+      images,
+      startPosition: index
+    })
+  }
+  onMounted(async () => {
+    initForm()
+  })
+</script>
+
+<style lang="scss" scoped>
+  .app-container {
+    header {
+      padding: 14px;
+      background-color: #f9ffff;
+      border-radius: 4px;
+      margin-top: 10px;
+    }
+    h4 {
+      margin: 10px 0;
+      height: 20px;
+      line-height: 20px;
+      &::before {
+        display: inline-block;
+        content: '';
+        background-color: #3c78e3;
+        width: 4px;
+        height: 20px;
+        margin-right: 4px;
+        vertical-align: top;
+      }
+    }
+    :deep(.flow-cell) {
+      margin-left: 22px;
+      display: flex;
+      justify-content: space-between;
+      color: #333;
+    }
+  }
+  .ck-editor {
+    height: calc(100vh - 100px);
+    overflow-y: auto;
+    padding: 0 10px;
+  }
+  .need-to-know {
+    height: calc(100% - 20px);
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    padding: 10px 20px;
+    white-space: pre-wrap;
+    p {
+      flex: 1;
+      overflow-y: auto;
+    }
+    footer {
+      flex: 0 0 45px;
+      margin-top: 4px;
+      border-top: 1px solid #f7f8fa;
+    }
+  }
+</style>

+ 226 - 0
src/view/laboratory/inspection/index.vue

@@ -0,0 +1,226 @@
+<!--
+ * @Author: wanglj wanglijie@dashoo.cn
+ * @Date: 2025-03-11 18:02:10
+ * @LastEditors: wanglj wanglijie@dashoo.cn
+ * @LastEditTime: 2025-04-16 16:19:33
+ * @FilePath: \vant-demo-master\vant\vue3-ts\src\view\login\index.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div class="entry-container">
+    <div class="search-wrap">
+      <van-search placeholder="请输入任务名称" v-model="state.queryParams.taskTitle" :clearabled="true" style="padding: 0; flex: 1" class="mr10"></van-search>
+      <div>
+        <van-button type="primary" style="width: 60px" shape="circle" size="small" @click="onLoad"> 搜索 </van-button>
+      </div>
+    </div>
+    <van-tabs v-model:active="state.queryParams.frcnStatus" @change="changeType">
+      <van-tab title="待整改" name="10"></van-tab>
+      <van-tab title="整改完成" name="40"></van-tab>
+      <van-tab title="全部" name=""></van-tab>
+    </van-tabs>
+    <div class="list-container">
+      <van-list v-model:loading="state.loading" :finished="state.finished" finished-text="没有更多了" @load="onLoad">
+        <van-cell v-for="item in state.list" :key="item" @click.stop="toDetails(item.id)">
+          <template #default>
+            <div class="list">
+              <header class="flex justify-between">
+                <strong class="title">{{ `${item.taskTitle}` }}</strong>
+                <van-tag v-if="item.frcnStatus == 10" type="primary">待整改</van-tag>
+                <van-tag v-else-if="item.frcnStatus == 40" type="success">整改完成</van-tag>
+              </header>
+              <p class="inst-title">
+                <span>实验室名称</span>
+                <span class="title ml8"> {{ item.labName }} </span>
+              </p>
+              <p class="inst-title">
+                <span>实验室负责人</span>
+                <span class="title ml8"> {{ item.frcnPmName }}</span>
+              </p>
+              <p class="inst-title">
+                <span>限定整改时间</span>
+                <span class="title ml8">
+                  {{ formatDate(new Date(item.frcnStartDate), 'YYYY-mm-dd') }}~{{ formatDate(new Date(item.frcnEndDate), 'YYYY-mm-dd') }}</span
+                >
+              </p>
+              <p class="inst-title">
+                <span>实际整改时间</span>
+                <span class="title ml8">{{ formatDate(new Date(item.frcnCompleteDate), 'YYYY-mm-dd') }}</span>
+              </p>
+              <!-- <footer class="flex justify-between mt4">
+                <span class="title">{{ item.createdName }}</span>
+                <span class="time">{{ formatDate(new Date(item.createdTime), 'YYYY-mm-dd') }}</span>
+              </footer> -->
+              <div class="flex mt20 btns">
+                <van-button
+                  style="width: 70px; height: 30px; margin: 0; font-size: 14px"
+                  type="success"
+                  size="small"
+                  v-if="item.frcnStatus == 10"
+                  @click.native.stop="onFeedback(item.id)"
+                >
+                  反馈
+                </van-button>
+              </div>
+            </div>
+          </template>
+        </van-cell>
+      </van-list>
+    </div>
+    <van-floating-bubble v-model:offset="offset" icon="plus" @click="onAdd" axis="y" />
+  </div>
+</template>
+
+<script name="repairReportHome" lang="ts" setup>
+  import to from 'await-to-js'
+  import { formatDate } from '/@/utils/formatTime'
+  import { onMounted, reactive, ref } from 'vue'
+  import { useRouter, useRoute } from 'vue-router'
+  import { useRectificationNewApi } from '/@/api/laboratory/inspection'
+  import { showImagePreview, showConfirmDialog, showNotify } from 'vant'
+  import 'vant/es/image-preview/style'
+
+  const inspectionNewApi = useRectificationNewApi()
+
+  const router = useRouter()
+  const route = useRoute()
+  const offset = ref({ x: -80, y: 450 })
+  const offsetScan = ref({ x: -80, y: 540 })
+  const state = reactive({
+    queryParams: {
+      taskTitle: '',
+      frcnStatus: '10',
+      pageNum: 1,
+      pageSize: 10
+    },
+    finished: false,
+    loading: true,
+    list: [] as any[]
+  })
+
+  const changeType = () => {
+    state.queryParams.pageNum = 1
+    state.list = []
+    onLoad()
+  }
+
+  const onLoad = async () => {
+    const [err, res]: ToResponse = await to(inspectionNewApi.getList(state.queryParams))
+    if (err) return
+    const list = res?.data?.list || []
+    for (const item of list) {
+      state.list.push(item)
+    }
+    state.loading = false
+    state.queryParams.pageNum++
+    if (list.length < state.queryParams.pageSize) {
+      state.finished = true
+    }
+  }
+
+  onMounted(() => {
+    onLoad()
+  })
+
+  const onClose = async (item: any) => {
+    // showConfirmDialog({
+    //   title: '提示',
+    //   message: '确认关闭当前报修记录?'
+    // }).then(async () => {
+    //   const [err, res]: ToResponse = await to(repairReportApi.close({ id: item.id }))
+    //   if (err) return
+    //   showNotify({ type: 'success', message: '关闭成功' })
+    //   changeType() // 刷新列表
+    // })
+  }
+
+  const showPreviewImg = (fullPhoto: string, index: number) => {
+    console.log('fullPhoto', fullPhoto)
+    const images = JSON.parse(fullPhoto).map((item: any) => item.url)
+    showImagePreview({
+      images,
+      startPosition: index
+    })
+  }
+
+  const onAdd = () => {
+    router.push('/lab/inspection/addInspTask')
+  }
+
+  const toDetails = async (id: number) => {
+    router.push('/lab/inspection/details?id=' + id)
+  }
+
+  const onFeedback = (id: number) => {
+    router.push('/lab/inspection/feedback?id=' + id)
+  }
+</script>
+
+<style lang="scss" scoped>
+  .entry-container {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    .list-container {
+      overflow-y: auto;
+      padding: 10px;
+      border-radius: 4px;
+      flex: 1;
+    }
+    .van-list {
+      .van-cell {
+        background-color: #fff;
+        + .van-cell {
+          margin-top: 10px;
+        }
+        header,
+        footer {
+          color: #333;
+        }
+        .title {
+          flex: 1;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          text-align: left;
+        }
+        .inst-title {
+          color: #333;
+          text-align: left;
+          flex: 1;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          margin-top: 4px;
+          span:first-child {
+            color: rgb(120, 120, 120);
+          }
+        }
+        .time {
+          color: #f69a4d;
+        }
+      }
+    }
+  }
+  .pic-col {
+    color: #333;
+    text-align: left;
+    flex: 1;
+    margin-top: 4px;
+    display: flex;
+    span:first-child {
+      width: 100px;
+      color: rgb(120, 120, 120);
+    }
+  }
+  .btns {
+    justify-content: flex-end;
+  }
+  .search-wrap {
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+    padding: 15px 15px 0;
+    background: #fff;
+  }
+</style>

+ 2 - 2
src/view/todo/component/approveTasks.vue

@@ -76,8 +76,8 @@
     title: '',
     submitTxt: ''
   })
-  const idList = ref<[]>([])
-  const state = reactive<PatrolMissionState>({
+  const idList = ref([])
+  const state = reactive<any>({
     taskDetail: {},
     detail: {},
     form: {