Parcourir la source

修改辨识仪脉诊的顺序 以及调养页面不勾选配送仍然是打勾的

张田田 il y a 6 mois
Parent
commit
570a14068a

+ 2 - 1
@types/typed-router.d.ts

@@ -27,7 +27,9 @@ declare module 'vue-router/auto-routes' {
     '//care/supplier': RouteRecordInfo<'//care/supplier', '/care/supplier', Record<never, never>, Record<never, never>>,
     '//care/systemService': RouteRecordInfo<'//care/systemService', '/care/systemService', Record<never, never>, Record<never, never>>,
     '//care/text': RouteRecordInfo<'//care/text', '/care/text', Record<never, never>, Record<never, never>>,
+    '//equipment/configured': RouteRecordInfo<'//equipment/configured', '/equipment/configured', Record<never, never>, Record<never, never>>,
     '//equipment/registe': RouteRecordInfo<'//equipment/registe', '/equipment/registe', Record<never, never>, Record<never, never>>,
+    '//equipment/reportManagement': RouteRecordInfo<'//equipment/reportManagement', '/equipment/reportManagement', Record<never, never>, Record<never, never>>,
     '//follow/assessment': RouteRecordInfo<'//follow/assessment', '/follow/assessment', Record<never, never>, Record<never, never>>,
     '//follow/plan': RouteRecordInfo<'//follow/plan', '/follow/plan', Record<never, never>, Record<never, never>>,
     '//follow/task': RouteRecordInfo<'//follow/task', '/follow/task', Record<never, never>, Record<never, never>>,
@@ -45,7 +47,6 @@ declare module 'vue-router/auto-routes' {
     '/aio/flow-config/panel/RegisterPanel': RouteRecordInfo<'/aio/flow-config/panel/RegisterPanel', '/aio/flow-config/panel/RegisterPanel', Record<never, never>, Record<never, never>>,
     '/aio/flow-config/panel/ReportPanel': RouteRecordInfo<'/aio/flow-config/panel/ReportPanel', '/aio/flow-config/panel/ReportPanel', Record<never, never>, Record<never, never>>,
     '/aio/flow-config/panel/StartPanel': RouteRecordInfo<'/aio/flow-config/panel/StartPanel', '/aio/flow-config/panel/StartPanel', Record<never, never>, Record<never, never>>,
-    '/aio/FlowConfigDemo': RouteRecordInfo<'/aio/FlowConfigDemo', '/aio/FlowConfigDemo', Record<never, never>, Record<never, never>>,
     '/login': RouteRecordInfo<'/login', '/login', Record<never, never>, Record<never, never>>,
   }
 }

+ 9 - 6
src/pages/index/care/issueService.vue

@@ -169,6 +169,7 @@ async function getCpRecordDetail(id: string) {
     selectedProvince.value = res?.provinceCode;
     selectedCity.value = res?.cityCode;
     selectedArea.value = res?.areaCode;
+    deliveryChecked.value = res?.isDelivery === 'Y' ? true : false;
   });
 }
 function getPatientList(id: string) {
@@ -348,11 +349,12 @@ watch(displayTableData, (newValue, oldValue) => {
     isShowDelivery.value = newValue.some((item) => {
       return item.conditioningProgramDetail?.isDelivery === 'Y';
     });
-    if (isShowDelivery.value) {
-      deliveryChecked.value = true;
-    } else {
-      deliveryChecked.value = false;
-    }
+    console.log(isShowDelivery.value, 'isShowDelivery.value');
+    // if (isShowDelivery.value) {
+    //   deliveryChecked.value = true;
+    // } else {
+    //   deliveryChecked.value = false;
+    // }
     newValue.forEach((row: any) => {
       row.frequencyTypeing = row.frequencyType ? [row.frequencyType] : [];
     });
@@ -666,6 +668,7 @@ async function handleSubmit() {
       delete item.id;
     });
   }
+  console.log(deliveryChecked.value, 'deliveryChecked.value');
   form.isDelivery = deliveryChecked.value ? 'Y' : 'N';
   form.id = Number(currentPatient.value.id);
   form.patientId = currentPatient.value.patientId;
@@ -1226,7 +1229,7 @@ function openPatientHealthRecord(row: { id: string }, showType: 'analysis' | 'sc
         <div class="delivery-row" v-if="isShowDelivery">
           <div v-if="btnType !== '转方案' && currentPatient?.status === '0'">
             <a-checkbox v-model:checked="deliveryChecked" disabled>配送</a-checkbox>
-            <span>地址:</span>
+            <span v-if="form.provinceName || form.cityName || form.areaName || form.detailAddress">地址:</span>
             <span>{{ form.provinceName }}{{ form.cityName }}{{ form.areaName }}{{ form.detailAddress }}</span>
             <span style="margin-left: 16px" v-if="form.phone">电话:</span>
             <span>{{ form.phone }}</span>

+ 4 - 21
src/pages/index/equipment/configured.vue

@@ -6,14 +6,13 @@ import { getDictionaryMethod } from '@/request/api/dictionary.api';
 import dayjs from 'dayjs';
 import EditConfigured from '@/components/EditConfigured.vue';
 import EditMoreConfigured from '@/components/EditMoreConfigured.vue';
-import { analysisRequestData, type FlowRequestData } from '@/pages/aio/flow-config/index';
 
 defineOptions({ name: 'EquipmentConfiguredPage' });
 
 import type { DeviceManageModel, DeviceManageQuery } from '@/model/device.model';
 
 // 接口数据
-import { deviceManageMethod, updateDeviceRegisterOrganizationMethod } from '@/request/api/device.api';
+import { deviceManageMethod } from '@/request/api/device.api';
 import { branchMethod } from '@/request/api/system.api';
 // 获取组织树
 const { data: branch, loading: branchLoading } = useRequest(branchMethod(0, 1, 1));
@@ -194,12 +193,12 @@ const gridOptions = reactive<VxeGridProps<DeviceManageModel>>({
       align: 'center',
       children: [
         { field: 'isPatientFile', title: '建档', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isPatientFile) },
-        { field: 'isTonguefaceUpload', title: '舌面诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isTonguefaceUpload) },
-        { field: 'tonguefaceUploadResultShowType', title: '舌面分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.tonguefaceUploadResultShowType) },
         { field: 'puisPulseUploadlse', title: '脉诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isPulseUpload) },
         { field: 'pulseReportShowType', title: '脉象分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.pulseReportShowType) },
+        { field: 'isTonguefaceUpload', title: '舌面诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isTonguefaceUpload) },
+        { field: 'tonguefaceUploadResultShowType', title: '舌面分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.tonguefaceUploadResultShowType) },
         { field: 'isTonguefaceAnalysis', title: '问诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isTonguefaceAnalysis) },
-        { field: 'healthAnalysisReportShowType', title: '健康分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.healthAnalysisReportShowType) },
+        { field: 'healthAnalysisReportShowType', title: '报告+方案', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.healthAnalysisReportShowType) },
         { field: 'isHealthAnalysisScheme', title: '调理方案', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isHealthAnalysisScheme) },
       ],
     },
@@ -239,7 +238,6 @@ const { loading, page, pageSize, total, onSuccess, refresh } = usePagination((pa
   immediate: false,
 });
 onSuccess(({ data: { data } }) => {
-  console.log(data, '获取数据');
   gridRef.value?.loadData(data);
 });
 
@@ -278,10 +276,7 @@ function showTypeFormatter(value: any) {
 // 编辑辨识仪配置
 function editConfigured(model?: DeviceManageModel) {
   VxeUI.modal.open({
-    // title: model?.id ? `修改配置` : `新增配置`,
     title: `修改配置`,
-    // height: 850,
-    // width: 900,
     fullscreen: true,
     escClosable: true,
     destroyOnClose: true,
@@ -325,18 +320,6 @@ function importOrganization() {
             refresh(page.value);
             VxeUI.modal.close('import-more-configured');
           },
-          // onSubmit(org: any) {
-          //   const deviceIds = selectedRows.map((item: DeviceManageModel) => item.id);
-          //   batchUpdateDeviceManageMethod({ deviceIds, orgId: org.orgId, institutionId: org.institutionId })
-          //     .then(() => {
-          //       notification.success({ message: '批量修改成功' });
-          //       refresh(page.value);
-          //       VxeUI.modal.close('import-more-configured');
-          //     })
-          //     .catch(() => {
-          //       notification.error({ message: '批量修改失败' });
-          //     });
-          // },
         });
       },
     },

+ 129 - 74
src/service/AddItems.vue

@@ -1,8 +1,7 @@
 <script lang="ts" setup>
-import { ref, watch, reactive, onMounted, h, computed } from 'vue';
+import { ref, watch, reactive, onMounted, h, computed, nextTick } from 'vue';
 import { message } from 'ant-design-vue';
 import { PlusOutlined } from '@ant-design/icons-vue'; // 确保导入
-import { notification } from 'ant-design-vue';
 import VxeUI from 'vxe-table';
 import { useRequest } from 'alova/client';
 import { getDictionaryMethod, cpMedicinesMethod } from '@/request/api/dictionary.api';
@@ -21,10 +20,13 @@ const formRef = ref<FormInstance>();
 const typeOptionsLoading = ref<boolean>(false);
 const typeOptions = ref<{ label: string; value: string }[]>([]);
 
+// 统一提升消息提示层级,避免被弹窗遮挡
+message.config({ zIndex: 5000, top: 80, maxCount: 3, duration: 2 });
+
 const supplierOptions = ref<{ label: string; value: string }[]>([]);
 
 const isRequired = ref<boolean>(true);
-
+// 使用单位
 const unitOptions = [
   { label: '袋', value: '袋' },
   { label: '包', value: '包' },
@@ -100,17 +102,36 @@ const checkedList = ref<string[]>(['1']); // 默认选中第一个
 const onlineArr = ref<string[]>([]);
 const deliverArr = ref<string[]>([]);
 
+// 添加推导逻辑编辑状态
+const isDerivationModalOpen = ref(false);
+
 const rules = {
   name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
   conditioningProgramType: [{ required: true, message: '请选择方案类型', trigger: 'change' }],
-  institutionId: [{ required: true, message: '请选择机构名称', trigger: 'change' }],
+  institutionId: [{ 
+    required: true, 
+    message: '请选择机构名称', 
+    trigger: 'blur',
+    validator: (rule: any, value: any, callback: any) => {
+      // 如果推导逻辑弹窗打开,跳过验证
+      if (isDerivationModalOpen.value) {
+        callback();
+        return;
+      }
+      if (!value) {
+        callback(new Error('请选择机构名称'));
+      } else {
+        callback();
+      }
+    }
+  }],
+  isOffline: [{ required: true, message: '请选择线下项目', trigger: 'change' }],
+  isDelivery: [{ required: true, message: '请选择是否配送', trigger: 'change' }],
 };
 const isShowOnline = ref<boolean>(false);
 const isShowDelivery = ref<boolean>(false);
 const supplierArr = ref<any[]>([]);
 
-// 弹层容器:避免模板中直接引用 document 导致类型检查报错
-const getBodyContainer = () => document.body as HTMLElement;
 
 // 获取所有的供应商
 async function getSupplier(params: any) {
@@ -223,23 +244,19 @@ function removeHerb(idx: number) {
   }
 }
 
-// 新增:处理自定义药材输入
-function handleCustomHerb(value: string, idx: number) {
-  if (form.cpMedicines && form.cpMedicines[idx]) {
-    form.cpMedicines[idx].name = value;
-    form.cpMedicines[idx].id = value; // 自定义选项使用输入值作为ID
-  }
-}
-
 function cancel() {
   VxeUI.modal.close(`add-items-modal`);
 }
 function doSubmit() {
+  // 手动验证方案类型
+  if (!form.conditioningProgramType) {
+    message.error('请选择方案类型');
+    return;
+  }
+  
   // 自定义验证:检查项目应用是否已选择
   if (!checkedList.value || checkedList.value.length === 0) {
-    notification.error({
-      message: '请选择项目应用',
-    });
+    message.error('请选择项目应用');
     return;
   }
   form.isForWrap = checkedList.value.includes('1') ? 'Y' : null;
@@ -248,9 +265,7 @@ function doSubmit() {
   if ((form.addType === 'itemsList' && checkedList.value.includes('1')) || form.addType === 'system') {
     // 计价规则
     if (!form.pricingType) {
-      notification.error({
-        message: '请选择计价规则',
-      });
+      message.error('请选择计价规则');
       return;
     }
     // 计价规则相关字段校验
@@ -258,9 +273,7 @@ function doSubmit() {
       const { unitPrice, pricingUnit, convertDose, convertUnit } = form.cpFixedPricingRule || {};
       const allFilled = (unitPrice !== '' && unitPrice !== null && unitPrice !== undefined) && pricingUnit && (convertDose !== '' && convertDose !== null && convertDose !== undefined) && convertUnit;
       if (!allFilled) {
-        notification.error({
-          message: '请将单价、计价单位、相当于、使用单位全部填写',
-        });
+        message.error('请将单价、计价单位、相当于、使用单位全部填写');
         return;
       }
       form.cpDynamicPricingRule = undefined;
@@ -272,21 +285,20 @@ function doSubmit() {
       rule1.max = 0;
       rule2.min = 0;
       if (!(allFilled1 && allFilled2)) {
-        notification.error({
-          message: '请将按穴位/经络/部位的所有计价字段全部填写',
-        });
+        message.error('请将按穴位/经络/部位的所有计价字段全部填写');
         return;
       }
       // 按穴位模式:清空一口价数据
       form.cpFixedPricingRule = undefined;
     }
     // 供应商
-    if (form.addType === 'itemsList' && checkedList.value.includes('1')) {
-      if (!form.conditioningProgramSupplierId) {
-        message.error('请选择供应商');
-        return;
-      }
-    } else if (form.addType === 'system') {
+    // if (form.addType === 'itemsList' && checkedList.value.includes('1')) {
+    //   // if (!form.conditioningProgramSupplierId) {
+    //   //   message.error('请选择供应商');
+    //   //   return;
+    //   // }
+    // } else
+     if (form.addType === 'system') {
       form.isOffline = 'N';
       form.isDelivery = 'N';
     }
@@ -360,11 +372,6 @@ function doSubmit() {
     }
     submit(form);
   });
-  // .catch((error: any) => {
-  //   notification.error({
-  //     message: error.message || '必填内容请填写完整',
-  //   });
-  // });
 }
 // 获取方案类型
 async function getConditioningProgramType() {
@@ -375,9 +382,7 @@ async function getConditioningProgramType() {
       typeOptions.value = res; // 直接使用返回的数据
     }
   } catch (error: any) {
-    notification.error({
-      message: error.message,
-    });
+    message.error(error.message);
   } finally {
     typeOptionsLoading.value = false;
   }
@@ -393,9 +398,7 @@ async function getJumpType() {
     jumpTypeOptions.value = res;
   }
 } catch (error: any) {
-  notification.error({
-    message: error.message,
-  });
+  message.error(error.message);
 } finally {
   jumpTypeOptionsLoading.value = false;
 }
@@ -409,12 +412,6 @@ function handleSelectClick() {
   }
 }
 
-// 搜索过滤函数
-function filterOption(input: string, option: any) {
-  const searchText = input.toLowerCase();
-  const optionText = option.label?.toLowerCase() || '';
-  return optionText.includes(searchText);
-}
 
 onMounted(async () => {
   const deptId = localStorage.getItem('deptId');
@@ -550,10 +547,26 @@ const uploading = ref(false);
 const progress = ref(0);
 const videoFileList = ref<UploadFile[]>([]);
 
-// 供应商校验规则:仅在“项目应用 勾选 服务包”且“新增项目(itemsList)”时必填
+// 供应商校验规则:仅在"项目应用 勾选 服务包"且"新增项目(itemsList)"时必填
 const supplierRules = computed(() => {
   const need = checkedList.value.includes('1') && form.addType === 'itemsList';
-  return need ? [{ required: true, message: '请选择供应商', trigger: ['change', 'blur'] }] : [];
+  return need ? [{ 
+    required: true, 
+    message: '请选择供应商', 
+    trigger: 'blur',
+    validator: (rule: any, value: any, callback: any) => {
+      // 如果推导逻辑弹窗打开,跳过验证
+      if (isDerivationModalOpen.value) {
+        callback();
+        return;
+      }
+      if (!value) {
+        callback(new Error('请选择供应商'));
+      } else {
+        callback();
+      }
+    }
+  }] : [];
 });
 
 // 上传前校验
@@ -714,10 +727,6 @@ watch(
     }
   }
 );
-function bindchange(e: any) {
-  form.conditioningProgramSupplierId = '';
-  form.isOffline = null;
-}
 function onlineChange(value: any) {
   form.isOffline = value[value.length - 1];
   deliverArr.value = [];
@@ -733,15 +742,6 @@ function getConditioningProgramSupplier(value: any) {
   form.isDelivery = null;
   isShowDelivery.value = false;
 }
-function handleSelect(value: any, node: any) {
-  form.institutionId = value;
-  if (node && node.label) {
-    form.institutionName = node.label;
-  } else if (node && node.title) {
-    form.institutionName = node.title;
-  }
-}
-
 // 项目应用数据
 const plainOptions = [
   { id: '1', name: '服务包项目' },
@@ -764,6 +764,9 @@ const isDerivationEmpty = computed(() => {
   });
 });
 function handleDerivation() {
+  // 设置推导逻辑弹窗打开状态
+  isDerivationModalOpen.value = true;
+  
   VxeUI.modal.open({
     title: `推导逻辑`,
     height: 750,
@@ -773,6 +776,13 @@ function handleDerivation() {
     id: `derivation-modal`,
     remember: true,
     storage: true,
+    onClose: () => {
+      // 弹窗关闭时清除验证状态并重置状态
+      isDerivationModalOpen.value = false;
+      nextTick(() => {
+        formRef.value?.clearValidate(['institutionId', 'conditioningProgramSupplierId']);
+      });
+    },
     slots: {
       default() {
         return h(Derivation, {
@@ -785,6 +795,19 @@ function handleDerivation() {
           onSubmit: (data: any) => {
             derivationData.value = data;
             hasDerivationLogic.value = true; // 设置推导逻辑已编辑
+            
+            // 重置状态并清除验证状态
+            isDerivationModalOpen.value = false;
+            nextTick(() => {
+              formRef.value?.clearValidate(['institutionId', 'conditioningProgramSupplierId']);
+            });
+          },
+          onCancel: () => {
+            // 取消时重置状态并清除验证状态
+            isDerivationModalOpen.value = false;
+            nextTick(() => {
+              formRef.value?.clearValidate(['institutionId', 'conditioningProgramSupplierId']);
+            });
           },
         });
       },
@@ -796,11 +819,21 @@ function handleDerivation() {
 <template>
   <div class="form-container">
     <a-form ref="formRef" :model="form" :rules="rules" layout="horizontal">
-      <a-form-item label="项目名称:" name="name" required>
+      <a-form-item label="项目名称:" name="name">
         <a-input v-model:value="form.name" placeholder="请输入" />
       </a-form-item>
-      <a-form-item label="方案类型:" name="conditioningProgramType" required style="width: 100%">
-        <vxe-select v-model="form.conditioningProgramType" :options="typeOptions" placeholder="请选择" clearable filterable transfer @change="bindchange" style="width: 100%" />
+      <a-form-item label="方案类型:" name="conditioningProgramType" style="width: 100%" required>
+        <vxe-select
+          v-model="form.conditioningProgramType"
+          :options="typeOptions"
+          placeholder="请选择方案类型"
+          clearable
+          filterable
+          transfer
+          empty-text="暂无数据"
+          @focus="handleSelectClick"
+          style="width: 100%"
+        />
       </a-form-item>
       <a-form-item label="项目应用:" required v-if="form.addType === 'itemsList'">
         <a-checkbox-group v-model:value="checkedList">
@@ -1080,15 +1113,18 @@ function handleDerivation() {
         ></a-tree-select>
       </a-form-item>
       <a-form-item label="供应商:" name="conditioningProgramSupplierId" :rules="supplierRules" style="width: 100%">
-        <vxe-select
-          v-model="form.conditioningProgramSupplierId"
+        <a-select
+          v-model:value="form.conditioningProgramSupplierId"
           :options="supplierOptions"
           placeholder="请选择"
-          clearable
-          filterable
-          transfer
-          @change="getConditioningProgramSupplier"
+          allow-clear
+          show-search
+          :getPopupContainer="getSafePopupContainer"
+          :dropdownMatchSelectWidth="false"
+          :dropdownStyle="{ zIndex: 5000 }"
           style="width: 100%"
+          @change="getConditioningProgramSupplier"
+          not-found-content="暂无数据"
         />
       </a-form-item>
       <a-form-item label="线下项目:" name="isOffline" v-if="isShowOnline" :required="checkedList.includes('1')">
@@ -1129,9 +1165,12 @@ function handleDerivation() {
 
 <style scoped>
 .form-container {
-  width: 760px;
+  width: 95%;
   margin: 0 auto;
   padding: 10px 0px 0 0;
+  display: flex;
+  flex-direction: column;
+  /* max-height: 80vh; */
 }
 .per-rule {
   margin-bottom: 16px;
@@ -1185,6 +1224,16 @@ function handleDerivation() {
   display: flex;
   justify-content: center;
   gap: 16px;
+  position: sticky;
+  bottom: 0;
+  background: #fff;
+  padding: 12px 0;
+}
+
+.form-container .ant-form {
+  display: flex;
+  flex-direction: column;
+  overflow: auto;
 }
 .slider-section {
   margin-bottom: 16px;
@@ -1482,3 +1531,9 @@ function handleDerivation() {
   font-size: 10px;
 }
 </style>
+<style>
+/* 提升 AntD Select 下拉层级,避免被弹窗/遮罩遮挡 */
+.ant-select-dropdown {
+  z-index: 5000 !important;
+}
+</style>

+ 2 - 0
src/service/Derivation.vue

@@ -10,6 +10,7 @@ type FollowModel = Partial<SystemItemModel>;
 const props = defineProps<{ data: FollowModel }>();
 const emit = defineEmits<{
   (e: 'submit', data: FollowModel): void;
+  (e: 'cancel'): void;
 }>();
 const formData = reactive<FollowModel>({
   cpPatientMatchRule: {
@@ -25,6 +26,7 @@ const formData = reactive<FollowModel>({
 
 // 取消
 function cancel() {
+  emit('cancel'); // 触发取消事件
   VxeUI.modal.close(`derivation-modal`);
 }
 // 确定