소스 검색

feat: 新增交班记录

Tong 2 년 전
부모
커밋
71c888995f
4개의 변경된 파일565개의 추가작업 그리고 3개의 파일을 삭제
  1. 41 0
      src/api/biz/visit/transferApi.ts
  2. 124 0
      src/views/biz/visit/transfer/data.ts
  3. 79 0
      src/views/biz/visit/transfer/formModal.vue
  4. 321 3
      src/views/biz/visit/transfer/index.vue

+ 41 - 0
src/api/biz/visit/transferApi.ts

@@ -0,0 +1,41 @@
+import { defHttp } from '/@/utils/http/axios';
+enum Api {
+  typeNumber = '/visit/handoverShifts/queryPersonNumber',
+  transfetList = '/visit/handoverShifts/query/page',
+  transferDel = '/visit/handoverShifts/removeByIds',
+  transferAdd = '/visit/handoverShifts/add',
+  transferEdit = '/visit/handoverShifts/edit',
+  transferById = '/visit/handoverShifts/detail',
+}
+
+/**
+ * @description: 获取透前准备页面人员信息
+ * @method: POET
+ */
+export const getTypeNumber = () => {
+  return defHttp.get({ url: Api.typeNumber });
+};
+
+export const getTransgerList = (params?: object) => {
+  return defHttp.post({ url: Api.transfetList, params: params });
+};
+
+export const transferDel = (params?: object) => {
+  return defHttp.post({ url: Api.transferDel, params: params });
+};
+
+export const transferExport = (params?: object) => {
+  return defHttp.post({ url: Api.transferDel, params: params });
+};
+
+export const transferAdd = (params?: object) => {
+  return defHttp.post({ url: Api.transferAdd, params: params });
+};
+
+export const transferEdit = (params?: object) => {
+  return defHttp.post({ url: Api.transferEdit, params: params });
+};
+
+export const transferById = (id: string) => {
+  return defHttp.get({ url: Api.transferById + '/' + id });
+};

+ 124 - 0
src/views/biz/visit/transfer/data.ts

@@ -0,0 +1,124 @@
+import { BasicColumn, FormSchema } from '/@/components/Table';
+import {
+  archivesPatientBasicQueryPage,
+  archivesPatientBasicDetail,
+} from '@/api/biz/archives/patientBasicApi';
+import { listDictModel } from '/@/api/common';
+
+export const columns: BasicColumn[] = [
+  {
+    title: '患者姓名',
+    dataIndex: 'name',
+  },
+  {
+    title: '信息',
+    dataIndex: 'message',
+  },
+  {
+    title: '交班类型',
+    dataIndex: 'type',
+  },
+  {
+    title: '交班重点内容',
+    dataIndex: 'content',
+  },
+  {
+    title: '记录日期',
+    dataIndex: 'shiftTime',
+  },
+  {
+    title: '记录人',
+    dataIndex: 'updatorName',
+  },
+];
+// 表单新增编辑
+export const dataFormSchema: FormSchema[] = [
+  {
+    label: '患者姓名',
+    field: 'patientBasicId',
+    required: true,
+    ifShow: ({ values }) => {
+      return values.id ? false : true;
+    },
+    component: 'ApiSelect',
+    componentProps: ({ formModel }) => {
+      return {
+        api: archivesPatientBasicQueryPage,
+        params: {
+          name: formModel.patientBasicName,
+          pageSize: 999,
+        },
+        labelField: 'name',
+        valueField: 'id',
+        resultField: 'data',
+        placeholder: '请输入患者姓名',
+        getPopupContainer: () => document.body,
+        showSearch: true,
+        filterOption: false,
+        onSearch: e => {
+          formModel.patientBasicName = e;
+        },
+        onChange: async e => {
+          const detail = await archivesPatientBasicDetail(e);
+          formModel.message = (detail.gender == 'pb_sex_man' ? '男' : '女') + detail.age;
+        },
+      };
+    },
+  },
+  {
+    label: '患者姓名',
+    field: 'name',
+    component: 'Input',
+    componentProps: {
+      disabled: true,
+    },
+    ifShow: ({ values }) => {
+      return values.name ? true : false;
+    },
+  },
+  {
+    label: '患者信息',
+    field: 'message',
+    component: 'Input',
+    componentProps: {
+      disabled: true,
+    },
+  },
+  {
+    label: 'ID',
+    field: 'id',
+    component: 'Input',
+    ifShow: false,
+  },
+  {
+    label: '交班日期',
+    field: 'shiftTime',
+    component: 'DatePicker',
+    componentProps: {
+      format: 'YYYY-MM-DD',
+      placeholder: '请输入上传日期',
+      getPopupContainer: () => document.body,
+      valueFormat: 'YYYY-MM-DD',
+    },
+  },
+  {
+    label: '交班类型',
+    field: 'type',
+    component: 'ApiSelect',
+    componentProps: {
+      placeholder: '请选择交班类型',
+      api: listDictModel,
+      params: {
+        dictCode: 'hb',
+      },
+    },
+  },
+  {
+    label: '交班内容',
+    field: 'content',
+    component: 'InputTextArea',
+    componentProps: {
+      placeholder: '请输入交班内容',
+    },
+  },
+];

+ 79 - 0
src/views/biz/visit/transfer/formModal.vue

@@ -0,0 +1,79 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    destroyOnClose
+    @register="registerModal"
+    :title="getTitle"
+    @ok="handleSubmit"
+    @cancel="handleCancel"
+  >
+    <BasicForm @register="registerForm">
+      <template #messageSlot="{ model, field }">
+        <div>{{ model[field] }}</div>
+      </template>
+    </BasicForm>
+  </BasicModal>
+</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 { transferAdd, transferById, transferEdit } from '/@/api/biz/visit/transferApi';
+
+  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: 100,
+    schemas: dataFormSchema,
+    showActionButtonGroup: false,
+    actionColOptions: {
+      span: 23,
+    },
+  });
+  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 transferById(data.record.id);
+      console.log('resData::::', resData);
+      resData.message = (resData.gender == 'pb_sex_man' ? '男' : '女') + resData.age;
+      await setFieldsValue({
+        ...resData,
+      });
+    }
+  });
+
+  // 提交按钮事件
+  async function handleSubmit() {
+    try {
+      const values = await validate();
+      setModalProps({ confirmLoading: true });
+      !unref(isUpdate)
+        ? await transferAdd({ ...values })
+        : await transferEdit({ ...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>

+ 321 - 3
src/views/biz/visit/transfer/index.vue

@@ -1,7 +1,325 @@
 <template>
-  <div> 占位符 </div>
+  <div class="m-4">
+    <div>
+      <XTTitle title="交班记录" :right-data="titleData" @click="callTitleClick" />
+      <div class="flex items-center justify-between my-4">
+        <XTTab
+          type="illness"
+          :width="180"
+          :selected="tabSelected"
+          :data="typeOptions"
+          @item-click="callTab"
+        />
+        <XTForm :form-data="formData" @change="callForm" />
+      </div>
+    </div>
+    <BasicTable @register="registerTable">
+      <template #bodyCell="{ column, record }">
+        <template v-if="column.key === 'type'">
+          <span :class="['table-dot', 'table-dot--' + record.type]" />
+          <span> {{ formatDictValue(responseTypeOptions, record.type) }}</span>
+        </template>
+        <template v-if="column.key === 'shiftTime'">
+          {{ dayjs(record.shiftTime).format('YYYY-MM-DD') }}
+        </template>
+        <template v-if="column.key === 'message'">
+          <Icon
+            v-if="record.gender == 'pb_sex_man'"
+            icon="icon-xt-male_sm|iconfont"
+            color="#0057FF"
+          />
+          <Icon
+            v-if="record.gender == 'pb_sex_woman'"
+            icon="icon-xt-female_sm|iconfont"
+            color="#FF0066"
+          />({{ record.age }})</template
+        >
+        <template v-if="column.key === 'updatorName'">
+          <div class="colUpdateAvatar">
+            <img class="colImg" :src="record.updateAvatar" />
+            {{ record.updatorName }}
+          </div>
+        </template>
+        <template v-if="column.key === 'action'">
+          <TableAction
+            :actions="[
+              {
+                auth: 'visit:handoverShifts:edit',
+                icon: 'icon-xt-details_edit_default|iconfont',
+                tooltip: '编辑',
+                onClick: handleEdit.bind(null, record),
+              },
+              {
+                auth: 'visit:handoverShifts:edit',
+                icon: 'icon-xt-details_delete_default|iconfont',
+                tooltip: '删除',
+                popConfirm: {
+                  title: '是否确认删除',
+                  placement: 'left',
+                  confirm: handleDelete.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 { Icon } from '/@/components/Icon';
+  import dayjs from 'dayjs';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import FormModal from './formModal.vue';
+  import { columns } from './data';
 
-<script setup lang="ts"></script>
+  import {
+    getTypeNumber,
+    getTransgerList,
+    transferDel,
+    transferExport,
+  } from '/@/api/biz/visit/transferApi';
+  import { listDictModel } from '/@/api/common';
+  import { formatDictValue } from '/@/utils';
+  import { useModal } from '/@/components/Modal';
+  import { XTTitle } from '/@/components/XTTitle/index';
+  import { XTTab } from '/@/components/XTTab/index';
+  import { XTForm } from '/@/components/XTForm/index';
 
-<style lang="less" scoped></style>
+  // 标题数据
+  const titleData = [
+    {
+      type: 'print',
+      icon: 'icon-xt-print_default',
+    },
+    {
+      type: 'import',
+      icon: 'icon-xt-import_default',
+    },
+    {
+      type: 'add',
+      btnIcon: 'icon-xt-add_default',
+      btnText: '新增记录',
+    },
+  ];
+  // formdata
+  const formData = [
+    {
+      name: 'shiftDate',
+      componentType: 'DatePicker',
+      format: 'YYYY-MM-DD',
+      placeholder: '请选择日期',
+      width: 220,
+    },
+  ];
+  // tab 切换选中
+  const tabSelected = ref();
+  // 操作名称
+  const shiftDate = ref('');
+
+  const typeOptions = ref();
+  const responseTypeOptions = ref();
+  onBeforeMount(async () => {
+    responseTypeOptions.value = await listDictModel({ dictCode: 'hb' });
+    getTab();
+  });
+
+  const { createConfirm, createMessage } = useMessage();
+  const [registerModal, { openModal }] = useModal();
+
+  const tableSort = ref([
+    {
+      field: 'create_time',
+      direction: 'DESC',
+    },
+  ]) as any;
+
+  const [registerTable, { reload, getSelectRowKeys, clearSelectedRowKeys }] = useTable({
+    api: getTransgerList,
+    batchDelApi: transferDel,
+    batchExportApi: transferExport,
+    delAuthList: ['visit:handoverShifts:remove'],
+    rowKey: 'id',
+    columns,
+    showIndexColumn: true,
+    rowSelection: { type: 'checkbox' },
+    bordered: true,
+    actionColumn: {
+      width: 200,
+      title: '操作',
+      dataIndex: 'action',
+    },
+    beforeFetch: handleBeforeFetch,
+    sortFn: handleSortFn,
+  });
+  // 详情按钮事件
+  function handleEdit(record) {
+    openModal(true, {
+      record,
+      isUpdate: true,
+    });
+  }
+
+  // 新增按钮事件
+  function callTitleClick(data) {
+    if (data.type == 'add') {
+      openModal(true, {
+        isUpdate: false,
+        record: data,
+      });
+    } else if (data.type == 'print') {
+      console.log('打印中...');
+    }
+  }
+
+  // 删除按钮事件
+  async function handleDelete(record: Recordable) {
+    if (record) {
+      await transferDel([record.id]);
+      createMessage.success('删除成功!');
+      clearSelectedRowKeys();
+      await reload();
+      await getTab();
+    } else {
+      createConfirm({
+        content: '你确定要删除?',
+        iconType: 'warning',
+        onOk: async () => {
+          const keys = getSelectRowKeys();
+          await transferDel(keys);
+          createMessage.success('删除成功!');
+          await reload();
+          await getTab();
+        },
+      });
+    }
+  }
+  // 表格点击字段排序
+  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) {
+    return {
+      ...params,
+      orders: tableSort.value,
+      shiftType: tabSelected.value,
+      shiftTime: shiftDate.value == '' ? undefined : shiftDate.value,
+    };
+  }
+
+  async function getTab() {
+    typeOptions.value = await listDictModel({ dictCode: 'hb' });
+    const typeNums = await getTypeNumber(); // 获取各类型数量
+    const typeList = [];
+    typeOptions.value.forEach(ele => {
+      // 变量各类型放置对应数量
+      let typeData = {};
+      Object.keys(typeNums).forEach(numKey => {
+        if (ele.value == numKey) {
+          typeData = {
+            key: ele.value,
+            label: ele.label,
+            value: typeNums[numKey],
+            hasValue: true,
+            prefixColor: ele.prefixColor,
+            hasBracket: true,
+          };
+          typeList.push(typeData);
+        }
+      });
+    });
+    typeList.splice(0, 0, {
+      key: '',
+      label: '全部',
+      value: typeNums.total,
+      hasValue: true,
+      hasBracket: true,
+    });
+    typeOptions.value = typeList;
+    tabSelected.value = typeOptions.value[0].key;
+  }
+
+  //取消按钮事件
+  async function handleCancel() {
+    clearSelectedRowKeys();
+    await reload();
+    await getTab();
+  }
+
+  // 弹窗回调事件
+  async function callSuccess({ isUpdate, values }) {
+    console.log(isUpdate);
+    console.log(values);
+    await reload();
+    await getTab();
+  }
+
+  // 组件回调
+  async function callTab(data) {
+    tabSelected.value = data.value;
+    await reload();
+  }
+  async function callForm(data) {
+    shiftDate.value = data.shiftDate == null ? '' : data.shiftDate;
+    await reload();
+  }
+</script>
+<style lang="less" scoped>
+  .table-dot {
+    display: inline-block;
+    width: 10px;
+    height: 10px;
+    margin-right: 6px;
+    border-radius: 50%;
+
+    &--hb_new_complication {
+      background-color: #f7b500;
+    }
+
+    &--hb_new_patient {
+      background-color: #1bc1b3;
+    }
+
+    &--hb_stop_dialysis {
+      background-color: #d3d8dd;
+    }
+
+    &--hb_else {
+      background-color: #854aff;
+    }
+
+    &--hb_none_heparin {
+      background-color: #2d5aff;
+    }
+  }
+
+  ::v-deep(.ant-btn-link) {
+    color: #8a99ac;
+  }
+
+  .colUpdateAvatar {
+    display: flex;
+    justify-content: center;
+    text-align: center;
+    line-height: 28px;
+  }
+
+  .colImg {
+    width: 28px;
+    height: 28px;
+    margin-right: 5px;
+  }
+</style>