Bläddra i källkod

feat: 机器消毒模块开发

Tong 2 år sedan
förälder
incheckning
6e8bf79519

+ 38 - 0
src/api/biz/visit/deviceDisinfectApi.ts

@@ -0,0 +1,38 @@
+import { defHttp } from '/@/utils/http/axios';
+import { setParams } from '/@/utils/index';
+
+enum Api {
+  disinfectRecordPage = '/visit/deviceDisinfectRecord/query/page',
+  disinfectRecordRemove = '/visit/deviceDisinfectRecord/removeByIds',
+  disinfectMaintenance = '/visit/deviceDisinfectMaintenance/all',
+  disinfectMaintenanceDetail = '/visit/deviceDisinfectMaintenance/query',
+  disinfectMaintenanceEdit = '/visit/deviceDisinfectMaintenance/edit',
+}
+// 获取机器消毒列表页
+export const getDisinfectRecordPage = (params?: object) => {
+  return defHttp.post({
+    url: Api.disinfectRecordPage,
+    params: setParams(params),
+  });
+};
+// 删除机器消毒记录
+export const disinfectRecordRemove = (params: Array<string | number>) => {
+  return defHttp.post({ url: Api.disinfectRecordRemove, params: params });
+};
+
+// 获取机器消毒维护数据
+export const disinfectMaintenance = () => {
+  return defHttp.get({
+    url: Api.disinfectMaintenance,
+  });
+};
+
+// 通过Id获取机器消毒维护数据
+export const disinfectMaintenanceDetail = (id?: string) => {
+  return defHttp.get({ url: Api.disinfectMaintenanceDetail + '/' + id });
+};
+
+// 修改机器消毒维护数据
+export const disinfectMaintenaceEdit = (params?: object) => {
+  return defHttp.post({ url: Api.disinfectMaintenanceEdit, params });
+};

+ 1 - 0
src/components/XTCard/index.ts

@@ -2,3 +2,4 @@ export { default as XTCard } from './src/XTCard.vue';
 export { default as DescCard } from './src/DescCard.vue';
 export { default as DescMultiCard } from './src/DescMultiCard.vue';
 export { default as SimpleCard } from './src/SimpleCard.vue';
+export { default as DeviceDisinfectCard } from './src/DeviceDisinfectCard.vue';

+ 137 - 0
src/components/XTCard/src/DeviceDisinfectCard.vue

@@ -0,0 +1,137 @@
+<template>
+  <Card :bordered="false" class="card">
+    <div class="title">
+      <div>{{ props.data.deviceName + '—' + props.data.deviceModel }}</div>
+      <Button shape="circle" @click="handleEditInfo(props.data)" v-auth="editAuth"
+        ><Icon icon="icon-xt-details_edit_default|iconfont" :size="12"
+      /></Button>
+    </div>
+    <template v-for="(item, index) in props.data.disinfection" :key="index">
+      <div class="card-row" v-if="item.disinfectionType === 'ddt_disinfectant_hot'">
+        <div class="row-title"
+          >热&nbsp;&nbsp; 消&nbsp;&nbsp; 毒:<span class="blank-font">{{
+            formatDictValue(bizDictOptions.hot, item.disinfectant)
+          }}</span></div
+        >
+        <div class="blank-font">{{ item.disinfectionTime }}min</div>
+      </div>
+
+      <div class="card-row" v-if="item.disinfectionType === 'ddt_disinfectant_chemistry'">
+        <div class="row-title"
+          >化&nbsp;学&nbsp;消&nbsp;毒:<span class="blank-font">{{
+            formatDictValue(bizDictOptions.chemistry, item.disinfectant)
+          }}</span></div
+        >
+        <div class="blank-font">{{ item.disinfectionTime }}min</div>
+      </div>
+
+      <div class="card-row" v-if="item.disinfectionType === 'ddt_disinfectant_chemistry_hot'">
+        <div class="row-title"
+          >热化学消毒:<span class="blank-font">{{
+            formatDictValue(bizDictOptions.chemistryHot, item.disinfectant)
+          }}</span></div
+        >
+        <div class="blank-font">{{ item.disinfectionTime }}min</div>
+      </div>
+      <div class="card-row" v-if="item.disinfectionType === 'ddt_disinfectant_other'">
+        <div class="row-title"
+          >其&nbsp;他&nbsp;消&nbsp;毒:<span class="blank-font">{{
+            formatDictValue(bizDictOptions.other, item.disinfectant)
+          }}</span></div
+        >
+        <div class="blank-font">{{ item.disinfectionTime }}min</div>
+      </div>
+    </template>
+  </Card>
+</template>
+
+<script setup lang="ts">
+  import { onBeforeMount, ref, reactive } from 'vue';
+  import { Card } from 'ant-design-vue';
+  import { Button } from '/@/components/Button';
+  import { Icon } from '/@/components/Icon';
+  import { listDictModelBatch } from '/@/api/common';
+  import { formatDictValue } from '/@/utils';
+  interface Props {
+    data: {
+      deviceId?: string;
+      deviceName?: string;
+      deviceModel?: string;
+      disinfection?: Array<{
+        disinfectionType?: string;
+        disinfectionTime?: string;
+        disinfectant?: string;
+      }>;
+    };
+    editAuth: Array<string>;
+  }
+
+  const props = withDefaults(defineProps<Props>(), {
+    data: () => {
+      return {
+        deviceId: 'ID',
+        deviceName: '设备名称',
+        deviceModel: '型号',
+        disinfection: [],
+      };
+    },
+    editAuth: () => [],
+  });
+  const bizDictData = ref([
+    { key: 'hot', dictCode: 'ddt_disinfectant_hot' },
+    { key: 'chemistry', dictCode: 'ddt_disinfectant_chemistry' },
+    { key: 'chemistryHot', dictCode: 'ddt_disinfectant_chemistry_hot' },
+    { key: 'other', dictCode: 'ddt_disinfectant_other' },
+  ]);
+  const bizDictOptions = reactive<any>({});
+  // 组件加载前事件
+  onBeforeMount(async () => {
+    const res = await listDictModelBatch(bizDictData.value.map(ele => ele.dictCode));
+    for (const i in res) {
+      const filter = bizDictData.value.filter(ele => ele.dictCode == i)[0];
+      bizDictOptions[filter.key] = res[i];
+    }
+  });
+  const emit = defineEmits(['edits']);
+  // 编辑按钮方法
+  function handleEditInfo(data) {
+    emit('edits', data);
+  }
+</script>
+
+<style lang="less" scoped>
+  .card {
+    border-radius: 4px;
+    border: 1px solid #efefef;
+    background-color: #fff;
+    width: 380px;
+    height: 202px;
+
+    .title {
+      font-size: 18px;
+      font-weight: 600;
+      margin-bottom: 20px;
+      color: #000a18;
+      display: flex;
+      justify-content: space-between;
+    }
+
+    .card-row {
+      display: flex;
+      justify-content: space-between;
+      margin-bottom: 6px;
+    }
+
+    .row-title {
+      font-size: 14px;
+      font-weight: 400;
+      color: #8a99ac;
+    }
+
+    .blank-font {
+      font-size: 14px;
+      font-weight: 400;
+      color: #000a18;
+    }
+  }
+</style>

+ 187 - 0
src/views/biz/visit/deviceDisinfect/data.ts

@@ -0,0 +1,187 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '@/components/Form';
+import { listDictModel } from '/@/api/common';
+
+export const disinfectRecordColumns: BasicColumn[] = [
+  {
+    title: '病区/床位',
+    dataIndex: 'inpatientWard',
+    width: 100,
+  },
+  {
+    title: '班次',
+    dataIndex: 'sailingSort',
+    width: 100,
+  },
+  {
+    title: '开始时间',
+    dataIndex: 'beginTime',
+    width: 170,
+  },
+  {
+    title: '设备编号',
+    dataIndex: 'deviceCode',
+    width: 110,
+  },
+  {
+    title: '设备型号',
+    dataIndex: 'deviceModel',
+    width: 110,
+  },
+  {
+    title: '内部消毒类型',
+    dataIndex: 'disinfectionType',
+    width: 150,
+  },
+  {
+    title: '内部消毒液',
+    dataIndex: 'disinfectant',
+    width: 150,
+  },
+  {
+    title: '物表消毒',
+    dataIndex: 'disinfectantName',
+    width: 150,
+  },
+  {
+    title: '细菌过滤器',
+    dataIndex: 'otherMaintenanceBacterialFilter',
+    width: 120,
+  },
+  {
+    title: '消毒液',
+    dataIndex: 'otherMaintenanceDisinfectant',
+    width: 120,
+  },
+  {
+    title: '操作人',
+    dataIndex: 'updatorName',
+    width: 150,
+  },
+];
+
+export const dataDisinfectMaintenanceFormSchema: FormSchema[] = [
+  {
+    field: 'ddt_disinfectant_hot',
+    component: 'PlainTitle',
+    defaultValue: '热消毒',
+    colProps: {
+      span: 24,
+    },
+  },
+  {
+    label: '消毒剂',
+    field: 'hot_disinfectant',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: listDictModel,
+      params: {
+        dictCode: 'ddt_disinfectant_hot',
+      },
+    },
+  },
+  {
+    label: '消毒时间(min)',
+    field: 'hot_disinfectionTime',
+    required: true,
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入消毒时间(min)',
+      min: 1,
+    },
+  },
+
+  {
+    field: 'ddt_disinfectant_chemistry',
+    component: 'PlainTitle',
+    defaultValue: '化学消毒',
+    colProps: {
+      span: 24,
+    },
+  },
+  {
+    label: '消毒剂',
+    field: 'chemistry_disinfectant',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: listDictModel,
+      params: {
+        dictCode: 'ddt_disinfectant_chemistry',
+      },
+    },
+  },
+  {
+    label: '消毒时间(min)',
+    field: 'chemistry_disinfectionTime',
+    required: true,
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入消毒时间(min)',
+      min: 1,
+    },
+  },
+
+  {
+    field: 'ddt_disinfectant_chemistry_hot',
+    component: 'PlainTitle',
+    defaultValue: '热化学消毒',
+    colProps: {
+      span: 24,
+    },
+  },
+  {
+    label: '消毒剂',
+    field: 'chemistryHot_disinfectant',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: listDictModel,
+      params: {
+        dictCode: 'ddt_disinfectant_chemistry_hot',
+      },
+    },
+  },
+  {
+    label: '消毒时间(min)',
+    field: 'chemistryHot_disinfectionTime',
+    required: true,
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入消毒时间(min)',
+      min: 1,
+    },
+  },
+
+  {
+    field: 'ddt_disinfectant_other',
+    component: 'PlainTitle',
+    defaultValue: '其他消毒',
+    colProps: {
+      span: 24,
+    },
+  },
+  {
+    label: '消毒剂',
+    field: 'other_disinfectant',
+    required: true,
+    component: 'ApiSelect',
+    componentProps: {
+      api: listDictModel,
+      params: {
+        dictCode: 'ddt_disinfectant_other',
+      },
+    },
+  },
+  {
+    label: '消毒时间(min)',
+    field: 'other_disinfectionTime',
+    required: true,
+    component: 'InputNumber',
+    componentProps: {
+      placeholder: '请输入消毒时间(min)',
+      min: 1,
+    },
+  },
+];

+ 128 - 0
src/views/biz/visit/deviceDisinfect/disinfectMaintenanceFormModal.vue

@@ -0,0 +1,128 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    destroyOnClose
+    @register="registerModal"
+    :title="getTitle"
+    :width="width"
+    @ok="handleSubmit"
+    :showFooter="true"
+  >
+    <BasicForm @register="registerForm" layout="vertical" />
+  </BasicModal>
+</template>
+<script lang="ts" setup>
+  import { ref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, useForm } from '/@/components/Form';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { dataDisinfectMaintenanceFormSchema } from './data';
+
+  import {
+    disinfectMaintenanceDetail,
+    disinfectMaintenaceEdit,
+  } from '/@/api/biz/visit/deviceDisinfectApi';
+
+  const emit = defineEmits(['success', 'register']);
+
+  const getTitle = '机器消毒维护';
+  const width = '35%';
+  const rowRes = ref();
+
+  const { createMessage } = useMessage();
+  const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
+    labelWidth: 150,
+    schemas: dataDisinfectMaintenanceFormSchema,
+    showActionButtonGroup: false,
+    actionColOptions: {
+      span: 23,
+    },
+    baseColProps: {
+      span: 12,
+    },
+    wrapperCol: {
+      span: 23,
+    },
+  });
+  const [registerModal, { setModalProps, closeModal }] = useModalInner(async data => {
+    await resetFields();
+    setModalProps({ confirmLoading: false });
+    if (data) {
+      const resData = await disinfectMaintenanceDetail(data?.record?.deviceId);
+      rowRes.value = resData;
+      if (resData && resData.disinfection.length > 0) {
+        const resVal = {
+          hot_disinfectant: '',
+          hot_disinfectionTime: '',
+          chemistry_disinfectant: '',
+          chemistry_disinfectionTime: '',
+          chemistryHot_disinfectant: '',
+          chemistryHot_disinfectionTime: '',
+          other_disinfectant: '',
+          other_disinfectionTime: '',
+        };
+        resData.disinfection.forEach(item => {
+          switch (item.disinfectionType) {
+            case 'ddt_disinfectant_hot':
+              resVal.hot_disinfectant = item.disinfectant;
+              resVal.hot_disinfectionTime = item.disinfectionTime;
+              break;
+            case 'ddt_disinfectant_chemistry':
+              resVal.chemistry_disinfectant = item.disinfectant;
+              resVal.chemistry_disinfectionTime = item.disinfectionTime;
+              break;
+            case 'ddt_disinfectant_chemistry_hot':
+              resVal.chemistryHot_disinfectant = item.disinfectant;
+              resVal.chemistryHot_disinfectionTime = item.disinfectionTime;
+              break;
+            case 'ddt_disinfectant_other':
+              resVal.other_disinfectant = item.disinfectant;
+              resVal.other_disinfectionTime = item.disinfectionTime;
+              break;
+          }
+        });
+        await setFieldsValue({
+          ...resVal,
+        });
+      }
+    }
+  });
+
+  // 提交按钮事件
+  async function handleSubmit() {
+    try {
+      const values = await validate();
+      setModalProps({ confirmLoading: true });
+      const params = rowRes.value;
+      params.disinfection.forEach(item => {
+        switch (item.disinfectionType) {
+          case 'ddt_disinfectant_hot':
+            item.disinfectant = values.hot_disinfectant;
+            item.disinfectionTime = values.hot_disinfectionTime + '';
+            break;
+          case 'ddt_disinfectant_chemistry':
+            debugger;
+            item.disinfectant = values.chemistry_disinfectant;
+            item.disinfectionTime = values.chemistry_disinfectionTime + '';
+            break;
+          case 'ddt_disinfectant_chemistry_hot':
+            item.disinfectant = values.chemistryHot_disinfectant;
+            item.disinfectionTime = values.chemistryHot_disinfectionTime + '';
+            break;
+          case 'ddt_disinfectant_other':
+            item.disinfectant = values.other_disinfectant;
+            item.disinfectionTime = values.other_disinfectionTime + '';
+            break;
+        }
+      });
+      await disinfectMaintenaceEdit({ ...params });
+      createMessage.success('机器消毒维护成功!');
+      closeModal();
+      emit('success', {
+        values: { ...values },
+      });
+    } finally {
+      setModalProps({ confirmLoading: false });
+    }
+  }
+</script>

+ 248 - 0
src/views/biz/visit/deviceDisinfect/index.vue

@@ -0,0 +1,248 @@
+<template>
+  <div class="m-4">
+    <div>
+      <XTTitle title="机器消毒" />
+      <PageWrapper>
+        <Card
+          :bordered="false"
+          :active-tab-key="activeKey"
+          :tab-list="tabList"
+          style="height: 800px"
+          @tabChange="handleTabChange"
+        >
+          <div :key="0" v-if="activeKey == 0">
+            <Row>
+              <Col :span="24">
+                <BasicTable @register="registerTable">
+                  <template #bodyCell="{ column, record }">
+                    <template v-if="column.key === 'inpatientWard'">
+                      {{ record.inpatientWard + record.bed }}
+                    </template>
+                    <template v-if="column.key === 'disinfectionType'">
+                      <span
+                        :color="formatDictColor(disinfectionTypeOptions, record.disinfectionType)"
+                        :style="
+                          'color:' +
+                          formatDictFontColor(disinfectionTypeOptions, record.disinfectionType)
+                        "
+                      >
+                        {{ formatDictValue(disinfectionTypeOptions, record.disinfectionType) }}
+                      </span>
+                    </template>
+                    <template v-if="column.key === 'disinfectant'">
+                      <span>
+                        {{ getDisinfectant(record) }}
+                      </span>
+                    </template>
+                    <template v-if="column.key === 'otherMaintenanceDisinfectant'">
+                      <span>
+                        {{ record.otherMaintenanceDisinfectant ? '已更换' : '未更换' }}
+                      </span>
+                    </template>
+                    <template v-if="column.key === 'otherMaintenanceBacterialFilter'">
+                      <span>
+                        {{ record.otherMaintenanceBacterialFilter ? '已更换' : '未更换' }}
+                      </span>
+                    </template>
+                    <template v-if="column.key === 'updatorName'">
+                      <img :src="record.updateAvatar" class="table-avatar" />
+                      {{ record.updatorName }}
+                    </template>
+                    <template v-if="column.key === 'action'">
+                      <TableAction
+                        :actions="[
+                          // {
+                          //   auth: 'bizSys:wardInfo:edit',
+                          //   icon: 'icon-xt-details_edit_default|iconfont',
+                          //   tooltip: '编辑',
+                          //   onClick: handleEditDisinfectRecord.bind(null, record),
+                          // },
+                          {
+                            auth: 'bizSys:wardInfo:remove',
+                            icon: 'icon-xt-details_delete_default|iconfont',
+                            tooltip: '删除',
+                            popConfirm: {
+                              title: '是否确认删除',
+                              placement: 'left',
+                              confirm: handleDelDisinfectRecord.bind(null, record),
+                            },
+                          },
+                        ]"
+                      />
+                    </template>
+                  </template>
+                </BasicTable>
+              </Col>
+            </Row>
+          </div>
+          <div :key="1" v-else>
+            <div class="card-list">
+              <DeviceDisinfectCard
+                class="cards"
+                v-for="(item, index) in disinfectMaintenanceList"
+                :data="item"
+                :editAuth="['biz:deviceDisinfectMaintenance:edit']"
+                :key="index"
+                @edits="handleEditDisinfectMaintenance"
+              />
+            </div>
+          </div>
+        </Card>
+      </PageWrapper>
+    </div>
+  </div>
+  <DisinfectMaintenanceFormModal
+    @register="registerModal"
+    @success="handleEditDisinfectMaintenanceSuccess"
+  />
+</template>
+
+<script lang="ts" setup>
+  import { onBeforeMount, ref } from 'vue';
+  import { XTTitle } from '/@/components/XTTitle/index';
+  import { PageWrapper } from '/@/components/Page';
+  import { DeviceDisinfectCard } from '@/components/XTCard/index';
+  import { Card, Row, Col } from 'ant-design-vue';
+  import { useModal } from '/@/components/Modal';
+  import DisinfectMaintenanceFormModal from './disinfectMaintenanceFormModal.vue';
+  import { BasicTable, useTable, TableAction } from '/@/components/TableCard';
+  import { disinfectRecordColumns } from './data';
+  import {
+    getDisinfectRecordPage,
+    disinfectRecordRemove,
+    disinfectMaintenance,
+  } from '/@/api/biz/visit/deviceDisinfectApi';
+  import { listDictModel, listDictModelBatch } from '/@/api/common';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { formatDictColor, formatDictFontColor, formatDictValue } from '/@/utils';
+  const { createMessage } = useMessage(); // createConfirm,
+  const tabList = ref([
+    { key: 0, tab: '消毒记录', type: 'WARD' },
+    { key: 1, tab: '机器消毒维护', type: 'WORK' },
+  ]);
+  const activeKey = ref(0);
+  const disinfectionTypeOptions = ref();
+  const disinfectantOptions = ref();
+  const disinfectMaintenanceList = ref();
+
+  const [registerModal, { openModal: openDisinfectMaintenance }] = useModal();
+  onBeforeMount(async () => {
+    disinfectionTypeOptions.value = await listDictModel({ dictCode: 'tv_ddt' });
+    const bizDictData = [] as any;
+    disinfectionTypeOptions.value.forEach(item => {
+      bizDictData.push({
+        key: item.value,
+        dictCode: item.value,
+      });
+    });
+    disinfectantOptions.value = await listDictModelBatch(bizDictData.map(ele => ele.dictCode));
+    await getDeviceDiisinfect();
+  });
+
+  const [registerTable, { reload }] = useTable({
+    api: getDisinfectRecordPage,
+    rowKey: 'id',
+    columns: disinfectRecordColumns,
+    showIndexColumn: false,
+    striped: false,
+    formConfig: {
+      labelWidth: 120,
+      autoSubmitOnEnter: true,
+      baseColProps: { xs: 24, sm: 12, md: 12, lg: 8 },
+      resetButtonOptions: {
+        preIcon: 'icon-delete|iconfont',
+      },
+      submitButtonOptions: {
+        preIcon: 'icon-search|iconfont',
+      },
+    },
+    useSearchForm: false,
+    actionColumn: {
+      width: 120,
+      title: '操作',
+      dataIndex: 'action',
+    },
+    beforeFetch: handleBeforeFetch,
+  });
+
+  const tableSort = ref([
+    {
+      field: 'sort',
+      direction: 'ASC',
+    },
+  ]);
+  const selectType = ref();
+
+  // 方法区
+  // 获取机器消毒维护列表
+  async function getDeviceDiisinfect() {
+    disinfectMaintenanceList.value = await disinfectMaintenance();
+    console.log('disinfectMaintenanceList:::', disinfectMaintenanceList.value);
+  }
+  // 获取病区信息前事件
+  function handleBeforeFetch(params) {
+    return { ...params, propertiesId: selectType.value, orders: tableSort.value };
+  }
+  // 停用启用病区方法
+  async function handleDelDisinfectRecord(record) {
+    await disinfectRecordRemove([record.id]);
+    createMessage.success('删除成功');
+    reload();
+  }
+  function getDisinfectant(record) {
+    for (const key in disinfectantOptions.value) {
+      if (key == record.disinfectionType) {
+        return formatDictValue(disinfectantOptions.value[key], record.disinfectant);
+      }
+    }
+  }
+  // 编辑机器消毒维护
+  function handleEditDisinfectMaintenance(record) {
+    openDisinfectMaintenance(true, {
+      record,
+    });
+  }
+  // 编辑机器消费维护成功回调方法
+  async function handleEditDisinfectMaintenanceSuccess() {
+    await getDeviceDiisinfect();
+  }
+
+  // 切换Tab
+  function handleTabChange(key) {
+    activeKey.value = key;
+    if (key) {
+      getDeviceDiisinfect();
+    }
+  }
+
+  // 编辑消毒记录
+  // function handleEditDisinfectRecord() {}
+</script>
+
+<style lang="less" scoped>
+  ::v-deep(.ant-card-head) {
+    background-color: #f6f8fa !important;
+    color: #000a18;
+    font-weight: 600;
+    font-size: 18px;
+  }
+
+  ::v-deep(.ant-card) {
+    background-color: #f6f8fa !important;
+  }
+
+  ::v-deep(.ant-btn-link) {
+    color: rgb(61 65 85 / 100%);
+  }
+
+  .card-list {
+    width: 100%;
+
+    .cards {
+      margin-left: 20px;
+      margin-top: 20px;
+      background-color: #fff !important;
+      display: inline-block;
+    }
+  }
+</style>