Kaynağa Gözat

feat: 增加生化管理模块

Tong 2 yıl önce
ebeveyn
işleme
01243eb3e6

+ 21 - 0
src/api/biz/bio/chemicalPollutantDetectionApi.ts

@@ -0,0 +1,21 @@
+import { defHttp } from '/@/utils/http/axios';
+import { setParams } from '/@/utils/index';
+
+enum Api {
+  chemicalPollutantDetectionQueryPage = '/biz/device/chemicalPollutantDetection/query/page',
+  chemicalPollutantDetectionAdd = '/biz/device/chemicalPollutantDetection/add',
+  chemicalPollutantDetectionRemove = '/biz/device/chemicalPollutantDetection/removeByIds',
+}
+
+// 查询设备列表
+export const chemicalPollutantDetectionQueryPage = (params?: object) => {
+  return defHttp.post({ url: Api.chemicalPollutantDetectionQueryPage, params: setParams(params) });
+};
+// 添加设备
+export const chemicalPollutantDetectionAdd = (params?: object) => {
+  return defHttp.post({ url: Api.chemicalPollutantDetectionAdd, params: params });
+};
+
+export const chemicalPollutantDetectionRemove = (params?: object) => {
+  return defHttp.post({ url: Api.chemicalPollutantDetectionRemove, params: params });
+};

+ 26 - 0
src/api/biz/bio/microbialDetectionDialysateApi.ts

@@ -0,0 +1,26 @@
+import { defHttp } from '/@/utils/http/axios';
+import { setParams } from '/@/utils/index';
+
+enum Api {
+  microbialDetectionDialysateQueryPage = '/biz/device/microbialDetection/dialysate/page',
+  microbialDetectionDialysateDetail = '/biz/device/microbialDetection/dialysate/detail',
+  microbialDetectionDialysateAdd = '/biz/device/microbialDetection/dialysate/add',
+  microbialDetectionDialysateEdit = '/biz/device/microbialDetection/dialysate/edit',
+}
+
+// 查询设备列表
+export const microbialDetectionDialysateQueryPage = (params?: object) => {
+  return defHttp.post({ url: Api.microbialDetectionDialysateQueryPage, params: setParams(params) });
+};
+// 添加设备
+export const microbialDetectionDialysateAdd = (params?: object) => {
+  return defHttp.post({ url: Api.microbialDetectionDialysateAdd, params: params });
+};
+// 编辑设备信息
+export const microbialDetectionDialysateEdit = (params?: object) => {
+  return defHttp.post({ url: Api.microbialDetectionDialysateEdit, params: params });
+};
+// 其他设备详情
+export const microbialDetectionDialysateDetail = (id: string) => {
+  return defHttp.get({ url: Api.microbialDetectionDialysateDetail + '/' + id });
+};

+ 26 - 0
src/api/biz/bio/microbialDetectionWaterApi.ts

@@ -0,0 +1,26 @@
+import { defHttp } from '/@/utils/http/axios';
+import { setParams } from '/@/utils/index';
+
+enum Api {
+  microbialDetectionWaterQueryPage = '/biz/device/microbialDetection/dialysisWater/page',
+  microbialDetectionWaterDetail = '/biz/device/microbialDetection/dialysisWater/detail',
+  microbialDetectionWaterAdd = '/biz/device/microbialDetection/dialysisWater/add',
+  microbialDetectionWaterEdit = '/biz/device/microbialDetection/dialysisWater/edit',
+}
+
+// 查询设备列表
+export const microbialDetectionWaterQueryPage = (params?: object) => {
+  return defHttp.post({ url: Api.microbialDetectionWaterQueryPage, params: setParams(params) });
+};
+// 添加设备
+export const microbialDetectionWaterAdd = (params?: object) => {
+  return defHttp.post({ url: Api.microbialDetectionWaterAdd, params: params });
+};
+// 编辑设备信息
+export const microbialDetectionWaterEdit = (params?: object) => {
+  return defHttp.post({ url: Api.microbialDetectionWaterEdit, params: params });
+};
+// 其他设备详情
+export const microbialDetectionWaterDetail = (id: string) => {
+  return defHttp.get({ url: Api.microbialDetectionWaterDetail + '/' + id });
+};

+ 5 - 0
src/api/biz/engineer/dialysisDeviceApi.ts

@@ -7,6 +7,7 @@ enum Api {
   engineerDialysisDeviceAdd = '/device/dialysisDevice/add',
   engineerDialysisDeviceEdit = '/device/dialysisDevice/edit',
   engineerDialysisDeviceRemove = '/device/dialysisDevice/removeByIds',
+  engineerDialysisDeviceList = '/device/dialysisDevice/query/noPage',
 }
 
 /**
@@ -67,3 +68,7 @@ export const engineerDialysisDeviceEdit = (params?: object) => {
 export const engineerDialysisDeviceRemove = (params: Array<string | number>) => {
   return defHttp.post({ url: Api.engineerDialysisDeviceRemove, params: params });
 };
+
+export const engineerDialysisDeviceList = (params?: object) => {
+  return defHttp.post({ url: Api.engineerDialysisDeviceList, params: params });
+};

+ 5 - 0
src/api/biz/engineer/waterApi.ts

@@ -7,6 +7,7 @@ enum Api {
   waterAdd = '/biz/waterTreatmentDevice/add',
   waterEdit = '/biz/waterTreatmentDevice/edit',
   waterRemove = '/biz/device/dialysisMaintain/removeByIds/',
+  waterList = '/biz/waterTreatmentDevice/query/noPage',
 }
 
 // 查询设备列表
@@ -29,3 +30,7 @@ export const waterEdit = (params?: object) => {
 export const waterDetail = (id: string) => {
   return defHttp.get({ url: Api.waterDetail + '/' + id });
 };
+
+export const waterList = (params?: object) => {
+  return defHttp.post({ url: Api.waterList, params: params });
+};

+ 474 - 0
src/views/biz/engineer/bio/chemicalPollutantDetection/data.ts

@@ -0,0 +1,474 @@
+import { BasicColumn, FormSchema } from '/@/components/Table';
+import { sysUserQueryPage } from '/@/api/sys/sysUserApi';
+import { waterList, waterDetail } from '/@/api/biz/engineer/waterApi';
+import dayjs from 'dayjs';
+export const columns: BasicColumn[] = [
+  {
+    title: '设备编号',
+    dataIndex: 'deviceUniqueCode',
+    width: 120,
+  },
+  {
+    title: '设备信息',
+    dataIndex: 'deviceInfo',
+    width: 160,
+  },
+  {
+    title: '检测时间',
+    dataIndex: 'detectionTime',
+    width: 160,
+  },
+  {
+    title: '透析用水中的有毒化学物质',
+    dataIndex: 'toxicChemicals',
+    children: [
+      {
+        title: '铝(mg/L) 正常值≤0.01',
+        dataIndex: 'aluminum',
+        width: 120,
+      },
+      {
+        title: '总氯(mg/L) 正常值≤0.1',
+        dataIndex: 'totalChlorine',
+        width: 120,
+      },
+      {
+        title: '铜(mg/L) 正常值≤0.01',
+        dataIndex: 'copper',
+        width: 120,
+      },
+      {
+        title: '氟化物 (mg/L) 正常值≤0.2',
+        dataIndex: 'fluoride',
+        width: 120,
+      },
+      {
+        title: '铅(mg/L) 正常值≤ 0.005',
+        dataIndex: 'lead',
+        width: 120,
+      },
+      {
+        title: '硝酸盐(氮)(mg/L)正常值≤2',
+        dataIndex: 'nitrate',
+        width: 130,
+      },
+      {
+        title: '硫酸盐 (mg/L) 正常值≤100',
+        dataIndex: 'sulfate',
+        width: 120,
+      },
+      {
+        title: '锌(mg/L) 正常值≤0.1',
+        dataIndex: 'zinc',
+        width: 120,
+      },
+    ],
+  },
+  {
+    title: '透析溶液中的电解质',
+    dataIndex: 'electrolyte',
+    children: [
+      {
+        title: '钙(mmol/L) 正常值≤2 (0.05mmol/L)',
+        dataIndex: 'calcium',
+        width: 120,
+      },
+      {
+        title: '镁(mmol/L) 正常值≤4 (0.15mmol/L)',
+        dataIndex: 'magnesium',
+        width: 120,
+      },
+      {
+        title: '钾(mmol/L) 正常值≤8 (0.2mmol/L)',
+        dataIndex: 'potassium',
+        width: 120,
+      },
+      {
+        title: '钠(mmol/L) 正常值≤70 (3.0mmol/L)',
+        dataIndex: 'sodium',
+        width: 120,
+      },
+    ],
+  },
+  {
+    title: '透析用水中的微量元素',
+    dataIndex: 'traceElement',
+    children: [
+      {
+        title: '锑(mg/L) 正常值≤0.006',
+        dataIndex: 'antimony',
+        width: 120,
+      },
+      {
+        title: '砷(mg/L) 正常值≤0.005',
+        dataIndex: 'arsenic',
+        width: 120,
+      },
+      {
+        title: '钡(mg/L) 正常值≤0.1',
+        dataIndex: 'barium',
+        width: 120,
+      },
+      {
+        title: '铍(mg/L) 正常值≤0.0004',
+        dataIndex: 'beryllium',
+        width: 120,
+      },
+      {
+        title: '镉(mg/L) 正常值≤0.001',
+        dataIndex: 'cadmium',
+        width: 120,
+      },
+      {
+        title: '铬(mg/L) 正常值≤0.014',
+        dataIndex: 'chromium',
+        width: 120,
+      },
+      {
+        title: '汞(mg/L) 正常值≤0.0002',
+        dataIndex: 'mercury',
+        width: 120,
+      },
+      {
+        title: '硒(mg/L) 正常值≤0.09',
+        dataIndex: 'selenium',
+        width: 120,
+      },
+      {
+        title: '银(mg/L) 正常值≤0.005',
+        dataIndex: 'silver',
+        width: 120,
+      },
+      {
+        title: '铊(mg/L) 正常值≤0.02',
+        dataIndex: 'thallium',
+        width: 120,
+      },
+    ],
+  },
+];
+// 表单新增编辑
+export const dataFormSchema: FormSchema[] = [
+  {
+    label: '设备编号搜索',
+    field: 'uniqueCodes',
+    component: 'Input',
+    ifShow: false,
+  },
+  {
+    field: 'selDervice',
+    component: 'PlainTitle',
+    defaultValue: '选择设备',
+  },
+  {
+    label: '设备编号',
+    field: 'deviceId',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: ({ formModel }) => {
+      return {
+        api: waterList,
+        params: {
+          uniqueCode: formModel.uniqueCodes,
+        },
+        labelField: 'uniqueCode',
+        valueField: 'id',
+        resultField: 'data',
+        placeholder: '请选择设备编号',
+        getPopupContainer: () => document.body,
+        showSearch: true,
+        filterOption: false,
+        onSearch: e => {
+          formModel.uniqueCodes = e;
+        },
+        onChange: async e => {
+          const resData = await waterDetail(e);
+          formModel['deviceManufacturer'] = resData?.manufacturer;
+          formModel['deviceModel'] = resData?.model;
+        },
+      };
+    },
+  },
+  {
+    label: '设备厂家',
+    field: 'deviceManufacturer',
+    required: true,
+    component: 'Input',
+    slot: 'deviceManufacturer',
+    componentProps: {
+      disabled: true,
+    },
+  },
+  {
+    label: '设备型号',
+    field: 'deviceModel',
+    required: true,
+    component: 'Input',
+    slot: 'deviceModel',
+    componentProps: {
+      disabled: true,
+    },
+  },
+  {
+    field: 'deteRecords',
+    component: 'PlainTitle',
+    defaultValue: '检测记录',
+  },
+  {
+    label: '检测时间',
+    field: 'detectionTime',
+    component: 'DatePicker',
+    componentProps: () => {
+      return {
+        placeholder: '请选择检测时间',
+        getPopupContainer: () => document.body,
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
+        showTime: true,
+      };
+    },
+    defaultValue: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+  },
+  {
+    label: '检测人',
+    field: 'inspectorId',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: sysUserQueryPage,
+      params: {
+        pageNum: 1,
+        pageSize: 999,
+        disable: '0',
+      },
+      mode: 'single',
+      labelField: 'nickname',
+      valueField: 'id',
+      resultField: 'data',
+      placeholder: '请选择检测人',
+    },
+  },
+  {
+    label: '铝(mg/L)',
+    field: 'to_aluminum',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入氟化物(mg/L)',
+    },
+  },
+  {
+    label: '总氯(mg/L)',
+    field: 'to_totalChlorine',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入总氯(mg/L)',
+    },
+  },
+  {
+    label: '铜(mg/L)',
+    field: 'to_copper',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入铜(mg/L)',
+    },
+  },
+  {
+    label: '氟化物(mg/L)',
+    field: 'to_fluoride',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入氟化物(mg/L)',
+    },
+  },
+  {
+    label: '铅(mg/L)',
+    field: 'to_lead',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入铅(mg/L)',
+    },
+  },
+
+  {
+    label: '硝酸盐(氮)(mg/L)',
+    field: 'to_nitrate',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入硝酸盐(氮)(mg/L)',
+    },
+  },
+  {
+    label: '锌(mg/L)',
+    field: 'to_zinc',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入锌(mg/L)',
+    },
+  },
+  {
+    label: '硫酸盐(mg/L)',
+    field: 'to_sulfate',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入硫酸盐(mg/L)',
+    },
+  },
+  {
+    label: '钙(mmol/L)',
+    field: 'el_calcium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入钙(mmol/L)',
+    },
+  },
+  {
+    label: '镁(mmol/L)',
+    field: 'el_magnesium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入镁(mmol/L)',
+    },
+  },
+  {
+    label: '钠(mmol/L)',
+    field: 'el_sodium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入钠(mmol/L)',
+    },
+  },
+  {
+    label: '钾(mmol/L)',
+    field: 'el_potassium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入钾(mmol/L)',
+    },
+  },
+  {
+    label: '砷(mg/L)',
+    field: 'tr_arsenic',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入砷(mg/L)',
+    },
+  },
+  {
+    label: '锑(mg/L)',
+    field: 'tr_antimony',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入锑(mg/L)',
+    },
+  },
+  {
+    label: '铍(mg/L)',
+    field: 'tr_beryllium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入铍(mg/L)',
+    },
+  },
+  {
+    label: '钡(mg/L)',
+    field: 'tr_barium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入钡(mg/L)',
+    },
+  },
+  {
+    label: '铬(mg/L)',
+    field: 'tr_chromium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入铬(mg/L)',
+    },
+  },
+  {
+    label: '镉(mg/L)',
+    field: 'tr_cadmium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入镉(mg/L)',
+    },
+  },
+  {
+    label: '硒(mg/L)',
+    field: 'tr_selenium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入硒(mg/L)',
+    },
+  },
+  {
+    label: '汞(mg/L)',
+    field: 'tr_mercury',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入汞(mg/L)',
+    },
+  },
+  {
+    label: '银(mg/L)',
+    field: 'tr_silver',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入银(mg/L)',
+    },
+  },
+  {
+    label: '铊(mg/L)',
+    field: 'tr_thallium',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入铊(mg/L)',
+    },
+  },
+];
+
+export const headerLabel = [
+  {
+    keys: 'deviceUniqueCode',
+    values: '设备编号',
+  },
+  {
+    keys: 'deviceInfo',
+    values: '设备信息',
+  },
+  {
+    keys: 'detectionTime',
+    values: '检测时间',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '透析用水中的有毒化学物质',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+  {
+    keys: 'deviceUniqueCode',
+    values: '铝(mg/L) 正常值≤0.01',
+  },
+];

+ 89 - 0
src/views/biz/engineer/bio/chemicalPollutantDetection/formDrawer.vue

@@ -0,0 +1,89 @@
+template<template>
+  <BasicDrawer
+    v-bind="$attrs"
+    destroyOnClose
+    @register="registerDrawer"
+    :title="getTitle"
+    :width="width"
+    @ok="handleSubmit"
+    :showFooter="true"
+    okText="确定"
+  >
+    <BasicForm @register="registerForm" layout="vertical" class="!px-6 !pt-2">
+      <template #deviceManufacturer="{ model, field }">
+        <span>&nbsp;&nbsp;&nbsp;&nbsp;{{ model[field] }}</span>
+      </template>
+      <template #deviceModel="{ model, field }">
+        <span>&nbsp;&nbsp;&nbsp;&nbsp;{{ model[field] }}</span>
+      </template>
+    </BasicForm>
+  </BasicDrawer>
+</template>
+<script lang="ts" setup>
+  import { ref } from 'vue';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+  import { BasicForm, useForm } from '/@/components/Form';
+  import { dataFormSchema } from './data';
+  import { chemicalPollutantDetectionAdd } from '/@/api/biz/bio/chemicalPollutantDetectionApi';
+  const emit = defineEmits(['success', 'register']);
+  const getTitle = ref(`筛选条件`);
+  const width = '35%';
+  const [registerForm, { resetFields, validate }] = useForm({
+    schemas: dataFormSchema,
+    showActionButtonGroup: false,
+    baseColProps: {
+      span: 12,
+    },
+  });
+  const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async data => {
+    await resetFields();
+    setDrawerProps({ confirmLoading: false });
+    console.log('data::::::::::', data);
+  });
+
+  // 提交按钮事件
+  async function handleSubmit() {
+    try {
+      const values = await validate();
+      setDrawerProps({ confirmLoading: true });
+      const toxicChemicals = {};
+      const electrolyte = {};
+      const traceElement = {};
+      Object.keys(values).forEach(key => {
+        if (key.indexOf('_') !== -1) {
+          const vals = key.split('_');
+          switch (vals[0]) {
+            case 'to':
+              toxicChemicals[vals[1]] = values[key];
+              delete values[key];
+              break;
+            case 'el':
+              electrolyte[vals[1]] = values[key];
+              delete values[key];
+              break;
+            case 'tr':
+              traceElement[vals[1]] = values[key];
+              delete values[key];
+              break;
+          }
+        }
+      });
+      values.toxicChemicals = toxicChemicals;
+      values.electrolyte = electrolyte;
+      values.traceElement = traceElement;
+      console.log('values:::::::::', values);
+      await chemicalPollutantDetectionAdd(values);
+      closeDrawer();
+      emit('success', values);
+    } finally {
+      setDrawerProps({ confirmLoading: false });
+    }
+  }
+</script>
+<style lang="less" scoped>
+  ::v-deep(.ant-picker) {
+    border-top: 0;
+    border-left: 0;
+    border-right: 0;
+  }
+</style>

+ 283 - 0
src/views/biz/engineer/bio/chemicalPollutantDetection/index.vue

@@ -0,0 +1,283 @@
+<template>
+  <div class="m-4 modals">
+    <div>
+      <div class="flex items-center justify-between my-4">
+        <div>
+          <a-button type="primary" size="large" class="btn-add" @click="handleCreate"
+            ><template #icon> <Icon icon="icon-xt-add_default|iconfont" /> </template
+            >新增检测</a-button
+          >
+        </div>
+        <div>
+          <XTForm :form-data="formData" @change="callForm" />
+        </div>
+      </div>
+    </div>
+    <BasicTable @register="registerTable">
+      <template #headerCell="{ column }">
+        <template v-if="column.key === 'deviceUniqueCode'"> 设备编号 </template>
+        <template v-if="column.key === 'deviceInfo'"> 设备信息 </template>
+        <template v-if="column.key === 'detectionTime'"> 检测时间 </template>
+        <template v-if="column.key === 'toxicChemicals'"> 透析用水中的有毒化学物质 </template>
+        <template v-if="column.key === 'aluminum'">铝(mg/L)<br />正常值≤0.01</template>
+        <template v-if="column.key === 'totalChlorine'"> 总氯(mg/L)<br />正常值≤0.1 </template>
+        <template v-if="column.key === 'copper'"> 铜(mg/L)<br />正常值≤0.01 </template>
+        <template v-if="column.key === 'fluoride'"> 氟化物 (mg/L)<br />正常值≤0.2 </template>
+        <template v-if="column.key === 'lead'"> 铅(mg/L)<br />正常值≤0.005 </template>
+        <template v-if="column.key === 'nitrate'">
+          硝酸盐(氮)<br />
+          (mg/L)正常值≤2</template
+        >
+        <template v-if="column.key === 'sulfate'">
+          硫酸盐 (mg/L)<br />
+          正常值≤100</template
+        >
+        <template v-if="column.key === 'zinc'"> 锌(mg/L)<br />正常值≤0.1 </template>
+        <template v-if="column.key === 'electrolyte'"> 透析溶液中的电解质 </template>
+        <template v-if="column.key === 'calcium'">
+          钙(mmol/L)<br />正常值≤2<br />(0.05mmol/L)
+        </template>
+        <template v-if="column.key === 'magnesium'">
+          镁(mmol/L)<br />正常值≤4<br />(0.15mmol/L)
+        </template>
+        <template v-if="column.key === 'potassium'">
+          钾(mmol/L)<br />正常值≤8<br />(0.2mmol/L)
+        </template>
+        <template v-if="column.key === 'sodium'">
+          钠(mmol/L)<br />正常值≤70<br />(3.0mmol/L)
+        </template>
+        <template v-if="column.key === 'traceElement'"> 透析用水中的微量元素 </template>
+        <template v-if="column.key === 'antimony'"> 锑(mg/L)<br />正常值≤0.006 </template>
+        <template v-if="column.key === 'arsenic'">砷(mg/L)<br />正常值≤0.005</template>
+        <template v-if="column.key === 'barium'"> 钡(mg/L)<br />正常值≤0.1 </template>
+        <template v-if="column.key === 'beryllium'"> 铍(mg/L)<br />正常值≤0.0004 </template>
+        <template v-if="column.key === 'cadmium'"> 镉(mg/L)<br />正常值≤0.001 </template>
+        <template v-if="column.key === 'chromium'"> 铬(mg/L)<br />正常值≤0.014 </template>
+        <template v-if="column.key === 'mercury'"> 汞(mg/L)<br />正常值≤0.0002 </template>
+        <template v-if="column.key === 'selenium'"> 硒(mg/L)<br />正常值≤0.09 </template>
+        <template v-if="column.key === 'silver'"> 银(mg/L)<br />正常值≤0.005 </template>
+        <template v-if="column.key === 'thallium'"> 铊(mg/L)<br />正常值≤0.02 </template>
+        <template v-if="column.key === 'action'"> 操作 </template>
+      </template>
+      <template #bodyCell="{ column, record }">
+        <template v-if="column.key === 'deviceInfo'">{{
+          record.deviceName + '(' + record.deviceModel + ')'
+        }}</template>
+        <template v-if="column.key === 'aluminum'">{{ record.toxicChemicals.aluminum }}</template>
+        <template v-if="column.key === 'totalChlorine'">{{
+          record.toxicChemicals.totalChlorine
+        }}</template>
+        <template v-if="column.key === 'copper'">{{ record.toxicChemicals.copper }}</template>
+        <template v-if="column.key === 'fluoride'">{{ record.toxicChemicals.fluoride }}</template>
+        <template v-if="column.key === 'lead'">{{ record.toxicChemicals.lead }}</template>
+        <template v-if="column.key === 'nitrate'">{{ record.toxicChemicals.nitrate }}</template>
+        <template v-if="column.key === 'sulfate'">{{ record.toxicChemicals.sulfate }}</template>
+        <template v-if="column.key === 'zinc'">{{ record.toxicChemicals.zinc }}</template>
+
+        <template v-if="column.key === 'calcium'">{{ record.electrolyte.calcium }}</template>
+        <template v-if="column.key === 'magnesium'">{{ record.electrolyte.magnesium }}</template>
+        <template v-if="column.key === 'potassium'">{{ record.electrolyte.potassium }}</template>
+        <template v-if="column.key === 'sodium'">{{ record.electrolyte.sodium }}</template>
+
+        <template v-if="column.key === 'antimony'">{{ record.traceElement.antimony }}</template>
+        <template v-if="column.key === 'arsenic'">{{ record.traceElement.arsenic }}</template>
+        <template v-if="column.key === 'barium'">{{ record.traceElement.barium }}</template>
+        <template v-if="column.key === 'beryllium'">{{ record.traceElement.beryllium }}</template>
+        <template v-if="column.key === 'cadmium'">{{ record.traceElement.cadmium }}</template>
+        <template v-if="column.key === 'chromium'">{{ record.traceElement.chromium }}</template>
+        <template v-if="column.key === 'mercury'">{{ record.traceElement.mercury }}</template>
+        <template v-if="column.key === 'selenium'">{{ record.traceElement.selenium }}</template>
+        <template v-if="column.key === 'silver'">{{ record.traceElement.silver }}</template>
+        <template v-if="column.key === 'thallium'">{{ record.traceElement.thallium }}</template>
+        <template v-if="column.key === 'action'">
+          <TableAction
+            :actions="[
+              {
+                auth: 'archives:patientReturn:remove',
+                icon: 'icon-xt-details_delete_default|iconfont',
+                tooltip: '删除',
+                popConfirm: {
+                  title: '是否取消删除',
+                  placement: 'left',
+                  confirm: handleDelete.bind(null, record, column),
+                },
+              },
+            ]"
+          />
+        </template>
+      </template>
+    </BasicTable>
+  </div>
+  <FormDrawer @register="registerDrawer" @success="callSuccess" />
+</template>
+<script lang="ts" setup>
+  import { onBeforeMount, ref } from 'vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/TableCard';
+  import Icon from '/@/components/Icon';
+  import { columns } from './data';
+  import {
+    chemicalPollutantDetectionQueryPage,
+    chemicalPollutantDetectionRemove,
+  } from '/@/api/biz/bio/chemicalPollutantDetectionApi';
+  import { listDictModel } from '/@/api/common';
+  import { XTForm } from '/@/components/XTForm/index';
+  import dayjs from 'dayjs';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useDrawer } from '@/components/Drawer';
+  import FormDrawer from './formDrawer.vue';
+  const { createMessage } = useMessage();
+
+  // formdata
+  const formData = [
+    {
+      label: '检测时间:',
+      name: 'shiftDate',
+      componentType: 'RangePicker',
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+      placeholder: '请选择日期',
+      width: 240,
+    },
+    {
+      name: 'searchNames',
+      componentType: 'Input',
+      prefix: 'icon-xt-search',
+      placeholder: '请输入设备编号',
+      width: 240,
+    },
+  ];
+  // tab 切换选中
+  const tabSelected = ref();
+  // 操作名称
+  const searchNames = ref('');
+  const shiftDate = ref([]);
+
+  const responseTypeOptions = ref();
+  const responsesupplierCategoryOptions = ref();
+  const [registerDrawer, { openDrawer }] = useDrawer();
+  onBeforeMount(async () => {
+    responseTypeOptions.value = await listDictModel({ dictCode: 'sys_disable_type' });
+    responsesupplierCategoryOptions.value = await listDictModel({ dictCode: 'pht' });
+  });
+
+  const tableSort = ref([
+    {
+      field: 'create_time',
+      direction: 'DESC',
+    },
+  ]) as any;
+
+  const [registerTable, { reload }] = useTable({
+    api: chemicalPollutantDetectionQueryPage,
+    rowKey: 'id',
+    columns,
+    showIndexColumn: false,
+    bordered: true,
+    actionColumn: {
+      width: 200,
+      title: '操作',
+      dataIndex: 'action',
+    },
+    beforeFetch: handleBeforeFetch,
+    sortFn: handleSortFn,
+  });
+  // 详情按钮事件
+  async function handleDelete(record) {
+    await chemicalPollutantDetectionRemove([record.id]);
+    createMessage.success('删除成功!');
+    await reload();
+  }
+
+  // 表格点击字段排序
+  function handleSortFn(sortInfo) {
+    if (sortInfo?.order && sortInfo?.columnKey) {
+      // 默认单列排序
+      tableSort.value = [
+        {
+          field: sortInfo.columnKey,
+          direction: sortInfo.order.replace(/(\w+)(end)/g, '$1').toUpperCase(),
+        },
+      ];
+    }
+  }
+
+  // 表格请求之前,对参数进行处理, 添加默认 排序
+  async function handleBeforeFetch(params) {
+    const shiftTimes = [];
+    if (shiftDate.value && shiftDate.value.length > 0) {
+      shiftTimes.push(shiftDate.value[0]);
+      shiftTimes.push(shiftDate.value[1]);
+      shiftTimes[1] = dayjs(shiftTimes[1]).add(1, 'day').format('YYYY-MM-DD');
+    }
+    return {
+      ...params,
+      orders: tableSort.value,
+      name: searchNames.value == '' ? undefined : searchNames.value,
+      status: tabSelected.value == '' ? undefined : tabSelected.value,
+      time: shiftTimes.length <= 0 ? undefined : shiftTimes,
+    };
+  }
+
+  // 新增按钮事件
+  function handleCreate() {
+    openDrawer(true, {
+      isUpdate: false,
+    });
+  }
+
+  //抽屉回返事件
+  // async function handleCancel() {
+  //   clearSelectedRowKeys();
+  //   await reload();
+  // }
+
+  async function callSuccess() {
+    await reload();
+  }
+
+  // 查询组件回调
+  async function callForm(data) {
+    shiftDate.value = data.shiftDate ? data.shiftDate : '';
+    searchNames.value = data.searchNames ? data.searchNames : '';
+    console.log('callForm:::', searchNames.value);
+    await reload();
+  }
+</script>
+<style lang="less" scoped>
+  .table-dot {
+    display: inline-block;
+    width: 10px;
+    height: 10px;
+    margin-right: 6px;
+    border-radius: 50%;
+  }
+
+  ::v-deep(.ant-btn-link) {
+    color: #3d4155;
+  }
+
+  ::v-deep(.ant-input-prefix) {
+    color: #8a99ac;
+  }
+
+  .colUpdateAvatar {
+    display: flex;
+    justify-content: center;
+    text-align: center;
+    line-height: 28px;
+  }
+
+  .colImg {
+    width: 28px;
+    height: 28px;
+    margin-right: 5px;
+  }
+
+  .upStatus {
+    color: #ff5d39;
+  }
+
+  .downStatus {
+    color: #ffad26;
+  }
+</style>

+ 7 - 0
src/views/biz/engineer/bio/data.ts

@@ -0,0 +1,7 @@
+export const BasicTab = [
+  { key: 'microbialDetectionDialysate', value: 0, title: '透析液-微生物检测' },
+  { key: 'microbialDetectionWater', value: 1, title: '透析用水-微生物检测' },
+  { key: 'upkeepList', value: 2, title: '透析用水-化学污染物检测' },
+];
+
+export const BasicTabActive = BasicTab[0].key;

+ 60 - 3
src/views/biz/engineer/bio/index.vue

@@ -1,7 +1,64 @@
 <template>
-  <div> 占位符 </div>
+  <div class="m-4">
+    <div class="mb-4">
+      <XTTitle :title="title" :go-back="true" />
+    </div>
+    <div class="py-2 bg-white">
+      <a-tabs v-model:activeKey="activeKey" :destroyInactiveTabPane="true">
+        <a-tab-pane
+          v-for="item in tabData"
+          :key="item.key"
+          :tab="item.title"
+          :class="'tab-' + item.key"
+        >
+          <!-- 透析液-微生物检测 0 -->
+          <div v-if="item.value == 0 && info.id">
+            <MicrobialDetectionDialysate :info="info" />
+          </div>
+          <!-- 透析用水-微生物检测 1 -->
+          <div v-if="item.value == 1 && info.id">
+            <MicrobialDetectionWater :info="info" />
+          </div>
+          <!-- 透析用水-化学污染物检测 2 -->
+          <div v-if="item.value == 2 && info.id">
+            <ChemicalPollutantDetection :info="info" />
+          </div>
+        </a-tab-pane>
+      </a-tabs>
+    </div>
+  </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+  import { ref } from 'vue';
+  import { BasicTab, BasicTabActive } from './data';
+  import MicrobialDetectionDialysate from './microbialDetectionDialysate/index.vue';
+  import MicrobialDetectionWater from './microbialDetectionWater/index.vue';
+  import ChemicalPollutantDetection from './chemicalPollutantDetection/index.vue';
+  import { useRoute } from 'vue-router';
+  import { XTTitle } from '/@/components/XTTitle/index';
 
-<style lang="less" scoped></style>
+  const route = useRoute();
+  console.log('🚀 ~ file: index.vue:25 ~ route:', route);
+  const info = ref({
+    id: String(route.query?.id),
+    name: route.query?.name,
+  });
+  const activeKey = ref(BasicTabActive);
+  const tabData = ref(BasicTab);
+  const title = '生化管理';
+</script>
+
+<style lang="less" scoped>
+  ::v-deep(.ant-tabs-tab) {
+    padding: 12px;
+  }
+
+  ::v-deep(.ant-tabs-tabpane) {
+    padding: 12px;
+  }
+
+  .tab-medicalDocuments {
+    padding: 0;
+  }
+</style>

+ 159 - 0
src/views/biz/engineer/bio/microbialDetectionDialysate/data.ts

@@ -0,0 +1,159 @@
+import { BasicColumn, FormSchema } from '/@/components/Table';
+import { sysUserQueryPage } from '/@/api/sys/sysUserApi';
+import {
+  engineerDialysisDeviceList,
+  engineerDialysisDeviceDetail,
+} from '/@/api/biz/engineer/dialysisDeviceApi';
+import dayjs from 'dayjs';
+// import { useMessage } from '@/hooks/web/useMessage';
+// const { createMessage } = useMessage();
+
+export const columns: BasicColumn[] = [
+  {
+    title: '设备编号',
+    dataIndex: 'deviceUniqueCode',
+    width: 120,
+  },
+  {
+    title: '设备厂家',
+    dataIndex: 'deviceManufacturer',
+    width: 120,
+  },
+  {
+    title: '设备型号',
+    dataIndex: 'deviceSerialNumber',
+  },
+  {
+    title: '检测时间',
+    dataIndex: 'detectionTime',
+  },
+  {
+    title: '进水口细菌(cfu/ml) 正常值≤100 干预值>50',
+    dataIndex: 'intakeBacteria',
+  },
+  {
+    title: '进水口内毒素(Eu/ml) 正常值≤0.5 干预值>0.25',
+    dataIndex: 'intakeEndotoxin',
+  },
+  {
+    title: '出水口细菌(cfu/ml) 正常值≤100 干预值>50',
+    dataIndex: 'outletBacteria',
+  },
+  {
+    title: '出水口内毒素(Eu/ml) 正常值≤0.5 干预值>0.25',
+    dataIndex: 'outletEndotoxin',
+  },
+];
+// 表单新增编辑
+export const dataFormSchema: FormSchema[] = [
+  {
+    label: '设备编号搜索',
+    field: 'uniqueCodes',
+    component: 'Input',
+    ifShow: false,
+  },
+  {
+    label: '设备编号',
+    field: 'deviceId',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: ({ formModel }) => {
+      return {
+        api: engineerDialysisDeviceList,
+        params: {
+          uniqueCode: formModel.uniqueCodes,
+        },
+        labelField: 'uniqueCode',
+        valueField: 'id',
+        resultField: 'data',
+        placeholder: '请选择设备编号',
+        getPopupContainer: () => document.body,
+        showSearch: true,
+        filterOption: false,
+        onSearch: e => {
+          formModel.uniqueCodes = e;
+        },
+        onChange: async e => {
+          console.log('e::::::::::::', e);
+          const resData = await engineerDialysisDeviceDetail(e);
+          formModel['deviceInfo'] = resData?.name + '(' + resData?.model + ')';
+        },
+      };
+    },
+  },
+  {
+    label: '设备信息',
+    field: 'deviceInfo',
+    required: true,
+    component: 'Input',
+    slot: 'deviceInfo',
+    componentProps: {
+      disabled: true,
+    },
+  },
+  {
+    label: '检测时间',
+    field: 'detectionTime',
+    component: 'DatePicker',
+    componentProps: () => {
+      return {
+        placeholder: '请选择检测时间',
+        getPopupContainer: () => document.body,
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
+        showTime: true,
+      };
+    },
+    defaultValue: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+  },
+  {
+    label: '检测人',
+    field: 'inspectorId',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: sysUserQueryPage,
+      params: {
+        pageNum: 1,
+        pageSize: 999,
+        disable: '0',
+      },
+      mode: 'single',
+      labelField: 'nickname',
+      valueField: 'id',
+      resultField: 'data',
+      placeholder: '请选择检测人',
+    },
+  },
+  {
+    label: '进水口细菌(cfu/ml)  正常值≤100  干预值>50',
+    field: 'intakeBacteria',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入进水口细菌(cfu/ml)',
+    },
+  },
+  {
+    label: '进水口内毒素(Eu/ml)  正常值≤0.5  干预值>0.25',
+    field: 'intakeEndotoxin',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入进水口内毒素(Eu/ml)',
+    },
+  },
+  {
+    label: '出水口细菌(cfu/ml)  正常值≤100  干预值>50',
+    field: 'outletBacteria',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入出水口细菌(cfu/ml)',
+    },
+  },
+  {
+    label: '出水口内毒素(Eu/ml)  正常值≤0.5  干预值>0.25',
+    field: 'outletEndotoxin',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入出水口内毒素(Eu/ml)',
+    },
+  },
+];

+ 96 - 0
src/views/biz/engineer/bio/microbialDetectionDialysate/formModal.vue

@@ -0,0 +1,96 @@
+<template>
+  <div class="modals">
+    <BasicModal
+      v-bind="$attrs"
+      destroyOnClose
+      @register="registerModal"
+      :title="getTitle"
+      @ok="handleSubmit"
+      :width="880"
+      @cancel="handleCancel"
+    >
+      <div class="!pl-8 !pt-4">
+        <BasicForm @register="registerForm">
+          <template #deviceInfo="{ model, field }">
+            <span>&nbsp;&nbsp;&nbsp;&nbsp;{{ model[field] }}</span>
+          </template>
+        </BasicForm>
+      </div>
+    </BasicModal>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { ref, computed, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, useForm } from '/@/components/Form';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { dataFormSchema } from './data';
+  import {
+    microbialDetectionDialysateAdd,
+    microbialDetectionDialysateEdit,
+    microbialDetectionDialysateDetail,
+  } from '/@/api/biz/bio/microbialDetectionDialysateApi';
+  import { engineerDialysisDeviceDetail } from '/@/api/biz/engineer/dialysisDeviceApi';
+  const emit = defineEmits(['success', 'cancel', 'register']);
+  const getTitle = computed(() => (!unref(isUpdate) ? '新增检测' : '编辑检测'));
+  const isUpdate = ref(false);
+  const rowId = ref();
+  const { createMessage } = useMessage();
+  const [registerForm, { resetFields, validate, setFieldsValue }] = useForm({
+    layout: 'vertical',
+    showResetButton: true,
+    labelWidth: 300,
+    schemas: dataFormSchema,
+    showActionButtonGroup: false,
+    actionColOptions: {
+      span: 24,
+    },
+    baseColProps: {
+      span: 12,
+    },
+    wrapperCol: {
+      span: 22,
+    },
+  });
+  const [registerModal, { setModalProps, closeModal }] = useModalInner(async data => {
+    await resetFields();
+    setModalProps({ confirmLoading: false });
+    isUpdate.value = !!data?.isUpdate;
+    if (unref(isUpdate)) {
+      rowId.value = data.record.id;
+      const resData = await microbialDetectionDialysateDetail(data.record.id);
+      const deviceInfos = await engineerDialysisDeviceDetail(resData?.deviceId);
+      resData.deviceInfo = deviceInfos?.name + '(' + deviceInfos?.model + ')';
+      console.log('resData::::', resData);
+      await setFieldsValue({
+        ...resData,
+      });
+    }
+  });
+
+  // 提交按钮事件
+  async function handleSubmit() {
+    try {
+      const values = await validate();
+      setModalProps({ confirmLoading: true });
+      !unref(isUpdate)
+        ? await microbialDetectionDialysateAdd({ ...values })
+        : await microbialDetectionDialysateEdit({ ...values, id: rowId.value });
+      !unref(isUpdate) ? createMessage.success('新增成功!') : createMessage.success('编辑成功!');
+      closeModal();
+      emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
+    } finally {
+      setModalProps({ confirmLoading: false, canFullscreen: false });
+    }
+  }
+
+  async function handleCancel() {
+    closeModal();
+    emit('cancel');
+  }
+</script>
+<style lang="less" scoped>
+  ::v-deep(.ant-modal) {
+    background-color: #000;
+  }
+</style>

+ 272 - 0
src/views/biz/engineer/bio/microbialDetectionDialysate/index.vue

@@ -0,0 +1,272 @@
+<template>
+  <div class="m-4 modals">
+    <div>
+      <div class="flex items-center justify-between my-4">
+        <div>
+          <a-button type="primary" size="large" class="btn-add" @click="handleCreate"
+            ><template #icon> <Icon icon="icon-xt-add_default|iconfont" /> </template
+            >新增检测</a-button
+          >
+        </div>
+        <div>
+          <XTForm :form-data="formData" @change="callForm" />
+        </div>
+      </div>
+    </div>
+    <BasicTable @register="registerTable">
+      <template #headerCell="{ column }">
+        <template v-if="column.key === 'deviceUniqueCode'">
+          <span>设备编号</span>
+        </template>
+        <template v-if="column.key === 'deviceManufacturer'">
+          <span>设备厂家</span>
+        </template>
+        <template v-if="column.key === 'deviceSerialNumber'">
+          <span>设备型号</span>
+        </template>
+        <template v-if="column.key === 'detectionTime'">
+          <span>检测时间</span>
+        </template>
+
+        <template v-if="column.key === 'intakeBacteria'">
+          <span>进水口细菌(cfu/ml)<br />正常值≤100<br />干预值>50</span>
+        </template>
+        <template v-if="column.key === 'intakeEndotoxin'">
+          <span>进水口内毒素(Eu/ml)<br />正常值≤0.5<br />干预值>0.25</span>
+        </template>
+        <template v-if="column.key === 'outletBacteria'">
+          <span>出水口细菌(cfu/ml)<br />正常值≤100<br />干预值>50</span>
+        </template>
+        <template v-if="column.key === 'outletEndotoxin'">
+          <span>出水口内毒素(Eu/ml)<br />正常值≤0.5<br />干预值>0.25</span>
+        </template>
+        <template v-if="column.key === 'action'">
+          <span>操作</span>
+        </template>
+      </template>
+      <template #bodyCell="{ column, record }">
+        <template v-if="column.key === 'disable'">
+          <span
+            :class="['table-dot']"
+            :style="{ backgroundColor: formatDictPreColor(responseTypeOptions, record.disable) }"
+          />
+          <span> {{ formatDictValue(responseTypeOptions, record.disable) }}</span>
+        </template>
+        <template v-if="column.key === 'supplierCategory'">
+          <span>
+            {{ formatDictValue(responsesupplierCategoryOptions, record.supplierCategory) }}</span
+          >
+        </template>
+        <template v-if="column.key === 'intakeBacteria'">
+          <span v-if="record.intakeBacteriaStatus === '0'">{{ record.intakeBacteria }}</span>
+          <span v-else :class="record.intakeBacteriaStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.intakeBacteria
+          }}</span>
+        </template>
+        <template v-if="column.key === 'intakeEndotoxin'">
+          <span v-if="record.intakeEndotoxinStatus === '0'">{{ record.intakeEndotoxin }}</span>
+          <span v-else :class="record.intakeEndotoxinStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.intakeEndotoxin
+          }}</span>
+        </template>
+        <template v-if="column.key === 'outletBacteria'">
+          <span v-if="record.outletBacteriaStatus === '0'">{{ record.outletBacteria }}</span>
+          <span v-else :class="record.outletBacteriaStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.outletBacteria
+          }}</span>
+        </template>
+        <template v-if="column.key === 'outletEndotoxin'">
+          <span v-if="record.outletEndotoxinStatus === '0'">{{ record.outletEndotoxin }}</span>
+          <span v-else :class="record.outletEndotoxinStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.outletEndotoxin
+          }}</span>
+        </template>
+        <template v-if="column.key === 'action'">
+          <TableAction
+            :actions="[
+              {
+                auth: 'biz:consumable:edit',
+                icon: 'icon-xt-details_edit_default|iconfont',
+                tooltip: '编辑',
+                onClick: handleEdit.bind(null, record),
+              },
+            ]"
+          />
+        </template>
+      </template>
+    </BasicTable>
+    <FormModal @register="registerModal" @success="callSuccess" @cancel="handleCancel" />
+  </div>
+</template>
+<script lang="ts" setup>
+  import { onBeforeMount, ref } from 'vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/TableCard';
+  import FormModal from './formModal.vue';
+  import Icon from '/@/components/Icon';
+  import { formatDictValue, formatDictPreColor } from '/@/utils';
+  import { columns } from './data';
+  import { microbialDetectionDialysateQueryPage } from '/@/api/biz/bio/microbialDetectionDialysateApi';
+  import { listDictModel } from '/@/api/common';
+  import { useModal } from '/@/components/Modal';
+  import { XTForm } from '/@/components/XTForm/index';
+  import dayjs from 'dayjs';
+
+  // formdata
+  const formData = [
+    {
+      label: '检测时间:',
+      name: 'shiftDate',
+      componentType: 'RangePicker',
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+      placeholder: '请选择日期',
+      width: 240,
+    },
+    {
+      name: 'searchNames',
+      componentType: 'Input',
+      prefix: 'icon-xt-search',
+      placeholder: '请输入设备编号',
+      width: 240,
+    },
+  ];
+  // tab 切换选中
+  const tabSelected = ref();
+  // 操作名称
+  const searchNames = ref('');
+  const shiftDate = ref([]);
+
+  const responseTypeOptions = ref();
+  const responsesupplierCategoryOptions = ref();
+  onBeforeMount(async () => {
+    responseTypeOptions.value = await listDictModel({ dictCode: 'sys_disable_type' });
+    responsesupplierCategoryOptions.value = await listDictModel({ dictCode: 'pht' });
+  });
+
+  const [registerModal, { openModal }] = useModal();
+
+  const tableSort = ref([
+    {
+      field: 'create_time',
+      direction: 'DESC',
+    },
+  ]) as any;
+
+  const [registerTable, { reload, clearSelectedRowKeys }] = useTable({
+    api: microbialDetectionDialysateQueryPage,
+    rowKey: 'id',
+    columns,
+    showIndexColumn: false,
+    bordered: true,
+    actionColumn: {
+      width: 200,
+      title: '操作',
+      dataIndex: 'action',
+    },
+    beforeFetch: handleBeforeFetch,
+    sortFn: handleSortFn,
+  });
+  // 详情按钮事件
+  function handleEdit(record) {
+    openModal(true, {
+      isUpdate: true,
+      record,
+    });
+  }
+
+  // 表格点击字段排序
+  function handleSortFn(sortInfo) {
+    if (sortInfo?.order && sortInfo?.columnKey) {
+      // 默认单列排序
+      tableSort.value = [
+        {
+          field: sortInfo.columnKey,
+          direction: sortInfo.order.replace(/(\w+)(end)/g, '$1').toUpperCase(),
+        },
+      ];
+    }
+  }
+
+  // 表格请求之前,对参数进行处理, 添加默认 排序
+  async function handleBeforeFetch(params) {
+    const shiftTimes = [];
+    if (shiftDate.value && shiftDate.value.length > 0) {
+      shiftTimes.push(shiftDate.value[0]);
+      shiftTimes.push(shiftDate.value[1]);
+      shiftTimes[1] = dayjs(shiftTimes[1]).add(1, 'day').format('YYYY-MM-DD');
+    }
+    return {
+      ...params,
+      orders: tableSort.value,
+      name: searchNames.value == '' ? undefined : searchNames.value,
+      status: tabSelected.value == '' ? undefined : tabSelected.value,
+      time: shiftTimes.length <= 0 ? undefined : shiftTimes,
+    };
+  }
+
+  // 新增按钮事件
+  function handleCreate() {
+    openModal(true, {
+      isUpdate: false,
+    });
+  }
+
+  //取消按钮事件
+  async function handleCancel() {
+    clearSelectedRowKeys();
+    await reload();
+  }
+
+  // 弹窗回调事件
+  async function callSuccess({ isUpdate, values }) {
+    console.log(isUpdate);
+    console.log(values);
+    await reload();
+  }
+
+  // 查询组件回调
+  async function callForm(data) {
+    shiftDate.value = data.shiftDate ? data.shiftDate : '';
+    searchNames.value = data.searchNames ? data.searchNames : '';
+    console.log('callForm:::', searchNames.value);
+    await reload();
+  }
+</script>
+<style lang="less" scoped>
+  .table-dot {
+    display: inline-block;
+    width: 10px;
+    height: 10px;
+    margin-right: 6px;
+    border-radius: 50%;
+  }
+
+  ::v-deep(.ant-btn-link) {
+    color: #3d4155;
+  }
+
+  ::v-deep(.ant-input-prefix) {
+    color: #8a99ac;
+  }
+
+  .colUpdateAvatar {
+    display: flex;
+    justify-content: center;
+    text-align: center;
+    line-height: 28px;
+  }
+
+  .colImg {
+    width: 28px;
+    height: 28px;
+    margin-right: 5px;
+  }
+
+  .upStatus {
+    color: #ff5d39;
+  }
+
+  .downStatus {
+    color: #ffad26;
+  }
+</style>

+ 155 - 0
src/views/biz/engineer/bio/microbialDetectionWater/data.ts

@@ -0,0 +1,155 @@
+import { BasicColumn, FormSchema } from '/@/components/Table';
+import { sysUserQueryPage } from '/@/api/sys/sysUserApi';
+import { waterList, waterDetail } from '/@/api/biz/engineer/waterApi';
+import dayjs from 'dayjs';
+// import { useMessage } from '@/hooks/web/useMessage';
+// const { createMessage } = useMessage();
+
+export const columns: BasicColumn[] = [
+  {
+    title: '设备编号',
+    dataIndex: 'deviceUniqueCode',
+    width: 120,
+  },
+  {
+    title: '设备厂家',
+    dataIndex: 'deviceManufacturer',
+    width: 120,
+  },
+  {
+    title: '设备型号',
+    dataIndex: 'deviceSerialNumber',
+  },
+  {
+    title: '检测时间',
+    dataIndex: 'detectionTime',
+  },
+  {
+    title: '进水口细菌(cfu/ml) 正常值≤100 干预值>50',
+    dataIndex: 'intakeBacteria',
+  },
+  {
+    title: '进水口内毒素(Eu/ml) 正常值≤0.5 干预值>0.25',
+    dataIndex: 'intakeEndotoxin',
+  },
+  {
+    title: '出水口细菌(cfu/ml) 正常值≤100 干预值>50',
+    dataIndex: 'outletBacteria',
+  },
+  {
+    title: '出水口内毒素(Eu/ml) 正常值≤0.5 干预值>0.25',
+    dataIndex: 'outletEndotoxin',
+  },
+];
+// 表单新增编辑
+export const dataFormSchema: FormSchema[] = [
+  {
+    label: '设备编号搜索',
+    field: 'uniqueCodes',
+    component: 'Input',
+    ifShow: false,
+  },
+  {
+    label: '设备编号',
+    field: 'deviceId',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: ({ formModel }) => {
+      return {
+        api: waterList,
+        params: {
+          uniqueCode: formModel.uniqueCodes,
+        },
+        labelField: 'uniqueCode',
+        valueField: 'id',
+        resultField: 'data',
+        placeholder: '请选择设备编号',
+        getPopupContainer: () => document.body,
+        showSearch: true,
+        filterOption: false,
+        onSearch: e => {
+          formModel.uniqueCodes = e;
+        },
+        onChange: async e => {
+          const resData = await waterDetail(e);
+          formModel['deviceInfo'] = resData?.name + '(' + resData?.model + ')';
+        },
+      };
+    },
+  },
+  {
+    label: '设备信息',
+    field: 'deviceInfo',
+    required: true,
+    component: 'Input',
+    slot: 'deviceInfo',
+    componentProps: {
+      disabled: true,
+    },
+  },
+  {
+    label: '检测时间',
+    field: 'detectionTime',
+    component: 'DatePicker',
+    componentProps: () => {
+      return {
+        placeholder: '请选择检测时间',
+        getPopupContainer: () => document.body,
+        valueFormat: 'YYYY-MM-DD HH:mm:ss',
+        showTime: true,
+      };
+    },
+    defaultValue: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+  },
+  {
+    label: '检测人',
+    field: 'inspectorId',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: sysUserQueryPage,
+      params: {
+        pageNum: 1,
+        pageSize: 999,
+        disable: '0',
+      },
+      mode: 'single',
+      labelField: 'nickname',
+      valueField: 'id',
+      resultField: 'data',
+      placeholder: '请选择检测人',
+    },
+  },
+  {
+    label: '进水口细菌(cfu/ml)  正常值≤100  干预值>50',
+    field: 'intakeBacteria',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入进水口细菌(cfu/ml)',
+    },
+  },
+  {
+    label: '进水口内毒素(Eu/ml)  正常值≤0.5  干预值>0.25',
+    field: 'intakeEndotoxin',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入进水口内毒素(Eu/ml)',
+    },
+  },
+  {
+    label: '出水口细菌(cfu/ml)  正常值≤100  干预值>50',
+    field: 'outletBacteria',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入出水口细菌(cfu/ml)',
+    },
+  },
+  {
+    label: '出水口内毒素(Eu/ml)  正常值≤0.5  干预值>0.25',
+    field: 'outletEndotoxin',
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入出水口内毒素(Eu/ml)',
+    },
+  },
+];

+ 96 - 0
src/views/biz/engineer/bio/microbialDetectionWater/formModal.vue

@@ -0,0 +1,96 @@
+<template>
+  <div class="modals">
+    <BasicModal
+      v-bind="$attrs"
+      destroyOnClose
+      @register="registerModal"
+      :title="getTitle"
+      @ok="handleSubmit"
+      :width="880"
+      @cancel="handleCancel"
+    >
+      <div class="!pl-8 !pt-4">
+        <BasicForm @register="registerForm">
+          <template #deviceInfo="{ model, field }">
+            <span>&nbsp;&nbsp;&nbsp;&nbsp;{{ model[field] }}</span>
+          </template>
+        </BasicForm>
+      </div>
+    </BasicModal>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { ref, computed, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, useForm } from '/@/components/Form';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { dataFormSchema } from './data';
+  import {
+    microbialDetectionWaterAdd,
+    microbialDetectionWaterEdit,
+    microbialDetectionWaterDetail,
+  } from '/@/api/biz/bio/microbialDetectionWaterApi';
+  import { waterDetail } from '@/api/biz/engineer/waterApi';
+  const emit = defineEmits(['success', 'cancel', 'register']);
+  const getTitle = computed(() => (!unref(isUpdate) ? '新增检测' : '编辑检测'));
+  const isUpdate = ref(false);
+  const rowId = ref();
+  const { createMessage } = useMessage();
+  const [registerForm, { resetFields, validate, setFieldsValue }] = useForm({
+    layout: 'vertical',
+    showResetButton: true,
+    labelWidth: 300,
+    schemas: dataFormSchema,
+    showActionButtonGroup: false,
+    actionColOptions: {
+      span: 24,
+    },
+    baseColProps: {
+      span: 12,
+    },
+    wrapperCol: {
+      span: 22,
+    },
+  });
+  const [registerModal, { setModalProps, closeModal }] = useModalInner(async data => {
+    await resetFields();
+    setModalProps({ confirmLoading: false });
+    isUpdate.value = !!data?.isUpdate;
+    if (unref(isUpdate)) {
+      rowId.value = data.record.id;
+      const resData = await microbialDetectionWaterDetail(data.record.id);
+      const deviceInfos = await waterDetail(resData?.deviceId);
+      resData.deviceInfo = deviceInfos?.name + '(' + deviceInfos?.model + ')';
+      console.log('resData::::', resData);
+      await setFieldsValue({
+        ...resData,
+      });
+    }
+  });
+
+  // 提交按钮事件
+  async function handleSubmit() {
+    try {
+      const values = await validate();
+      setModalProps({ confirmLoading: true });
+      !unref(isUpdate)
+        ? await microbialDetectionWaterAdd({ ...values })
+        : await microbialDetectionWaterEdit({ ...values, id: rowId.value });
+      !unref(isUpdate) ? createMessage.success('新增成功!') : createMessage.success('编辑成功!');
+      closeModal();
+      emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
+    } finally {
+      setModalProps({ confirmLoading: false, canFullscreen: false });
+    }
+  }
+
+  async function handleCancel() {
+    closeModal();
+    emit('cancel');
+  }
+</script>
+<style lang="less" scoped>
+  ::v-deep(.ant-modal) {
+    background-color: #000;
+  }
+</style>

+ 272 - 0
src/views/biz/engineer/bio/microbialDetectionWater/index.vue

@@ -0,0 +1,272 @@
+<template>
+  <div class="m-4 modals">
+    <div>
+      <div class="flex items-center justify-between my-4">
+        <div>
+          <a-button type="primary" size="large" class="btn-add" @click="handleCreate"
+            ><template #icon> <Icon icon="icon-xt-add_default|iconfont" /> </template
+            >新增检测</a-button
+          >
+        </div>
+        <div>
+          <XTForm :form-data="formData" @change="callForm" />
+        </div>
+      </div>
+    </div>
+    <BasicTable @register="registerTable">
+      <template #headerCell="{ column }">
+        <template v-if="column.key === 'deviceUniqueCode'">
+          <span>设备编号</span>
+        </template>
+        <template v-if="column.key === 'deviceManufacturer'">
+          <span>设备厂家</span>
+        </template>
+        <template v-if="column.key === 'deviceSerialNumber'">
+          <span>设备型号</span>
+        </template>
+        <template v-if="column.key === 'detectionTime'">
+          <span>检测时间</span>
+        </template>
+
+        <template v-if="column.key === 'intakeBacteria'">
+          <span>进水口细菌(cfu/ml)<br />正常值≤100<br />干预值>50</span>
+        </template>
+        <template v-if="column.key === 'intakeEndotoxin'">
+          <span>进水口内毒素(Eu/ml)<br />正常值≤0.5<br />干预值>0.25</span>
+        </template>
+        <template v-if="column.key === 'outletBacteria'">
+          <span>出水口细菌(cfu/ml)<br />正常值≤100<br />干预值>50</span>
+        </template>
+        <template v-if="column.key === 'outletEndotoxin'">
+          <span>出水口内毒素(Eu/ml)<br />正常值≤0.5<br />干预值>0.25</span>
+        </template>
+        <template v-if="column.key === 'action'">
+          <span>操作</span>
+        </template>
+      </template>
+      <template #bodyCell="{ column, record }">
+        <template v-if="column.key === 'disable'">
+          <span
+            :class="['table-dot']"
+            :style="{ backgroundColor: formatDictPreColor(responseTypeOptions, record.disable) }"
+          />
+          <span> {{ formatDictValue(responseTypeOptions, record.disable) }}</span>
+        </template>
+        <template v-if="column.key === 'supplierCategory'">
+          <span>
+            {{ formatDictValue(responsesupplierCategoryOptions, record.supplierCategory) }}</span
+          >
+        </template>
+        <template v-if="column.key === 'intakeBacteria'">
+          <span v-if="record.intakeBacteriaStatus === '0'">{{ record.intakeBacteria }}</span>
+          <span v-else :class="record.intakeBacteriaStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.intakeBacteria
+          }}</span>
+        </template>
+        <template v-if="column.key === 'intakeEndotoxin'">
+          <span v-if="record.intakeEndotoxinStatus === '0'">{{ record.intakeEndotoxin }}</span>
+          <span v-else :class="record.intakeEndotoxinStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.intakeEndotoxin
+          }}</span>
+        </template>
+        <template v-if="column.key === 'outletBacteria'">
+          <span v-if="record.outletBacteriaStatus === '0'">{{ record.outletBacteria }}</span>
+          <span v-else :class="record.outletBacteriaStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.outletBacteria
+          }}</span>
+        </template>
+        <template v-if="column.key === 'outletEndotoxin'">
+          <span v-if="record.outletEndotoxinStatus === '0'">{{ record.outletEndotoxin }}</span>
+          <span v-else :class="record.outletEndotoxinStatus === '2' ? 'upStatus' : 'downStatus'">{{
+            record.outletEndotoxin
+          }}</span>
+        </template>
+        <template v-if="column.key === 'action'">
+          <TableAction
+            :actions="[
+              {
+                auth: 'biz:consumable:edit',
+                icon: 'icon-xt-details_edit_default|iconfont',
+                tooltip: '编辑',
+                onClick: handleEdit.bind(null, record),
+              },
+            ]"
+          />
+        </template>
+      </template>
+    </BasicTable>
+    <FormModal @register="registerModal" @success="callSuccess" @cancel="handleCancel" />
+  </div>
+</template>
+<script lang="ts" setup>
+  import { onBeforeMount, ref } from 'vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/TableCard';
+  import FormModal from './formModal.vue';
+  import Icon from '/@/components/Icon';
+  import { formatDictValue, formatDictPreColor } from '/@/utils';
+  import { columns } from './data';
+  import { microbialDetectionWaterQueryPage } from '/@/api/biz/bio/microbialDetectionWaterApi';
+  import { listDictModel } from '/@/api/common';
+  import { useModal } from '/@/components/Modal';
+  import { XTForm } from '/@/components/XTForm/index';
+  import dayjs from 'dayjs';
+
+  // formdata
+  const formData = [
+    {
+      label: '检测时间:',
+      name: 'shiftDate',
+      componentType: 'RangePicker',
+      format: 'YYYY-MM-DD',
+      valueFormat: 'YYYY-MM-DD',
+      placeholder: '请选择日期',
+      width: 240,
+    },
+    {
+      name: 'searchNames',
+      componentType: 'Input',
+      prefix: 'icon-xt-search',
+      placeholder: '请输入设备编号',
+      width: 240,
+    },
+  ];
+  // tab 切换选中
+  const tabSelected = ref();
+  // 操作名称
+  const searchNames = ref('');
+  const shiftDate = ref([]);
+
+  const responseTypeOptions = ref();
+  const responsesupplierCategoryOptions = ref();
+  onBeforeMount(async () => {
+    responseTypeOptions.value = await listDictModel({ dictCode: 'sys_disable_type' });
+    responsesupplierCategoryOptions.value = await listDictModel({ dictCode: 'pht' });
+  });
+
+  const [registerModal, { openModal }] = useModal();
+
+  const tableSort = ref([
+    {
+      field: 'create_time',
+      direction: 'DESC',
+    },
+  ]) as any;
+
+  const [registerTable, { reload, clearSelectedRowKeys }] = useTable({
+    api: microbialDetectionWaterQueryPage,
+    rowKey: 'id',
+    columns,
+    showIndexColumn: false,
+    bordered: true,
+    actionColumn: {
+      width: 200,
+      title: '操作',
+      dataIndex: 'action',
+    },
+    beforeFetch: handleBeforeFetch,
+    sortFn: handleSortFn,
+  });
+  // 详情按钮事件
+  function handleEdit(record) {
+    openModal(true, {
+      isUpdate: true,
+      record,
+    });
+  }
+
+  // 表格点击字段排序
+  function handleSortFn(sortInfo) {
+    if (sortInfo?.order && sortInfo?.columnKey) {
+      // 默认单列排序
+      tableSort.value = [
+        {
+          field: sortInfo.columnKey,
+          direction: sortInfo.order.replace(/(\w+)(end)/g, '$1').toUpperCase(),
+        },
+      ];
+    }
+  }
+
+  // 表格请求之前,对参数进行处理, 添加默认 排序
+  async function handleBeforeFetch(params) {
+    const shiftTimes = [];
+    if (shiftDate.value && shiftDate.value.length > 0) {
+      shiftTimes.push(shiftDate.value[0]);
+      shiftTimes.push(shiftDate.value[1]);
+      shiftTimes[1] = dayjs(shiftTimes[1]).add(1, 'day').format('YYYY-MM-DD');
+    }
+    return {
+      ...params,
+      orders: tableSort.value,
+      name: searchNames.value == '' ? undefined : searchNames.value,
+      status: tabSelected.value == '' ? undefined : tabSelected.value,
+      time: shiftTimes.length <= 0 ? undefined : shiftTimes,
+    };
+  }
+
+  // 新增按钮事件
+  function handleCreate() {
+    openModal(true, {
+      isUpdate: false,
+    });
+  }
+
+  //取消按钮事件
+  async function handleCancel() {
+    clearSelectedRowKeys();
+    await reload();
+  }
+
+  // 弹窗回调事件
+  async function callSuccess({ isUpdate, values }) {
+    console.log(isUpdate);
+    console.log(values);
+    await reload();
+  }
+
+  // 查询组件回调
+  async function callForm(data) {
+    shiftDate.value = data.shiftDate ? data.shiftDate : '';
+    searchNames.value = data.searchNames ? data.searchNames : '';
+    console.log('callForm:::', searchNames.value);
+    await reload();
+  }
+</script>
+<style lang="less" scoped>
+  .table-dot {
+    display: inline-block;
+    width: 10px;
+    height: 10px;
+    margin-right: 6px;
+    border-radius: 50%;
+  }
+
+  ::v-deep(.ant-btn-link) {
+    color: #3d4155;
+  }
+
+  ::v-deep(.ant-input-prefix) {
+    color: #8a99ac;
+  }
+
+  .colUpdateAvatar {
+    display: flex;
+    justify-content: center;
+    text-align: center;
+    line-height: 28px;
+  }
+
+  .colImg {
+    width: 28px;
+    height: 28px;
+    margin-right: 5px;
+  }
+
+  .upStatus {
+    color: #ff5d39;
+  }
+
+  .downStatus {
+    color: #ffad26;
+  }
+</style>

+ 1 - 1
src/views/biz/engineer/dialysis/data.ts

@@ -79,7 +79,7 @@ export const siftFormSchema: FormSchema[] = [
 export const columns: BasicColumn[] = [
   {
     title: '设备编号',
-    dataIndex: 'unique',
+    dataIndex: 'uniqueCode',
     align: 'left',
   },
   {

+ 3 - 0
src/views/biz/engineer/other/data.ts

@@ -91,6 +91,7 @@ export const dataFormSchema: FormSchema[] = [
   {
     label: '型号',
     field: 'model',
+    required: true,
     component: 'Input',
     componentProps: {
       placeholder: '请输入型号',
@@ -100,6 +101,7 @@ export const dataFormSchema: FormSchema[] = [
     label: '入账日期',
     field: 'purchaseDate',
     component: 'DatePicker',
+    required: true,
     componentProps: {
       format: 'YYYY-MM-DD',
       placeholder: '请选择入账日期',
@@ -111,6 +113,7 @@ export const dataFormSchema: FormSchema[] = [
     label: '生产日期',
     field: 'produceDate',
     component: 'DatePicker',
+    required: true,
     componentProps: {
       format: 'YYYY-MM-DD',
       placeholder: '请选择生产日期',

+ 4 - 0
src/views/biz/engineer/water/data.ts

@@ -88,6 +88,7 @@ export const dataFormSchema: FormSchema[] = [
   {
     label: '序列号',
     field: 'serialNumber',
+    required: true,
     component: 'Input',
     componentProps: {
       placeholder: '请输入型号',
@@ -116,6 +117,7 @@ export const dataFormSchema: FormSchema[] = [
     label: '生产日期',
     field: 'produceDate',
     component: 'DatePicker',
+    required: true,
     componentProps: {
       format: 'YYYY-MM-DD',
       placeholder: '请选择生产日期',
@@ -127,6 +129,7 @@ export const dataFormSchema: FormSchema[] = [
     label: '入账日期',
     field: 'purchaseDate',
     component: 'DatePicker',
+    required: true,
     componentProps: {
       format: 'YYYY-MM-DD',
       placeholder: '请选择生产日期',
@@ -211,6 +214,7 @@ export const maintenanceDataFormSchema: FormSchema[] = [
   {
     label: '维修方',
     field: 'maintenanceCompany',
+    required: true,
     component: 'ApiSelect',
     componentProps: {
       api: listDictModel,

+ 2 - 2
src/views/biz/engineer/water/treatmentList/index.vue

@@ -63,9 +63,9 @@
   const formData = [
     {
       name: 'patrolTime',
-      label: '保养时间',
+      label: '检查时间',
       componentType: 'RangePicker',
-      placeholder: '请选择保养时间',
+      placeholder: '请选择检查时间',
       format: 'YYYY-MM-DD',
       valueFormat: 'YYYY-MM-DD',
     },