Jelajahi Sumber

优化304,307的bug

张田田 7 bulan lalu
induk
melakukan
173ae64fc4

+ 13 - 6
src/components/Follow.vue

@@ -40,8 +40,15 @@ const activeObj = ref<any>({ fillin: {}, symptomsData: [] });
 const isExpired = computed(() => {
   const t = activeObj.value?.arrangeTime;
   if (!t) return false;
-  const ts = new Date(t as any).getTime();
-  return !Number.isNaN(ts) && ts < Date.now();
+  const arrange = new Date(t as any);
+  const ts = arrange.getTime();
+  console.log(ts,"获取此数据",t,Date.now());
+  if (Number.isNaN(ts)) return false;
+  const arrangeDay = new Date(arrange);
+  arrangeDay.setHours(0, 0, 0, 0);
+  const today = new Date();
+  today.setHours(0, 0, 0, 0);
+  return arrangeDay.getTime() < today.getTime();
 });
 const isReadOnly = computed(() => isExpired.value || activeObj.value?.progress === '2' || activeObj.value?.progress === '0');
 // 切换侧边栏任务
@@ -413,14 +420,14 @@ const previewImg = ref<string>('');
           感谢您的配合,为了更好地了解您的回复情况,我们将会在<span class="text-blue-600"> {{ activeObj?.arrangeTime }} </span
           >再次对您进行随访,届时请点击随访链接参与,再次感谢您!
         </div>
-        <div class="ml-2 mt-1" v-else> 
+        <div class="ml-2 mt-1 mb-6" v-else> 
           感谢您的耐心配合。
         </div>
       </div>
     </div>
-    <div class="flex items-center justify-center mt-6 mb-6" v-if="!isReadOnly">
+    <div class="flex items-center justify-center mb-6" v-if="activeObj.progress === '1' && !isReadOnly">
       <a-button size="small" class="mr-4" @click="cancelFollowContent">取消</a-button>
-      <a-button type="primary" size="small" @click="subFollowContent" v-show="activeObj.progress === '1'">提交 </a-button>
+      <a-button type="primary" size="small" @click="subFollowContent" :disabled="isReadOnly">提交</a-button>
     </div>
   </div>
 </template>
@@ -448,7 +455,7 @@ const previewImg = ref<string>('');
 
 .animated-vertical-tabs {
   display: flex;
-  height: 730px;
+  // height: 730px;
   width: 17%;
   overflow: auto;
 }

+ 15 - 14
src/components/RecordsIndicatorPreview.vue

@@ -3,7 +3,9 @@ import type { PatientModel }            from '@/model';
 import { indicatorUpdateRecordsMethod } from '@/request/api/report.api';
 import ReportIndicatorChartWidget       from '@/widgets/ReportIndicatorChartWidget.vue';
 import { useWatcher }                   from 'alova/client';
-
+import {
+  transformIndicators,
+} from '@/model'; 
 
 const props = defineProps<{
   patient: PatientModel;
@@ -19,19 +21,18 @@ const { data: indicatorRecords, loading } = useWatcher(
     middleware: (_, next) => { if ( patientId.value ) next(); },
   },
 );
-onMounted(() => {
-  if (props.records) {
-    indicatorRecords.value = props.records;
-  }
-
-});
-watch(() => props.records, (newVal) => {
-  console.log(newVal, 'newVal----watch');
-  if (newVal) {
-    indicatorRecords.value = newVal as any[];
-  }
-  console.log(indicatorRecords.value, 'records.value222----watch');
-}, { immediate: false, deep: true });
+// 外部直接传入 records 时,优先使用外部数据,不请求接口
+watch(
+  () => props.records,
+  (records) => {
+    if (records && records.length > 0) {
+      indicatorRecords.value = transformIndicators(records);
+    } else if (!patientId.value) {
+      indicatorRecords.value = [];
+    }
+  },
+  { immediate: true, deep: true },
+);
 </script>
 <template>
   <div ref="containerRef" class="h-full">

+ 8 - 3
src/pages/index/care/configured.vue

@@ -175,7 +175,7 @@ const gridOptions = reactive<VxeGridProps<ConditioningSchemeModel>>({
 const gridEvents: VxeGridListeners = {};
 
 // 获取设备分页列表
-const { loading, page, pageSize, total, onSuccess, replace, refresh, remove } = usePagination((page, size) => getConditioningSchemeMethod(page, size, model.value), {
+const { loading, page, pageSize, total, onSuccess, replace, refresh, remove, send: sendRefresh } = usePagination((page, size) => getConditioningSchemeMethod(page, size, model.value), {
   initialData: { data: [], total: 0 },
   initialPage: 1,
   initialPageSize: 100,
@@ -219,8 +219,13 @@ function editConfigured(model?: ConditioningSchemeModel, index?: number) {
       default() {
         return h(EditConfigured, <any>{
           data: model,
-          onSubmit(data: ConditioningSchemeModel) {
-            refresh(page.value);
+          onSubmit(success: boolean, data?: ConditioningSchemeModel) {
+            console.log(success, 'success');
+            // 只有成功时才刷新列表
+            if (success) {
+              // 使用 sendRefresh 强制刷新,避免页面闪烁
+              sendRefresh();
+            }
             VxeUI.modal.close(`configured-modal`);
           },
         });

+ 32 - 11
src/pages/index/care/issueService.vue

@@ -480,7 +480,8 @@ function detailPreview(row) {
     message.warning('请先添加服务包');
   }
 }
-function editPart(row) {
+function editPart(row: any) {
+  console.log(row, '编辑穴位');
   VxeUI.modal.open({
     title: `编辑部位`,
     height: 700,
@@ -495,6 +496,10 @@ function editPart(row) {
         return h(AcupointEdit, {
           data: row,
           onSubmit(data: any) {
+            console.log(data.acuPointNames, 'data穴位', data.acuMeridianNames, 'data经络');
+            let arr = data.acuPointNames.concat(data.acuMeridianNames)?.join('、');
+            console.log(arr, 'arr');
+            row.acuPointMeridianNames = arr;
             VxeUI.modal.close(`edit-part-modal`);
           },
         } as any);
@@ -507,13 +512,13 @@ function getAcupointText(row: any): string {
   const meridians: string[] = Array.isArray(row?.acuMeridianNames)
     ? row.acuMeridianNames
     : Array.isArray(row?.cwcpAcuMeridians)
-    ? row.cwcpAcuMeridians.map((it: any) => it?.name).filter(Boolean)
-    : [];
+      ? row.cwcpAcuMeridians.map((it: any) => it?.name).filter(Boolean)
+      : [];
   const points: string[] = Array.isArray(row?.acuPointNames)
     ? row.acuPointNames
     : Array.isArray(row?.cwcpAcuPoints)
-    ? row.cwcpAcuPoints.map((it: any) => it?.name).filter(Boolean)
-    : [];
+      ? row.cwcpAcuPoints.map((it: any) => it?.name).filter(Boolean)
+      : [];
   const parts = [...meridians, ...points].filter(Boolean);
   return parts.length ? parts.join('、') : '-';
 }
@@ -664,7 +669,11 @@ async function handleSubmit() {
   form.items = formData.items;
   // 添加电话号码验证
   if (form.phone && !isValidPhone(form.phone)) {
-    message.error('请输入有效的手机号码');
+    notification.error({ message: '请输入有效的手机号码' });
+    return;
+  }
+  if(!form.estimatedStartDate) {
+    notification.error({ message: '请选择调养日期' });
     return;
   }
   await addConditioningSchemeMethod(form).then(async () => {
@@ -1071,9 +1080,19 @@ function openPatientHealthRecord(row: { id: string }, showType: 'analysis' | 'sc
                 <div v-if="row.conditioningProgramDetail?.name === '健康咨询' || row.conditioningProgramDetail?.name === '健康评估'" class="flex items-center">
                   <div class="flex items-center mr-4">
                     <span>每</span>
-                    <a-input v-model:value="row.frequencyType" style="width: 50px" @change="() => calculateCount(row)" :disabled="currentPatient?.status === '0' || row.frequencyType === '不限'" />
+                    <a-input
+                      v-model:value="row.frequencyType"
+                      style="width: 50px"
+                      @change="() => calculateCount(row)"
+                      :disabled="currentPatient?.status === '0' || row.frequencyType === '不限'"
+                    />
                     <span>天</span>
-                    <a-input v-model:value="row.frequencyMeasure" style="width: 50px" @change="() => calculateCount(row)" :disabled="currentPatient?.status === '0' || row.frequencyType === '不限'" />
+                    <a-input
+                      v-model:value="row.frequencyMeasure"
+                      style="width: 50px"
+                      @change="() => calculateCount(row)"
+                      :disabled="currentPatient?.status === '0' || row.frequencyType === '不限'"
+                    />
                     <span>{{ row.conditioningProgramDetail?.cpFixedPricingRule?.convertUnit ? row.conditioningProgramDetail?.cpFixedPricingRule?.convertUnit : '次' }}</span>
                   </div>
                   <div>
@@ -1147,10 +1166,12 @@ function openPatientHealthRecord(row: { id: string }, showType: 'analysis' | 'sc
             <vxe-column field="conditioningProgramDetail.pricingType" title="穴位/经络/部位" width="160">
               <template #default="{ row }">
                 <a
-                  v-if="row.conditioningProgramDetail.pricingType === '1' && currentPatient?.status !== '0'"
-                  @click="editPart(row)"
+                  v-if="row.conditioningProgramDetail.pricingType === '1'"
+                  @click="currentPatient?.status === '0' ? null : editPart(row)"
                   :style="{ color: '#1890ff', cursor: 'pointer' }"
-                >编辑</a>
+                >
+                  {{ row?.acuPointNames.concat(row?.acuMeridianNames)?.join('、') === '' ? (currentPatient?.status === '0' ? '' : '编辑') : row?.acuPointNames.concat(row?.acuMeridianNames)?.join('、') }}
+                </a>
               </template>
             </vxe-column>
             <vxe-column field="remark" title="说明" width="180">

+ 1 - 0
src/request/api/report.api.ts

@@ -182,6 +182,7 @@ export function indicatorUpdateRecordsMethod(patientId: string, filter = true) {
     hitSource: 'update-indicator',
     params: { patientId },
     transform(data, headers) {
+      console.log(data, 'data----indicatorUpdateRecordsMethod');
       const indicators = transformIndicators(data);
       return filter ? indicators.filter(model => !!model.records?.length) : indicators;
     },

+ 2 - 0
src/service/AcupointEdit.vue

@@ -94,6 +94,8 @@ function save() {
   props.data.acuMeridianNames = [...meridianList.value].map((item) => item.name);
   props.data.acuPointNames = [...acupointList.value].map((item) => item.name);
   emit('submit', props.data);
+  console.log(props.data.acuMeridianNames, 'props.data');
+  console.log(props.data.acuPointNames, 'props.data');
   VxeUI.modal.close(`edit-part-modal`);
 }
 onMounted(() => {

+ 15 - 6
src/service/AddItems.vue

@@ -235,7 +235,9 @@ function cancel() {
 function doSubmit() {
   // 自定义验证:检查项目应用是否已选择
   if (!checkedList.value || checkedList.value.length === 0) {
-    message.error('请选择项目应用');
+    notification.error({
+      message: '请选择项目应用',
+    });
     return;
   }
   form.isForWrap = checkedList.value.includes('1') ? 'Y' : null;
@@ -244,16 +246,21 @@ function doSubmit() {
   if ((form.addType === 'itemsList' && checkedList.value.includes('1')) || form.addType === 'system') {
     // 计价规则
     if (!form.pricingType) {
-      message.error('请选择计价规则');
+      notification.error({
+        message: '请选择计价规则',
+      });
       return;
     }
     // console.log(form.pricingType, 'form.pricingType==>', form);
     // 计价规则相关字段校验
     if (form.pricingType === '0') {
+      console.log(form.cpFixedPricingRule, 'form.cpFixedPricingRule');
       const { unitPrice, pricingUnit, convertDose, convertUnit } = form.cpFixedPricingRule || {};
-      const allFilled = unitPrice && pricingUnit && convertDose && convertUnit;
+      const allFilled = (unitPrice !== '' && unitPrice !== null && unitPrice !== undefined) && pricingUnit && (convertDose !== '' && convertDose !== null && convertDose !== undefined) && convertUnit;
       if (!allFilled) {
-        message.error('请将单价、计价单位、相当于、使用单位全部填写');
+        notification.error({
+          message: '请将单价、计价单位、相当于、使用单位全部填写',
+        });
         return;
       }
       form.cpDynamicPricingRule = undefined;
@@ -265,7 +272,9 @@ function doSubmit() {
       rule1.max = 0;
       rule2.min = 0;
       if (!(allFilled1 && allFilled2)) {
-        message.error('请将按穴位/经络/部位的所有计价字段全部填写');
+        notification.error({
+          message: '请将按穴位/经络/部位的所有计价字段全部填写',
+        });
         return;
       }
       // 按穴位模式:清空一口价数据
@@ -295,7 +304,7 @@ function doSubmit() {
     // 计价规则非必填时,做全填/全空校验
     if (form.pricingType === '0') {
       const { unitPrice, pricingUnit, convertDose, convertUnit } = form.cpFixedPricingRule || {};
-      const allFilled = unitPrice && pricingUnit && convertDose && convertUnit;
+      const allFilled = (unitPrice !== '' && unitPrice !== null && unitPrice !== undefined) && pricingUnit && (convertDose !== '' && convertDose !== null && convertDose !== undefined) && convertUnit;
       const allEmpty = !unitPrice && !pricingUnit && !convertDose && !convertUnit;
       if (!(allFilled || allEmpty)) {
         message.error('单价、计价单位、相当于、使用单位要么全部填写,要么全部为空');

+ 30 - 28
src/service/CareProgress.vue

@@ -2,6 +2,7 @@
 import { ref, defineAsyncComponent, watch } from 'vue';
 import { getConditioningProcessMethod } from '@/request/api/care.api';
 import type { ConditioningRecordListModel, OpenConditioningSchemeModel } from '@/model/care.model';
+import RecordsIndicatorPreview from '@/components/RecordsIndicatorPreview.vue';
 import { useWatcher } from 'alova/client';
 import { patientMethod } from '@/request/api/patient.api';
 import { VxeUI } from 'vxe-pc-ui';
@@ -37,9 +38,9 @@ const { data: patient } = useWatcher(() => patientMethod(props.data.patientId!),
 const careProcessList = ref<OpenConditioningSchemeModel>();
 const showCareBox = ref<boolean>(false);
 async function getCareProgress() {
-  const res:any = await getConditioningProcessMethod(Number(props.data.id));
+  const res: any = await getConditioningProcessMethod(Number(props.data.id));
   careProcessList.value = res as OpenConditioningSchemeModel;
-  if(res.provinceName || res.cityName || res.areaName || res.detailAddress || res.phone){
+  if (res.provinceName || res.cityName || res.areaName || res.detailAddress || res.phone) {
     showCareBox.value = true;
   }
 }
@@ -266,8 +267,8 @@ const progressTextMap: Record<string, string> = {
         >
       </div>
     </div>
-      <div v-if="isShowDelivery && showCareBox" class="delivery-info" style="margin-left: 75px">
-        <a-checkbox checked style="color: #52c41a; margin-right: 8px" />
+    <div v-if="isShowDelivery && showCareBox" class="delivery-info" style="margin-left: 75px">
+      <a-checkbox checked style="color: #52c41a; margin-right: 8px" />
       <span style="margin-right: 15px">配送</span>
       <span v-if="careProcessList?.provinceName || careProcessList?.cityName || careProcessList?.areaName || careProcessList?.detailAddress"
         >地址:{{ careProcessList?.provinceName }}{{ careProcessList?.cityName }}{{ careProcessList?.areaName }}{{ careProcessList?.detailAddress }}</span
@@ -291,7 +292,7 @@ const progressTextMap: Record<string, string> = {
           <vxe-column field="acuPointNames" title="穴位" />
         </vxe-table>
         <div class="mt-3">
-          <div class="mb-1">预定频率:每{{ item.frequencyType }}天{{ item.frequencyMeasure }}{{ item?.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit || '次' }}</div>
+          <div class="mb-1">预定频率:每{{ item.frequencyType }}天{{ item.frequencyMeasure }}{{ item?.conditioningProgramDetail?.cpFixedPricingRule?.convertUnit || '次' }}</div>
           <div v-if="item.remark">操作指南:{{ item.remark }}</div>
         </div>
       </div>
@@ -301,7 +302,7 @@ const progressTextMap: Record<string, string> = {
           <span class="mr-10" style="font-size: 14px; font-weight: bold; color: black">◇ {{ item?.conditioningProgramDetail?.name }}</span>
           <span>数量:{{ item.totalMeasure }} {{ item?.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit || '次' }}</span>
         </div>
-        <div class="mb-1">预定频率:每{{ item.frequencyType }}天{{ item.frequencyMeasure }}{{ item?.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit || '次' }}</div>
+        <div class="mb-1">预定频率:每{{ item.frequencyType }}天{{ item.frequencyMeasure }} {{ item?.conditioningProgramDetail?.cpFixedPricingRule?.convertUnit || '次' }}</div>
         <div v-if="item.remark">操作指南:{{ item.remark }}</div>
       </div>
       <!-- 健康评估 -->
@@ -325,44 +326,45 @@ const progressTextMap: Record<string, string> = {
           <div class="mb-1">
             预定频率:
             <span v-if="item?.frequencyType === '不限'">不限</span>
-            <span v-else>每{{ item?.frequencyType }}天{{ item?.frequencyMeasure }}{{ item?.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit }} </span>
+            <span v-else>每{{ item?.frequencyType }}天{{ item?.frequencyMeasure }}{{ item?.conditioningProgramDetail?.cpFixedPricingRule?.convertUnit || '次' }} </span>
           </div>
           <div v-if="item?.remark">操作指南:{{ item?.remark }}</div>
         </div>
       </div>
     </div>
     <!-- 调养效果 -->
-    <div class="care-box" v-if="careProcessList?.patientConditioningScores && careProcessList.patientConditioningScores.length > 0">
+    <div class="care-box">
       <h3 style="color: black">调养效果</h3>
       <div class="care-box-content">
-      <!-- 评分 折线图 -->
-      <div class="chart-wrapper">
-        <v-chart :option="option" style="width: 350px; height: 200px" />
-      </div>
-      <!-- 健康记录 -->
-      <div class="health-records-card">
-        <a-tabs class="panel-wrapper" v-model:activeKey="activePanel" v-if="careProcessList?.healthAnalysisReports && careProcessList?.healthAnalysisReports.length > 0">
-          <a-tab-pane v-for="panel in panels" :key="panel.id" class="panel-pane">
-            <div class="panel-title">记录</div>
-            <component :is="panel.component" :patient="patient" :healthAnalysisReports="careProcessList?.healthAnalysisReports" :type="type"></component>
-          </a-tab-pane>
-        </a-tabs>
+        <!-- 评分 折线图 -->
+        <div class="chart-wrapper" v-if="careProcessList?.patientConditioningScores && careProcessList.patientConditioningScores.length > 0">
+          <v-chart :option="option" style="width: 350px; height: 200px" />
+        </div>
+        <!-- 健康记录 -->
+        <div class="health-records-card" v-if="careProcessList?.healthAnalysisReports && careProcessList?.healthAnalysisReports.length > 0">
+          <a-tabs class="panel-wrapper" v-model:activeKey="activePanel">
+            <a-tab-pane v-for="panel in panels" :key="panel.id" class="panel-pane">
+              <div class="panel-title">记录</div>
+              <component :is="panel.component" :patient="patient" :healthAnalysisReports="careProcessList?.healthAnalysisReports" :type="type"></component>
+            </a-tab-pane>
+          </a-tabs>
+        </div>
+
+        <!-- 指标 -->
+        <div class="mt-3" v-if="careProcessList?.patientQuotaGroups && careProcessList?.patientQuotaGroups.length > 0">
+          <b>指标</b>
+          <!-- <a-button type="link" @click="openIndicatorRecordsPreview">查看指标记录</a-button>
+            -->
+          <RecordsIndicatorPreview :records="careProcessList?.patientQuotaGroups" />
+        </div>
       </div>
-  
-    <!-- 指标 -->
-    <div v-if="careProcessList?.patientQuotaGroups && careProcessList?.patientQuotaGroups.length > 0" class="mt-3">
-      <b>指标</b>
-      <a-button type="link" @click="openIndicatorRecordsPreview">查看指标记录</a-button>
     </div>
   </div>
-</div>
-  </div>
 </template>
 
 <style scoped>
 .care-box {
   margin: 20px 0 10px 0;
- 
 }
 .care-box-content {
   border: 1px solid lightgray !important;

+ 14 - 6
src/service/EditConfigured.vue

@@ -19,12 +19,12 @@ interface TableRowData {
   isNewRow?: boolean; // 用于标识是否是新添加的行
 }
 const emits = defineEmits<{
-  submit: [data?: Array<TableRowData>];
+  submit: [success: boolean, data?: Array<TableRowData>];
 }>();
+let formattedData: any[] = [];
+
 const { loading: submitting, send: submit } = useRequest(updateConditioningSchemeMethod, {
   immediate: false,
-}).onSuccess(({ data }) => {
-  emits('submit');
 });
 const props = defineProps<{ data: ConditioningModel }>();
 // 表格数据
@@ -88,9 +88,9 @@ const deleteRow = (row: any) => {
 };
 
 // 保存
-const saveData = () => {
+const saveData = async () => {
   // 数据验证和格式化
-  const formattedData = tableData.value.map((row) => ({
+  formattedData = tableData.value.map((row) => ({
     ...row,
     knowledgeCpShowType: row.knowledgeCpShowType,
     showCount: row.showCount || globalItemLimit.value,
@@ -117,7 +117,15 @@ const saveData = () => {
     return;
   }
 
-  submit(props.data.orgId, formattedData);
+  // 使用 async/await 确保正确处理成功和失败
+  try {
+    await submit(props.data.orgId, formattedData);
+    // 成功时通知父组件
+    emits('submit', true, formattedData);
+  } catch (error) {
+    // 失败时也通知父组件
+    emits('submit', false);
+  }
   VxeUI.modal.close(`configured-modal`);
 };
 

+ 1 - 1
src/service/ServicePackageDetail.vue

@@ -292,7 +292,7 @@ watch(
               <a-input v-model:value="row.frequencyType" style="width: 60px" @change="() => calculateCount(row)" :disabled="true" />
               <span>天</span>
               <a-input v-model:value="row.frequencyMeasure" style="width: 60px" @change="() => calculateCount(row)" :disabled="true" />
-              <span>{{ row.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit }}</span>
+              <span>{{ row.conditioningProgramDetail?.cpFixedPricingRule?.convertUnit || '次' }}</span>
             </div>
           </template>
         </vxe-column>