Przeglądaj źródła

上传营养评估

chenying2100 10 miesięcy temu
rodzic
commit
b09ad19791
29 zmienionych plików z 5046 dodań i 2766 usunięć
  1. 18 2
      src/api/patients/nutrition/index.ts
  2. 13 22
      src/api/patients/nutrition/types.ts
  3. 8 0
      src/api/system/screeningAssessmentConfig/index.ts
  4. 33 1
      src/api/system/screeningAssessmentConfig/types.ts
  5. BIN
      src/assets/images/shiXiao.png
  6. BIN
      src/assets/images/zuoFei.png
  7. 26 0
      src/store/modules/history.ts
  8. 8 8
      src/store/modules/permission.ts
  9. 19 0
      src/store/modules/productCategory.ts
  10. 79 88
      src/views/patients/enteralNutrition/components/LeftCard.vue
  11. 70 47
      src/views/patients/enteralNutrition/components/history/LeftCard.vue
  12. 563 157
      src/views/patients/enteralNutrition/components/history/RightCard.vue
  13. 191 175
      src/views/patients/enteralNutrition/components/table/ConfigureTable.vue
  14. 378 77
      src/views/patients/enteralNutrition/components/table/MaterialTable.vue
  15. 380 79
      src/views/patients/enteralNutrition/components/table/MaterialTable2.vue
  16. 240 211
      src/views/patients/enteralNutrition/components/table/NutritionTable.vue
  17. 379 147
      src/views/patients/enteralNutrition/components/table/PackageTable.vue
  18. 4 6
      src/views/patients/enteralNutrition/history.vue
  19. 3 4
      src/views/patients/enteralNutrition/index.vue
  20. 72 8
      src/views/patients/evaluation/add.vue
  21. 5 0
      src/views/patients/evaluation/index.vue
  22. 575 0
      src/views/patients/hospitalRecord/index.vue
  23. 59 58
      src/views/patients/medicalRecord/index.vue
  24. 498 508
      src/views/patients/nutritionSetting/addForm.vue
  25. 357 321
      src/views/patients/nutritionSetting/index.vue
  26. 617 628
      src/views/patients/screening/add.vue
  27. 95 97
      src/views/patients/screening/index.vue
  28. 147 108
      src/views/system/screeningAssessmentConfig/add.vue
  29. 209 14
      src/views/system/screeningAssessmentConfig/index.vue

+ 18 - 2
src/api/patients/nutrition/index.ts

@@ -1,11 +1,12 @@
 import request from '@/utils/request';
-import { AxiosPromise } from 'axios';
-import { EnteralNutritionVO, EnteralNutritionForm, EnteralNutritionQuery,EnteralNutritionSaveForm } from '@/api/patients/nutrition/types';
+import {AxiosPromise} from 'axios';
+import {EnteralNutritionVO, EnteralNutritionForm, EnteralNutritionQuery, EnteralNutritionSaveForm} from '@/api/patients/nutrition/types';
 
 /**
  * 查询肠内营养列表
  * @param query
  * @returns {*}
+ *
  */
 
 export const listEnteralNutrition = (query?: EnteralNutritionQuery): AxiosPromise<EnteralNutritionVO[]> => {
@@ -16,6 +17,21 @@ export const listEnteralNutrition = (query?: EnteralNutritionQuery): AxiosPromis
   });
 };
 
+export const listEnteralNutritionHistory = (query?: EnteralNutritionQuery): AxiosPromise<EnteralNutritionVO[]> => {
+  return request({
+    url: '/system/nutrition/listHistory',
+    method: 'get',
+    params: query
+  });
+};
+
+export const listEnteralNutritionDetail = (id?: number): AxiosPromise<EnteralNutritionVO[]> => {
+  return request({
+    url: '/system/nutrition/detail?id=' + id,
+    method: 'get'
+  });
+};
+
 /**
  * 查询肠内营养详细
  * @param id

+ 13 - 22
src/api/patients/nutrition/types.ts

@@ -118,37 +118,35 @@ export interface EnteralNutritionVO {
    * 状态(0正常 1停用)
    */
   status: string;
-
 }
 
-
 export interface EnteralNutritionSaveForm extends BaseEntity {
   /**
    * 结算管理id
    */
   settlementId?: string | number;
 
-      /**
-     * 患者ID
-     */
-  patientId?: string  | number;
+  /**
+   * 患者ID
+   */
+  patientId?: string | number;
 
-    /**
+  /**
    * 看诊类型
    */
   visitType?: string | number;
-  
-    /**
+
+  /**
    * 收费类型
    */
   chargeType?: string | number;
 
-    /**
+  /**
    * 门诊/住院号
    */
   patientNo?: string | number;
 
-    /**
+  /**
    * 状态(0正常 1停用 2草稿)
    */
   status?: string | number;
@@ -277,17 +275,13 @@ export interface EnteralNutritionForm extends BaseEntity {
    */
   amount?: number;
 
-
-
   /**
    * 状态(0正常 1停用)
    */
   status?: string;
-
 }
 
 export interface EnteralNutritionQuery extends PageQuery {
-
   /**
    * 结算管理id
    */
@@ -403,11 +397,8 @@ export interface EnteralNutritionQuery extends PageQuery {
    */
   status?: string;
 
-    /**
-     * 日期范围参数
-     */
-    params?: any;
+  /**
+   * 日期范围参数
+   */
+  params?: any;
 }
-
-
-

+ 8 - 0
src/api/system/screeningAssessmentConfig/index.ts

@@ -51,6 +51,14 @@ export const updateScreeningAssessmentConfig = (data: ScreeningAssessmentConfigF
   });
 };
 
+export const updateConclusion = (data: ScreeningAssessmentConfigForm) => {
+  return request({
+    url: '/system/screeningAssessmentConfig/editConclusion',
+    method: 'post',
+    data: data
+  });
+};
+
 export const changeConfigStatus = (configId: string | number, status: string) => {
   const data = {
     configId,

+ 33 - 1
src/api/system/screeningAssessmentConfig/types.ts

@@ -28,11 +28,28 @@ export interface ScreeningAssessmentConfigVO {
    * 量表说明
    */
   description: string;
+  
 
   /**
    * 备注
    */
   remark: string;
+  
+  /**
+   * 结论
+   */
+  conclusion: string;
+ 
+
+    /**
+     * 来源
+     */
+    source : string;
+  
+    /**
+     * 目的
+     */
+    purpose : string;
 
   /**
    * 状态(0正常 1停用)
@@ -56,6 +73,7 @@ export interface QuestionAttrVO {
 }
 
 export interface QuestionVO {
+  qid?: string;
   /**
    * 主键ID
    */
@@ -148,6 +166,20 @@ export interface ScreeningAssessmentConfigForm extends BaseEntity {
    * 备注
    */
   remark?: string;
+  /**
+   * 结论
+   */
+  conclusion?: string;
+
+  /**
+   * 来源
+   */
+  source?: string;
+
+  /**
+   * 目的
+   */
+  purpose?: string;
 
   /**
    * 状态(0正常 1停用)
@@ -156,7 +188,7 @@ export interface ScreeningAssessmentConfigForm extends BaseEntity {
 
   baseInfo?: QuestionVO;
 
-  otherInfo?: QuestionVO[];
+  otherInfo?: QuestionVO[];  
 }
 
 export interface ScreeningAssessmentConfigQuery extends PageQuery {

BIN
src/assets/images/shiXiao.png


BIN
src/assets/images/zuoFei.png


+ 26 - 0
src/store/modules/history.ts

@@ -0,0 +1,26 @@
+import {defineStore} from 'pinia';
+import {reactive} from 'vue';
+
+interface NoticeItem {
+  title?: string;
+  read: boolean;
+  message: any;
+  time: string;
+}
+
+export const useHistoryStore = defineStore('history', () => {
+  const historyList = ref([]);
+
+  const setHistoryList = (list: any) => {
+    historyList.value = list;
+  };
+
+  const getHistoryList = () => {
+    return historyList.value;
+  };
+  return {
+    historyList,
+    setHistoryList,
+    getHistoryList
+  };
+});

+ 8 - 8
src/store/modules/permission.ts

@@ -1,14 +1,14 @@
-import { defineStore } from 'pinia';
-import router, { constantRoutes, dynamicRoutes } from '@/router';
+import {defineStore} from 'pinia';
+import router, {constantRoutes, dynamicRoutes} from '@/router';
 import store from '@/store';
-import { getRouters } from '@/api/menu';
+import {getRouters} from '@/api/menu';
 import auth from '@/plugins/auth';
-import { RouteRecordRaw } from 'vue-router';
+import {RouteRecordRaw} from 'vue-router';
 import Layout from '@/layout/index.vue';
 import ParentView from '@/components/ParentView/index.vue';
 import InnerLink from '@/layout/components/InnerLink/index.vue';
-import { ref } from 'vue';
-import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
+import {ref} from 'vue';
+import {createCustomNameComponent} from '@/utils/createCustomNameComponent';
 
 // 匹配views里面所有的.vue文件
 const modules = import.meta.glob('./../../views/**/*.vue');
@@ -47,7 +47,7 @@ export const usePermissionStore = defineStore('permission', () => {
   };
   const generateRoutes = async (): Promise<RouteRecordRaw[]> => {
     const res = await getRouters();
-    const { data } = res;
+    const {data} = res;
     const sdata = JSON.parse(JSON.stringify(data));
     const rdata = JSON.parse(JSON.stringify(data));
     const defaultData = JSON.parse(JSON.stringify(data));
@@ -150,7 +150,7 @@ export const loadView = (view: any, name: string) => {
     let dir = path.substring(viewsIndex + 7);
     dir = dir.substring(0, dir.lastIndexOf('.vue'));
     if (dir === view) {
-      res = createCustomNameComponent(modules[path], { name });
+      res = createCustomNameComponent(modules[path], {name});
       return res;
     }
   }

+ 19 - 0
src/store/modules/productCategory.ts

@@ -0,0 +1,19 @@
+import {defineStore} from 'pinia';
+
+export const useProductCategoryStore = defineStore('productCategory', () => {
+  const productCategoryList = ref([]);
+
+  const setProductCategoryList = (list: any) => {
+    productCategoryList.value = list;
+  };
+
+  const getProductCategoryList = () => {
+    return productCategoryList.value;
+  };
+
+  return {
+    productCategoryList,
+    setProductCategoryList,
+    getProductCategoryList
+  };
+});

+ 79 - 88
src/views/patients/enteralNutrition/components/LeftCard.vue

@@ -10,29 +10,30 @@
             <el-row>
               <el-col :span="8">
                 <span class="label">日期时间:</span>
-                <el-date-picker v-model="prescriptionDate" :clearable="false" type="date" 
-                :disabled-date="disabledBeforeToday"  placeholder="请选择"  value-format="YYYY-MM-DD"/>
-              </el-col>
-              <el-col :span="4">
-                
+                <el-date-picker
+                  v-model="prescriptionDate"
+                  :clearable="false"
+                  type="date"
+                  :disabled-date="disabledBeforeToday"
+                  placeholder="请选择"
+                  value-format="YYYY-MM-DD"
+                />
               </el-col>
+              <el-col :span="4"> </el-col>
               <el-col class="right_btn" :span="12">
                 <el-button type="primary" plain @click="submitForm('2')">存为草稿</el-button>
                 <el-button type="primary" @click="submitForm('0')" :loading="buttonLoading">提交</el-button>
                 <el-button type="danger" @click="deleteFrom">删除</el-button>
                 <el-button type="primary" plain>打印知情同意书</el-button>
-                <el-button type="success" @click="goHistoryPrescription">历史处方</el-button>                
+                <el-button type="success" @click="goHistoryPrescription">历史处方</el-button>
               </el-col>
             </el-row>
 
             <!-- 添加按钮组 -->
             <div class="add-buttons">
-              <el-button :class="['add-btn', {'is-active': prescriptionType === 'normal'}]"
-                @click="addPrescription">添加配置处方</el-button>
-              <el-button :class="['add-btn', {'is-active': prescriptionType === 'package'}]"
-                @click="addTemplate">添加预包装处方</el-button>
-              <el-button :class="['add-btn', {'is-active': prescriptionType === 'long-term'}]"
-                @click="addLongTerm">添加长期医嘱处方</el-button>
+              <el-button :class="['add-btn', {'is-active': prescriptionType === 'normal'}]" @click="addPrescription">添加配置处方</el-button>
+              <el-button :class="['add-btn', {'is-active': prescriptionType === 'package'}]" @click="addTemplate">添加预包装处方</el-button>
+              <el-button :class="['add-btn', {'is-active': prescriptionType === 'long-term'}]" @click="addLongTerm">添加长期医嘱处方</el-button>
             </div>
 
             <!-- 开方原因 -->
@@ -52,15 +53,15 @@
           <!-- 处方表格 -->
           <div class="prescription-tables">
             <template v-if="tableType === 'normal'">
-              <ConfigureTable @change="updateConfigureData" v-model="configData"/>
-              <MaterialTable v-model="configData" @change="updateMaterialData"/>
+              <ConfigureTable @change="updateConfigureData" v-model="configData" />
+              <MaterialTable v-model="configData" @change="updateMaterialData" />
             </template>
             <template v-else-if="tableType === 'package'">
-              <PackageTable @change="updatePackageData"/>
+              <PackageTable @change="updatePackageData" />
             </template>
             <template v-else>
-              <NutritionTable @change="updateLongTermData" v-model="longTermData" :prescriptionDate="prescriptionDate"/>
-              <MaterialTable2 v-model="longTermData" @change="updateMaterial2Data"/>
+              <NutritionTable @change="updateLongTermData" v-model="longTermData" :prescriptionDate="prescriptionDate" />
+              <MaterialTable2 v-model="longTermData" @change="updateMaterial2Data" />
             </template>
           </div>
         </div>
@@ -78,25 +79,24 @@ import NutritionTable from './table/NutritionTable.vue';
 import MaterialTable from './table/MaterialTable.vue';
 import MaterialTable2 from './table/MaterialTable2.vue';
 import PackageTable from './table/PackageTable.vue';
-import ConfigureTable from './table/ConfigureTable.vue'; 
- 
-import { listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition } from '@/api/patients/nutrition';
-import { EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm, EnteralNutritionSaveForm } from '@/api/patients/nutrition/types';
+import ConfigureTable from './table/ConfigureTable.vue';
+
+import {listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition} from '@/api/patients/nutrition';
+import {EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm, EnteralNutritionSaveForm} from '@/api/patients/nutrition/types';
+
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
 
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- 
 const emit = defineEmits(['gotoTop']);
 const buttonLoading = ref(false);
-const { patientInfo } = defineProps<{ patientInfo: any }>()
-
+const {patientInfo} = defineProps<{patientInfo: any}>();
 
 // 顶部tab切换
-const activeTab = ref('nutrition'); 
-const configData= ref('');
-const packageData= ref('');
-const longTermData= ref('');
-const materialData= ref('');
-const materialData2= ref('');
+const activeTab = ref('nutrition');
+const configData = ref('');
+const packageData = ref('');
+const longTermData = ref('');
+const materialData = ref('');
+const materialData2 = ref('');
 
 // 表格类型
 const tableType = ref<'normal' | 'package' | 'long-term'>('normal');
@@ -107,32 +107,30 @@ const prescriptionDate = ref('');
 // 处方类型
 const prescriptionType = ref<'normal' | 'package' | 'long-term'>('normal');
 
-const updateConfigureData = (val:string) => {  
-  configData.value=val; 
+const updateConfigureData = (val: string) => {
+  configData.value = val;
 };
 
-const updateLongTermData = (val:string) => {  
-  longTermData.value=val;   
+const updateLongTermData = (val: string) => {
+  longTermData.value = val;
 };
 
-const updatePackageData = (val:string) => {  
-  packageData.value=val;    
+const updatePackageData = (val: string) => {
+  packageData.value = val;
 };
 
-const updateMaterialData = (val:string) => {  
-  materialData.value=val;          
+const updateMaterialData = (val: string) => {
+  materialData.value = val;
 };
 
-const updateMaterial2Data = (val:string) => {  
-  materialData2.value=val;  
+const updateMaterial2Data = (val: string) => {
+  materialData2.value = val;
 };
 
-const deleteFrom =async ( ) => {
-  configData.value=JSON.stringify([]);         
+const deleteFrom = async () => {
+  configData.value = JSON.stringify([]);
 };
 
- 
-
 const submitForm = async (status: string) => {
   let param = ref<EnteralNutritionSaveForm>({});
   param.value.patientId = patientInfo.id;
@@ -144,35 +142,33 @@ const submitForm = async (status: string) => {
   if (prescriptionType.value == 'normal') {
     param.value.chargeType = '3';
     if (!configData.value || configData.value.length == 0) {
-      proxy?.$modal.msgError("营养产品不为空");
+      proxy?.$modal.msgError('营养产品不为空');
       return;
     }
     param.value.nutritionList = JSON.parse(configData.value);
 
     if (!materialData.value || materialData.value.length == 0) {
-      proxy?.$modal.msgError("耗材不为空");
+      proxy?.$modal.msgError('耗材不为空');
       return;
     }
     param.value.consumableList = JSON.parse(materialData.value);
-
   } else if (prescriptionType.value == 'package') {
     param.value.chargeType = '2';
     if (!packageData.value || packageData.value.length == 0) {
-      proxy?.$modal.msgError("营养产品不为空");
+      proxy?.$modal.msgError('营养产品不为空');
       return;
     }
     param.value.nutritionList = JSON.parse(packageData.value);
-
   } else {
     param.value.chargeType = '4';
     if (!longTermData.value || longTermData.value.length == 0) {
-      proxy?.$modal.msgError("营养产品不为空");
+      proxy?.$modal.msgError('营养产品不为空');
       return;
     }
     param.value.nutritionList = JSON.parse(longTermData.value);
 
     if (!materialData2.value || materialData2.value.length == 0) {
-      proxy?.$modal.msgError("耗材不为空");
+      proxy?.$modal.msgError('耗材不为空');
       return;
     }
     param.value.consumableList = JSON.parse(materialData2.value);
@@ -181,23 +177,23 @@ const submitForm = async (status: string) => {
   if (param.value.chargeType != '2') {
     for (let item of param.value.consumableList) {
       if (!item.consumableId) {
-        proxy?.$modal.msgError("耗材没有选择");
+        proxy?.$modal.msgError('耗材没有选择');
         return;
       }
 
       item.groupNo = item.sn;
-      let arr = item.consumableId.split("_");
+      let arr = item.consumableId.split('_');
       item.consumableId = arr[0];
     }
-    
+
     for (let item of param.value.nutritionList) {
       if (!item.products || item.products.length == 0) {
-        proxy?.$modal.msgError("营养产品没有记录");
+        proxy?.$modal.msgError('营养产品没有记录');
         return;
       }
 
-      let tsList = []
-      item.timeSlots.forEach(ts => {
+      let tsList = [];
+      item.timeSlots.forEach((ts) => {
         tsList.push(ts.checked ? ts.time : '');
       });
       item.mealTime = tsList.join(',');
@@ -206,11 +202,11 @@ const submitForm = async (status: string) => {
 
       for (let pd of item.products) {
         if (!pd.nutritionProductId) {
-          proxy?.$modal.msgError("营养产品没有选择");
+          proxy?.$modal.msgError('营养产品没有选择');
           return;
         }
 
-        let arr = pd.nutritionProductId.split("_");
+        let arr = pd.nutritionProductId.split('_');
         pd.nutritionProductId = arr[0];
         pd.usage = item.usage ;
         pd.preparationVolumePerTime = item.preparationVolumePerTime ;
@@ -221,10 +217,10 @@ const submitForm = async (status: string) => {
         pd.groupNo = item.sn;
       }
     }
-  }else{
+  } else {
     for (let item of param.value.nutritionList) {
-      let tsList = []
-      item.timeSlots.forEach(ts => {
+      let tsList = [];
+      item.timeSlots.forEach((ts) => {
         tsList.push(ts.checked ? ts.time : '');
       });
       item.mealTime = tsList.join(',');
@@ -232,23 +228,21 @@ const submitForm = async (status: string) => {
       item.prescriptionType = param.value.chargeType;
 
       if (!item.nutritionProductId) {
-          proxy?.$modal.msgError("营养产品没有选择");
-          return;
-        }
+        proxy?.$modal.msgError('营养产品没有选择');
+        return;
+      }
 
-        let arr = item.nutritionProductId.split("_");
-        item.nutritionProductId = arr[0];
+      let arr = item.nutritionProductId.split('_');
+      item.nutritionProductId = arr[0];
 
-        item.prescriptionDate = prescriptionDate.value;
-        item.groupNo = item.sn;
+      item.prescriptionDate = prescriptionDate.value;
+      item.groupNo = item.sn;
     }
   }
- 
-  await addEnteralNutrition(param.value).finally(() => buttonLoading.value = false);
-  proxy?.$modal.msgSuccess("操作成功");
-};
-
 
+  await addEnteralNutrition(param.value).finally(() => (buttonLoading.value = false));
+  proxy?.$modal.msgSuccess('操作成功');
+};
 
 // 添加配置处方
 const addPrescription = () => {
@@ -270,30 +264,27 @@ const addLongTerm = () => {
 
 // 跳转历史处方页面
 const goHistoryPrescription = () => {
-  emit('gotoTop')
+  emit('gotoTop');
 };
 
 function formatDate(date) {
-  const pad = n => n < 10 ? '0' + n : n;
-  return date.getFullYear() + '-' +
-    pad(date.getMonth() + 1) + '-' +
-    pad(date.getDate()) ;
+  const pad = (n) => (n < 10 ? '0' + n : n);
+  return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate());
 }
 
 // 禁用今天之前的日期
 const disabledBeforeToday = (date) => {
-  const today = new Date()
+  const today = new Date();
   // 设置时间为今天凌晨,确保比较的是日期而非具体时间
-  today.setHours(0, 0, 0, 0)
-  return date < today
-}
+  today.setHours(0, 0, 0, 0);
+  return date < today;
+};
 
 onMounted(() => {
-  let now=new Date();
-  let start=formatDate(now);
-  prescriptionDate.value=start;
+  let now = new Date();
+  let start = formatDate(now);
+  prescriptionDate.value = start;
 });
-
 </script>
 
 <style lang="scss" scoped>

+ 70 - 47
src/views/patients/enteralNutrition/components/history/LeftCard.vue

@@ -13,16 +13,16 @@
     <div class="prescription-list">
       <div
         v-for="item in prescriptionList"
-        :key="item.id"
-        :class="['prescription-item', {active: item.id === activeId}]"
+        :key="item.settlementId"
+        :class="['prescription-item', {active: item.settlementId === activeId}]"
         @click="handleItemClick(item)"
       >
         <!-- 时间 -->
-        <div class="item-time">{{ item.time }}</div>
+        <div class="item-time">{{ item.orderTime }}</div>
         <!-- 处方类型 -->
-        <div class="item-type">{{ item.type }}</div>
+        <div class="item-type">{{ item.chargeTypeMame }}</div>
         <!-- 处方ID -->
-        <div class="item-id">处方ID:{{ item.id }}</div>
+        <div class="item-id">处方ID:{{ item.settlementId }}</div>
         <!-- 已编辑角标 -->
         <div v-if="item.isEdited" class="edit-badge">
           <span>已编辑</span>
@@ -33,58 +33,81 @@
 </template>
 
 <script setup lang="ts">
-import {ref} from 'vue';
+import {ref, onMounted} from 'vue';
 import {Search} from '@element-plus/icons-vue';
 
+import { listEnteralNutritionHistory,listEnteralNutritionDetail} from '@/api/patients/nutrition';
+import {useHistoryStore} from '@/store/modules/history';
+ 
+
+const historyStore = useHistoryStore();
+
 // 搜索值
 const searchValue = ref('');
+const {patientInfo} = defineProps<{patientInfo: any}>();
+
+const queryParams = ref({
+  pageNum: 1,
+  pageSize: 10,
+  patientId: patientInfo.id
+});
+
+const prescriptionList = ref([]);
+const getListEnteralNutritionFn = () => {
+  listEnteralNutritionHistory(queryParams.value).then((res) => {
+    prescriptionList.value = res.rows;    
+    // 如果有数据,自动选中第一个处方
+    if (prescriptionList.value && prescriptionList.value.length > 0) {
+      const firstPrescription = prescriptionList.value[0];
+      activeId.value = firstPrescription.settlementId;
+
+      listEnteralNutritionDetail(firstPrescription.settlementId).then(detailRes => {
+        let data = detailRes.data;
+        data.nutritionList.forEach(lt=>{
+          lt.paymentStatus=firstPrescription.paymentStatus;
+          lt.delFlag=firstPrescription.delFlag;
+          lt.stopFlag=firstPrescription.stopFlag;
+          lt.settlementId=firstPrescription.settlementId;          
+          lt.prescriptionDate=firstPrescription.chargeType=='4'?lt.prescriptionDate.substring(0,10):null;
+        });
+
+        historyStore.setHistoryList({
+          nutritionList: data.nutritionList || [],
+          consumableList: data.consumableList || []
+        });
+      });      
+    }
+  });
+  // console.log(patientInfo, 'patientInfo');
+};
+
+onMounted(() => {
+  getListEnteralNutritionFn();
+});
 
 // 当前选中的处方ID
 const activeId = ref('');
 
-// 处方列表数据
-const prescriptionList = ref([
-  {
-    id: '194705349732148019',
-    time: '2025-07-23 10:57:18',
-    type: '长期处方',
-    isEdited: false
-  },
-  {
-    id: '194754209113291980',
-    time: '2025-07-22 14:19:53',
-    type: '配置处方',
-    isEdited: true
-  },
-  {
-    id: '194753542425735168',
-    time: '2025-07-22 13:53:23',
-    type: '长期处方',
-    isEdited: true
-  },
-  {
-    id: '194746976848480665',
-    time: '2025-07-22 09:32:30',
-    type: '长期处方',
-    isEdited: false
-  },
-  {
-    id: '194746840280684134',
-    time: '2025-07-22 09:27:04',
-    type: '长期处方',
-    isEdited: false
-  },
-  {
-    id: '194746840280681234',
-    time: '2025-07-21 16:28:56',
-    type: '长期处方',
-    isEdited: true
-  }
-]);
-
 // 点击处方项
 const handleItemClick = (item) => {
-  activeId.value = item.id;
+  activeId.value = item.settlementId;
+
+  listEnteralNutritionDetail(item.settlementId).then(detailRes => {
+    let data = detailRes.data;
+    data.nutritionList.forEach(lt=>{
+          lt.paymentStatus=item.paymentStatus;
+          lt.delFlag=item.delFlag;
+          lt.stopFlag=item.stopFlag;
+          lt.settlementId=item.settlementId;
+          lt.prescriptionDate=item.chargeType=='4'?lt.prescriptionDate.substring(0,10):null;
+        });
+
+    historyStore.setHistoryList({
+      nutritionList: data.nutritionList || [],
+      consumableList: data.consumableList || []
+    });
+  }); 
+ 
 };
 </script>
 

+ 563 - 157
src/views/patients/enteralNutrition/components/history/RightCard.vue

@@ -4,121 +4,120 @@
     <div class="operation-buttons">
       <div class="left-buttons">
         <el-button plain @click="goBack">返回</el-button>
-        <el-button plain>打印</el-button>
+        <!-- <el-button plain>打印</el-button> -->
         <el-button type="success" plain>引用处方</el-button>
-        <el-button type="danger" plain>处方作废</el-button>
+        <el-button type="danger" plain @click="deleteNutrition" v-if="!status.delFlag">处方作废</el-button>
       </div>
       <div class="pay-status">
-        <img src="@/assets/images/pay.png" alt="待支付" />
+        <template v-if="status.delFlag">
+          <img src="@/assets/images/zuoFei.png" alt="已作废" />
+        </template>
+        <template v-else-if="status.paymentStatus=='0'">
+          <img src="@/assets/images/pay.png" alt="待支付" />
+        </template>
+        <template v-else-if="status.paymentStatus=='2'">
+          <img src="@/assets/images/pay.png" alt="已退款" />
+        </template>
+        <template v-else-if="status.paymentStatus=='3'">
+          <img src="@/assets/images/shiXiao.png" alt="已失效" />
+        </template>
+        <template v-else">
+          <img src="@/assets/images/pay.png" alt="已支付" />
+        </template>
       </div>
     </div>
 
     <!-- 停嘱日期 -->
-    <div class="stop-date">
+    <div class="stop-date" v-if="status.prescriptionDate!=null">
       <span class="label">停嘱日期:</span>
-      <span class="value">2025-07-24</span>
+      <span class="value">{{ status.prescriptionDate }}</span>
     </div>
 
     <!-- 处方表格 -->
     <div class="prescription-tables">
       <!-- 营养产品表格 -->
-      <el-table :data="productData" border>
-        <el-table-column type="index" label="组号" width="60" align="center" />
-        <el-table-column label="营养产品" min-width="180" prop="product" />
-        <el-table-column label="用量/次" width="100" align="center">
-          <template #default="{row}">
-            <span>{{ row.dosage }}g</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="餐次时间" width="180" align="center" prop="mealTime" />
-        <el-table-column label="频次" width="100" align="center">
-          <template #default>一天3次</template>
-        </el-table-column>
-        <el-table-column label="首日" width="80" align="center">
-          <template #default="{row}">
-            <span>{{ row.firstDay }}次</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="用量/日" width="100" align="center">
-          <template #default="{row}">
-            <span>{{ row.dailyDosage }}g</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="规格" width="140" align="center">
-          <template #default="{row}">
-            <span>{{ row.specification }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="用法" width="80" align="center" prop="usage" />
-        <el-table-column label="制剂液量/次" width="120" align="center">
-          <template #default="{row}">
-            <span>{{ row.liquidVolume }}ml</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="制剂浓度/次" width="120" align="center">
-          <template #default="{row}">
-            <span>{{ row.concentration }}%</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="能量密度/次" width="140" align="center">
-          <template #default="{row}">
-            <span>{{ row.energyDensity }}kcal/ml</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="处方备注" min-width="150" prop="note" />
-        <el-table-column label="每日热量" width="100" align="center">
-          <template #default="{row}">
-            <span>{{ row.dailyCalories }}</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="金额" width="100" align="right">
-          <template #default="{row}">
-            <span>{{ row.amount }}</span>
-          </template>
-        </el-table-column>
-      </el-table>
+      <div class="table-wrapper">
+        <table class="custom-table">
+          <thead>
+            <tr>
+              <th width="60" class="fixed-width">组号</th>
+              <th width="160" class="fixed-width">营养产品</th>
+              <th width="100" class="fixed-width">用量/次</th>
+              <th width="180" class="fixed-width">餐次时间</th>
+              <th width="100" class="fixed-width">频次</th>
+              <th width="80" class="fixed-width">首日</th>
+              <th width="100" class="fixed-width">用量/日</th>
+              <th width="140" class="fixed-width">规格</th>
+              <th width="80" class="fixed-width">用法</th>
+              <th width="120" class="fixed-width">制剂液量/次</th>
+              <th width="120" class="fixed-width">制剂浓度/次</th>
+              <th width="140" class="fixed-width">能量密度/次</th>
+              <th width="150" class="fixed-width">处方备注</th>
+              <th width="100" class="fixed-width">每日热量</th>
+              <th width="100" class="fixed-width">金额</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr v-for="(item, index) in tableNutritionData" :key="item.id">
+              <td>{{ index + 1 }}</td>
+              <td>{{ item.nutritionProduct || '--' }}</td>
+              <td>{{ item.dosePerTime || '--' }}g</td>
+              <td>{{ item.mealTime || '--' }}</td>
+              <td>一天{{ item.frequency || '--' }}次</td>
+              <td>{{ item.firstDay || '--' }}次</td>
+              <td>{{ item.dosePerDay || '--' }}g</td>
+              <td>{{ item.specification || '--' }}</td>
+              <td>{{ item.usage || '--' }}</td>
+              <td>{{ item.preparationVolumePerTime || '--' }}ml</td>
+              <td>{{ item.preparationConcentrationPerTime || '--' }}%</td>
+              <td>{{ item.energyDensityPerTime || '--' }}kcal/ml</td>
+              <td>{{ item.prescriptionRemark || '--' }}</td>
+              <td>{{ item.dailyCalories || '--' }}</td>
+              <td class="text-right">{{ item.amount || '--' }}</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
 
       <!-- 耗材表格 -->
-      <el-table :data="materialData" border>
-        <el-table-column type="index" label="组号" width="60" align="center" />
-        <el-table-column label="耗材" min-width="200" />
-        <el-table-column label="规格" width="120" align="center" />
-        <el-table-column label="用量/次" width="100" align="center">
-          <template #default="{row}">
-            <span>{{ row.dosage }}袋</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="频次" width="100" align="center">
-          <template #default>一天3次</template>
-        </el-table-column>
-        <el-table-column label="用量/日" width="100" align="center">
-          <template #default="{row}">
-            <span>{{ row.dailyDosage }}袋</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="首日" width="80" align="center">
-          <template #default="{row}">
-            <span>{{ row.firstDay }}次</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="数量" width="80" align="center">
-          <template #default="{row}">
-            <span>{{ row.quantity }}袋</span>
-          </template>
-        </el-table-column>
-        <el-table-column label="处方备注" min-width="150" />
-        <el-table-column label="金额" width="100" align="right">
-          <template #default="{row}">
-            <span>{{ row.amount }}</span>
-          </template>
-        </el-table-column>
-      </el-table>
+      <div class="table-wrapper">
+        <table class="custom-table">
+          <thead>
+            <tr>
+              <th width="60" class="fixed-width">组号</th>
+              <th width="200" class="fixed-width">耗材</th>
+              <th width="120" class="fixed-width">规格</th>
+              <th width="100" class="fixed-width">用量/次</th>
+              <th width="100" class="fixed-width">频次</th>
+              <th width="100" class="fixed-width">用量/日</th>
+              <th width="80" class="fixed-width">首日</th>
+              <th width="80" class="fixed-width">数量</th>
+              <th width="150" class="fixed-width">处方备注</th>
+              <th width="100" class="fixed-width">金额</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr v-for="(item, index) in consumableListData" :key="item.id">
+              <td>{{ index + 1 }}</td>
+              <td>{{ item.consumable || '--' }}</td>
+              <td>{{ item.specification || '--' }}</td>
+              <td>{{ item.dosePerTime || '--' }}袋</td>
+              <td>一天{{ item.frequency || '--' }}次</td>
+              <td>{{ item.dosePerDay || '--' }}袋</td>
+              <td>{{ item.firstDay || '--' }}次</td>
+              <td>{{ item.quantity || '--' }}袋</td>
+              <td>{{ item.prescriptionRemark || '--' }}</td>
+              <td>{{ item.amount || '--' }}</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
 
       <!-- 费用统计 -->
       <div class="table-cost">
-        <div class="cost-item">处方费用:¥15.25</div>
-        <div class="cost-item">营养配置费:¥5</div>
-        <div class="cost-item total">总计:¥20.25</div>
+        <div class="cost-item">处方费用:¥{{ totalCost.nutritionCost }}</div>
+        <div class="cost-item">营养配置费:¥{{ totalCost.configCost }}</div>
+        <div class="cost-item total">总计:¥{{ totalCost.total }}</div>
       </div>
     </div>
 
@@ -139,12 +138,26 @@
           <div class="analysis-detail">
             <!-- 左侧表格 -->
             <div class="table-container">
-              <el-table :data="nutritionData" border>
-                <el-table-column label="三大营养素" prop="name" width="120" />
-                <el-table-column label="质量 (g)" prop="mass" width="120" align="center" />
-                <el-table-column label="热量占比" prop="ratio" width="120" align="center" />
-                <el-table-column label="参考值" prop="reference" min-width="120" align="center" />
-              </el-table>
+              <div class="table-wrapper">
+                <table class="custom-table">
+                  <thead>
+                    <tr>
+                      <th width="120" class="fixed-width">三大营养素</th>
+                      <th width="120" class="fixed-width">质量 (g)</th>
+                      <th width="120" class="fixed-width">热量占比</th>
+                      <th width="120" class="fixed-width">参考值</th>
+                    </tr>
+                  </thead>
+                  <tbody>
+                    <tr v-for="(item, index) in nutritionData" :key="index">
+                      <td>{{ item.name }}</td>
+                      <td>{{ item.mass }}</td>
+                      <td>{{ item.ratio }}</td>
+                      <td>{{ item.reference }}</td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
               <div class="extra-info">
                 <div class="info-item">
                   <span class="label">氮含量:</span>
@@ -179,72 +192,149 @@
         </div>
       </el-tab-pane>
       <el-tab-pane label="营养数据分析" name="data">
-        <el-table :data="nutritionAnalysisData" border>
-          <el-table-column label="元素类型" prop="type" width="120" align="center" />
-          <el-table-column label="元素名称" prop="name" width="120" align="center" />
-          <el-table-column label="单位" prop="unit" width="80" align="center" />
-          <el-table-column label="肠内营养含量/天" align="center">
-            <el-table-column label="当前处方" prop="current" width="120" align="center" />
-            <el-table-column label="历史处方" prop="history" width="120" align="center" />
-          </el-table-column>
-          <el-table-column label="肠外营养含量/天" prop="parenteral" width="140" align="center" />
-          <el-table-column label="膳食营养含量/天" prop="dietary" width="140" align="center" />
-          <el-table-column label="营养设定" prop="target" width="120" align="center" />
-        </el-table>
+        <div class="table-wrapper table-fixed-header">
+          <table class="custom-table">
+            <thead>
+              <tr>
+                <th width="120" class="fixed-width">元素类型</th>
+                <th width="120" class="fixed-width">元素名称</th>
+                <th width="80" class="fixed-width">单位</th>
+                <th colspan="2" class="fixed-width text-center">肠内营养含量/天</th>
+                <th width="140" class="fixed-width">肠外营养含量/天</th>
+                <th width="140" class="fixed-width">膳食营养含量/天</th>
+                <th width="120" class="fixed-width">营养设定</th>
+              </tr>
+              <tr>
+                <th colspan="3"></th>
+                <th width="120" class="fixed-width">当前处方</th>
+                <th width="120" class="fixed-width">历史处方</th>
+                <th colspan="3"></th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr v-for="(item, index) in nutritionAnalysisData" :key="index">
+                <td v-if="isFirstInGroup(item, index)" :rowspan="getGroupRowSpan(item.type)">{{ item.type }}</td>
+                <td>{{ item.name }}</td>
+                <td>{{ item.unit }}</td>
+                <td>{{ item.current }}</td>
+                <td>{{ item.history || '--' }}</td>
+                <td>{{ item.parenteral || '--' }}</td>
+                <td>{{ item.dietary || '--' }}</td>
+                <td>{{ item.target }}</td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
       </el-tab-pane>
     </el-tabs>
   </el-card>
 </template>
 
 <script setup lang="ts">
-import {ref, onMounted} from 'vue';
+import { ref, onMounted, watch, computed } from 'vue';
 import * as echarts from 'echarts';
+import { useHistoryStore } from '@/store/modules/history';
+import {delEnteralNutrition} from '@/api/patients/nutrition';
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const historyStore = useHistoryStore();
 
 const activeTab = ref('nutrition');
 const pieChart = ref(null);
 
-// 营养产品数据
-const productData = ref([
-  {
-    product: '孕妇营养包(1-12月)',
-    dosage: '1.0000',
-    mealTime: '08:00,12:00,18:00',
-    firstDay: 2,
-    dailyDosage: '3.0000',
-    specification: '840.0000g/袋',
-    usage: '口服',
-    liquidVolume: '100.0000',
-    concentration: '0.9900',
-    energyDensity: '0.0410',
-    note: '--',
-    dailyCalories: '12.3000',
-    amount: '5.25'
-  }
-]);
+// 营养产品表格数据
+const tableNutritionData = ref([]);
+// 耗材表格数据
+const consumableListData = ref([]);
+const status = ref({
+  paymentStatus: '1',
+  delFlag: false,
+  stopFlag: false,
+  prescriptionDate:null,
+  settlementId: '0'
+});
 
-// 耗材数据
-const materialData = ref([
-  {
-    material: '肠内营养空白合剂',
-    specification: '3g/袋',
-    dosage: '1.0000',
-    dailyDosage: '3.000',
-    firstDay: 2,
-    quantity: '5.0000',
-    amount: '10.00'
-  }
-]);
+const delResult = ref({});
+
+const deleteNutrition = () => {
+  delEnteralNutrition(status.value.settlementId).then(() => {
+    delResult.value[status.value.settlementId]=true;
+    status.value.delFlag=true;
+    let row=tableNutritionData.value[0];
+    row.delFlag=true;
+    proxy?.$modal.msgSuccess('作废成功');
+  });
+};
+
+
+// 监听 store 数据变化
+watch(
+  () => historyStore.historyList,
+  (newVal: any) => {
+    if (newVal) {
+      // 如果是数组,取第一个元素的数据
+      if (Array.isArray(newVal)) {
+        tableNutritionData.value = newVal[0]?.nutritionList || [];
+        consumableListData.value = newVal[0]?.consumableList || [];       
+      } else {
+        // 如果是单个对象,直接取数据
+        tableNutritionData.value = newVal?.nutritionList || [];
+        consumableListData.value = newVal?.consumableList || [];
+      }
+
+      if(tableNutritionData.value.length>0){
+          let row=tableNutritionData.value[0];
+          let delFlag=delResult.value[row.settlementId];
+
+          status.value = {
+            paymentStatus: row.paymentStatus,
+            delFlag: delFlag!=null?delFlag:row.delFlag,
+            stopFlag: row.stopFlag,
+            prescriptionDate: row.prescriptionDate,
+            settlementId: row.settlementId
+          }
+        }        
+    } else {
+      // 如果没有数据,设置为空数组
+      tableNutritionData.value = [];
+      consumableListData.value = [];
+    }
+  },
+  { immediate: true, deep: true }
+);
+
+// 计算总费用
+const totalCost = computed(() => {
+  // 营养产品费用
+  const nutritionCost = tableNutritionData.value.reduce((sum, item) => {
+    return sum + (Number(item.amount) || 0);
+  }, 0);
+
+  // 耗材费用
+  const consumableCost = consumableListData.value.reduce((sum, item) => {
+    return sum + (Number(item.amount) || 0);
+  }, 0);
+
+  // 配置费用固定为 5 元
+  const configCost = 5;
+
+  return {
+    nutritionCost: nutritionCost.toFixed(2),
+    consumableCost: consumableCost.toFixed(2),
+    configCost: configCost.toFixed(2),
+    total: (nutritionCost + consumableCost + configCost).toFixed(2)
+  };
+});
 
 // 营养素分析数据
 const nutritionData = ref([
   {
-    name: '蛋白质',
+    name: '蛋白质11',
     mass: '0.729',
     ratio: '23.71%',
     reference: '10% - 15%'
   },
   {
-    name: '脂肪',
+    name: '脂肪22',
     mass: '0.39',
     ratio: '28.54%',
     reference: '20% - 30%'
@@ -257,14 +347,27 @@ const nutritionData = ref([
   }
 ]);
 
+// 判断是否是组内第一个元素
+const isFirstInGroup = (item: any, index: number) => {
+  if (index === 0) return true;
+  return item.type !== nutritionAnalysisData.value[index - 1].type;
+};
+
+// 获取组的行数
+const getGroupRowSpan = (type: string) => {
+  return nutritionAnalysisData.value.filter((item) => item.type === type).length;
+};
+ 
+
 // 营养数据分析数据
 const nutritionAnalysisData = ref([
+  // 热能及三大营养素
   {
     type: '热能及三大营养素',
     name: '热量',
     unit: 'kcal',
     current: '12.3',
-    history: '12.3',
+    history: '60.42',
     parenteral: '--',
     dietary: '--',
     target: '897.3'
@@ -274,7 +377,7 @@ const nutritionAnalysisData = ref([
     name: '热能',
     unit: 'kj',
     current: '51.45',
-    history: '51.45',
+    history: '252.72',
     parenteral: '--',
     dietary: '--',
     target: '3754.3'
@@ -284,7 +387,7 @@ const nutritionAnalysisData = ref([
     name: '碳水化合物',
     unit: 'g',
     current: '1.278',
-    history: '1.28',
+    history: '6.91',
     parenteral: '--',
     dietary: '--',
     target: '112.16'
@@ -294,7 +397,7 @@ const nutritionAnalysisData = ref([
     name: '蛋白质',
     unit: 'g',
     current: '0.729',
-    history: '0.73',
+    history: '3.88',
     parenteral: '--',
     dietary: '--',
     target: '50'
@@ -304,17 +407,18 @@ const nutritionAnalysisData = ref([
     name: '脂肪',
     unit: 'g',
     current: '0.39',
-    history: '0.39',
+    history: '0.78',
     parenteral: '--',
     dietary: '--',
     target: '19.94'
   },
+  // 常量元素
   {
     type: '常量元素',
     name: '钠',
     unit: 'mg',
     current: '9',
-    history: '9',
+    history: '51',
     parenteral: '--',
     dietary: '--',
     target: '1500'
@@ -388,6 +492,220 @@ const nutritionAnalysisData = ref([
     parenteral: '--',
     dietary: '--',
     target: '7.5'
+  },
+  // 微量元素
+  {
+    type: '微量元素',
+    name: '硒',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '60'
+  },
+  {
+    type: '微量元素',
+    name: '铜',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '0.8'
+  },
+  {
+    type: '微量元素',
+    name: '锰',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '4.5'
+  },
+  {
+    type: '微量元素',
+    name: '碘',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '120'
+  },
+  {
+    type: '微量元素',
+    name: '氟',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '1.5'
+  },
+  {
+    type: '微量元素',
+    name: '铬',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '30'
+  },
+  {
+    type: '微量元素',
+    name: '钼',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '100'
+  },
+  // 脂肪酸
+  {
+    type: '脂肪酸',
+    name: '多不饱和脂肪酸',
+    unit: 'g',
+    current: '0.0033',
+    history: '0.01',
+    parenteral: '--',
+    dietary: '--',
+    target: '--'
+  },
+  // 维生素
+  {
+    type: '维生素',
+    name: '维生素A',
+    unit: 'μgRAE',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '700'
+  },
+  {
+    type: '维生素',
+    name: '维生素D',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '10'
+  },
+  {
+    type: '维生素',
+    name: '维生素E',
+    unit: 'mgα-TE',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '14'
+  },
+  {
+    type: '维生素',
+    name: '维生素K',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '80'
+  },
+  {
+    type: '维生素',
+    name: '维生素B1',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '1.2'
+  },
+  {
+    type: '维生素',
+    name: '维生素B2',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '1.2'
+  },
+  {
+    type: '维生素',
+    name: '维生素B6',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '1.4'
+  },
+  {
+    type: '维生素',
+    name: '维生素B12',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '2.4'
+  },
+  {
+    type: '维生素',
+    name: '烟酸(尼克酸)',
+    unit: 'mgNE',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '12'
+  },
+  {
+    type: '维生素',
+    name: '维生素C',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '100'
+  },
+  {
+    type: '维生素',
+    name: '生物素',
+    unit: 'μg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '40'
+  },
+  {
+    type: '维生素',
+    name: '泛酸',
+    unit: 'mg',
+    current: '0',
+    history: '--',
+    parenteral: '--',
+    dietary: '--',
+    target: '5'
+  },
+  // 其他
+  {
+    type: '其他',
+    name: '膳食纤维',
+    unit: 'g',
+    current: '0.363',
+    history: '1.45',
+    parenteral: '--',
+    dietary: '--',
+    target: '25'
   }
 ]);
 
@@ -460,12 +778,10 @@ onMounted(() => {
   });
 });
 
-
 const emit = defineEmits(['goBack']);
 const goBack = () => {
-  emit('goBack')
+  emit('goBack');
 };
-
 </script>
 
 <style lang="scss" scoped>
@@ -655,4 +971,94 @@ const goBack = () => {
     font-size: 12px;
   }
 }
+
+.table-wrapper {
+  margin-bottom: 20px;
+  overflow-x: auto;
+
+  &.table-fixed-header {
+    position: relative;
+    height: calc(100vh - 400px); // 调整合适的高度
+    overflow-y: auto;
+
+    thead {
+      position: sticky;
+      top: 0;
+      z-index: 1;
+
+      tr:first-child th {
+        position: sticky;
+        top: 0;
+        background: #f5f7fa;
+        border-bottom: none;
+      }
+
+      tr:last-child th {
+        position: sticky;
+        top: 41px; // 第一行表头的高度
+        background: #f5f7fa;
+      }
+    }
+
+    tbody {
+      tr:first-child td {
+        border-top: none;
+      }
+    }
+  }
+
+  // 添加横向滚动条的样式
+  &::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+  }
+
+  &::-webkit-scrollbar-thumb {
+    background-color: #909399;
+    border-radius: 4px;
+  }
+
+  &::-webkit-scrollbar-track {
+    background-color: #f5f7fa;
+  }
+}
+
+.custom-table {
+  width: max-content;
+  min-width: 100%;
+  border-collapse: separate; // 改为 separate 以支持固定表头
+  border-spacing: 0;
+  border: 1px solid #ebeef5;
+
+  th,
+  td {
+    padding: 12px 8px;
+    border: 1px solid #ebeef5;
+    text-align: center;
+    font-size: 14px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    background-color: #fff; // 添加背景色防止内容透明
+
+    &.text-center {
+      text-align: center;
+    }
+  }
+
+  th {
+    background-color: #f5f7fa;
+    color: #303133;
+    font-weight: 600;
+    height: 40px; // 固定表头高度
+  }
+
+  tbody tr:hover {
+    background-color: #f5f7fa;
+
+    td {
+      background-color: #f5f7fa;
+    }
+  }
+}
 </style>

+ 191 - 175
src/views/patients/enteralNutrition/components/table/ConfigureTable.vue

@@ -5,10 +5,14 @@
       <el-table-column label="营养产品" min-width="300">
         <template #default="{row}">
           <div class="product-group">
-            <div v-for="(product, index) in row.products" :key="index" class="product-row" style="margin-bottom:5px;">
+            <div v-for="(product, index) in row.products" :key="index" class="product-row" style="margin-bottom: 5px">
               <el-select v-model="product.nutritionProductId" placeholder="请选择" @change="changeProductSelect">
-                <el-option v-for="pn in productNutritionList" :key="pn.id" :label="pn.productName"
-                  :value="pn.id+'_'+row.sn+'_'+index"></el-option>
+                <el-option
+                  v-for="pn in productNutritionList"
+                  :key="pn.id"
+                  :label="pn.productName"
+                  :value="pn.id + '_' + row.sn + '_' + index"
+                ></el-option>
               </el-select>
               <div class="action-buttons">
                 <el-button class="icon-btn" @click="addProduct(row)">
@@ -30,8 +34,12 @@
         <template #default="{row}">
           <div class="dosage-group">
             <div v-for="(product, index) in row.products" :key="index" class="dosage-input">
-              <el-input v-model="product.dosePerTime" placeholder="请输入" class="input-center"  
-              @input="dosePerTimeInput(product.dosePerTime,row.sn+'_'+index)"/>
+              <el-input
+                v-model="product.dosePerTime"
+                placeholder="请输入"
+                class="input-center"
+                @input="dosePerTimeInput(product.dosePerTime, row.sn + '_' + index)"
+              />
               <span class="unit">g</span>
             </div>
           </div>
@@ -42,42 +50,72 @@
           <div class="time-slots">
             <div class="time-row">
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[0].checked" @change="changeTimeSelection(row.timeSlots[0].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[0].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[0].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[0].checked" @change="changeTimeSelection(row.timeSlots[0].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[0].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[0].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[1].checked" @change="changeTimeSelection(row.timeSlots[1].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[1].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[1].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[1].checked" @change="changeTimeSelection(row.timeSlots[1].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[1].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[1].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[2].checked" @change="changeTimeSelection(row.timeSlots[2].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[2].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[2].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[2].checked" @change="changeTimeSelection(row.timeSlots[2].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[2].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[2].checked"
+                />
               </div>
             </div>
             <div class="time-row">
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[3].checked" @change="changeTimeSelection(row.timeSlots[3].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[3].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[3].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[3].checked" @change="changeTimeSelection(row.timeSlots[3].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[3].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[3].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[4].checked" @change="changeTimeSelection(row.timeSlots[4].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[4].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[4].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[4].checked" @change="changeTimeSelection(row.timeSlots[4].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[4].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[4].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[5].checked" @change="changeTimeSelection(row.timeSlots[5].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[5].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[5].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[5].checked" @change="changeTimeSelection(row.timeSlots[5].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[5].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[5].checked"
+                />
               </div>
             </div>
           </div>
@@ -85,12 +123,12 @@
       </el-table-column>
       <el-table-column label="频次" width="120" align="center">
         <template #default="{row}">
-          <span>一天{{row.frequency}}次</span>
+          <span>一天{{ row.frequency }}次</span>
         </template>
       </el-table-column>
       <el-table-column label="首日" width="150" align="center">
         <template #default="{row}">
-          <el-input v-model="row.firstDay" @input="firstDayInput(row.firstDay,row.sn)">
+          <el-input v-model="row.firstDay" @input="firstDayInput(row.firstDay, row.sn)">
             <template #append>次</template>
           </el-input>
         </template>
@@ -98,15 +136,15 @@
       <el-table-column label="用量/日" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.dosePerDay }}</span>   
-            <span class="unit">{{ product.productSpecUnit }}</span> 
+            <span>{{ product.dosePerDay }}</span>
+            <span class="unit">{{ product.productSpecUnit }}</span>
           </div>
         </template>
       </el-table-column>
       <el-table-column label="使用天数" width="200" align="center">
         <template #default="{row}">
           <div class="daily-size">
-            <el-input-number v-model="row.usageDays" :min="1" @change="changeUsageDays(row.usageDays,row.sn)"/>
+            <el-input-number v-model="row.usageDays" :min="1" @change="changeUsageDays(row.usageDays, row.sn)" />
           </div>
         </template>
       </el-table-column>
@@ -114,8 +152,8 @@
       <el-table-column label="用量/总" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.totalDose }}</span>  
-            <span class="unit">{{ product.productSpecUnit }}</span>            
+            <span>{{ product.totalDose }}</span>
+            <span class="unit">{{ product.productSpecUnit }}</span>
           </div>
         </template>
       </el-table-column>
@@ -123,23 +161,22 @@
       <el-table-column label="规格" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.specification }}</span>             
+            <span>{{ product.specification }}</span>
           </div>
         </template>
       </el-table-column>
 
       <el-table-column label="用法" width="150" align="center">
         <template #default="{row}">
-          <el-select v-model="row.usage" placeholder="请选择" @change="changeUsage(row.usage,row.sn)">
-            <el-option v-for="dict in default_usage" :key="dict.value" :label="dict.label"
-              :value="dict.value"></el-option>
+          <el-select v-model="row.usage" placeholder="请选择" @change="changeUsage(row.usage, row.sn)">
+            <el-option v-for="dict in default_usage" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
           </el-select>
         </template>
       </el-table-column>
 
       <el-table-column label="制剂液量/次" width="170" align="center">
         <template #default="{row}">
-          <el-input v-model="row.preparationVolumePerTime" @change="changePreparationVolumePerTime(row.preparationVolumePerTime,row.sn)">
+          <el-input v-model="row.preparationVolumePerTime" @change="changePreparationVolumePerTime(row.preparationVolumePerTime, row.sn)">
             <template #append>ml</template>
           </el-input>
         </template>
@@ -156,7 +193,7 @@
 
       <el-table-column label="能量密度/次" width="200" align="center">
         <template #default="{row}">
-          <el-input v-model="row.energyDensityPerTime" @change="changeEnergyDensityPerTime(row.energyDensityPerTime,row.sn)">
+          <el-input v-model="row.energyDensityPerTime" @change="changeEnergyDensityPerTime(row.energyDensityPerTime, row.sn)">
             <template #append>kcal/ml</template>
           </el-input>
         </template>
@@ -164,26 +201,29 @@
 
       <el-table-column label="处方备注" width="200" align="center">
         <template #default="{row}">
-          <template v-for="(product, index) in row.products" >
-            <el-input v-model="product.prescriptionRemark" :maxlength="100" :show-word-limit="true" 
-            @change="changePrescriptionRemark(product.prescriptionRemark,row.sn)"/>
-          </template>          
+          <template v-for="(product, index) in row.products">
+            <el-input
+              v-model="product.prescriptionRemark"
+              :maxlength="100"
+              :show-word-limit="true"
+              @change="changePrescriptionRemark(product.prescriptionRemark, row.sn)"
+            />
+          </template>
         </template>
       </el-table-column>
 
       <el-table-column label="每日热量" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.dailyCalories }}</span>             
+            <span>{{ product.dailyCalories }}</span>
           </div>
         </template>
       </el-table-column>
 
-
       <el-table-column label="金额" width="100" align="center">
-        <template #default="{row}"> 
+        <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.amount }}</span>
+            <span>{{ product.amount }}</span>
           </div>
         </template>
       </el-table-column>
@@ -211,20 +251,18 @@
 <script setup lang="ts">
 import {ref} from 'vue';
 import {Plus, Delete, CirclePlus} from '@element-plus/icons-vue';
-import { listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition } from '@/api/patients/nutrition';
-import { EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm } from '@/api/patients/nutrition/types';
-import { listNutrition, listAllNutrition  } from '@/api/warehouse/productNutrition/index';
-import { NutritionVO, NutritionQuery, NutritionForm } from '@/api/warehouse/productNutrition/types';
- 
+import {listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition} from '@/api/patients/nutrition';
+import {EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm} from '@/api/patients/nutrition/types';
+import {listNutrition, listAllNutrition} from '@/api/warehouse/productNutrition/index';
+import {NutritionVO, NutritionQuery, NutritionForm} from '@/api/warehouse/productNutrition/types';
 
-const prop=defineProps({
+const prop = defineProps({
   modelValue: {
     type: String,
     default: () => undefined
-  },
+  }
 });
 
-
 watch(
   () => prop.modelValue,
   async (val: string) => {
@@ -232,33 +270,31 @@ watch(
       return;
     }
 
-    let arr =JSON.parse(val);
-    if(Array.isArray(arr)&&arr.length==0){
-      tableData.value=[];
+    let arr = JSON.parse(val);
+    if (Array.isArray(arr) && arr.length == 0) {
+      tableData.value = [];
     }
   },
-  { deep: true, immediate: true }
+  {deep: true, immediate: true}
 );
 
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {default_usage} = toRefs<any>(proxy?.useDict('default_usage'));
 
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { default_usage } = toRefs < any > (proxy ?.useDict('default_usage'));
-
-let productNutritionList=ref<NutritionVO[]>([]);
-let tableId=ref<number>(0);
+let productNutritionList = ref<NutritionVO[]>([]);
+let tableId = ref<number>(0);
 
 const getProductNutritionList = async () => {
   const res = await listAllNutrition();
   productNutritionList.value = res.rows;
-}
-
+};
 
 interface TimeSlot {
   checked: boolean;
   time: string;
-} 
+}
 
-interface TableRow  extends EnteralNutritionForm {
+interface TableRow extends EnteralNutritionForm {
   products: EnteralNutritionForm[];
   timeSlots: TimeSlot[];
   sn: number;
@@ -267,7 +303,7 @@ interface TableRow  extends EnteralNutritionForm {
 
 // 创建默认行数据的函数
 const createDefaultRow = (): TableRow => ({
-  products: [{specification:'',totalDose:'',dosePerDay:''}],
+  products: [{specification: '', totalDose: '', dosePerDay: ''}],
   timeSlots: [
     {checked: true, time: '08:00'},
     {checked: false, time: '08:30'},
@@ -276,11 +312,11 @@ const createDefaultRow = (): TableRow => ({
     {checked: true, time: '18:00'},
     {checked: false, time: '18:30'}
   ],
-  usageDays:1,
-  frequency:3,
-  firstDay:2,
-  sn:0,
-  tableId:tableId.value++,
+  usageDays: 1,
+  frequency: 3,
+  firstDay: 2,
+  sn: 0,
+  tableId: tableId.value++
 });
 
 const emit = defineEmits(['change']);
@@ -291,18 +327,18 @@ const tableData = ref<TableRow[]>([createDefaultRow()]);
 // 新增行
 const addNewRow = () => {
   let row: TableRow = createDefaultRow();
-  row.sn = tableData.value.length ;
+  row.sn = tableData.value.length;
   tableData.value.push(row);
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 const changeProductSelect = async (id: string) => {
-  let arr=id.split('_');
+  let arr = id.split('_');
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
+      continue;
     }
-    
+
     let row = tableData.value[Number(arr[1])];
     let pt = row.products[Number(arr[2])];
     pt.specification=item.productSpec;
@@ -310,16 +346,14 @@ const changeProductSelect = async (id: string) => {
     pt.dailyCalories=null;
     pt.productSpecUnit=item.productSpecUnit;
     pt.amount=null; 
-    if(!row.usage){
-      row.usage=item.defaultUsage;
-    }    
+    row.usage=item.defaultUsage;
     pt.totalDose='0' ;
     pt.dosePerDay='0';
     pt.firstDay=Math.ceil(row.frequency/2.0);
     break;
   }
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 // 新增产品输入框
@@ -335,162 +369,145 @@ const removeProduct = (row: TableRow, index: number) => {
     if (rowIndex !== -1) {
       tableData.value.splice(rowIndex, 1);
     }
-    emit('change',JSON.stringify(tableData.value))
+    emit('change', JSON.stringify(tableData.value));
   } else {
     // 否则只删除当前输入框
     row.products.splice(index, 1);
   }
 };
- 
 
 // 复制行
 const copyRow = (index: number) => {
   const newRow = JSON.parse(JSON.stringify(tableData.value[index]));
-  newRow.tableId = tableId.value++
+  newRow.tableId = tableId.value++;
   tableData.value.splice(index + 1, 0, newRow);
   tableData.value.forEach((item, index) => {
     item.sn = index;
     item.products.forEach((ch, idx) => {
-      if(ch.nutritionProductId){
+      if (ch.nutritionProductId) {
         let arr = ch.nutritionProductId.split('_');
         ch.nutritionProductId = arr[0] + '_' + index + '_' + idx;
-      }     
+      }
     });
   });
-  emit('change', JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 // 删除行
-const deleteRow = (index: number) => {   
+const deleteRow = (index: number) => {
   tableData.value.splice(index, 1);
 
   tableData.value.forEach((item, index) => {
     item.sn = index;
-  });  
+  });
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
- 
-const changeUsageDays = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);   
-}
 
-const changeUsage = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const changeUsageDays = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
+
+const changeUsage = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
 const changePreparationVolumePerTime = (value: string, sn:string) => { 
-  let row = tableData.value[sn];
-  if(row.preparationVolumePerTime){
-    row.preparationConcentrationPerTime=2;
-    row.energyDensityPerTime=Number(row.preparationVolumePerTime)*row.preparationConcentrationPerTime/100.0;
-  }
   changeTimeSelection(null,sn);
 }
 
 const changeEnergyDensityPerTime = (value: string, sn:string) => { 
-  let row = tableData.value[sn];
-  if(row.preparationConcentrationPerTime!=null){     
-    row.preparationVolumePerTime=Number(row.energyDensityPerTime)/(row.preparationConcentrationPerTime/100.0);
-  }
-
-  changeTimeSelection(null,sn);
-}
-
-const changePrescriptionRemark = (value: string, sn:string) => { 
   changeTimeSelection(null,sn);
 }
 
+const changePrescriptionRemark = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const firstDayInput = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const firstDayInput = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const changeTimeSelection = (value: string, sn:string) => {
+const changeTimeSelection = (value: string, sn: string) => {
   let row = tableData.value[sn];
-  let frequency=0;
-  row.timeSlots.forEach(item=>{
-    if(item.checked){
+  let frequency = 0;
+  row.timeSlots.forEach((item) => {
+    if (item.checked) {
       frequency++;
     }
   })
   row.frequency=frequency;
   if(value!=null){
     row.firstDay=Math.ceil(row.frequency/2.0);
-  } 
+  }
 
-  row.products.forEach(pt => {
+  row.products.forEach((pt) => {
     if (!pt.dosePerTime || pt.dosePerTime.trim().length == 0) {
       return;
     }
-    let arr=pt.nutritionProductId.split('_');
+    let arr = pt.nutritionProductId.split('_');
 
     for (let item of productNutritionList.value) {
-    if (item.id.toString() != arr[0]) {
-      continue
-    }    
-    
-    
-    let val=item.calorie*row.frequency*Number(pt.dosePerTime)/100.0
-    pt.dailyCalories=val.toFixed(4);
-
-    let firstDay=Number(row.firstDay.toString());
-    val=(row.frequency*(row.usageDays-1)+firstDay)*item.configSalePrice*Number(pt.dosePerTime)
-    pt.amount=Math.round(val*100)/100;
-
-    val=(row.frequency*(row.usageDays-1)+firstDay)*Number(pt.dosePerTime)
-    pt.totalDose=val.toFixed(4) ;
-
-    val=row.frequency*Number(pt.dosePerTime)
-    pt.dosePerDay=val.toFixed(4) ;
-    break;
-  }
+      if (item.id.toString() != arr[0]) {
+        continue;
+      }
+
+      let val = (item.calorie * row.frequency * Number(pt.dosePerTime)) / 100.0;
+      pt.dailyCalories = val.toFixed(4);
+
+      let firstDay = Number(row.firstDay.toString());
+      val = (row.frequency * (row.usageDays - 1) + firstDay) * item.configSalePrice * Number(pt.dosePerTime);
+      pt.amount = Math.round(val * 100) / 100;
+
+      val = (row.frequency * (row.usageDays - 1) + firstDay) * Number(pt.dosePerTime);
+      pt.totalDose = val.toFixed(4);
 
-  });  
+      val = row.frequency * Number(pt.dosePerTime);
+      pt.dosePerDay = val.toFixed(4);
+      break;
+    }
+  });
 
-  emit('change',JSON.stringify(tableData.value));
+  emit('change', JSON.stringify(tableData.value));
 };
 
-const dosePerTimeInput = (value: string, str:string) => {
-  let arr=str.split('_');
+const dosePerTimeInput = (value: string, str: string) => {
+  let arr = str.split('_');
   let row = tableData.value[Number(arr[0])];
   let pt = row.products[Number(arr[1])];
-  if(!pt.dosePerTime||pt.dosePerTime.trim().length==0){
-    pt.dailyCalories=null;
-    pt.amount=null; 
+  if (!pt.dosePerTime || pt.dosePerTime.trim().length == 0) {
+    pt.dailyCalories = null;
+    pt.amount = null;
     return;
   }
 
-  arr=pt.nutritionProductId.split('_');
+  arr = pt.nutritionProductId.split('_');
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
-    }    
-    
-    
-    let val=item.calorie*row.frequency*Number(pt.dosePerTime)/100.0
-    pt.dailyCalories=val.toFixed(4);
-
-    let firstDay=Number(row.firstDay.toString());
-    val=(row.frequency*(row.usageDays-1)+firstDay)*item.configSalePrice*Number(pt.dosePerTime)
-    pt.amount=Math.round(val*100)/100;
-
-    val=(row.frequency*(row.usageDays-1)+firstDay)*Number(pt.dosePerTime)
-    pt.totalDose=val.toFixed(4) ;
-
-    val=row.frequency*Number(pt.dosePerTime)
-    pt.dosePerDay=val.toFixed(4) ;
+      continue;
+    }
+
+    let val = (item.calorie * row.frequency * Number(pt.dosePerTime)) / 100.0;
+    pt.dailyCalories = val.toFixed(4);
+
+    let firstDay = Number(row.firstDay.toString());
+    val = (row.frequency * (row.usageDays - 1) + firstDay) * item.configSalePrice * Number(pt.dosePerTime);
+    pt.amount = Math.round(val * 100) / 100;
+
+    val = (row.frequency * (row.usageDays - 1) + firstDay) * Number(pt.dosePerTime);
+    pt.totalDose = val.toFixed(4);
+
+    val = row.frequency * Number(pt.dosePerTime);
+    pt.dosePerDay = val.toFixed(4);
     break;
   }
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
-
-onMounted(() => { 
+onMounted(() => {
   getProductNutritionList();
 });
-
 </script>
 
 <style lang="scss" scoped>
@@ -709,8 +726,7 @@ onMounted(() => {
   }
 }
 
-
 :deep(.daily-size div) {
   width: 100px;
-} 
+}
 </style>

+ 378 - 77
src/views/patients/enteralNutrition/components/table/MaterialTable.vue

@@ -5,10 +5,9 @@
       <el-table-column label="耗材" min-width="300">
         <template #default="{row}">
           <div class="material-group">
-            <div class="material-row" style="margin-bottom:10px;">
+            <div class="material-row" style="margin-bottom: 10px">
               <el-select v-model="row.consumableId" placeholder="请选择" @change="changeConsumableSelect">
-                <el-option v-for="pn in suppliesList" :key="pn.id" :label="pn.suppliesName"
-                  :value="pn.id+'_'+row.sn"></el-option>
+                <el-option v-for="pn in suppliesList" :key="pn.id" :label="pn.suppliesName" :value="pn.id + '_' + row.sn"></el-option>
               </el-select>
             </div>
           </div>
@@ -17,7 +16,7 @@
       <el-table-column label="规格" width="100" align="center">
         <template #default="{row}">
           <div class="spec-group">
-            <span>{{ row.specification }}</span>            
+            <span>{{ row.specification }}</span>
           </div>
         </template>
       </el-table-column>
@@ -25,17 +24,17 @@
         <template #default="{row}">
           <div class="dosage-group">
             <div class="dosage-input">
-              <el-input v-model="row.dosePerTime" placeholder="请输入" class="input-center" @input="dosePerTimeInput(row.dosePerTime,row.sn)">
+              <el-input v-model="row.dosePerTime" placeholder="请输入" class="input-center" @input="dosePerTimeInput(row.dosePerTime, row.sn)">
                 <template #append>袋</template>
-              </el-input>              
-            </div>             
+              </el-input>
+            </div>
           </div>
         </template>
       </el-table-column>
-       
+
       <el-table-column label="频次" width="100" align="center">
         <template #default="{row}">
-          <span>一天{{row.frequency}}次</span>
+          <span>一天{{ row.frequency }}次</span>
         </template>
       </el-table-column>
       <el-table-column label="用量/日" width="100" align="center">
@@ -63,7 +62,7 @@
 
       <el-table-column label="处方备注" width="200" align="center">
         <template #default="{row}">
-          <el-input v-model="row.prescriptionRemark" :maxlength="100" :show-word-limit="true" @change="prescriptionRemark"/>        
+          <el-input v-model="row.prescriptionRemark" :maxlength="100" :show-word-limit="true" @change="prescriptionRemark" />
         </template>
       </el-table-column>
 
@@ -72,19 +71,18 @@
           <span>{{ row.amount }}</span>
         </template>
       </el-table-column>
-
     </el-table>
     <div class="table-footer">
       <div class="left-buttons">
         <el-button type="primary" plain>登为个人模板</el-button>
         <el-button type="primary" plain>批量添加营养品</el-button>
-        <el-button type="primary" plain>处方模板</el-button>
+        <el-button type="primary" plain @click="openTemplate">处方模板</el-button>
       </div>
       <div class="right-summary">
         <div class="summary-list">
           <div class="summary-item">
             <span class="label">处方费用:</span>
-            <span class="value">¥{{ nutritionalFee + otherlFee  }}</span>
+            <span class="value">¥{{ nutritionalFee + otherlFee }}</span>
           </div>
           <div class="summary-item">
             <span class="label">营养配置费:</span>
@@ -92,39 +90,104 @@
           </div>
           <div class="summary-item total">
             <span class="label">总计:</span>
-            <span class="value">¥{{ totalFee+otherlFee }}</span>
+            <span class="value">¥{{ totalFee + otherlFee }}</span>
           </div>
         </div>
       </div>
     </div>
+
+    <!-- 处方模板弹窗 -->
+    <el-dialog v-model="dialogVisible" title="选择处方模板" width="60%" :close-on-click-modal="false" class="template-dialog">
+      <!-- 提示信息 -->
+      <div class="tip-box">如部分模版未显示请检查预包装库位产品库存,无库存则含该产品的协定方模板将不再显示</div>
+
+      <div class="search-box">
+        <el-input v-model="searchValue" placeholder="请输入名称" class="search-input">
+          <template #append>
+            <el-button type="primary">查询</el-button>
+          </template>
+        </el-input>
+      </div>
+
+      <div class="dialog-content">
+        <!-- 左侧树形控件 -->
+        <div class="left-tree">
+          <el-tree
+            ref="treeRef"
+            :data="treeData"
+            :props="defaultProps"
+            node-key="id"
+            :default-expanded-keys="['1']"
+            show-checkbox
+            @check="handleCheck"
+          />
+        </div>
+
+        <!-- 右侧表格 -->
+        <div class="right-table">
+          <div class="table-wrapper">
+            <table class="custom-table">
+              <thead>
+                <tr>
+                  <th width="60">组号</th>
+                  <th>产品名称</th>
+                  <th width="120">用量/次</th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr v-for="(item, index) in templateTableData" :key="index">
+                  <td>{{ index + 1 }}</td>
+                  <td>{{ item.productName }}</td>
+                  <td>{{ item.dosePerTime }}{{ item.unit }}</td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+        </div>
+      </div>
+
+      <div class="selected-count">已选 ({{ selectedCount }})</div>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleConfirm">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import {ref,defineProps} from 'vue';
-import {  listAll  } from '@/api/warehouse/suppliesManage';
-import { SuppliesManageVO } from '@/api/warehouse/suppliesManage/types';
-import { listNutritionConsumable, getNutritionConsumable, delNutritionConsumable, addNutritionConsumable, updateNutritionConsumable } from '@/api/patients/nutritionConsumable';
-import {NutritionConsumableForm } from '@/api/patients/nutritionConsumable/types';
- 
-let prescriptionFee=ref(1.0);
-let nutritionalFee=ref(0.0);
-let otherlFee=ref(0.0);
-let totalFee=ref(1.0);
+import {ref, defineProps} from 'vue';
+import {listAll} from '@/api/warehouse/suppliesManage';
+import {SuppliesManageVO} from '@/api/warehouse/suppliesManage/types';
+import {
+  listNutritionConsumable,
+  getNutritionConsumable,
+  delNutritionConsumable,
+  addNutritionConsumable,
+  updateNutritionConsumable
+} from '@/api/patients/nutritionConsumable';
+import {NutritionConsumableForm} from '@/api/patients/nutritionConsumable/types';
+
+let prescriptionFee = ref(1.0);
+let nutritionalFee = ref(0.0);
+let otherlFee = ref(0.0);
+let totalFee = ref(1.0);
 
 const emit = defineEmits(['change']);
 
-const prop=defineProps({
+const prop = defineProps({
   modelValue: {
     type: String,
     default: () => undefined
-  },
+  }
 });
 
-
-interface TableRow extends NutritionConsumableForm {  
-  sn?: number;   
-  tableId?: number;   
+interface TableRow extends NutritionConsumableForm {
+  sn?: number;
+  tableId?: number;
 }
 
 // 示例数据
@@ -141,43 +204,39 @@ const tableData = ref<TableRow[]>([
   }
 ]);
 
-
-let suppliesList=ref<SuppliesManageVO[]>([]);
- 
+let suppliesList = ref<SuppliesManageVO[]>([]);
 
 const getSuppliesList = async () => {
   const res = await listAll();
   suppliesList.value = res.rows;
-}
-
- 
+};
 
 const changeConsumableSelect = async (id: string) => {
-  let arr=id.split('_');
+  let arr = id.split('_');
   for (let item of suppliesList.value) {
     let row = tableData.value[Number(arr[1])];
     if (item.id.toString() != arr[0]) {
-      otherlFee.value+=item.sellPrice * row.quantity;;
-      continue
+      otherlFee.value += item.sellPrice * row.quantity;
+      continue;
     }
 
     let dosePerTime = 0;
     if (row.dosePerTime) {
       dosePerTime = row.dosePerTime;
     }
-    
-    row.specification=item.suppliesSpec;
+
+    row.specification = item.suppliesSpec;
     row.dosePerDay = row.frequency * dosePerTime;
-    row.quantity = ((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime;   
+    row.quantity = ((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime;
 
     if (row.consumableId) {
       let consumableId = row.consumableId.split('_')[0];
       for (let item of suppliesList.value) {
         if (item.id.toString() != consumableId) {
-          continue
+          continue;
         }
 
-        row.amount = item.sellPrice * row.quantity;       
+        row.amount = item.sellPrice * row.quantity;
         break;
       }
     }
@@ -185,17 +244,16 @@ const changeConsumableSelect = async (id: string) => {
     break;
   }
 
-  otherlFee.value=0;
-  tableData.value.forEach(row => {
-    if(row.amount){
-      otherlFee.value+=row.amount;
+  otherlFee.value = 0;
+  tableData.value.forEach((row) => {
+    if (row.amount) {
+      otherlFee.value += row.amount;
     }
   });
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
-
 watch(
   () => prop.modelValue,
   async (val: string) => {
@@ -204,7 +262,7 @@ watch(
     }
 
     let configData = JSON.parse(val);
-    let tableDataMap = {}
+    let tableDataMap = {};
     tableData.value.forEach((item: any) => {
       tableDataMap[item.tableId] = item;
     });
@@ -214,11 +272,11 @@ watch(
     totalFee.value = 0;
     otherlFee.value = 0;
     nutritionalFee.value = 0;
-    prescriptionFee.value+=configData.length;
-    totalFee.value+=configData.length;
+    prescriptionFee.value += configData.length;
+    totalFee.value += configData.length;
 
     configData.forEach((item: any) => {
-      item.products.forEach(pd => {        
+      item.products.forEach((pd) => {
         if (pd.amount) {
           nutritionalFee.value += pd.amount;
           totalFee.value += pd.amount;
@@ -238,7 +296,7 @@ watch(
       if (tmpData) {
         row = tmpData;
       }
-      let dosePerTime=0;
+      let dosePerTime = 0;
       if (row.dosePerTime) {
         dosePerTime = row.dosePerTime;
       }
@@ -253,17 +311,17 @@ watch(
         let consumableId = row.consumableId.split('_')[0];
         for (let item of suppliesList.value) {
           if (item.id.toString() != consumableId) {
-            continue
+            continue;
           }
 
-          row.amount = item.sellPrice * row.quantity;                    
+          row.amount = item.sellPrice * row.quantity;
           break;
         }
       }
 
-      if(row.amount){
-        otherlFee.value+=row.amount; 
-      }     
+      if (row.amount) {
+        otherlFee.value += row.amount;
+      }
 
       newTableList.value.push(row);
     });
@@ -271,53 +329,205 @@ watch(
     tableData.value = newTableList.value;
     emit('change', JSON.stringify(tableData.value));
   },
-  { deep: true, immediate: true }
+  {deep: true, immediate: true}
 );
 
-
 const dosePerTimeInput = (value: string, sn: number) => {
   let row = tableData.value[sn];
-  let dosePerTime=0;
+  let dosePerTime = 0;
   if (row.dosePerTime) {
-    dosePerTime=row.dosePerTime;
+    dosePerTime = row.dosePerTime;
   }
   row.dosePerDay = row.frequency * dosePerTime;
   row.quantity = ((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime;
-  otherlFee.value=0;
+  otherlFee.value = 0;
 
   if (row.consumableId) {
     let consumableId = row.consumableId.split('_')[0];
     for (let item of suppliesList.value) {
       if (item.id.toString() != consumableId) {
-        otherlFee.value+=item.sellPrice * row.quantity;
-        continue
+        otherlFee.value += item.sellPrice * row.quantity;
+        continue;
       }
 
       row.amount = item.sellPrice * row.quantity;
-      otherlFee.value+=row.amount;
+      otherlFee.value += row.amount;
       break;
     }
   }
 
-  otherlFee.value=0;
-  tableData.value.forEach(row => {
-    if(row.amount){
-      otherlFee.value+=row.amount;
+  otherlFee.value = 0;
+  tableData.value.forEach((row) => {
+    if (row.amount) {
+      otherlFee.value += row.amount;
     }
   });
 
-  emit('change', JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 const prescriptionRemark = (value: string) => {
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
+// 弹窗显示控制
+const dialogVisible = ref(false);
 
-onMounted(() => { 
-  getSuppliesList();  
-});
+// 搜索值
+const searchValue = ref('');
+// 选中的节点
+const selectedNode = ref('');
+// 已选数量
+const selectedCount = ref(2);
+
+// 树形控件数据
+const treeData = ref([
+  {
+    id: '1',
+    label: '基础公共模板',
+    children: [
+      {
+        id: '1-1',
+        label: '精氨酸组件'
+      },
+      {
+        id: '1-2',
+        label: '谷氨酰胺组件'
+      },
+      {
+        id: '1-3',
+        label: '免疫营养组件'
+      },
+      {
+        id: '1-4',
+        label: '肠内营养组件'
+      },
+      {
+        id: '1-5',
+        label: '肠外营养组件'
+      }
+    ]
+  },
+  {
+    id: '2',
+    label: '万颗星营养智能医院',
+    children: [
+      {
+        id: '2-1',
+        label: '中链甘油三酯MCT组件'
+      },
+      {
+        id: '2-2',
+        label: '口服补糖盐饮品'
+      },
+      {
+        id: '2-3',
+        label: '膳食纤维组件'
+      },
+      {
+        id: '2-4',
+        label: 'ERAS专用碳水化合物饮品'
+      },
+      {
+        id: '2-5',
+        label: '白蛋白肽组件'
+      },
+      {
+        id: '2-6',
+        label: '乳清蛋白组件'
+      },
+      {
+        id: '2-7',
+        label: '益生菌组件'
+      },
+      {
+        id: '2-8',
+        label: '鱼油蛋白组件'
+      }
+    ]
+  },
+  {
+    id: '3',
+    label: '个人模板',
+    children: [
+      {
+        id: '3-1',
+        label: '术前营养支持方案'
+      },
+      {
+        id: '3-2',
+        label: '术后恢复营养方案'
+      },
+      {
+        id: '3-3',
+        label: '重症营养支持方案'
+      }
+    ]
+  },
+  {
+    id: '4',
+    label: '科室模板',
+    children: [
+      {
+        id: '4-1',
+        label: '外科营养支持方案'
+      },
+      {
+        id: '4-2',
+        label: '内科营养支持方案'
+      },
+      {
+        id: '4-3',
+        label: 'ICU营养支持方案'
+      },
+      {
+        id: '4-4',
+        label: '肿瘤科营养支持方案'
+      }
+    ]
+  }
+]);
+
+// 树形控件配置
+const defaultProps = {
+  children: 'children',
+  label: 'label'
+};
+
+// 模板表格数据
+const templateTableData = ref([
+  {
+    productName: '氨基酸型复配营养粉2',
+    dosePerTime: '5.0000',
+    unit: 'g'
+  },
+  {
+    productName: '肠内营养全营养复合膜',
+    dosePerTime: '1.0000',
+    unit: '袋'
+  }
+]);
+
+// 树节点选中事件
+const handleCheck = (data: any, checked: any) => {
+  console.log(data, checked);
+  // 这里处理节点选中逻辑
+};
+
+// 打开处方模板
+const openTemplate = () => {
+  dialogVisible.value = true;
+};
 
+// 确认选择模板
+const handleConfirm = () => {
+  dialogVisible.value = false;
+  // 这里处理选中模板后的逻辑
+};
+
+onMounted(() => {
+  getSuppliesList();
+});
 </script>
 
 <style lang="scss" scoped>
@@ -533,4 +743,95 @@ onMounted(() => {
     }
   }
 }
+
+.template-dialog {
+  :deep(.el-dialog__body) {
+    padding: 0 20px;
+  }
+
+  .tip-box {
+    background-color: #e6f7ff;
+    padding: 12px 16px;
+    color: #606266;
+    font-size: 14px;
+    margin-bottom: 16px;
+  }
+
+  .search-box {
+    margin-bottom: 16px;
+
+    .search-input {
+      width: 300px;
+    }
+  }
+
+  .dialog-content {
+    display: flex;
+    min-height: 350px;
+    border: 1px solid #ebeef5;
+
+    .left-tree {
+      width: 220px;
+      padding: 12px;
+      border-right: 1px solid #ebeef5;
+      max-height: 350px;
+      overflow-y: auto;
+
+      :deep(.el-tree-node__content) {
+        height: 32px;
+      }
+
+      :deep(.el-tree-node__content:hover) {
+        background-color: #f5f7fa;
+      }
+
+      :deep(.el-tree-node.is-current > .el-tree-node__content) {
+        background-color: #f5f7fa;
+      }
+    }
+
+    .right-table {
+      flex: 1;
+      padding: 12px;
+      overflow: auto;
+
+      .table-wrapper {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+  .selected-count {
+    margin: 16px 0;
+    color: #409eff;
+    font-size: 14px;
+  }
+}
+
+.custom-table {
+  width: 100%;
+  border-collapse: collapse;
+  border: 1px solid #ebeef5;
+
+  th,
+  td {
+    padding: 12px 8px;
+    border: 1px solid #ebeef5;
+    text-align: center;
+    font-size: 14px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  th {
+    background-color: #f5f7fa;
+    color: #303133;
+    font-weight: 600;
+  }
+
+  tbody tr:hover {
+    background-color: #f5f7fa;
+  }
+}
 </style>

+ 380 - 79
src/views/patients/enteralNutrition/components/table/MaterialTable2.vue

@@ -5,10 +5,9 @@
       <el-table-column label="耗材" min-width="300">
         <template #default="{row}">
           <div class="material-group">
-            <div class="material-row" style="margin-bottom:10px;">
+            <div class="material-row" style="margin-bottom: 10px">
               <el-select v-model="row.consumableId" placeholder="请选择" @change="changeConsumableSelect">
-                <el-option v-for="pn in suppliesList" :key="pn.id" :label="pn.suppliesName"
-                  :value="pn.id+'_'+row.sn"></el-option>
+                <el-option v-for="pn in suppliesList" :key="pn.id" :label="pn.suppliesName" :value="pn.id + '_' + row.sn"></el-option>
               </el-select>
             </div>
           </div>
@@ -17,7 +16,7 @@
       <el-table-column label="规格" width="100" align="center">
         <template #default="{row}">
           <div class="spec-group">
-            <span>{{ row.specification }}</span>            
+            <span>{{ row.specification }}</span>
           </div>
         </template>
       </el-table-column>
@@ -25,17 +24,17 @@
         <template #default="{row}">
           <div class="dosage-group">
             <div class="dosage-input">
-              <el-input v-model="row.dosePerTime" placeholder="请输入" class="input-center" @input="dosePerTimeInput(row.dosePerTime,row.sn)">
+              <el-input v-model="row.dosePerTime" placeholder="请输入" class="input-center" @input="dosePerTimeInput(row.dosePerTime, row.sn)">
                 <template #append>袋</template>
-              </el-input>              
-            </div>             
+              </el-input>
+            </div>
           </div>
         </template>
       </el-table-column>
-       
+
       <el-table-column label="频次" width="100" align="center">
         <template #default="{row}">
-          <span>一天{{row.frequency}}次</span>
+          <span>一天{{ row.frequency }}次</span>
         </template>
       </el-table-column>
       <el-table-column label="用量/日" width="100" align="center">
@@ -63,7 +62,7 @@
 
       <el-table-column label="处方备注" width="200" align="center">
         <template #default="{row}">
-          <el-input v-model="row.prescriptionRemark" :maxlength="100" :show-word-limit="true" @change="prescriptionRemark"/>        
+          <el-input v-model="row.prescriptionRemark" :maxlength="100" :show-word-limit="true" @change="prescriptionRemark" />
         </template>
       </el-table-column>
 
@@ -72,19 +71,18 @@
           <span>{{ row.amount }}</span>
         </template>
       </el-table-column>
-
     </el-table>
     <div class="table-footer">
       <div class="left-buttons">
         <el-button type="primary" plain>登为个人模板</el-button>
         <el-button type="primary" plain>批量添加营养品</el-button>
-        <el-button type="primary" plain>处方模板</el-button>
+        <el-button type="primary" plain @click="openTemplate">处方模板</el-button>
       </div>
       <div class="right-summary">
         <div class="summary-list">
           <div class="summary-item">
             <span class="label">处方费用:</span>
-            <span class="value">¥{{ nutritionalFee + otherlFee  }}</span>
+            <span class="value">¥{{ nutritionalFee + otherlFee }}</span>
           </div>
           <div class="summary-item">
             <span class="label">营养配置费:</span>
@@ -92,39 +90,104 @@
           </div>
           <div class="summary-item total">
             <span class="label">总计:</span>
-            <span class="value">¥{{ totalFee+otherlFee }}</span>
+            <span class="value">¥{{ totalFee + otherlFee }}</span>
           </div>
         </div>
       </div>
     </div>
   </div>
+
+  <!-- 处方模板弹窗 -->
+  <el-dialog v-model="dialogVisible" title="选择处方模板" width="60%" :close-on-click-modal="false" class="template-dialog">
+    <!-- 提示信息 -->
+    <div class="tip-box">如部分模版未显示请检查预包装库位产品库存,无库存则含该产品的协定方模板将不再显示</div>
+
+    <div class="search-box">
+      <el-input v-model="searchValue" placeholder="请输入名称" class="search-input">
+        <template #append>
+          <el-button type="primary">查询</el-button>
+        </template>
+      </el-input>
+    </div>
+
+    <div class="dialog-content">
+      <!-- 左侧树形控件 -->
+      <div class="left-tree">
+        <el-tree
+          ref="treeRef"
+          :data="treeData"
+          :props="defaultProps"
+          node-key="id"
+          :default-expanded-keys="['1']"
+          show-checkbox
+          @check="handleCheck"
+        />
+      </div>
+
+      <!-- 右侧表格 -->
+      <div class="right-table">
+        <div class="table-wrapper">
+          <table class="custom-table">
+            <thead>
+              <tr>
+                <th width="60">组号</th>
+                <th>产品名称</th>
+                <th width="120">用量/次</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr v-for="(item, index) in templateTableData" :key="index">
+                <td>{{ index + 1 }}</td>
+                <td>{{ item.productName }}</td>
+                <td>{{ item.dosePerTime }}{{ item.unit }}</td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+
+    <div class="selected-count">已选 ({{ selectedCount }})</div>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleConfirm">确定</el-button>
+      </span>
+    </template>
+  </el-dialog>
 </template>
 
 <script setup lang="ts">
-import {ref,defineProps} from 'vue';
-import {  listAll  } from '@/api/warehouse/suppliesManage';
-import { SuppliesManageVO } from '@/api/warehouse/suppliesManage/types';
-import { listNutritionConsumable, getNutritionConsumable, delNutritionConsumable, addNutritionConsumable, updateNutritionConsumable } from '@/api/patients/nutritionConsumable';
-import {NutritionConsumableForm } from '@/api/patients/nutritionConsumable/types';
- 
-let prescriptionFee=ref(1.0);
-let nutritionalFee=ref(0.0);
-let otherlFee=ref(0.0);
-let totalFee=ref(1.0);
+import {ref, defineProps, watch, onMounted} from 'vue';
+import {listAll} from '@/api/warehouse/suppliesManage';
+import {SuppliesManageVO} from '@/api/warehouse/suppliesManage/types';
+import {
+  listNutritionConsumable,
+  getNutritionConsumable,
+  delNutritionConsumable,
+  addNutritionConsumable,
+  updateNutritionConsumable
+} from '@/api/patients/nutritionConsumable';
+import {NutritionConsumableForm} from '@/api/patients/nutritionConsumable/types';
+
+let prescriptionFee = ref(1.0);
+let nutritionalFee = ref(0.0);
+let otherlFee = ref(0.0);
+let totalFee = ref(1.0);
 
 const emit = defineEmits(['change']);
 
-const prop=defineProps({
+const prop = defineProps({
   modelValue: {
     type: String,
     default: () => undefined
-  },
+  }
 });
 
-
-interface TableRow extends NutritionConsumableForm {  
-  sn?: number;   
-  tableId?: number;   
+interface TableRow extends NutritionConsumableForm {
+  sn?: number;
+  tableId?: number;
 }
 
 // 示例数据
@@ -141,43 +204,39 @@ const tableData = ref<TableRow[]>([
   }
 ]);
 
-
-let suppliesList=ref<SuppliesManageVO[]>([]);
- 
+let suppliesList = ref<SuppliesManageVO[]>([]);
 
 const getSuppliesList = async () => {
   const res = await listAll();
   suppliesList.value = res.rows;
-}
-
- 
+};
 
 const changeConsumableSelect = async (id: string) => {
-  let arr=id.split('_');
+  let arr = id.split('_');
   for (let item of suppliesList.value) {
     let row = tableData.value[Number(arr[1])];
     if (item.id.toString() != arr[0]) {
-      otherlFee.value+=item.sellPrice * row.quantity;;
-      continue
+      otherlFee.value += item.sellPrice * row.quantity;
+      continue;
     }
 
     let dosePerTime = 0;
     if (row.dosePerTime) {
       dosePerTime = Number(row.dosePerTime);
     }
-    
-    row.specification=item.suppliesSpec;
+
+    row.specification = item.suppliesSpec;
     row.dosePerDay = row.frequency * dosePerTime;
-    row.quantity =Math.max(0,((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime) ;   
+    row.quantity = Math.max(0, ((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime);
 
     if (row.consumableId) {
       let consumableId = row.consumableId.split('_')[0];
       for (let item of suppliesList.value) {
         if (item.id.toString() != consumableId) {
-          continue
+          continue;
         }
 
-        row.amount = item.sellPrice * row.quantity;       
+        row.amount = item.sellPrice * row.quantity;
         break;
       }
     }
@@ -185,17 +244,16 @@ const changeConsumableSelect = async (id: string) => {
     break;
   }
 
-  otherlFee.value=0;
-  tableData.value.forEach(row => {
-    if(row.amount){
-      otherlFee.value+=row.amount;
+  otherlFee.value = 0;
+  tableData.value.forEach((row) => {
+    if (row.amount) {
+      otherlFee.value += row.amount;
     }
   });
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
-
 watch(
   () => prop.modelValue,
   async (val: string) => {
@@ -204,7 +262,7 @@ watch(
     }
 
     let configData = JSON.parse(val);
-    let tableDataMap = {}
+    let tableDataMap = {};
     tableData.value.forEach((item: any) => {
       tableDataMap[item.tableId] = item;
     });
@@ -214,11 +272,11 @@ watch(
     totalFee.value = 0;
     otherlFee.value = 0;
     nutritionalFee.value = 0;
-    prescriptionFee.value+=configData.length;
-    totalFee.value+=configData.length;
+    prescriptionFee.value += configData.length;
+    totalFee.value += configData.length;
 
     configData.forEach((item: any) => {
-      item.products.forEach(pd => {        
+      item.products.forEach((pd) => {
         if (pd.amount) {
           nutritionalFee.value += pd.amount;
           totalFee.value += pd.amount;
@@ -238,7 +296,7 @@ watch(
       if (tmpData) {
         row = tmpData;
       }
-      let dosePerTime=0;
+      let dosePerTime = 0;
       if (row.dosePerTime) {
         dosePerTime = Number(row.dosePerTime);
       }
@@ -247,23 +305,23 @@ watch(
       row.usageDays = Number(item.usageDays);
       row.firstDay = Number(item.firstDay);
       row.dosePerDay = item.frequency * dosePerTime;
-      row.quantity =Math.max(0,((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime) ;
+      row.quantity = Math.max(0, ((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime);
 
       if (row.consumableId) {
         let consumableId = row.consumableId.split('_')[0];
         for (let item of suppliesList.value) {
           if (item.id.toString() != consumableId) {
-            continue
+            continue;
           }
 
-          row.amount = item.sellPrice * row.quantity;                    
+          row.amount = item.sellPrice * row.quantity;
           break;
         }
       }
 
-      if(row.amount){
-        otherlFee.value+=row.amount; 
-      }     
+      if (row.amount) {
+        otherlFee.value += row.amount;
+      }
 
       newTableList.value.push(row);
     });
@@ -271,53 +329,205 @@ watch(
     tableData.value = newTableList.value;
     emit('change', JSON.stringify(tableData.value));
   },
-  { deep: true, immediate: true }
+  {deep: true, immediate: true}
 );
 
-
 const dosePerTimeInput = (value: string, sn: number) => {
   let row = tableData.value[sn];
-  let dosePerTime=0;
+  let dosePerTime = 0;
   if (row.dosePerTime) {
-    dosePerTime=row.dosePerTime;
+    dosePerTime = row.dosePerTime;
   }
   row.dosePerDay = row.frequency * dosePerTime;
-  row.quantity =Math.max(0,((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime) ;
-  otherlFee.value=0;
+  row.quantity = Math.max(0, ((row.usageDays - 1) * row.frequency + row.firstDay) * dosePerTime);
+  otherlFee.value = 0;
 
   if (row.consumableId) {
     let consumableId = row.consumableId.split('_')[0];
     for (let item of suppliesList.value) {
       if (item.id.toString() != consumableId) {
-        otherlFee.value+=item.sellPrice * row.quantity;
-        continue
+        otherlFee.value += item.sellPrice * row.quantity;
+        continue;
       }
 
       row.amount = item.sellPrice * row.quantity;
-      otherlFee.value+=row.amount;
+      otherlFee.value += row.amount;
       break;
     }
   }
 
-  otherlFee.value=0;
-  tableData.value.forEach(row => {
-    if(row.amount){
-      otherlFee.value+=row.amount;
+  otherlFee.value = 0;
+  tableData.value.forEach((row) => {
+    if (row.amount) {
+      otherlFee.value += row.amount;
     }
   });
 
-  emit('change', JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 const prescriptionRemark = (value: string) => {
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
+// 弹窗显示控制
+const dialogVisible = ref(false);
 
-onMounted(() => { 
-  getSuppliesList();  
-});
+// 搜索值
+const searchValue = ref('');
+// 选中的节点
+const selectedNode = ref('');
+// 已选数量
+const selectedCount = ref(2);
+
+// 树形控件数据
+const treeData = ref([
+  {
+    id: '1',
+    label: '基础公共模板',
+    children: [
+      {
+        id: '1-1',
+        label: '精氨酸组件'
+      },
+      {
+        id: '1-2',
+        label: '谷氨酰胺组件'
+      },
+      {
+        id: '1-3',
+        label: '免疫营养组件'
+      },
+      {
+        id: '1-4',
+        label: '肠内营养组件'
+      },
+      {
+        id: '1-5',
+        label: '肠外营养组件'
+      }
+    ]
+  },
+  {
+    id: '2',
+    label: '万颗星营养智能医院',
+    children: [
+      {
+        id: '2-1',
+        label: '中链甘油三酯MCT组件'
+      },
+      {
+        id: '2-2',
+        label: '口服补糖盐饮品'
+      },
+      {
+        id: '2-3',
+        label: '膳食纤维组件'
+      },
+      {
+        id: '2-4',
+        label: 'ERAS专用碳水化合物饮品'
+      },
+      {
+        id: '2-5',
+        label: '白蛋白肽组件'
+      },
+      {
+        id: '2-6',
+        label: '乳清蛋白组件'
+      },
+      {
+        id: '2-7',
+        label: '益生菌组件'
+      },
+      {
+        id: '2-8',
+        label: '鱼油蛋白组件'
+      }
+    ]
+  },
+  {
+    id: '3',
+    label: '个人模板',
+    children: [
+      {
+        id: '3-1',
+        label: '术前营养支持方案'
+      },
+      {
+        id: '3-2',
+        label: '术后恢复营养方案'
+      },
+      {
+        id: '3-3',
+        label: '重症营养支持方案'
+      }
+    ]
+  },
+  {
+    id: '4',
+    label: '科室模板',
+    children: [
+      {
+        id: '4-1',
+        label: '外科营养支持方案'
+      },
+      {
+        id: '4-2',
+        label: '内科营养支持方案'
+      },
+      {
+        id: '4-3',
+        label: 'ICU营养支持方案'
+      },
+      {
+        id: '4-4',
+        label: '肿瘤科营养支持方案'
+      }
+    ]
+  }
+]);
+
+// 树形控件配置
+const defaultProps = {
+  children: 'children',
+  label: 'label'
+};
+
+// 模板表格数据
+const templateTableData = ref([
+  {
+    productName: '氨基酸型复配营养粉2',
+    dosePerTime: '5.0000',
+    unit: 'g'
+  },
+  {
+    productName: '肠内营养全营养复合膜',
+    dosePerTime: '1.0000',
+    unit: '袋'
+  }
+]);
+
+// 树节点选中事件
+const handleCheck = (data: any, checked: any) => {
+  console.log(data, checked);
+  // 这里处理节点选中逻辑
+};
+
+// 打开处方模板
+const openTemplate = () => {
+  dialogVisible.value = true;
+};
+
+// 确认选择模板
+const handleConfirm = () => {
+  dialogVisible.value = false;
+  // 这里处理选中模板后的逻辑
+};
 
+onMounted(() => {
+  getSuppliesList();
+});
 </script>
 
 <style lang="scss" scoped>
@@ -533,4 +743,95 @@ onMounted(() => {
     }
   }
 }
+
+.template-dialog {
+  :deep(.el-dialog__body) {
+    padding: 0 20px;
+  }
+
+  .tip-box {
+    background-color: #e6f7ff;
+    padding: 12px 16px;
+    color: #606266;
+    font-size: 14px;
+    margin-bottom: 16px;
+  }
+
+  .search-box {
+    margin-bottom: 16px;
+
+    .search-input {
+      width: 300px;
+    }
+  }
+
+  .dialog-content {
+    display: flex;
+    min-height: 350px;
+    border: 1px solid #ebeef5;
+
+    .left-tree {
+      width: 220px;
+      padding: 12px;
+      border-right: 1px solid #ebeef5;
+      max-height: 350px;
+      overflow-y: auto;
+
+      :deep(.el-tree-node__content) {
+        height: 32px;
+      }
+
+      :deep(.el-tree-node__content:hover) {
+        background-color: #f5f7fa;
+      }
+
+      :deep(.el-tree-node.is-current > .el-tree-node__content) {
+        background-color: #f5f7fa;
+      }
+    }
+
+    .right-table {
+      flex: 1;
+      padding: 12px;
+      overflow: auto;
+
+      .table-wrapper {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+  .selected-count {
+    margin: 16px 0;
+    color: #409eff;
+    font-size: 14px;
+  }
+}
+
+.custom-table {
+  width: 100%;
+  border-collapse: collapse;
+  border: 1px solid #ebeef5;
+
+  th,
+  td {
+    padding: 12px 8px;
+    border: 1px solid #ebeef5;
+    text-align: center;
+    font-size: 14px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  th {
+    background-color: #f5f7fa;
+    color: #303133;
+    font-weight: 600;
+  }
+
+  tbody tr:hover {
+    background-color: #f5f7fa;
+  }
+}
 </style>

+ 240 - 211
src/views/patients/enteralNutrition/components/table/NutritionTable.vue

@@ -1,37 +1,49 @@
 <template>
   <div class="nutrition-table">
     <!-- 停嘱日期 (仅长期医嘱显示) -->
-    <div  class="stop-date">
+    <div class="stop-date">
       <span class="required">*</span>
       <span class="label">停嘱日期</span>
-      <el-date-picker v-model="stopDate" type="date" placeholder="请选择" format="YYYY-MM-DD" value-format="YYYY-MM-DD" :clearable="false"
-      @change="handleStopDateChange" :disabled-date="disabledBeforeToday"/>
-      <span class="days">(使用天数:{{daysDifference}}天)</span>
+      <el-date-picker
+        v-model="stopDate"
+        type="date"
+        placeholder="请选择"
+        format="YYYY-MM-DD"
+        value-format="YYYY-MM-DD"
+        :clearable="false"
+        @change="handleStopDateChange"
+        :disabled-date="disabledBeforeToday"
+      />
+      <span class="days">(使用天数:{{ daysDifference }}天)</span>
     </div>
 
     <el-table :data="tableData" border>
       <el-table-column type="index" label="组号" width="60" align="center" />
       <el-table-column label="营养产品" min-width="300">
         <template #default="{row}">
-          <div class="product-group">             
-              <div v-for="(product, index) in row.products" :key="index" class="product-row">
-                <el-select v-model="product.nutritionProductId" placeholder="请选择" @change="changeProductSelect">
-                  <el-option v-for="pn in productNutritionList" :key="pn.id" :label="pn.productName"
-                    :value="pn.id + '_' + row.sn + '_' + index"></el-option>
-                </el-select>
-                <div class="action-buttons">
-                  <el-button class="icon-btn" @click="addProduct(row)">
-                    <el-icon>
-                      <Plus />
-                    </el-icon>
-                  </el-button>
-                  <el-button class="icon-btn" @click="removeProduct(row, index)">
-                    <el-icon>
-                      <Delete />
-                    </el-icon>
-                  </el-button>
-                </div>
-              </div>  
+          <div class="product-group">
+            <div v-for="(product, index) in row.products" :key="index" class="product-row">
+              <el-select v-model="product.nutritionProductId" placeholder="请选择" @change="changeProductSelect">
+                <el-option
+                  v-for="pn in productNutritionList"
+                  :key="pn.id"
+                  :label="pn.productName"
+                  :value="pn.id + '_' + row.sn + '_' + index"
+                ></el-option>
+              </el-select>
+              <div class="action-buttons">
+                <el-button class="icon-btn" @click="addProduct(row)">
+                  <el-icon>
+                    <Plus />
+                  </el-icon>
+                </el-button>
+                <el-button class="icon-btn" @click="removeProduct(row, index)">
+                  <el-icon>
+                    <Delete />
+                  </el-icon>
+                </el-button>
+              </div>
+            </div>
           </div>
         </template>
       </el-table-column>
@@ -39,8 +51,12 @@
         <template #default="{row}">
           <div class="dosage-group">
             <div v-for="(product, index) in row.products" :key="index" class="dosage-input">
-              <el-input v-model="product.dosePerTime" placeholder="请输入" class="input-center"  
-              @input="dosePerTimeInput(product.dosePerTime,row.sn+'_'+index)"/>
+              <el-input
+                v-model="product.dosePerTime"
+                placeholder="请输入"
+                class="input-center"
+                @input="dosePerTimeInput(product.dosePerTime, row.sn + '_' + index)"
+              />
               <span class="unit">g</span>
             </div>
           </div>
@@ -51,42 +67,72 @@
           <div class="time-slots">
             <div class="time-row">
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[0].checked" @change="changeTimeSelection(row.timeSlots[0].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[0].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[0].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[0].checked" @change="changeTimeSelection(row.timeSlots[0].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[0].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[0].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[1].checked" @change="changeTimeSelection(row.timeSlots[1].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[1].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[1].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[1].checked" @change="changeTimeSelection(row.timeSlots[1].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[1].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[1].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[2].checked" @change="changeTimeSelection(row.timeSlots[2].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[2].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[2].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[2].checked" @change="changeTimeSelection(row.timeSlots[2].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[2].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[2].checked"
+                />
               </div>
             </div>
             <div class="time-row">
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[3].checked" @change="changeTimeSelection(row.timeSlots[3].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[3].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[3].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[3].checked" @change="changeTimeSelection(row.timeSlots[3].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[3].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[3].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[4].checked" @change="changeTimeSelection(row.timeSlots[4].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[4].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[4].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[4].checked" @change="changeTimeSelection(row.timeSlots[4].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[4].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[4].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[5].checked" @change="changeTimeSelection(row.timeSlots[5].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[5].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[5].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[5].checked" @change="changeTimeSelection(row.timeSlots[5].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[5].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[5].checked"
+                />
               </div>
             </div>
           </div>
@@ -94,13 +140,13 @@
       </el-table-column>
       <el-table-column label="频次" width="120" align="center">
         <template #default="{row}">
-          <span>一天{{row.frequency}}次</span>
+          <span>一天{{ row.frequency }}次</span>
         </template>
       </el-table-column>
 
       <el-table-column label="首日" width="150" align="center">
         <template #default="{row}">
-          <el-input v-model="row.firstDay" @input="firstDayInput(row.firstDay,row.sn)">
+          <el-input v-model="row.firstDay" @input="firstDayInput(row.firstDay, row.sn)">
             <template #append>次</template>
           </el-input>
         </template>
@@ -109,8 +155,8 @@
       <el-table-column label="用量/日" width="150" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.dosePerDay }}</span>   
-            <span class="unit">{{ product.productSpecUnit }}</span> 
+            <span>{{ product.dosePerDay }}</span>
+            <span class="unit">{{ product.productSpecUnit }}</span>
           </div>
         </template>
       </el-table-column>
@@ -118,23 +164,22 @@
       <el-table-column label="规格" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.specification }}</span>             
+            <span>{{ product.specification }}</span>
           </div>
         </template>
       </el-table-column>
 
       <el-table-column label="用法" width="150" align="center">
         <template #default="{row}">
-          <el-select v-model="row.usage" placeholder="请选择" @change="changeUsage(row.usage,row.sn)">
-            <el-option v-for="dict in default_usage" :key="dict.value" :label="dict.label"
-              :value="dict.value"></el-option>
+          <el-select v-model="row.usage" placeholder="请选择" @change="changeUsage(row.usage, row.sn)">
+            <el-option v-for="dict in default_usage" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
           </el-select>
         </template>
       </el-table-column>
 
       <el-table-column label="制剂液量/次" width="170" align="center">
         <template #default="{row}">
-          <el-input v-model="row.preparationVolumePerTime" @change="changePreparationVolumePerTime(row.preparationVolumePerTime,row.sn)">
+          <el-input v-model="row.preparationVolumePerTime" @change="changePreparationVolumePerTime(row.preparationVolumePerTime, row.sn)">
             <template #append>ml</template>
           </el-input>
         </template>
@@ -151,7 +196,7 @@
 
       <el-table-column label="能量密度/次" width="200" align="center">
         <template #default="{row}">
-          <el-input v-model="row.energyDensityPerTime" @change="changeEnergyDensityPerTime(row.energyDensityPerTime,row.sn)">
+          <el-input v-model="row.energyDensityPerTime" @change="changeEnergyDensityPerTime(row.energyDensityPerTime, row.sn)">
             <template #append>kcal/ml</template>
           </el-input>
         </template>
@@ -159,30 +204,33 @@
 
       <el-table-column label="处方备注" width="200" align="center">
         <template #default="{row}">
-          <template v-for="(product, index) in row.products" >
-            <el-input v-model="product.prescriptionRemark" :maxlength="100" :show-word-limit="true" 
-            @change="changePrescriptionRemark(product.prescriptionRemark,row.sn)"/>
-          </template>          
+          <template v-for="(product, index) in row.products">
+            <el-input
+              v-model="product.prescriptionRemark"
+              :maxlength="100"
+              :show-word-limit="true"
+              @change="changePrescriptionRemark(product.prescriptionRemark, row.sn)"
+            />
+          </template>
         </template>
       </el-table-column>
 
       <el-table-column label="每日热量" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.dailyCalories }}</span>             
+            <span>{{ product.dailyCalories }}</span>
           </div>
         </template>
       </el-table-column>
 
-
       <el-table-column label="金额" width="100" align="center">
-        <template #default="{row}"> 
+        <template #default="{row}">
           <div class="daily-dosage" v-for="(product, index) in row.products" :key="index">
-            <span>{{product.amount }}</span>
+            <span>{{ product.amount }}</span>
           </div>
         </template>
       </el-table-column>
-       
+
       <el-table-column label="操作" width="160" align="center" fixed="right">
         <template #default="{$index}">
           <div class="operation-cell">
@@ -206,22 +254,22 @@
 <script setup lang="ts">
 import {ref, defineProps} from 'vue';
 import {Plus, Delete, CirclePlus} from '@element-plus/icons-vue';
-import { listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition } from '@/api/patients/nutrition';
-import { EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm } from '@/api/patients/nutrition/types';
-import { listNutrition, listAllNutrition  } from '@/api/warehouse/productNutrition/index';
-import { NutritionVO, NutritionQuery, NutritionForm } from '@/api/warehouse/productNutrition/types';
+import {listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition} from '@/api/patients/nutrition';
+import {EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm} from '@/api/patients/nutrition/types';
+import {listNutrition, listAllNutrition} from '@/api/warehouse/productNutrition/index';
+import {NutritionVO, NutritionQuery, NutritionForm} from '@/api/warehouse/productNutrition/types';
 
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { default_usage } = toRefs < any > (proxy ?.useDict('default_usage'));
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {default_usage} = toRefs<any>(proxy?.useDict('default_usage'));
 
-let productNutritionList=ref<NutritionVO[]>([]);
-let tableId=ref<number>(0);
+let productNutritionList = ref<NutritionVO[]>([]);
+let tableId = ref<number>(0);
 
-const prop=defineProps({
+const prop = defineProps({
   prescriptionDate: {
     type: String,
     default: () => undefined
-  },
+  }
 });
 
 const emit = defineEmits(['change']);
@@ -235,7 +283,7 @@ interface TimeSlot {
   time: string;
 }
 
-interface TableRow  extends EnteralNutritionForm {
+interface TableRow extends EnteralNutritionForm {
   products: EnteralNutritionForm[];
   timeSlots: TimeSlot[];
   sn: number;
@@ -244,7 +292,7 @@ interface TableRow  extends EnteralNutritionForm {
 
 // 创建默认行数据的函数
 const createDefaultRow = (): TableRow => ({
-  products: [{specification:'',totalDose:'',dosePerDay:''}],
+  products: [{specification: '', totalDose: '', dosePerDay: ''}],
   timeSlots: [
     {checked: true, time: '08:00'},
     {checked: false, time: '08:30'},
@@ -253,54 +301,51 @@ const createDefaultRow = (): TableRow => ({
     {checked: true, time: '18:00'},
     {checked: false, time: '18:30'}
   ],
-  usageDays:0,
-  frequency:3,
-  firstDay:2,
-  sn:0,
-  tableId:tableId.value++,
+  usageDays: 0,
+  frequency: 3,
+  firstDay: 2,
+  sn: 0,
+  tableId: tableId.value++
 });
 
 // 示例数据
 const tableData = ref<TableRow[]>([createDefaultRow()]);
 
-
 const changeProductSelect = async (id: string) => {
-  let arr=id.split('_');
+  let arr = id.split('_');
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
+      continue;
     }
-    
+
     let row = tableData.value[Number(arr[1])];
     let pt = row.products[Number(arr[2])];
     pt.specification=item.productSpec;
     pt.dosePerTime=null;     
     pt.dailyCalories=null;
     pt.productSpecUnit=item.productSpecUnit;
-    pt.amount=null;      
-    if(!row.usage){
-      row.usage=item.defaultUsage;
-    }  
+    pt.amount=null; 
+    row.usage=item.defaultUsage;
     pt.totalDose='0' ;
     pt.dosePerDay='0';
     pt.firstDay=Math.ceil(row.frequency/2.0);
     break;
-  } 
+  }
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 const getProductNutritionList = async () => {
   const res = await listAllNutrition();
   productNutritionList.value = res.rows;
-}
+};
 
 // 新增行
 const addNewRow = () => {
   let row: TableRow = createDefaultRow();
-  row.sn = tableData.value.length ;
+  row.sn = tableData.value.length;
   tableData.value.push(row);
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 // 新增产品输入框
@@ -316,159 +361,144 @@ const removeProduct = (row: TableRow, index: number) => {
     if (rowIndex !== -1) {
       tableData.value.splice(rowIndex, 1);
     }
-    emit('change',JSON.stringify(tableData.value))
+    emit('change', JSON.stringify(tableData.value));
   } else {
     // 否则只删除当前输入框
     row.products.splice(index, 1);
   }
 };
- 
 
 // 复制行
 const copyRow = (index: number) => {
   const newRow = JSON.parse(JSON.stringify(tableData.value[index]));
-  newRow.tableId = tableId.value++
+  newRow.tableId = tableId.value++;
   tableData.value.splice(index + 1, 0, newRow);
   tableData.value.forEach((item, index) => {
     item.sn = index;
     item.products.forEach((ch, idx) => {
-      if(ch.nutritionProductId){
+      if (ch.nutritionProductId) {
         let arr = ch.nutritionProductId.split('_');
         ch.nutritionProductId = arr[0] + '_' + index + '_' + idx;
-      }     
+      }
     });
   });
-  emit('change', JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 // 删除行
-const deleteRow = (index: number) => {   
+const deleteRow = (index: number) => {
   tableData.value.splice(index, 1);
 
   tableData.value.forEach((item, index) => {
     item.sn = index;
-  });  
-  
-  emit('change',JSON.stringify(tableData.value))
-};
+  });
 
+  emit('change', JSON.stringify(tableData.value));
+};
 
-const changeUsageDays = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);   
-}
+const changeUsageDays = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const changeUsage = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const changeUsage = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
 const changePreparationVolumePerTime = (value: string, sn:string) => { 
-  let row = tableData.value[sn];
-  if(row.preparationVolumePerTime){
-    row.preparationConcentrationPerTime=2;
-    row.energyDensityPerTime=Number(row.preparationVolumePerTime)*row.preparationConcentrationPerTime/100.0;
-  }
   changeTimeSelection(null,sn);
 }
 
 const changeEnergyDensityPerTime = (value: string, sn:string) => { 
-  let row = tableData.value[sn];
-  if(row.preparationConcentrationPerTime!=null){     
-    row.preparationVolumePerTime=Number(row.energyDensityPerTime)/(row.preparationConcentrationPerTime/100.0);
-  }
-  changeTimeSelection(null,sn);
-}
-
-const changePrescriptionRemark = (value: string, sn:string) => { 
   changeTimeSelection(null,sn);
 }
 
+const changePrescriptionRemark = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const firstDayInput = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const firstDayInput = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const changeTimeSelection = (value: string, sn:string) => {
+const changeTimeSelection = (value: string, sn: string) => {
   let row = tableData.value[sn];
-  let frequency=0;
-  row.timeSlots.forEach(item=>{
-    if(item.checked){
+  let frequency = 0;
+  row.timeSlots.forEach((item) => {
+    if (item.checked) {
       frequency++;
     }
-  })
-  row.frequency=frequency;
-  if(value!=null){
-    row.firstDay=Math.ceil(row.frequency/2.0);
+  });
+  row.frequency = frequency;
+  if (value != null) {
+    row.firstDay = Math.ceil(row.frequency / 2.0);
   }
 
-  row.products.forEach(pt => {
+  row.products.forEach((pt) => {
     if (!pt.dosePerTime || pt.dosePerTime.trim().length == 0) {
       return;
     }
-    let arr=pt.nutritionProductId.split('_');
+    let arr = pt.nutritionProductId.split('_');
 
     for (let item of productNutritionList.value) {
-    if (item.id.toString() != arr[0]) {
-      continue
-    }    
-    
-    
-    let val=item.calorie*row.frequency*Number(pt.dosePerTime)/100.0
-    pt.dailyCalories=val.toFixed(4);
-
-    let firstDay=Number(row.firstDay.toString());
-    val=(row.frequency*(daysDifference.value-1)+firstDay)*item.configSalePrice*Number(pt.dosePerTime);
-    val=Math.max(0,val);
-    pt.amount=Math.round(val*100)/100;
-
-    val=(row.frequency*(daysDifference.value-1)+firstDay)*Number(pt.dosePerTime);
-    val=Math.max(0,val);
-    pt.totalDose=val.toFixed(4) ;
-
-    val=row.frequency*Number(pt.dosePerTime)
-    pt.dosePerDay=val.toFixed(4) ;
-    break;
-  }
+      if (item.id.toString() != arr[0]) {
+        continue;
+      }
+
+      let val = (item.calorie * row.frequency * Number(pt.dosePerTime)) / 100.0;
+      pt.dailyCalories = val.toFixed(4);
 
-  });  
+      let firstDay = Number(row.firstDay.toString());
+      val = (row.frequency * (daysDifference.value - 1) + firstDay) * item.configSalePrice * Number(pt.dosePerTime);
+      val = Math.max(0, val);
+      pt.amount = Math.round(val * 100) / 100;
+
+      val = (row.frequency * (daysDifference.value - 1) + firstDay) * Number(pt.dosePerTime);
+      val = Math.max(0, val);
+      pt.totalDose = val.toFixed(4);
+
+      val = row.frequency * Number(pt.dosePerTime);
+      pt.dosePerDay = val.toFixed(4);
+      break;
+    }
+  });
 
-  emit('change',JSON.stringify(tableData.value));
+  emit('change', JSON.stringify(tableData.value));
 };
 
-const dosePerTimeInput = (value: string, str:string) => {
-  let arr=str.split('_');
+const dosePerTimeInput = (value: string, str: string) => {
+  let arr = str.split('_');
   let row = tableData.value[Number(arr[0])];
   let pt = row.products[Number(arr[1])];
-  if(!pt.dosePerTime||pt.dosePerTime.trim().length==0){
-    pt.dailyCalories=null;
-    pt.amount=null; 
+  if (!pt.dosePerTime || pt.dosePerTime.trim().length == 0) {
+    pt.dailyCalories = null;
+    pt.amount = null;
     return;
   }
 
-  arr=pt.nutritionProductId.split('_');
+  arr = pt.nutritionProductId.split('_');
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
-    }    
-    
-    
-    let val=item.calorie*row.frequency*Number(pt.dosePerTime)/100.0
-    pt.dailyCalories=val.toFixed(4);
-
-    let firstDay=Number(row.firstDay.toString());
-    val=(row.frequency*(daysDifference.value-1)+firstDay)*item.configSalePrice*Number(pt.dosePerTime);
-    val=Math.max(0,val);
-    pt.amount=Math.round(val*100)/100;
-
-    val=(row.frequency*(daysDifference.value-1)+firstDay)*Number(pt.dosePerTime);
-    val=Math.max(0,val);
-    pt.totalDose=val.toFixed(4) ;
-
-    val=row.frequency*Number(pt.dosePerTime)
-    pt.dosePerDay=val.toFixed(4) ;
+      continue;
+    }
+
+    let val = (item.calorie * row.frequency * Number(pt.dosePerTime)) / 100.0;
+    pt.dailyCalories = val.toFixed(4);
+
+    let firstDay = Number(row.firstDay.toString());
+    val = (row.frequency * (daysDifference.value - 1) + firstDay) * item.configSalePrice * Number(pt.dosePerTime);
+    val = Math.max(0, val);
+    pt.amount = Math.round(val * 100) / 100;
+
+    val = (row.frequency * (daysDifference.value - 1) + firstDay) * Number(pt.dosePerTime);
+    val = Math.max(0, val);
+    pt.totalDose = val.toFixed(4);
+
+    val = row.frequency * Number(pt.dosePerTime);
+    pt.dosePerDay = val.toFixed(4);
     break;
   }
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 // 禁用今天之前的日期
@@ -476,27 +506,27 @@ const disabledBeforeToday = (date) => {
   const start = new Date(prop.prescriptionDate);
   const today = new Date();
   // 设置时间为今天凌晨,确保比较的是日期而非具体时间
-  today.setHours(0, 0, 0, 0)
+  today.setHours(0, 0, 0, 0);
   today.setDate(start.getDate() + 1);
-  return date < today
-}
+  return date < today;
+};
 
 watch(
   () => prop.prescriptionDate,
   async (val: string) => {
-    if (!val || val.trim().length == 0||!stopDate.value||stopDate.value.trim().length == 0) {
+    if (!val || val.trim().length == 0 || !stopDate.value || stopDate.value.trim().length == 0) {
       return;
     }
 
     const end = new Date(stopDate.value);
     const start = new Date(prop.prescriptionDate);
-    if(start>=end){
-      stopDate.value='';
-    }else{
+    if (start >= end) {
+      stopDate.value = '';
+    } else {
       handleStopDateChange(stopDate.value);
-    }    
+    }
   },
-  { deep: true, immediate: true }
+  {deep: true, immediate: true}
 );
 
 const handleStopDateChange = (dateVal: any) => {
@@ -507,29 +537,28 @@ const handleStopDateChange = (dateVal: any) => {
   // 计算时间差(毫秒)
   const timeDifference = end.getTime() - start.getTime();
 
-  // 将毫秒差转换为天数差  
+  // 将毫秒差转换为天数差
   daysDifference.value = timeDifference / (1000 * 60 * 60 * 24) + 1;
   if (daysDifference.value <= 0) {
     daysDifference.value = 0;
     stopDate.value = '';
   }
 
-  tableData.value.forEach(item=>{
-    item.stopDate=stopDate.value;
-    item.prescriptionDate=prop.prescriptionDate;
-    item.usageDays=daysDifference.value;
+  tableData.value.forEach((item) => {
+    item.stopDate = stopDate.value;
+    item.prescriptionDate = prop.prescriptionDate;
+    item.usageDays = daysDifference.value;
   });
 
-  emit('change',JSON.stringify(tableData.value));
-}
-
+  emit('change', JSON.stringify(tableData.value));
+};
 
-onMounted(() => { 
+onMounted(() => {
   getProductNutritionList();
-  tableData.value.forEach(item=>{
-    item.stopDate=stopDate.value;
-    item.prescriptionDate=prop.prescriptionDate;
-    item.usageDays=daysDifference.value;
+  tableData.value.forEach((item) => {
+    item.stopDate = stopDate.value;
+    item.prescriptionDate = prop.prescriptionDate;
+    item.usageDays = daysDifference.value;
   });
 });
 </script>

+ 379 - 147
src/views/patients/enteralNutrition/components/table/PackageTable.vue

@@ -5,10 +5,9 @@
       <el-table-column label="营养产品" min-width="300">
         <template #default="{row}">
           <div class="product-group">
-            <div  class="product-row" style="margin-bottom:5px;">
+            <div class="product-row" style="margin-bottom: 5px">
               <el-select v-model="row.nutritionProductId" placeholder="请选择" @change="changeProductSelect">
-                <el-option v-for="pn in productNutritionList" :key="pn.id" :label="pn.productName"
-                  :value="pn.id+'_'+row.sn"></el-option>
+                <el-option v-for="pn in productNutritionList" :key="pn.id" :label="pn.productName" :value="pn.id + '_' + row.sn"></el-option>
               </el-select>
 
               <div class="action-buttons">
@@ -26,8 +25,8 @@
       <el-table-column label="数量" width="150" align="center">
         <template #default="{row}">
           <div class="quantity-group">
-            <div  class="quantity-input">
-              <el-input v-model="row.quantity" placeholder="请输入" class="input-center" @change="changeQuantityInput"/>
+            <div class="quantity-input">
+              <el-input v-model="row.quantity" placeholder="请输入" class="input-center" @change="changeQuantityInput" />
               <span class="unit">袋</span>
             </div>
           </div>
@@ -36,8 +35,8 @@
       <el-table-column label="用量/次" width="150" align="center">
         <template #default="{row}">
           <div class="dosage-group">
-            <div  class="dosage-input">
-              <el-input v-model="row.dosePerTime" placeholder="请输入" class="input-center" @input="dosePerTimeInput(row.dosePerTime,row.sn)"/>
+            <div class="dosage-input">
+              <el-input v-model="row.dosePerTime" placeholder="请输入" class="input-center" @input="dosePerTimeInput(row.dosePerTime, row.sn)" />
               <span class="unit">g</span>
             </div>
           </div>
@@ -48,42 +47,72 @@
           <div class="time-slots">
             <div class="time-row">
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[0].checked" @change="changeTimeSelection(row.timeSlots[0].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[0].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[0].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[0].checked" @change="changeTimeSelection(row.timeSlots[0].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[0].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[0].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[1].checked" @change="changeTimeSelection(row.timeSlots[1].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[1].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[1].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[1].checked" @change="changeTimeSelection(row.timeSlots[1].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[1].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[1].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[2].checked" @change="changeTimeSelection(row.timeSlots[2].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[2].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[2].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[2].checked" @change="changeTimeSelection(row.timeSlots[2].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[2].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[2].checked"
+                />
               </div>
             </div>
             <div class="time-row">
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[3].checked" @change="changeTimeSelection(row.timeSlots[3].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[3].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[3].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[3].checked" @change="changeTimeSelection(row.timeSlots[3].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[3].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[3].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[4].checked" @change="changeTimeSelection(row.timeSlots[4].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[4].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[4].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[4].checked" @change="changeTimeSelection(row.timeSlots[4].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[4].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[4].checked"
+                />
               </div>
               <div class="time-group">
-                <el-checkbox v-model="row.timeSlots[5].checked" @change="changeTimeSelection(row.timeSlots[5].checked,row.sn)"/>
-                <el-time-select v-model="row.timeSlots[5].time" start="00:00" step="00:30" end="23:30"
-                  placeholder="选择时间" :disabled="!row.timeSlots[5].checked" 
-                  />
+                <el-checkbox v-model="row.timeSlots[5].checked" @change="changeTimeSelection(row.timeSlots[5].checked, row.sn)" />
+                <el-time-select
+                  v-model="row.timeSlots[5].time"
+                  start="00:00"
+                  step="00:30"
+                  end="23:30"
+                  placeholder="选择时间"
+                  :disabled="!row.timeSlots[5].checked"
+                />
               </div>
             </div>
           </div>
@@ -91,12 +120,12 @@
       </el-table-column>
       <el-table-column label="频次" width="120" align="center">
         <template #default="{row}">
-          <span>一天{{row.frequency}}次</span>
+          <span>一天{{ row.frequency }}次</span>
         </template>
       </el-table-column>
       <el-table-column label="首日" width="150" align="center">
         <template #default="{row}">
-          <el-input v-model="row.firstDay" @input="firstDayInput(row.firstDay,row.sn)">
+          <el-input v-model="row.firstDay" @input="firstDayInput(row.firstDay, row.sn)">
             <template #append>次</template>
           </el-input>
         </template>
@@ -104,54 +133,53 @@
       <el-table-column label="用量/日" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage">
-            <span>{{row.dosePerDay }}</span>
-            <span class="unit">{{ row.productSpecUnit }}</span> 
+            <span>{{ row.dosePerDay }}</span>
+            <span class="unit">{{ row.productSpecUnit }}</span>
           </div>
         </template>
       </el-table-column>
       <el-table-column label="使用天数" width="200" align="center">
         <template #default="{row}">
           <div class="daily-size">
-            <el-input-number v-model="row.usageDays" :min="1" @change="changeUsageDays(row.usageDays,row.sn)"/>
+            <el-input-number v-model="row.usageDays" :min="1" @change="changeUsageDays(row.usageDays, row.sn)" />
           </div>
         </template>
       </el-table-column>
 
       <el-table-column label="规格" width="100" align="center">
         <template #default="{row}">
-          <div class="daily-dosage"  >
-            <span>{{row.specification }}</span>             
+          <div class="daily-dosage">
+            <span>{{ row.specification }}</span>
           </div>
         </template>
       </el-table-column>
 
       <el-table-column label="用法" width="150" align="center">
         <template #default="{row}">
-          <el-select v-model="row.usage" placeholder="请选择" @change="changeUsage(row.usage,row.sn)">
-            <el-option v-for="dict in default_usage" :key="dict.value" :label="dict.label"
-              :value="dict.value"></el-option>
+          <el-select v-model="row.usage" placeholder="请选择" @change="changeUsage(row.usage, row.sn)">
+            <el-option v-for="dict in default_usage" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
           </el-select>
         </template>
       </el-table-column>
 
       <el-table-column label="处方备注" width="200" align="center">
         <template #default="{row}">
-          <el-input v-model="row.prescriptionRemark" :maxlength="100" :show-word-limit="true" @change="changePrescriptionRemark(row.usage,row.sn)"/>         
+          <el-input v-model="row.prescriptionRemark" :maxlength="100" :show-word-limit="true" @change="changePrescriptionRemark(row.usage, row.sn)" />
         </template>
       </el-table-column>
 
       <el-table-column label="每日热量" width="100" align="center">
         <template #default="{row}">
           <div class="daily-dosage">
-            <span>{{row.dailyCalories }}</span>             
+            <span>{{ row.dailyCalories }}</span>
           </div>
         </template>
       </el-table-column>
 
       <el-table-column label="金额" width="100" align="center">
-        <template #default="{row}"> 
-          <div class="daily-dosage"  >
-            <span>{{row.amount }}</span>
+        <template #default="{row}">
+          <div class="daily-dosage">
+            <span>{{ row.amount }}</span>
           </div>
         </template>
       </el-table-column>
@@ -177,13 +205,13 @@
       <div class="left-buttons">
         <el-button type="primary" plain>存为个人模板</el-button>
         <el-button type="primary" plain>批量添加营养品</el-button>
-        <el-button type="primary" plain>处方模板</el-button>
+        <el-button type="primary" plain @click="openPreTemplate()">处方模板</el-button>
       </div>
       <div class="right-summary">
         <div class="summary-list">
           <div class="summary-item">
             <span class="label">处方费用:</span>
-            <span class="value">¥{{ nutritionalFee}}</span>
+            <span class="value">¥{{ nutritionalFee }}</span>
           </div>
           <div class="summary-item total">
             <span class="label">总计:</span>
@@ -193,33 +221,136 @@
       </div>
     </div>
   </div>
+
+  <!-- 处方模板弹窗 -->
+  <el-dialog v-model="dialogVisible" title="选择处方模板" width="60%" :close-on-click-modal="false" class="template-dialog">
+    <!-- 提示信息 -->
+    <div class="tip-box">如部分模版未显示请检查预包装库位产品库存,无库存则含该产品的协定方模板将不再显示</div>
+
+    <div class="search-box">
+      <el-input v-model="searchValue" placeholder="请输入名称" class="search-input">
+        <template #append>
+          <el-button type="primary">查询</el-button>
+        </template>
+      </el-input>
+    </div>
+
+    <div class="dialog-content">
+      <!-- 左侧单选框区域 -->
+      <div class="left-panel">
+        <el-radio-group v-model="selectedTemplate" direction="vertical" @change="handleTemplateChange">
+          <el-radio label="基础公共模版">基础公共模版</el-radio>
+          <el-radio label="个人模版">个人模版</el-radio>
+        </el-radio-group>
+      </div>
+
+      <!-- 右侧表格区域 -->
+      <div class="right-panel">
+        <table class="custom-table">
+          <thead>
+            <tr>
+              <th>产品名称</th>
+              <th width="120">数量</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr v-for="(item, index) in templateTableData" :key="index">
+              <td>{{ item.productName }}</td>
+              <td>{{ item.dosePerTime }}{{ item.unit }}</td>
+            </tr>
+            <tr v-if="templateTableData.length === 0">
+              <td colspan="3" class="no-data">暂无数据</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <div class="selected-info">
+      <span class="selected-count">已选 ({{ selectedCount }})</span>
+    </div>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleConfirm">确定</el-button>
+      </span>
+    </template>
+  </el-dialog>
 </template>
 
 <script setup lang="ts">
 import {ref} from 'vue';
 import {Plus, Delete, CirclePlus} from '@element-plus/icons-vue';
-import { listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition } from '@/api/patients/nutrition';
-import { EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm } from '@/api/patients/nutrition/types';
-import { listNutrition, listAllNutrition  } from '@/api/warehouse/productNutrition/index';
-import { NutritionVO, NutritionQuery, NutritionForm } from '@/api/warehouse/productNutrition/types';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { default_usage } = toRefs < any > (proxy ?.useDict('default_usage'));
-
+import {listEnteralNutrition, getEnteralNutrition, delEnteralNutrition, addEnteralNutrition, updateEnteralNutrition} from '@/api/patients/nutrition';
+import {EnteralNutritionVO, EnteralNutritionQuery, EnteralNutritionForm} from '@/api/patients/nutrition/types';
+import {listNutrition, listAllNutrition} from '@/api/warehouse/productNutrition/index';
+import {NutritionVO, NutritionQuery, NutritionForm} from '@/api/warehouse/productNutrition/types';
+
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {default_usage} = toRefs<any>(proxy?.useDict('default_usage'));
+
+let productNutritionList = ref<NutritionVO[]>([]);
+let tableId = ref<number>(0);
+
+let nutritionalFee = ref(0.0);
+let totalFee = ref(0.0);
+
+// 弹窗显示控制
+const dialogVisible = ref(false);
+
+// 搜索值
+const searchValue = ref('');
+
+// 选中的模板
+const selectedTemplate = ref('基础公共模版');
+
+// 已选数量
+const selectedCount = ref(0);
+
+// 添加单选框选择变化处理方法
+const handleTemplateChange = (value) => {
+  console.log('选中的模板类型:', value);
+  // value 就是选中的值:"基础公共模版" 或 "个人模版"
+
+  // 根据选择更新右侧表格数据
+  if (value === '基础公共模版') {
+    templateTableData.value = [
+      {productName: '基础产品1', dosePerTime: '5.0000', unit: 'g'},
+      {productName: '基础产品2', dosePerTime: '1.0000', unit: '袋'},
+      {productName: '基础产品2', dosePerTime: '1.0000', unit: '袋'},
+      {productName: '基础产品2', dosePerTime: '1.0000', unit: '袋'}
+    ];
+    selectedCount.value = templateTableData.value.length;
+  } else if (value === '个人模版') {
+    templateTableData.value = [
+      {productName: '个人产品1', dosePerTime: '3.0000', unit: 'g'},
+      {productName: '个人产品2', dosePerTime: '2.0000', unit: '袋'}
+    ];
+    selectedCount.value = templateTableData.value.length;
+  }
+};
 
-let productNutritionList=ref<NutritionVO[]>([]);
-let tableId=ref<number>(0);
- 
-let nutritionalFee=ref(0.0); 
-let totalFee=ref(0.0);
+// 模板表格数据
+const templateTableData = ref([
+  {
+    productName: '氨基酸型复配营养粉1',
+    dosePerTime: '5.0000',
+    unit: 'g'
+  },
+  {
+    productName: '肠内营养专用配置袋',
+    dosePerTime: '1.0000',
+    unit: '袋'
+  }
+]);
 
 interface TimeSlot {
   checked: boolean;
   time: string;
-} 
-
+}
 
-interface TableRow  extends EnteralNutritionForm {
+interface TableRow extends EnteralNutritionForm {
   products: EnteralNutritionForm[];
   timeSlots: TimeSlot[];
   sn: number;
@@ -228,7 +359,7 @@ interface TableRow  extends EnteralNutritionForm {
 
 // 创建默认行数据
 const createDefaultRow = (): TableRow => ({
-  products: [{specification:'', dosePerDay:''}],
+  products: [{specification: '', dosePerDay: ''}],
   timeSlots: [
     {checked: true, time: '08:00'},
     {checked: false, time: '08:30'},
@@ -237,16 +368,16 @@ const createDefaultRow = (): TableRow => ({
     {checked: true, time: '18:00'},
     {checked: false, time: '18:30'}
   ],
-  usageDays:1,
-  frequency:3,
-  firstDay:2,
-  sn:0,
-  tableId:tableId.value++,
+  usageDays: 1,
+  frequency: 3,
+  firstDay: 2,
+  sn: 0,
+  tableId: tableId.value++
 });
 
 // 表格数据
 const tableData = ref<TableRow[]>([createDefaultRow()]);
-const emit = defineEmits(['change']); 
+const emit = defineEmits(['change']);
 
 // 添加产品输入框
 const addProduct = (row: TableRow) => {
@@ -261,51 +392,47 @@ const deleteProduct = (row: TableRow, index: number) => {
     if (rowIndex !== -1) {
       tableData.value.splice(rowIndex, 1);
     }
-    totalFee.value=0.0;
-    nutritionalFee.value=0.0;
+    totalFee.value = 0.0;
+    nutritionalFee.value = 0.0;
   } else {
     // 否则只删除当前输入框
     row.products.splice(index, 1);
   }
 };
 
- 
-
 // 删除行
 const deleteRow = (index: number) => {
   tableData.value.splice(index, 1);
   tableData.value.forEach((item, index) => {
     item.sn = index;
-  });   
+  });
 
-  if(tableData.value.length==0){
-    totalFee.value=0.0;
-    nutritionalFee.value=0.0;
+  if (tableData.value.length == 0) {
+    totalFee.value = 0.0;
+    nutritionalFee.value = 0.0;
   }
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
 // 添加行
 const addRow = () => {
   let row: TableRow = createDefaultRow();
-  row.sn = tableData.value.length ;
-  tableData.value.push(row);  
-  emit('change',JSON.stringify(tableData.value))
+  row.sn = tableData.value.length;
+  tableData.value.push(row);
+  emit('change', JSON.stringify(tableData.value));
 };
 
-
-
 const getProductNutritionList = async () => {
   const res = await listAllNutrition();
   productNutritionList.value = res.rows;
-}
+};
 
 const changeQuantityInput = async () => {
-  emit('change',JSON.stringify(tableData.value));
-}
+  emit('change', JSON.stringify(tableData.value));
+};
 
-const dosePerTimeInput = (value: string, sn: number) => {  
+const dosePerTimeInput = (value: string, sn: number) => {
   let row = tableData.value[sn];
 
   if (!row.dosePerTime || row.dosePerTime.trim().length == 0) {
@@ -314,126 +441,128 @@ const dosePerTimeInput = (value: string, sn: number) => {
     return;
   }
 
-  totalFee.value=0.0;
-  nutritionalFee.value=0.0;
+  totalFee.value = 0.0;
+  nutritionalFee.value = 0.0;
 
   let arr = row.nutritionProductId.split('_');
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
+      continue;
     }
 
-
-    let val = item.calorie * row.frequency * Number(row.dosePerTime) / 100.0
+    let val = (item.calorie * row.frequency * Number(row.dosePerTime)) / 100.0;
     row.dailyCalories = val.toFixed(4);
 
-    let  firstDay=Number(row.firstDay.toString());
-    val = (row.frequency * (row.usageDays - 1) + firstDay) * item.configSalePrice * Number(row.dosePerTime)
+    let firstDay = Number(row.firstDay.toString());
+    val = (row.frequency * (row.usageDays - 1) + firstDay) * item.configSalePrice * Number(row.dosePerTime);
     row.amount = Math.round(val * 100) / 100;
-    totalFee.value+=row.amount;
-    nutritionalFee.value+=row.amount;
+    totalFee.value += row.amount;
+    nutritionalFee.value += row.amount;
 
-    val = row.frequency * Number(row.dosePerTime)
+    val = row.frequency * Number(row.dosePerTime);
     row.dosePerDay = val.toFixed(4);
     break;
   }
 
-  emit('change', JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
-
 const changeProductSelect = async (id: string) => {
-  let arr=id.split('_');
+  let arr = id.split('_');
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
+      continue;
     }
-    
+
     let row = tableData.value[Number(arr[1])];
     row.specification=item.productSpec;
     row.dosePerTime=null;     
     row.dailyCalories=null;
     row.amount=null; 
-    row.productSpecUnit=item.productSpecUnit;         
-    if(!row.usage){
-      row.usage=item.defaultUsage;
-    }  
+    row.productSpecUnit=item.productSpecUnit;
+    row.usage=item.defaultUsage;     
     row.dosePerDay='0';
     row.firstDay=Math.ceil(row.frequency/2.0);
     break;
   }
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
-const changeUsageDays = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const changeUsageDays = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const changeUsage = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const changeUsage = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const changePrescriptionRemark = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);
-}
+const changePrescriptionRemark = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const firstDayInput = (value: string, sn:string) => { 
-  changeTimeSelection(null,sn);    
-}
+const firstDayInput = (value: string, sn: string) => {
+  changeTimeSelection(null, sn);
+};
 
-const changeTimeSelection = (value: string, sn:string) => {
+const changeTimeSelection = (value: string, sn: string) => {
   let row = tableData.value[sn];
-  let frequency=0;  
-  row.timeSlots.forEach(item=>{
-    if(item.checked){
+  let frequency = 0;
+  row.timeSlots.forEach((item) => {
+    if (item.checked) {
       frequency++;
     }
-  })
-  row.frequency=frequency;
-   
-  if(value!=null){
-    row.firstDay=Math.ceil(row.frequency/2.0);
-  }  
+  });
+  row.frequency = frequency;
+
+  if (value != null) {
+    row.firstDay = Math.ceil(row.frequency / 2.0);
+  }
 
   if (!row.dosePerTime || row.dosePerTime.trim().length == 0) {
     return;
   }
 
-  totalFee.value=0.0;
-  nutritionalFee.value=0.0;
-  let arr=row.nutritionProductId.split('_');
+  totalFee.value = 0.0;
+  nutritionalFee.value = 0.0;
+  let arr = row.nutritionProductId.split('_');
 
   for (let item of productNutritionList.value) {
     if (item.id.toString() != arr[0]) {
-      continue
+      continue;
     }
 
-
-    let val = item.calorie * row.frequency * Number(row.dosePerTime) / 100.0
+    let val = (item.calorie * row.frequency * Number(row.dosePerTime)) / 100.0;
     row.dailyCalories = val.toFixed(4);
 
-    let firstDay=Number(row.firstDay.toString());
-    val = (row.frequency * (row.usageDays - 1) + firstDay) * item.configSalePrice * Number(row.dosePerTime)
-     
+    let firstDay = Number(row.firstDay.toString());
+    val = (row.frequency * (row.usageDays - 1) + firstDay) * item.configSalePrice * Number(row.dosePerTime);
+
     row.amount = Math.round(val * 100) / 100;
-    totalFee.value+=row.amount;
-    nutritionalFee.value+=row.amount;
+    totalFee.value += row.amount;
+    nutritionalFee.value += row.amount;
 
-    val = row.frequency * Number(row.dosePerTime)
+    val = row.frequency * Number(row.dosePerTime);
     row.dosePerDay = val.toFixed(4);
     break;
   }
- 
 
-  emit('change',JSON.stringify(tableData.value))
+  emit('change', JSON.stringify(tableData.value));
 };
 
+// 预包装的处方模板
+const openPreTemplate = () => {
+  dialogVisible.value = true;
+};
 
-onMounted(() => { 
+// 确认选择模板
+const handleConfirm = () => {
+  dialogVisible.value = false;
+  // 这里处理选中模板后的逻辑
+};
+onMounted(() => {
   getProductNutritionList();
 });
-
 </script>
 
 <style lang="scss" scoped>
@@ -671,4 +800,107 @@ onMounted(() => {
     }
   }
 }
+
+.template-dialog {
+  :deep(.el-dialog__body) {
+    padding: 0 20px;
+  }
+
+  .tip-box {
+    background-color: #e6f7ff;
+    padding: 12px 16px;
+    color: #606266;
+    font-size: 14px;
+    margin-bottom: 16px;
+  }
+
+  .search-box {
+    margin-bottom: 16px;
+
+    .search-input {
+      width: 300px;
+    }
+  }
+
+  .dialog-content {
+    display: flex;
+    gap: 20px;
+    min-height: 400px;
+    border: 1px solid #ebeef5;
+
+    .left-panel {
+      width: 200px;
+      padding: 20px;
+      border-right: 1px solid #ebeef5;
+
+      :deep(.el-radio-group) {
+        display: flex;
+        gap: 16px;
+      }
+
+      :deep(.el-radio) {
+        margin-right: 0;
+        height: auto;
+
+        .el-radio__label {
+          font-size: 14px;
+          color: #606266;
+        }
+      }
+    }
+
+    .right-panel {
+      flex: 1;
+      padding: 16px;
+      overflow: auto;
+    }
+  }
+
+  .selected-info {
+    margin: 16px 0;
+
+    .selected-count {
+      color: #409eff;
+      font-size: 14px;
+    }
+  }
+
+  :deep(.el-dialog__footer) {
+    padding: 16px 20px;
+    border-top: 1px solid #ebeef5;
+  }
+}
+
+.custom-table {
+  width: 100%;
+  border-collapse: collapse;
+  border: 1px solid #ebeef5;
+
+  th,
+  td {
+    padding: 12px 8px;
+    border: 1px solid #ebeef5;
+    text-align: center;
+    font-size: 14px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  th {
+    background-color: #f5f7fa;
+    color: #303133;
+    font-weight: 600;
+  }
+
+  tbody tr:hover {
+    background-color: #f5f7fa;
+  }
+
+  .no-data {
+    color: #909399;
+    text-align: center;
+    padding: 40px;
+  }
+}
 </style>

+ 4 - 6
src/views/patients/enteralNutrition/history.vue

@@ -1,21 +1,19 @@
 <template>
   <div class="history-container">
-    <LeftCard />
-    <RightCard  @goBack="goBack"/>
+    <LeftCard :patientInfo="patientInfo" />
+    <RightCard @goBack="goBack" />
   </div>
 </template>
 
 <script setup lang="ts">
 import LeftCard from './components/history/LeftCard.vue';
 import RightCard from './components/history/RightCard.vue';
-const { patientInfo } = defineProps<{ patientInfo: any }>()
-
+const {patientInfo} = defineProps<{patientInfo: any}>();
 
 const emit = defineEmits(['change']);
 const goBack = () => {
-  emit('change','enteralNutrition')
+  emit('change', 'enteralNutrition');
 };
-
 </script>
 
 <style lang="scss" scoped>

+ 3 - 4
src/views/patients/enteralNutrition/index.vue

@@ -2,7 +2,7 @@
   <div class="container">
     <div class="main-content">
       <!-- 左侧卡片 -->
-      <LeftCard  @gotoTop="goHistoryPrescription" :patientInfo="patientInfo"/>
+      <LeftCard @gotoTop="goHistoryPrescription" :patientInfo="patientInfo" />
       <!-- 右侧卡片 -->
       <RightCard />
     </div>
@@ -13,14 +13,13 @@
 import LeftCard from './components/LeftCard.vue';
 import RightCard from './components/RightCard.vue';
 
-const { patientInfo } = defineProps<{ patientInfo: any }>()
+const {patientInfo} = defineProps<{patientInfo: any}>();
 // 解决bug核心
 const emit = defineEmits(['change']);
 
 const goHistoryPrescription = () => {
-  emit('change', 'enteralNutritionHistory')
+  emit('change', 'enteralNutritionHistory');
 };
-
 </script>
 
 <style lang="scss" scoped>

+ 72 - 8
src/views/patients/evaluation/add.vue

@@ -3,11 +3,14 @@
     <el-card>
       <!-- 新增顶部操作栏 -->
       <el-row>
-        <el-col :span="4">
-          <el-button type="primary" plain @click="close" style="margin-right: 20px;margin-left: 30px;">返回</el-button>
-          <span style="font-size: 14px;  vertical-align: middle;">{{ screeningName }}</span>
+        <el-col :span="1" style="margin-right: 10px;">
+          <el-button type="primary" plain @click="close" >返回</el-button>           
+        </el-col>         
+        <el-col :span="22">           
+          <span style="font-size: 14px; vertical-align: middle">{{ screeningName }}</span>
+          <div style="font-size: 14px; vertical-align: middle">来源:{{ sourceName }}</div>          
         </el-col>
-      </el-row>
+      </el-row> 
     </el-card>
 
     <el-card>
@@ -423,6 +426,40 @@
           </div>
         </template>
         <!-- 其他:人体测量、膳食状况、营养生化检查 -->
+
+
+        <!--通过文件导入的输入框 -->
+      <template v-if="item.questionType=='inputBox'">
+        <div style="margin-bottom: 10px; padding-top: 20px;" class="zebra-row">
+          <el-row>
+            <el-col :span="24">
+              <span style="color: #f56c6c; margin-right: 4px;">*</span>
+              <span style="font-weight: bold;">{{idx + 1 + (form.baseInfo&&form.baseInfo.contentList&&form.baseInfo.contentList.length>0?1:0) +'. '+ item.title }}</span>
+            </el-col>
+          </el-row>
+          <el-row style="margin-bottom: 20px;margin-top: 8px;">
+            <el-col :span="24">
+              <el-form :inline="true" label-width="100px">
+                <el-form-item>
+                  <template v-if="item.questionChildType=='inputNumber'">
+                    <el-input clearable v-model="item.value" :disabled="isView" type="number" @change="changeInputNumber"/>
+                  </template>
+                  <template v-else-if="item.questionChildType=='inputText'">
+                    <el-input  v-model="item.value" :disabled="isView" />
+                  </template>
+                  <template v-else-if="item.questionChildType=='calculated'">
+                    <el-input  v-model="item.value" :disabled="true" />
+                  </template>
+                  <template v-else>
+                    <el-input  v-model="item.value" :disabled="isView" />
+                  </template>
+                  </el-form-item>
+              </el-form>
+            </el-col>
+          </el-row>
+        </div>
+      </template>
+      <!--通过文件导入的输入框 -->
       </template>
     </el-card>
 
@@ -451,6 +488,7 @@ let paramForm = ref<EvaluationForm>({});
  
 
 const screeningName = ref(''); 
+const sourceName = ref('');
 const { patientInfo } = defineProps<{ patientInfo: any }>()
 const emit = defineEmits(['change'])
 let form=ref<ScreeningAssessmentConfigForm>({});   
@@ -469,11 +507,13 @@ const getList = async () => {
         const res =await getEvaluation(id as string);
         const content =JSON.parse(res.data.content);
         screeningName.value = content.name;
+        sourceName.value = content.source;
         Object.assign(form.value, content);
     } else {
         isView.value = false;
         const res = await getScreeningAssessmentConfig(id as string);
         screeningName.value = res.data.name;
+        sourceName.value = res.data.source;
         Object.assign(form.value, res.data);
     }
 }
@@ -538,8 +578,8 @@ const submitForm = async () => {
         }
     }
 
-  buttonLoading.value = true;
-  paramForm.value.content = JSON.stringify(form.value);
+  buttonLoading.value = true; 
+  paramForm.value.content =window.btoa(encodeURI(JSON.stringify(form.value))) ;
   if (paramForm.value.id) {
     await updateEvaluation(paramForm.value).finally(() => buttonLoading.value = false);
   } else {
@@ -575,8 +615,32 @@ const selectScaleQuestions = async (idx:number, n:number) => {
     }
 }
 
-
-
+const changeInputNumber = async (val:number) => {  
+  let conclusion=form.value.conclusion;
+  if(!conclusion||conclusion.length<=0){
+    return;
+  }
+  let conclusionObj=JSON.parse(conclusion); 
+  let formula=conclusionObj.formula;
+  if(!formula||formula.length<=0){ 
+    return;
+  }   
+  let arr=formula.split(/[;;]+/);
+  formula=arr[0].toString();
+  let otherInfo=form.value.otherInfo;  
+
+  let argArr=[];
+  otherInfo.forEach(item=>{
+    arr=item.title.split(/[\\((]+/);
+    if(formula.indexOf(arr[0])>=0){
+      formula=formula.replaceAll(arr[0],'Q'+item.qid);
+      argArr.push('Q'+item.qid+'='+item.value);
+    }
+    
+    
+    console.log( argArr,'++++++++++++++++++',formula);
+  });
+}
 
 onMounted(() => {
   paramForm.value.patientId=patientInfo.id;

+ 5 - 0
src/views/patients/evaluation/index.vue

@@ -307,5 +307,10 @@ onMounted(() => {
   font-size: 16px;
   height: 48px;
   border-radius: 8px;  
+  white-space: normal;
+    word-wrap: break-word;
+    text-align: center;
+    line-height: 1.2;
+    padding: 8px 12px;
 }
 </style>

+ 575 - 0
src/views/patients/hospitalRecord/index.vue

@@ -0,0 +1,575 @@
+<template>
+  <div class="hospital-record-layout">
+    <!-- 顶部搜索区域 -->
+    <div class="top-search">
+      <div class="search-container">
+        <!-- 日期范围 -->
+        <div class="search-item">
+          <el-date-picker
+            v-model="dateRange"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="2024-11-19"
+            end-placeholder="2025-07-30"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            size="default"
+            style="width: 280px"
+          />
+        </div>
+
+        <!-- 科室 -->
+        <div class="search-item">
+          <span class="search-label">科室</span>
+          <el-select v-model="selectedDept" placeholder="请选择" clearable style="width: 120px">
+            <el-option label="口腔科" value="oral" />
+            <el-option label="营养科" value="nutrition" />
+            <el-option label="内科" value="internal" />
+          </el-select>
+        </div>
+
+        <!-- 就诊类型 -->
+        <div class="search-item">
+          <span class="search-label">就诊类型</span>
+          <el-select v-model="visitType" placeholder="请选择" clearable style="width: 120px">
+            <el-option label="门诊" value="outpatient" />
+            <el-option label="住院" value="inpatient" />
+          </el-select>
+        </div>
+
+        <!-- 搜索框 -->
+        <div class="search-item">
+          <el-input v-model="searchKeyword" placeholder="姓名/姓名/门诊号/住院号" style="width: 200px" />
+        </div>
+
+        <!-- 按钮组 -->
+        <div class="search-buttons">
+          <el-button type="primary">查询</el-button>
+          <el-button>重置</el-button>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主体内容区域 -->
+    <div class="main-content">
+      <!-- 左侧时间线区域 -->
+      <div class="left-timeline">
+        <!-- 左侧虚线 -->
+        <div class="timeline-line"></div>
+
+        <div class="timeline-content">
+          <!-- 日期节点 -->
+          <div class="timeline-node date-node">
+            <div class="node-marker">1</div>
+            <div class="node-content">
+              <div class="date-label">2024-11-19</div>
+            </div>
+          </div>
+
+          <!-- 口腔科形节点 -->
+          <div class="timeline-node normal-node">
+            <div class="node-content">
+              <div class="record-header">
+                <span class="record-type">口腔矫形</span>
+                <span class="doctor-info">主管医生:系统管理员</span>
+              </div>
+            </div>
+          </div>
+
+          <!-- 营养筛查节点(蓝色标记) -->
+          <div class="timeline-node active-node">
+            <div class="node-blue-marker active"></div>
+            <div class="node-content">
+              <div class="record-type active">营养筛查</div>
+
+              <div class="record-list">
+                <div class="record-item">
+                  <div class="record-time">2025-07-07 17:57:07</div>
+                  <div class="record-doctor">筛查医生/护士:yingpai</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>1.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-07-07 17:53:39</div>
+                  <div class="record-doctor">筛查医生/护士:yingpai</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>0.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-05-27 10:34:40</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>4.00分,患者存在营养风险,开始制定营养支持/治疗计划</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-01-03 10:35:09</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>2.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-01-03 10:35:09</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>2.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-01-03 10:35:09</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>2.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-01-03 10:35:09</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>2.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-01-03 10:35:09</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>2.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2025-01-03 10:35:09</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>2.00分,每周复查营养风险筛查</div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2024-11-19 09:24:56</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail">
+                    <strong>营养不良筛查工具(MUST):</strong
+                    >4.00分,患者风险:治疗转介营养师。营养师方案评估应动用处方规划程序,监测和审视营养支持计划;除非营养师常规临床检查:护理营养支持,但若病房没有住院,请与医院营养小区安排一次,护理之后和社区每月一次。
+                  </div>
+                </div>
+
+                <div class="record-item">
+                  <div class="record-time">2024-11-19 09:24:50</div>
+                  <div class="record-doctor">筛查医生/护士:系统管理员</div>
+                  <div class="record-detail"><strong>NRS2002营养风险筛查:</strong>3.00分,患者存在营养风险,开始制定营养支持/治疗计划</div>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <!-- 营养评估节点 -->
+          <div class="timeline-node normal-node">
+            <div class="node-blue-marker"></div>
+            <div class="node-content">
+              <div class="record-type">营养评估</div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 右侧导航区域 -->
+      <div class="right-navigation">
+        <el-timeline>
+          <el-timeline-item v-for="(navItem, index) in navigationItems" :key="index" :type="navItem.active ? 'primary' : 'info'" size="normal">
+            <div class="nav-timeline-content" :class="{active: navItem.active}" @click="handleNavClick(navItem.key)">
+              <span class="nav-title">{{ navItem.label }}</span>
+            </div>
+          </el-timeline-item>
+        </el-timeline>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts" name="HospitalRecord">
+import {ref} from 'vue';
+
+// 响应式数据
+const dateRange = ref(['2024-11-19', '2025-07-30']);
+const selectedDept = ref('');
+const visitType = ref('');
+const searchKeyword = ref('');
+
+// 右侧导航数据
+const navigationItems = ref([
+  {
+    key: 'screening',
+    label: '营养筛查',
+    active: false
+  },
+  {
+    key: 'evaluation',
+    label: '营养评估',
+    active: false
+  },
+  {
+    key: 'diagnosis',
+    label: '营养诊断',
+    active: false
+  },
+  {
+    key: 'prescription',
+    label: '营养处方',
+    active: true
+  },
+  {
+    key: 'meal',
+    label: '营养膳食',
+    active: false
+  }
+]);
+
+// 导航点击处理
+const handleNavClick = (key: string) => {
+  // 重置所有项的激活状态
+  navigationItems.value.forEach((item) => {
+    item.active = false;
+  });
+
+  // 设置当前点击项为激活状态
+  const currentItem = navigationItems.value.find((item) => item.key === key);
+  if (currentItem) {
+    currentItem.active = true;
+  }
+
+  console.log('导航切换到:', key);
+  // 这里可以添加具体的页面切换逻辑
+};
+</script>
+
+<style lang="scss" scoped>
+.hospital-record-layout {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background: #f5f5f5;
+
+  .top-search {
+    background: white;
+    padding: 16px 20px;
+    .search-container {
+      display: flex;
+      align-items: center;
+      flex-wrap: nowrap;
+      gap: 60px;
+
+      .search-item {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+        flex-shrink: 0;
+
+        .search-label {
+          font-size: 14px;
+          color: #606266;
+          white-space: nowrap;
+        }
+      }
+
+      .search-buttons {
+        display: flex;
+        gap: 8px;
+        margin-left: auto;
+        flex-shrink: 0;
+      }
+    }
+  }
+
+  .main-content {
+    flex: 1;
+    display: flex;
+    overflow: hidden;
+
+    .left-timeline {
+      flex: 1;
+      background: white;
+      overflow-y: auto;
+      padding: 20px;
+      border-right: 1px solid #e4e7ed;
+      position: relative;
+
+      .timeline-line {
+        position: absolute;
+        left: 40px;
+        top: 0;
+        height: 100%;
+        width: 0;
+        border-left: 2px dashed #d0d7de;
+        z-index: 1;
+      }
+
+      .timeline-content {
+        position: relative;
+        z-index: 2;
+      }
+
+      .timeline-node {
+        position: relative;
+        margin-bottom: 16px;
+
+        &:last-child {
+          margin-bottom: 0;
+        }
+
+        .node-marker {
+          position: absolute;
+          left: 6px;
+          top: -4px;
+          width: 30px;
+          height: 30px;
+          border-radius: 50%;
+          background: white;
+          border: 2px solid #e4e7ed;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          font-size: 12px;
+          font-weight: bold;
+          color: #606266;
+          z-index: 3;
+
+          &.active {
+            background: #409eff;
+            border-color: #409eff;
+            color: white;
+            width: 22px;
+            height: 22px;
+            left: 30px;
+          }
+        }
+
+        .node-blue-marker {
+          width: 20px;
+          height: 15px;
+          border-radius: 0 50% 50% 0;
+          background: #76b4f4;
+          position: absolute;
+          left: 20px;
+          top: 5px;
+          z-index: 3;
+        }
+
+        .node-content {
+          margin-left: 60px;
+
+          .date-label {
+            font-size: 16px;
+            font-weight: 500;
+            color: #303133;
+          }
+
+          .record-header {
+            display: flex;
+            align-items: center;
+            gap: 20px;
+            margin-bottom: 8px;
+
+            .record-type {
+              margin-bottom: 0;
+            }
+
+            .doctor-info {
+              margin-bottom: 0;
+              color: #909399;
+              font-size: 13px;
+            }
+          }
+
+          .record-type {
+            font-size: 14px;
+            color: #333;
+            margin-bottom: 8px;
+
+            &.active {
+              color: #409eff;
+              background: #f0f9ff;
+              padding: 8px 12px;
+              border-radius: 4px;
+              display: inline-block;
+            }
+          }
+
+          .doctor-info {
+            font-size: 14px;
+            color: #606266;
+            margin-bottom: 16px;
+          }
+
+          .record-list {
+            .record-item {
+              margin-bottom: 16px;
+              padding: 12px 0;
+              border-bottom: 1px solid #f0f0f0;
+
+              &:last-child {
+                border-bottom: none;
+              }
+
+              .record-time {
+                font-size: 13px;
+                color: #909399;
+                margin-bottom: 4px;
+              }
+
+              .record-doctor {
+                font-size: 13px;
+                color: #606266;
+                margin-bottom: 8px;
+              }
+
+              .record-detail {
+                font-size: 14px;
+                color: #303133;
+                line-height: 1.5;
+
+                strong {
+                  color: #303133;
+                  font-weight: 600;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      // 特殊节点样式
+      .date-node {
+        .node-marker {
+          background: #f5f7fa;
+          border-color: #909399;
+          color: #606266;
+        }
+      }
+
+      .normal-node {
+        .node-marker {
+          background: white;
+          border-color: #e4e7ed;
+        }
+      }
+
+      .active-node {
+        .node-marker {
+          background: #409eff;
+          border: none;
+          color: white;
+          width: 24px;
+          height: 12px;
+          left: 29px;
+          border-radius: 12px;
+        }
+      }
+    }
+
+    .center-divider {
+      width: 80px;
+      background: #f8f9fa;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border-left: 1px solid #e4e7ed;
+      border-right: 1px solid #e4e7ed;
+
+      .divider-text {
+        writing-mode: vertical-lr;
+        font-size: 14px;
+        color: #909399;
+      }
+    }
+
+    .right-navigation {
+      width: 160px;
+      background: white;
+
+      // 自定义右侧时间线样式
+      :deep(.el-timeline) {
+        padding-left: 16px;
+        margin-top: 10px;
+
+        .el-timeline-item {
+          padding-bottom: 20px;
+
+          &:last-child {
+            padding-bottom: 0;
+
+            .el-timeline-item__tail {
+              display: none;
+            }
+          }
+
+          .el-timeline-item__node {
+            width: 8px;
+            height: 8px;
+            left: -4px;
+            border: 1px solid #e4e7ed;
+            background: white;
+
+            &.el-timeline-item__node--primary {
+              border-color: #409eff;
+              background: #409eff;
+            }
+
+            &.el-timeline-item__node--info {
+              border-color: #e4e7ed;
+              background: #e4e7ed;
+            }
+          }
+
+          .el-timeline-item__tail {
+            left: -1px;
+            border-left: 1px solid #e4e7ed;
+          }
+
+          .el-timeline-item__content {
+            top: -4px;
+          }
+        }
+      }
+
+      .nav-timeline-content {
+        cursor: pointer;
+        padding: 2px 0;
+        transition: all 0.3s ease;
+
+        .nav-title {
+          font-size: 14px;
+          color: #606266;
+          font-weight: normal;
+          line-height: 1.2;
+          white-space: nowrap;
+        }
+
+        &:hover {
+          .nav-title {
+            color: #409eff;
+          }
+        }
+
+        &.active {
+          .nav-title {
+            color: #409eff;
+            font-weight: 500;
+          }
+        }
+      }
+    }
+  }
+
+  // 滚动条样式
+  :deep(.left-timeline::-webkit-scrollbar) {
+    width: 6px;
+  }
+
+  :deep(.left-timeline::-webkit-scrollbar-track) {
+    background: #f1f1f1;
+    border-radius: 3px;
+  }
+
+  :deep(.left-timeline::-webkit-scrollbar-thumb) {
+    background: #c1c1c1;
+    border-radius: 3px;
+
+    &:hover {
+      background: #a8a8a8;
+    }
+  }
+}
+</style>

+ 59 - 58
src/views/patients/medicalRecord/index.vue

@@ -11,7 +11,7 @@
         <el-menu-item index="medicalRecord">
           <span>营养病例</span>
         </el-menu-item>
-        <el-menu-item index="visitRecord">
+        <el-menu-item index="hospitalRecord">
           <span>就诊记录</span>
         </el-menu-item>
         <el-menu-item index="checkLabel">
@@ -141,7 +141,8 @@ const NutritionSetting = defineAsyncComponent(() => import('@/views/patients/nut
 const DietTherapy = defineAsyncComponent(() => import('@/views/patients/dietTherapy/index.vue'));
 const ParenteralNutrition = defineAsyncComponent(() => import('@/views/patients/parenteralNutrition/index.vue'));
 const EnteralNutrition = defineAsyncComponent(() => import('@/views/patients/enteralNutrition/index.vue'));
-const EnteralNutritionHistory = defineAsyncComponent(() => import('@/views/patients/enteralNutrition/history.vue'));  
+const EnteralNutritionHistory = defineAsyncComponent(() => import('@/views/patients/enteralNutrition/history.vue'));
+const HospitalRecord = defineAsyncComponent(() => import('@/views/patients/hospitalRecord/index.vue'));
 
 const componentMap = {
   medicalRecord: MedicalRecord,
@@ -157,6 +158,7 @@ const componentMap = {
   parenteralNutrition: ParenteralNutrition,
   enteralNutrition: EnteralNutrition,
   enteralNutritionHistory: EnteralNutritionHistory,
+  hospitalRecord: HospitalRecord
 };
 const currentComponent = ref(componentMap['medicalRecord']);
 const route = useRoute();
@@ -177,9 +179,7 @@ const patientInfo = ref({
   height: '',
   weight: '',
   bmi: '',
-  activity: '',
-
- 
+  activity: ''
 });
 
 // 弹窗控制
@@ -193,9 +193,10 @@ const editData = ref({} as any);
 const handleSelect = (key: string, other?: string[]) => {
   if (key == 'nutritionScreeningAdd' || key == 'nutritionEvaluationAdd') {
     activeMenu.value = key.replace('Add', '');
-  } if(key=='enteralNutritionHistory'){            
-            activeMenu.value = key.replace('History',''); 
-  }else {
+  }
+  if (key == 'enteralNutritionHistory') {
+    activeMenu.value = key.replace('History', '');
+  } else {
     activeMenu.value = key;
   }
   currentComponent.value = componentMap[key] || null;
@@ -325,7 +326,7 @@ const getList = async () => {
       params.searchFlag = searchValue.value;
     }
     const res = await listTreatmentUser(params);
-    patientList.value = (res.rows || []).map(item => ({
+    patientList.value = (res.rows || []).map((item) => ({
       id: item.id,
       name: item.treatName,
       type: item.type,
@@ -337,14 +338,14 @@ const getList = async () => {
       BMI: item.bmi,
       height: item.height,
       weight: item.weight,
-      activity: item.activity,
+      activity: item.activity
     }));
     waitingCount.value = patientList.value.length;
     // 如果有患者数据,根据路由参数或默认选中第一个
     if (patientList.value.length > 0) {
-      const { id } = route.query;
+      const {id} = route.query;
       if (typeof id === 'string') {
-        const targetIndex = patientList.value.findIndex(patient => patient.id === id);
+        const targetIndex = patientList.value.findIndex((patient) => patient.id === id);
         if (targetIndex !== -1) {
           patientInfo.value = patientList.value[targetIndex];
           patientInfo.value.type = typeof route.query.type === 'string' ? route.query.type : '';
@@ -376,7 +377,7 @@ const handleSearch = () => {
 
 onMounted(() => {
   // 获取体力活动字典
-  const { physical_activity } = toRefs(proxy?.useDict('physical_activity'));
+  const {physical_activity} = toRefs(proxy?.useDict('physical_activity'));
   physicalActivityDict.value = physical_activity?.value || [];
   patientInfo.value.type = typeof route.query.type === 'string' ? route.query.type : '';
   patientInfo.value.outpatientNo = typeof route.query.outpatientNo === 'string' ? route.query.outpatientNo : '';
@@ -459,28 +460,28 @@ onMounted(() => {
   overflow-x: auto;
 }
 
-    .table-patients {
-        table-layout: fixed;
-        width: 100%;
-        min-width: 220px;
-        white-space: nowrap;
-
-        .el-table__header th {
-            background: #f5f7fa;
-            color: #409eff;
-            font-weight: bold;
-            font-size: 13px;
-            padding: 4px 0;
-        }
+.table-patients {
+  table-layout: fixed;
+  width: 100%;
+  min-width: 220px;
+  white-space: nowrap;
+
+  .el-table__header th {
+    background: #f5f7fa;
+    color: #409eff;
+    font-weight: bold;
+    font-size: 13px;
+    padding: 4px 0;
+  }
 
-        .el-table__row {
-            cursor: pointer;
-        }
+  .el-table__row {
+    cursor: pointer;
+  }
 
-        .el-table__row.current-row {
-            background: #eaf4ff !important;
-        }
-    }
+  .el-table__row.current-row {
+    background: #eaf4ff !important;
+  }
+}
 
 .nav-btns {
   display: flex;
@@ -522,34 +523,34 @@ onMounted(() => {
   margin-left: 30px;
 }
 
-    .info-row {
-        display: flex;
-        align-items: center;
-        white-space: nowrap;
-    }
+.info-row {
+  display: flex;
+  align-items: center;
+  white-space: nowrap;
+}
 
-    .info-row .name {
-        font-size: 22px;
-    }
+.info-row .name {
+  font-size: 22px;
+}
 
-    .info-row .age {
-        margin-left: 30px;
-    }
+.info-row .age {
+  margin-left: 30px;
+}
 
-    .gender-icon {
-        margin-left: 30px;
-        font-size: 25px;
-        font-weight: bold;
-        line-height: 1;
-        display: inline-block;
-        vertical-align: middle;
-    }
+.gender-icon {
+  margin-left: 30px;
+  font-size: 25px;
+  font-weight: bold;
+  line-height: 1;
+  display: inline-block;
+  vertical-align: middle;
+}
 
-    .gender-icon.female {
-        color: #ff4949;
-    }
+.gender-icon.female {
+  color: #ff4949;
+}
 
-    .gender-icon.male {
-        color: #409eff;
-    }
+.gender-icon.male {
+  color: #409eff;
+}
 </style>

+ 498 - 508
src/views/patients/nutritionSetting/addForm.vue

@@ -1,538 +1,528 @@
 <template>
-    <div class="page-current">
-        <el-button type="primary" @click="onBack">返回</el-button>
+  <div class="page-current">
+    <el-button type="primary" @click="onBack">返回</el-button>
+  </div>
+  <div class="question-main">
+    <!-- 顶部信息区(完全还原图片样式) -->
+    <div class="info-card info-card-bee">
+      <div class="info-title">
+        <span class="bee-title">{{ title }}</span>
+      </div>
+      <el-row :gutter="20" align="middle" class="info-row">
+        <el-col :span="2"><span>性别:</span>{{ form.gender }}</el-col>
+        <el-col :span="2"><span>年龄:</span>{{ form.age }}</el-col>
+        <el-col :span="2"
+          ><span class="required">*</span><span>BMI:{{ form.bmi }}</span></el-col
+        >
+        <el-col :span="4"
+          ><span class="required">*</span><span>身高:</span> <el-input v-model="form.height" style="width: 120px" /> <span>cm</span></el-col
+        >
+        <el-col :span="4"
+          ><span class="required">*</span><span>体力活动:</span>
+          <el-select v-model="form.activity" style="width: 150px">
+            <el-option v-for="dict in physical_activity" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-select>
+        </el-col>
+        <el-col :span="4" v-if="title === 'BEE'"
+          ><span class="required">*</span><span>应激状态:</span>
+          <el-select v-model="form.stressType" style="width: 150px">
+            <el-option v-for="dict in stress_level" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-select>
+        </el-col>
+        <el-col :span="3" v-if="title === '烧伤公式'"
+          ><span>烧伤面积:</span> <el-input v-model="form.burnArea" style="width: 120px" /> <span>%</span>
+        </el-col>
+        <el-col :span="3"><span>体重:</span> <el-input v-model="form.weight" style="width: 120px" /> <span>kg</span> </el-col>
+        <el-col :span="3"><span>上臂围:</span> <el-input v-model="form.armCircumference" style="width: 120px" /> <span>cm</span> </el-col>
+      </el-row>
+      <el-row style="margin-top: 10px">
+        <el-col :span="3"><span>小腿围:</span> <el-input v-model="form.calfCircumference" style="width: 120px" /> <span>cm</span> </el-col>
+        <el-col :span="20" style="text-align: right">
+          <el-button
+            type="primary"
+            class="recalc-btn"
+            @click="() => recalculate(form.gender, form.age, form.height, form.weight, form.activity, form.stressType)"
+            >重新计算</el-button
+          >
+        </el-col>
+      </el-row>
     </div>
-    <div class="question-main">
-        <!-- 顶部信息区(完全还原图片样式) -->
-        <div class="info-card info-card-bee">
-            <div class="info-title">
-                <span class="bee-title">{{ title }}</span>
-            </div>
-            <el-row :gutter="20" align="middle" class="info-row">
-                <el-col :span="2"><span>性别:</span>{{form.gender}}</el-col>
-                <el-col :span="2"><span>年龄:</span>{{form.age}}</el-col>
-                <el-col :span="2"><span class="required">*</span><span>BMI:{{ form.bmi }}</span></el-col>
-                <el-col :span="4"><span class="required">*</span><span>身高:</span>
-                    <el-input v-model="form.height" style="width: 120px;" /> <span>cm</span></el-col>
-                <el-col :span="4"><span class="required">*</span><span>体力活动:</span>
-                    <el-select v-model="form.activity" style="width: 150px;">
-                        <el-option v-for="dict in physical_activity" :key="dict.value" :label="dict.label" :value="dict.value" />
-                    </el-select>
-                </el-col>
-                <el-col :span="4" v-if="title === 'BEE'"><span class="required">*</span><span>应激状态:</span>
-                    <el-select v-model="form.stressType" style="width: 150px;">
-                        <el-option v-for="dict in stress_level" :key="dict.value" :label="dict.label" :value="dict.value" />
-                    </el-select>
-                </el-col>
-                <el-col :span="3" v-if="title === '烧伤公式'"><span>烧伤面积:</span>
-                    <el-input v-model="form.burnArea" style="width: 120px;" /> <span>%</span>
-                </el-col>
-                <el-col :span="3"><span>体重:</span>
-                    <el-input v-model="form.weight" style="width: 120px;" /> <span>kg</span>
-                </el-col>
-                <el-col :span="3"><span>上臂围:</span>
-                    <el-input v-model="form.armCircumference" style="width: 120px;" /> <span>cm</span>
-                </el-col>
-            </el-row>
-            <el-row style="margin-top: 10px;">
-                <el-col :span="3"><span>小腿围:</span>
-                    <el-input v-model="form.calfCircumference" style="width: 120px;" /> <span>cm</span>
-                </el-col>
-                <el-col :span="20" style="text-align:right;">
-                    <el-button type="primary" class="recalc-btn" @click="()=>recalculate(form.gender, form.age, form.height, form.weight, form.activity, form.stressType)">重新计算</el-button>
-                </el-col>
-            </el-row>
+    <!-- 警示提示区 -->
+    <div class="tips-box">注:常量元素、微量元素、维生素、氨基酸、脂肪酸、膳食纤维默认为DRIS数据,如有必要请自行修改。</div>
+    <div v-show="showFlag == 'true'">
+      <el-form ref="NutritionSettingFormRef" :model="form" :rules="rules" label-position="right" label-width="170px">
+        <!-- 能量及三大营养素 -->
+        <div class="group-card">
+          <div class="group-title">能量及三大营养素</div>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="所需热量:" class="right-label">
+                <el-input v-model="form.caloriesKcalPerDay" style="width: 200px" />
+                <span class="unit">kcal/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需热量:" class="right-label">
+                <span>{{ form.caloriesKcalPerKgDay }}</span>
+                <span class="unit">kcal/kg*d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需热量:" class="right-label">
+                <span>{{ form.caloriesKjPerDay }}</span>
+                <span class="unit">kJ/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="蛋白质热量占比:" class="right-label">
+                <el-input v-model="form.proteinCaloriePercentage" style="width: 200px" />
+                <span class="unit">%</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需蛋白质:" class="right-label">
+                <span>{{ form.proteinGPerKgDay }}</span>
+                <span class="unit">g/kg*d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需蛋白质:" class="right-label">
+                <span>{{ form.proteinGPerDay }}</span>
+                <span class="unit">g/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="脂肪热量占比:" class="right-label">
+                <el-input v-model="form.fatCaloriePercentage" style="width: 200px" />
+                <span class="unit">%</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需脂肪:" class="right-label">
+                <span>{{ form.fatGPerKgDay }}</span>
+                <span class="unit">g/kg*d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需脂肪:" class="right-label">
+                <span>{{ form.fatGPerDay }}</span>
+                <span class="unit">g/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="碳水化合物热量占比:" class="right-label">
+                <el-input v-model="form.carbohydrateCaloriePercentage" style="width: 200px" />
+                <span class="unit">%</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需碳水化合物:" class="right-label">
+                <span>{{ form.carbohydrateGPerKgDay }}</span> <span class="unit">g/kg·d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="所需碳水化合物:" class="right-label">
+                <span>{{ form.carbohydrateGPerDay }}</span>
+                <span class="unit">g/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
         </div>
-        <!-- 警示提示区 -->
-        <div class="tips-box">
-            注:常量元素、微量元素、维生素、氨基酸、脂肪酸、膳食纤维默认为DRIS数据,如有必要请自行修改。
+        <!-- 常量元素 -->
+        <div class="group-card">
+          <div class="group-title">常量元素</div>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="钙:" class="right-label">
+                <el-input v-model="form.calcium" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="磷:" class="right-label">
+                <el-input v-model="form.phosphorus" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="钾:" class="right-label">
+                <el-input v-model="form.potassium" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="钠:" class="right-label">
+                <el-input v-model="form.sodium" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="镁:" class="right-label">
+                <el-input v-model="form.magnesium" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="氯:" class="right-label">
+                <el-input v-model="form.chloride" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
         </div>
-        <div v-show="showFlag=='true'">
-            <el-form ref="NutritionSettingFormRef" :model="form" :rules="rules" label-position="right" label-width="170px">
-                <!-- 能量及三大营养素 -->
-                <div class="group-card">
-                    <div class="group-title">能量及三大营养素</div>
-                    <el-row :gutter="20">
-                        <el-col :span="8">
-                            <el-form-item label="所需热量:" class="right-label">
-                                <el-input v-model="form.caloriesKcalPerDay" style="width: 200px;" />
-                                <span class="unit">kcal/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需热量:" class="right-label">
-                                <span>{{ form.caloriesKcalPerKgDay }}</span>
-                                <span class="unit">kcal/kg*d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需热量:" class="right-label">
-                                <span>{{form.caloriesKjPerDay}}</span>
-                                <span class="unit">kJ/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="蛋白质热量占比:" class="right-label">
-                                <el-input v-model="form.proteinCaloriePercentage" style="width: 200px;" />
-                                <span class="unit">%</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需蛋白质:" class="right-label">
-                                <span>{{ form.proteinGPerKgDay }}</span>
-                                <span class="unit">g/kg*d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需蛋白质:" class="right-label">
-                                <span>{{ form.proteinGPerDay }}</span>
-                                <span class="unit">g/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="脂肪热量占比:" class="right-label">
-                                <el-input v-model="form.fatCaloriePercentage" style="width: 200px;" />
-                                <span class="unit">%</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需脂肪:" class="right-label">
-                                <span>{{ form.fatGPerKgDay }}</span>
-                                <span class="unit">g/kg*d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需脂肪:" class="right-label">
-                                <span>{{ form.fatGPerDay }}</span>
-                                <span class="unit">g/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="碳水化合物热量占比:" class="right-label">
-                                <el-input v-model="form.carbohydrateCaloriePercentage" style="width: 200px;" />
-                                <span class="unit">%</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需碳水化合物:" class="right-label">
-                                <span>{{ form.carbohydrateGPerKgDay }}</span> <span class="unit">g/kg·d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="所需碳水化合物:" class="right-label">
-                                <span>{{ form.carbohydrateGPerDay }}</span>
-                                <span class="unit">g/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-
-                </div>
-                <!-- 常量元素 -->
-                <div class="group-card">
-                    <div class="group-title">常量元素</div>
-                    <el-row :gutter="20">
-                        <el-col :span="8">
-                            <el-form-item label="钙:" class="right-label">
-                                <el-input v-model="form.calcium" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="磷:" class="right-label">
-                                <el-input v-model="form.phosphorus" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="钾:" class="right-label">
-                                <el-input v-model="form.potassium" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="钠:" class="right-label">
-                                <el-input v-model="form.sodium" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="镁:" class="right-label">
-                                <el-input v-model="form.magnesium" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="氯:" class="right-label">
-                                <el-input v-model="form.chloride" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-
-
-                    </el-row>
-
-                </div>
-                <!-- 微量元素 -->
-                <div class="group-card">
-                    <div class="group-title">微量元素</div>
-                    <el-row :gutter="20">
-                        <el-col :span="8">
-                            <el-form-item label="铁:" class="right-label">
-                                <el-input v-model="form.iron" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="锌:" class="right-label">
-                                <el-input v-model="form.zinc" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="硒:" class="right-label">
-                                <el-input v-model="form.selenium" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="铜:" class="right-label">
-                                <el-input v-model="form.copper" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="锰:" class="right-label">
-                                <el-input v-model="form.manganese" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="碘:" class="right-label">
-                                <el-input v-model="form.iodine" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="氟:" class="right-label">
-                                <el-input v-model="form.fluoride" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="铬:" class="right-label">
-                                <el-input v-model="form.chromium" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="钼:" class="right-label">
-                                <el-input v-model="form.molybdenum" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                </div>
-                <!-- 脂溶性维生素 -->
-                <div class="group-card">
-                    <div class="group-title">脂溶性维生素</div>
-                    <el-row :gutter="20">
-                        <el-col :span="8">
-                            <el-form-item label="维生素A:" class="right-label">
-                                <el-input v-model="form.vitaminA" style="width: 200px;" />
-                                <span class="unit">μgRAE/d</span>
-                            </el-form-item>
-                        </el-col>
-
-                        <el-col :span="8">
-                            <el-form-item label="维生素D:" class="right-label">
-                                <el-input v-model="form.vitaminD" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="维生素E:" class="right-label">
-                                <el-input v-model="form.vitaminE" style="width: 200px;" />
-                                <span class="unit">mgα-TE/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="维生素K:" class="right-label">
-                                <el-input v-model="form.vitaminK" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                </div>
-                <!-- 水溶性维生素 -->
-                <div class="group-card">
-                    <div class="group-title">水溶性维生素</div>
-                    <el-row :gutter="20">
-                        <el-col :span="8">
-                            <el-form-item label="维生素B1:" class="right-label">
-                                <el-input v-model="form.vitaminBOne" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="维生素B2:" class="right-label">
-                                <el-input v-model="form.vitaminBTwo" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="维生素B6:" class="right-label">
-                                <el-input v-model="form.vitaminBSix" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="维生素B12:" class="right-label">
-                                <el-input v-model="form.vitaminBTwelve" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="烟酸(尼克酸):" class="right-label">
-                                <el-input v-model="form.niacin" style="width: 200px;" />
-                                <span class="unit">mgNE/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="维生素C:" class="right-label">
-                                <el-input v-model="form.vitaminC" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="叶酸:" class="right-label">
-                                <el-input v-model="form.folicAcid" style="width: 200px;" />
-                                <span class="unit">μgDFE/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="生物素:" class="right-label">
-                                <el-input v-model="form.biotin" style="width: 200px;" />
-                                <span class="unit">μg/d</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="8">
-                            <el-form-item label="胆碱:" class="right-label">
-                                <el-input v-model="form.choline" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                    <el-row :gutter="20" style="margin-top: 8px;">
-                        <el-col :span="8">
-                            <el-form-item label="泛酸:" class="right-label">
-                                <el-input v-model="form.pantothenicAcid" style="width: 200px;" />
-                                <span class="unit">mg/d</span>
-                            </el-form-item>
-                        </el-col>
-
-                    </el-row>
-                </div>
-                <!-- 其他 -->
-                <div class="group-card">
-                    <div class="group-title">其他</div>
-                    <el-row :gutter="20">
-                        <el-col :span="8">
-                            <el-form-item label="膳食纤维:" class="right-label">
-                                <el-input v-model="form.dietaryFiber" style="width: 200px;" />
-                                <span class="unit">g/d</span>
-                            </el-form-item>
-                        </el-col>
-                    </el-row>
-                </div>
-            </el-form>
-            <div class="flex justify-center gap-2 mt-4">
-                <el-button :loading="buttonLoading" type="primary" @click="submitForm">保 存</el-button>
-            </div>
+        <!-- 微量元素 -->
+        <div class="group-card">
+          <div class="group-title">微量元素</div>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="铁:" class="right-label">
+                <el-input v-model="form.iron" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="锌:" class="right-label">
+                <el-input v-model="form.zinc" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="硒:" class="right-label">
+                <el-input v-model="form.selenium" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="铜:" class="right-label">
+                <el-input v-model="form.copper" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="锰:" class="right-label">
+                <el-input v-model="form.manganese" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="碘:" class="right-label">
+                <el-input v-model="form.iodine" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="氟:" class="right-label">
+                <el-input v-model="form.fluoride" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="铬:" class="right-label">
+                <el-input v-model="form.chromium" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="钼:" class="right-label">
+                <el-input v-model="form.molybdenum" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
         </div>
+        <!-- 脂溶性维生素 -->
+        <div class="group-card">
+          <div class="group-title">脂溶性维生素</div>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="维生素A:" class="right-label">
+                <el-input v-model="form.vitaminA" style="width: 200px" />
+                <span class="unit">μgRAE/d</span>
+              </el-form-item>
+            </el-col>
 
+            <el-col :span="8">
+              <el-form-item label="维生素D:" class="right-label">
+                <el-input v-model="form.vitaminD" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="维生素E:" class="right-label">
+                <el-input v-model="form.vitaminE" style="width: 200px" />
+                <span class="unit">mgα-TE/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="维生素K:" class="right-label">
+                <el-input v-model="form.vitaminK" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+        <!-- 水溶性维生素 -->
+        <div class="group-card">
+          <div class="group-title">水溶性维生素</div>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="维生素B1:" class="right-label">
+                <el-input v-model="form.vitaminBOne" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="维生素B2:" class="right-label">
+                <el-input v-model="form.vitaminBTwo" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="维生素B6:" class="right-label">
+                <el-input v-model="form.vitaminBSix" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="维生素B12:" class="right-label">
+                <el-input v-model="form.vitaminBTwelve" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="烟酸(尼克酸):" class="right-label">
+                <el-input v-model="form.niacin" style="width: 200px" />
+                <span class="unit">mgNE/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="维生素C:" class="right-label">
+                <el-input v-model="form.vitaminC" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="叶酸:" class="right-label">
+                <el-input v-model="form.folicAcid" style="width: 200px" />
+                <span class="unit">μgDFE/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="生物素:" class="right-label">
+                <el-input v-model="form.biotin" style="width: 200px" />
+                <span class="unit">μg/d</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="胆碱:" class="right-label">
+                <el-input v-model="form.choline" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20" style="margin-top: 8px">
+            <el-col :span="8">
+              <el-form-item label="泛酸:" class="right-label">
+                <el-input v-model="form.pantothenicAcid" style="width: 200px" />
+                <span class="unit">mg/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+        <!-- 其他 -->
+        <div class="group-card">
+          <div class="group-title">其他</div>
+          <el-row :gutter="20">
+            <el-col :span="8">
+              <el-form-item label="膳食纤维:" class="right-label">
+                <el-input v-model="form.dietaryFiber" style="width: 200px" />
+                <span class="unit">g/d</span>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+      </el-form>
+      <div class="flex justify-center gap-2 mt-4">
+        <el-button :loading="buttonLoading" type="primary" @click="submitForm">保 存</el-button>
+      </div>
     </div>
+  </div>
 </template>
 
 <script setup lang="ts">
-    import { ref, toRefs, getCurrentInstance } from 'vue';
-    import { addSetting, updateSetting, recalculateValue } from '@/api/patients/nutritionSetting';
-    import type { FormInstance } from 'element-plus';
-    const { proxy } = getCurrentInstance() as any;
-    const { physical_activity, stress_level } = toRefs(proxy ?.useDict('physical_activity', 'stress_level'));
-    const emit = defineEmits(['change'])
-    const props = defineProps({
-        form: { type: Object, required: true },
-        rules: { type: Object, required: true },
-        buttonLoading: { type: Boolean, required: true },
-        cancel: { type: Function, required: true },
-        handleCancelOne: { type: Function, required: true },
-        title: { type: String }
-    });
-    const { handleCancelOne, form, rules } = props;
-    const { title } = toRefs(props);
-    const showFlag = ref('false');
-    const buttonLoading = ref(false);
-    const NutritionSettingFormRef = ref < FormInstance > ();
-
+import {ref, toRefs, getCurrentInstance} from 'vue';
+import {addSetting, updateSetting, recalculateValue} from '@/api/patients/nutritionSetting';
+import type {FormInstance} from 'element-plus';
+const {proxy} = getCurrentInstance() as any;
+const {physical_activity, stress_level} = toRefs(proxy?.useDict('physical_activity', 'stress_level'));
+const emit = defineEmits(['change']);
+const props = defineProps({
+  form: {type: Object, required: true},
+  rules: {type: Object, required: true},
+  buttonLoading: {type: Boolean, required: true},
+  cancel: {type: Function, required: true},
+  handleCancelOne: {type: Function, required: true},
+  title: {type: String}
+});
+const {handleCancelOne, form, rules} = props;
+const {title} = toRefs(props);
+const showFlag = ref('false');
+const buttonLoading = ref(false);
+const NutritionSettingFormRef = ref<FormInstance>();
 
-    const recalculate = async (gender, age, height, weight, activity, stressType) => {
-        const res = await recalculateValue({ gender, age, height, weight, activity, stressType });
-        if (res) {
-            const keepSettingType = form.settingType;
-            Object.assign(form, res);
-            form.settingType = keepSettingType; // 恢复settingType的值
+const recalculate = async (gender, age, height, weight, activity, stressType) => {
+  const res = await recalculateValue({gender, age, height, weight, activity, stressType});
+  if (res) {
+    const keepSettingType = form.settingType;
+    Object.assign(form, res);
+    form.settingType = keepSettingType; // 恢复settingType的值
+  }
+  showFlag.value = 'true';
+};
 
+/** 提交按钮 */
+const submitForm = async () => {
+  if (!NutritionSettingFormRef.value) return;
+  await NutritionSettingFormRef.value.validate(async (valid: boolean) => {
+    if (valid) {
+      buttonLoading.value = true;
+      try {
+        if (form.id) {
+          await updateSetting(form);
+        } else {
+          console.log(form.settingType);
+          await addSetting(form);
         }
-        showFlag.value = 'true';
-    };
-
-    /** 提交按钮 */
-    const submitForm = async () => {
-        if (!NutritionSettingFormRef.value) return;
-        await NutritionSettingFormRef.value.validate(async (valid: boolean) => {
-            if (valid) {
-                buttonLoading.value = true;
-                try {
-                    if (form.id) {
-                        await updateSetting(form);
-                    } else {
-                        console.log(form.settingType);
-                        await addSetting(form);
-                    }
-                    proxy ?.$modal.msgSuccess('操作成功');
-                    onBack();
-                } catch (error) {
-                    console.error('提交失败', error);
-                } finally {
-                    buttonLoading.value = false;
-                }
-            }
-        });
-    };
-    const close = async () => {
-
-    };
+        proxy?.$modal.msgSuccess('操作成功');
+        onBack();
+      } catch (error) {
+        console.error('提交失败', error);
+      } finally {
+        buttonLoading.value = false;
+      }
+    }
+  });
+};
+const close = async () => {};
 
-    const onBack = () => {
-        showFlag.value = 'false';
-        emit('change', 'nutritionSetting');
-        handleCancelOne();
-    };
+const onBack = () => {
+  showFlag.value = 'false';
+  emit('change', 'nutritionSetting');
+  handleCancelOne();
+};
 </script>
 
 <style scoped>
-    .page-current {
-        display: flex;
-        align-items: center;
-        padding: 20px;
-        background: #fff;
-        border-bottom: 1px solid #e6e6e6;
-    }
+.page-current {
+  display: flex;
+  align-items: center;
+  padding: 20px;
+  background: #fff;
+  border-bottom: 1px solid #e6e6e6;
+}
 
-    .question-main {
-        padding: 20px 0 100px;
-    }
+.question-main {
+  padding: 20px 0 100px;
+}
 
-    .info-card-bee {
-        margin-bottom: 16px;
-        background: #f8fafc;
-        border-radius: 8px;
-        box-shadow: 0 2px 8px #f0f1f2;
-        padding: 18px 24px 10px 24px;
-        border: none;
-    }
+.info-card-bee {
+  margin-bottom: 16px;
+  background: #f8fafc;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px #f0f1f2;
+  padding: 18px 24px 10px 24px;
+  border: none;
+}
 
-    .info-title {
-        font-weight: bold;
-        font-size: 16px;
-        color: #409EFF;
-        margin-bottom: 8px;
-        padding-left: 2px;
-    }
+.info-title {
+  font-weight: bold;
+  font-size: 16px;
+  color: #409eff;
+  margin-bottom: 8px;
+  padding-left: 2px;
+}
 
-    .bee-title {
-        border-left: 4px solid #409EFF;
-        padding-left: 8px;
-        font-size: 16px;
-        font-weight: bold;
-        color: #409EFF;
-    }
+.bee-title {
+  border-left: 4px solid #409eff;
+  padding-left: 8px;
+  font-size: 16px;
+  font-weight: bold;
+  color: #409eff;
+}
 
-    .info-row {
-        background: #f8fafc;
-        font-size: 16px;
-        padding: 0 0 0 0;
-        margin: 0;
-    }
+.info-row {
+  background: #f8fafc;
+  font-size: 16px;
+  padding: 0 0 0 0;
+  margin: 0;
+}
 
-    .required {
-        color: #f56c6c;
-        margin-right: 2px;
-    }
+.required {
+  color: #f56c6c;
+  margin-right: 2px;
+}
 
-    .recalc-btn {
-        margin-left: 12px;
-    }
+.recalc-btn {
+  margin-left: 12px;
+}
 
-    .tips-box {
-        color: #ff5e4c;
-        margin: 16px 0;
-        font-size: 14px;
-    }
+.tips-box {
+  color: #ff5e4c;
+  margin: 16px 0;
+  font-size: 14px;
+}
 
-    .group-card {
-        background: #fff;
-        border-radius: 8px;
-        margin-bottom: 24px;
-        box-shadow: 0 2px 8px #f0f1f2;
-        padding: 16px 24px;
-    }
+.group-card {
+  background: #fff;
+  border-radius: 8px;
+  margin-bottom: 24px;
+  box-shadow: 0 2px 8px #f0f1f2;
+  padding: 16px 24px;
+}
 
-    .group-title {
-        background: #f5f7fa;
-        padding: 8px 16px;
-        font-weight: bold;
-        border-radius: 4px;
-        margin-bottom: 16px;
-        font-size: 16px;
-    }
+.group-title {
+  background: #f5f7fa;
+  padding: 8px 16px;
+  font-weight: bold;
+  border-radius: 4px;
+  margin-bottom: 16px;
+  font-size: 16px;
+}
 
-    .unit {
-        margin-left: 4px;
-        color: #888;
-    }
+.unit {
+  margin-left: 4px;
+  color: #888;
+}
 
-    .right-label .el-form-item__label {
-        text-align: right !important;
-        justify-content: flex-end;
-        display: flex;
-    }
+.right-label .el-form-item__label {
+  text-align: right !important;
+  justify-content: flex-end;
+  display: flex;
+}
 
-    ::v-deep .el-form-item__label {
-        text-align: right !important;
-        justify-content: flex-end;
-        display: flex;
-    }
-</style>
+::v-deep .el-form-item__label {
+  text-align: right !important;
+  justify-content: flex-end;
+  display: flex;
+}
+</style>

+ 357 - 321
src/views/patients/nutritionSetting/index.vue

@@ -1,347 +1,383 @@
 <template>
-    <div class="p-2">
-        <div v-show="type=='list'">
-            <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-                <div v-show="showSearch" class="mb-[10px]">
-                    <el-card shadow="hover">
-                        <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
-                            <el-form-item label="时间:">
-                                <el-date-picker v-model="queryParams.dateRange" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
-                            </el-form-item>
-                            <el-form-item label="看诊类型:">
-                                <el-select v-model="queryParams.type" class="spec-unit-select">
-                                    <el-option v-for="dict in treatment_user_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-                                </el-select>
-                            </el-form-item>
-                            <el-form-item label="营养设定方式:">
-                                <el-select v-model="queryParams.settingType" class="spec-unit-select">
-                                    <el-option v-for="dict in nutrition_setting_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-                                </el-select>
-                            </el-form-item>
-                            <el-form-item>
-                                <el-input v-model="queryParams.searchValue" placeholder="门诊/住院号、医生" style="width: 240px; " clearable />
-                            </el-form-item>
-                            <el-form-item>
-                                <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                                <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-                            </el-form-item>
-                        </el-form>
-                    </el-card>
-                </div>
-            </transition>
+  <div class="p-2">
+    <div v-show="type == 'list'">
+      <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+        <div v-show="showSearch" class="mb-[10px]">
+          <el-card shadow="hover">
+            <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
+              <el-form-item label="时间:">
+                <el-date-picker
+                  v-model="queryParams.dateRange"
+                  type="daterange"
+                  range-separator="-"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                />
+              </el-form-item>
+              <el-form-item label="看诊类型:">
+                <el-select v-model="queryParams.type" class="spec-unit-select">
+                  <el-option v-for="dict in treatment_user_type" :key="dict.value" :label="dict.label" :value="dict.value" />
+                </el-select>
+              </el-form-item>
+              <el-form-item label="营养设定方式:">
+                <el-select v-model="queryParams.settingType" class="spec-unit-select">
+                  <el-option v-for="dict in nutrition_setting_type" :key="dict.value" :label="dict.label" :value="dict.value" />
+                </el-select>
+              </el-form-item>
+              <el-form-item>
+                <el-input v-model="queryParams.searchValue" placeholder="门诊/住院号、医生" style="width: 240px" clearable />
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+                <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+              </el-form-item>
+            </el-form>
+          </el-card>
+        </div>
+      </transition>
 
-            <el-card shadow="never">
-                <template #header>
-                    <el-row :gutter="10" class="mb8">
-                        <el-col :span="1.5">
-                            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['patients:nutritionSetting:add']">新增营养设定</el-button>
-                        </el-col>
-                        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-                    </el-row>
-                </template>
-                <el-table v-loading="loading" border :data="settingList" @selection-change="handleSelectionChange">
-                    <el-table-column type="selection" width="55" align="center" />
-                    <el-table-column label="时间" align="center" prop="createTime" />
-                    <el-table-column label="看诊类型" align="center" prop="type">
-                        <template #default="scope">
-                            <span>{{getDictLabel(treatment_user_type ,scope.row.type )|| '--' }}</span>
-                        </template>
-                    </el-table-column>
-                    <el-table-column label="门诊/住院号" align="center" prop="outpatientNo" />
-                    <el-table-column label="营养设定方式" align="center" prop="settingType">
-                        <template #default="scope">
-                            <span>{{getDictLabel(nutrition_setting_type ,scope.row.settingType )|| '--' }}</span>
-                        </template>
-                    </el-table-column>
-                    <el-table-column label="所需热量(kcal/d)" align="center" prop="caloriesKcalPerDay" />
-                    <el-table-column label="评估医生" align="center" prop="createByUser" />
-                    <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-                        <template #default="scope">
-                            <!-- <el-tooltip content="修改" placement="top">
+      <el-card shadow="never">
+        <template #header>
+          <el-row :gutter="10" class="mb8">
+            <el-col :span="1.5">
+              <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['patients:nutritionSetting:add']">新增营养设定</el-button>
+            </el-col>
+            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+          </el-row>
+        </template>
+        <el-table v-loading="loading" border :data="settingList" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" align="center" />
+          <el-table-column label="时间" align="center" prop="createTime" />
+          <el-table-column label="看诊类型" align="center" prop="type">
+            <template #default="scope">
+              <span>{{ getDictLabel(treatment_user_type, scope.row.type) || '--' }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="门诊/住院号" align="center" prop="outpatientNo" />
+          <el-table-column label="营养设定方式" align="center" prop="settingType">
+            <template #default="scope">
+              <span>{{ getDictLabel(nutrition_setting_type, scope.row.settingType) || '--' }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="所需热量(kcal/d)" align="center" prop="caloriesKcalPerDay" />
+          <el-table-column label="评估医生" align="center" prop="createByUser" />
+          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+            <template #default="scope">
+              <!-- <el-tooltip content="修改" placement="top">
                                 <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['patients:nutritionSetting:edit']"></el-button>
                             </el-tooltip> -->
-                            <el-tooltip content="删除" placement="top">
-                                <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['patients:nutritionSetting:remove']">删除</el-button>
-                            </el-tooltip>
-                        </template>
-                    </el-table-column>
-                </el-table>
-                <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
-            </el-card>
-        </div>
-        <div>
-            <el-dialog :title="'选择营养设定'" v-model="dialog.visible" width="737px" append-to-body :close-on-click-modal="false" :show-close="true" class="nutrition-setting-dialog">
-                <el-row :gutter="20" style="margin-bottom: 10px;">
-                    <el-col :span="12">
-                        <el-button :class="['setting-type-btn', form.settingType === '1' ? 'active' : '']" style="width: 100%; height: 46px;" @click="handleSelectSettingType('1', 'BEE')">BEE</el-button>
-                    </el-col>
-                    <el-col :span="12">
-                        <el-button :class="['setting-type-btn', form.settingType === '2' ? 'active' : '']" style="width: 100%; height: 46px;" @click="handleSelectSettingType('2', 'DRIS')">DRIS</el-button>
-                    </el-col>
-                </el-row>
-                <el-row :gutter="20">
-                    <el-col :span="12">
-                        <el-button :class="['setting-type-btn', form.settingType === '3' ? 'active' : '']" style="width: 100%; height: 46px;" @click="handleSelectSettingType('3','拇指测法')">拇指测法</el-button>
-                    </el-col>
-                    <el-col :span="12">
-                        <el-button :class="['setting-type-btn', form.settingType === '4' ? 'active' : '']" style="width: 100%; height: 46px;" @click="handleSelectSettingType('4','烧伤公式')">烧伤公式</el-button>
-                    </el-col>
-                </el-row>
-            </el-dialog>
-        </div>
-        <div v-show="type=='addForm'">
-            <!-- 添加或修改营养设定对话框 -->
-            <add-form :form="form" :rules="rules" :buttonLoading="buttonLoading" :cancel="cancel" :handleCancelOne="handleCancelOne" :title="title" />
-        </div>
+              <el-tooltip content="删除" placement="top">
+                <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['patients:nutritionSetting:remove']"
+                  >删除</el-button
+                >
+              </el-tooltip>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+      </el-card>
     </div>
-
+    <div>
+      <el-dialog
+        :title="'选择营养设定'"
+        v-model="dialog.visible"
+        width="737px"
+        append-to-body
+        :close-on-click-modal="false"
+        :show-close="true"
+        class="nutrition-setting-dialog"
+      >
+        <el-row :gutter="20" style="margin-bottom: 10px">
+          <el-col :span="12">
+            <el-button
+              :class="['setting-type-btn', form.settingType === '1' ? 'active' : '']"
+              style="width: 100%; height: 46px"
+              @click="handleSelectSettingType('1', 'BEE')"
+              >BEE</el-button
+            >
+          </el-col>
+          <el-col :span="12">
+            <el-button
+              :class="['setting-type-btn', form.settingType === '2' ? 'active' : '']"
+              style="width: 100%; height: 46px"
+              @click="handleSelectSettingType('2', 'DRIS')"
+              >DRIS</el-button
+            >
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-button
+              :class="['setting-type-btn', form.settingType === '3' ? 'active' : '']"
+              style="width: 100%; height: 46px"
+              @click="handleSelectSettingType('3', '拇指测法')"
+              >拇指测法</el-button
+            >
+          </el-col>
+          <el-col :span="12">
+            <el-button
+              :class="['setting-type-btn', form.settingType === '4' ? 'active' : '']"
+              style="width: 100%; height: 46px"
+              @click="handleSelectSettingType('4', '烧伤公式')"
+              >烧伤公式</el-button
+            >
+          </el-col>
+        </el-row>
+      </el-dialog>
+    </div>
+    <div v-show="type == 'addForm'">
+      <!-- 添加或修改营养设定对话框 -->
+      <add-form :form="form" :rules="rules" :buttonLoading="buttonLoading" :cancel="cancel" :handleCancelOne="handleCancelOne" :title="title" />
+    </div>
+  </div>
 </template>
 
 <script setup name="NutritionSetting" lang="ts">
-    // 变量声明区
-    import { ref, reactive, toRefs, onMounted, getCurrentInstance, nextTick } from 'vue';
-    import { listSetting, getSetting, delSetting, addSetting, updateSetting } from '@/api/patients/nutritionSetting';
-    import { NutritionSettingVO, NutritionSettingQuery, NutritionSettingForm } from '@/api/patients/nutritionSetting/types';
-    import AddForm from './addForm.vue';
-    const emit = defineEmits(['change'])
-    import { log } from 'vxe-table';
+// 变量声明区
+import {ref, reactive, toRefs, onMounted, getCurrentInstance, nextTick} from 'vue';
+import {listSetting, getSetting, delSetting, addSetting, updateSetting} from '@/api/patients/nutritionSetting';
+import {NutritionSettingVO, NutritionSettingQuery, NutritionSettingForm} from '@/api/patients/nutritionSetting/types';
+import AddForm from './addForm.vue';
+const emit = defineEmits(['change']);
+import {log} from 'vxe-table';
 
-    const { proxy } = getCurrentInstance();
-    const { treatment_user_type, nutrition_setting_type } = toRefs(proxy ?.useDict('treatment_user_type', 'nutrition_setting_type'));
+const {proxy} = getCurrentInstance();
+const {treatment_user_type, nutrition_setting_type} = toRefs(proxy?.useDict('treatment_user_type', 'nutrition_setting_type'));
 
-    const settingList = ref < NutritionSettingVO[] > ([]);
-    const buttonLoading = ref(false);
-    const loading = ref(true);
-    const showSearch = ref(true);
-    const ids = ref < Array < string | number >> ([]);
-    const single = ref(true);
-    const multiple = ref(true);
-    const total = ref(0);
-    const type = ref('list');
-    const title = ref('');
+const settingList = ref<NutritionSettingVO[]>([]);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref<Array<string | number>>([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const type = ref('list');
+const title = ref('');
 
-    const queryFormRef = ref();
-    const NutritionSettingFormRef = ref();
+const queryFormRef = ref();
+const NutritionSettingFormRef = ref();
 
-    const dialog = reactive({
-        visible: false,
-        title: ''
-    });
+const dialog = reactive({
+  visible: false,
+  title: ''
+});
 
-    const props = defineProps({
-        patientInfo: {
-            type: Object,
-            required: true,
-            default: () => ({
-                id: '',
-                name: '',
-                age: '',
-                deptId: '',
-                gender: ''
-            })
-        }
-    });
+const props = defineProps({
+  patientInfo: {
+    type: Object,
+    required: true,
+    default: () => ({
+      id: '',
+      name: '',
+      age: '',
+      deptId: '',
+      gender: ''
+    })
+  }
+});
 
-    const initFormData: NutritionSettingForm = {
-        id: undefined,
-        caloriesKcalPerDay: undefined,
-        caloriesKcalPerKgDay: undefined,
-        caloriesKjPerDay: undefined,
-        proteinCaloriePercentage: undefined,
-        fatCaloriePercentage: undefined,
-        carbohydrateCaloriePercentage: undefined,
-        proteinGPerKgDay: undefined,
-        proteinGPerDay: undefined,
-        fatGPerKgDay: undefined,
-        fatGPerDay: undefined,
-        carbohydrateGPerKgDay: undefined,
-        carbohydrateGPerDay: undefined,
-        calcium: undefined,
-        potassium: undefined,
-        sodium: undefined,
-        magnesium: undefined,
-        phosphorus: undefined,
-        chloride: undefined,
-        iron: undefined,
-        selenium: undefined,
-        manganese: undefined,
-        fluoride: undefined,
-        molybdenum: undefined,
-        zinc: undefined,
-        copper: undefined,
-        iodine: undefined,
-        chromium: undefined,
-        vitaminA: undefined,
-        vitaminD: undefined,
-        vitaminE: undefined,
-        vitaminK: undefined,
-        vitaminBOne: undefined,
-        vitaminBTwo: undefined,
-        vitaminBSix: undefined,
-        vitaminBTwelve: undefined,
-        niacin: undefined,
-        vitaminC: undefined,
-        folicAcid: undefined,
-        choline: undefined,
-        biotin: undefined,
-        pantothenicAcid: undefined,
-        dietaryFiber: undefined,
-        settingType: undefined,
-        type: props.patientInfo ?.type,
-        deptId: props.patientInfo ?.deptId,
-        deptName: undefined,
-        outpatientNo: props.patientInfo ?.outpatientNo,
-        bmi: props.patientInfo ?.bmi,
-        height: props.patientInfo ?.height,
-        weight: props.patientInfo ?.weight,
-        activity: props.patientInfo ?.activity,
-        stressType: undefined,
-        highHip: undefined,
-        lowHip: undefined,
-        burnArea: undefined,
-        gender: props.patientInfo ?.gender,
-        age: props.patientInfo ?.age,
+const initFormData: NutritionSettingForm = {
+  id: undefined,
+  caloriesKcalPerDay: undefined,
+  caloriesKcalPerKgDay: undefined,
+  caloriesKjPerDay: undefined,
+  proteinCaloriePercentage: undefined,
+  fatCaloriePercentage: undefined,
+  carbohydrateCaloriePercentage: undefined,
+  proteinGPerKgDay: undefined,
+  proteinGPerDay: undefined,
+  fatGPerKgDay: undefined,
+  fatGPerDay: undefined,
+  carbohydrateGPerKgDay: undefined,
+  carbohydrateGPerDay: undefined,
+  calcium: undefined,
+  potassium: undefined,
+  sodium: undefined,
+  magnesium: undefined,
+  phosphorus: undefined,
+  chloride: undefined,
+  iron: undefined,
+  selenium: undefined,
+  manganese: undefined,
+  fluoride: undefined,
+  molybdenum: undefined,
+  zinc: undefined,
+  copper: undefined,
+  iodine: undefined,
+  chromium: undefined,
+  vitaminA: undefined,
+  vitaminD: undefined,
+  vitaminE: undefined,
+  vitaminK: undefined,
+  vitaminBOne: undefined,
+  vitaminBTwo: undefined,
+  vitaminBSix: undefined,
+  vitaminBTwelve: undefined,
+  niacin: undefined,
+  vitaminC: undefined,
+  folicAcid: undefined,
+  choline: undefined,
+  biotin: undefined,
+  pantothenicAcid: undefined,
+  dietaryFiber: undefined,
+  settingType: undefined,
+  type: props.patientInfo?.type,
+  deptId: props.patientInfo?.deptId,
+  deptName: undefined,
+  outpatientNo: props.patientInfo?.outpatientNo,
+  bmi: props.patientInfo?.bmi,
+  height: props.patientInfo?.height,
+  weight: props.patientInfo?.weight,
+  activity: props.patientInfo?.activity,
+  stressType: undefined,
+  highHip: undefined,
+  lowHip: undefined,
+  burnArea: undefined,
+  gender: props.patientInfo?.gender,
+  age: props.patientInfo?.age
+};
 
-    };
+const form = ref({...initFormData});
+const queryParams = ref({
+  patientId: props.patientInfo?.id,
+  dateRange: [new Date(), new Date()],
+  type: '',
+  settingType: '',
+  searchValue: '',
+  pageNum: 1,
+  pageSize: 10
+});
 
-    const form = ref({ ...initFormData });
-    const queryParams = ref({
-        patientId: props.patientInfo ?.id,
-        dateRange: [new Date(), new Date()],
-        type: '',
-        settingType: '',
-        searchValue: '',
-        pageNum: 1,
-        pageSize: 10
-    });
+const rules = ref({
+  height: [{required: true, message: '身高不能为空', trigger: 'blur'}],
+  activity: [{required: true, message: '体力活动不能为空', trigger: 'change'}],
+  // 只有在 BEE 公式下才校验应激状态
+  stressType: [
+    {
+      required: true,
+      message: '应激状态不能为空',
+      trigger: 'change',
+      validator: (rule, value, callback) => {
+        if (title.value === 'BEE' && (value === undefined || value === null || value === '')) {
+          callback(new Error('应激状态不能为空'));
+        } else {
+          callback();
+        }
+      }
+    }
+  ]
+});
 
-    const rules = ref({
-        height: [
-            { required: true, message: '身高不能为空', trigger: 'blur' }
-        ],
-        activity: [
-            { required: true, message: '体力活动不能为空', trigger: 'change' }
-        ],
-        // 只有在 BEE 公式下才校验应激状态
-        stressType: [{
-            required: true,
-            message: '应激状态不能为空',
-            trigger: 'change',
-            validator: (rule, value, callback) => {
-                if (title.value === 'BEE' && (value === undefined || value === null || value === '')) {
-                    callback(new Error('应激状态不能为空'));
-                } else {
-                    callback();
-                }
-            }
-        }]
-    });
+// 事件函数区
+const handleDelete = async (row?: NutritionSettingVO) => {
+  const _ids = row?.id || ids.value;
+  await proxy?.$modal.confirm('是否确认删除营养设定编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
+  await delSetting(_ids);
+  proxy?.$modal.msgSuccess('删除成功');
+  await getList();
+};
 
-    // 事件函数区
-    const handleDelete = async (row ? : NutritionSettingVO) => {
-        const _ids = row ?.id || ids.value;
-        await proxy ?.$modal.confirm('是否确认删除营养设定编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-        await delSetting(_ids);
-        proxy ?.$modal.msgSuccess('删除成功');
-        await getList();
-    };
+const handleExport = () => {
+  proxy?.download(
+    '/patients/nutritionSetting/export',
+    {
+      ...queryParams.value
+    },
+    `setting_${new Date().getTime()}.xlsx`
+  );
+};
 
-    const handleExport = () => {
-        proxy ?.download('/patients/nutritionSetting/export', {
-            ...queryParams.value
-        }, `setting_${new Date().getTime()}.xlsx`)
-    };
+const handleSelectSettingType = (settingType, typeName) => {
+  form.value.settingType = settingType;
+  title.value = typeName;
+  dialog.visible = false;
+  nextTick(() => {
+    type.value = 'addForm';
+  });
+};
 
-    const handleSelectSettingType = (settingType, typeName) => {
-        form.value.settingType = settingType;
-        title.value = typeName;
-        dialog.visible = false;
-        nextTick(() => {
-            type.value = 'addForm';
-        });
-    };
+// 字典label工具
+function getDictLabel(dictList: any[], value: string) {
+  if (!dictList || !Array.isArray(dictList)) return value || '--';
+  const found = dictList.find((item) => item.value === value);
+  return found ? found.label : value || '--';
+}
 
-    // 字典label工具
-    function getDictLabel(dictList: any[], value: string) {
-        if (!dictList || !Array.isArray(dictList)) return value || '--';
-        const found = dictList.find(item => item.value === value);
-        return found ? found.label : value || '--';
-    }
+const cancel = () => {
+  reset();
+  dialog.visible = false;
+};
+const handleCancel = () => {
+  type.value = 'list';
+};
+const handleCancelOne = () => {
+  getList();
+  type.value = 'list';
+};
+const reset = () => {
+  form.value = {...initFormData};
+  NutritionSettingFormRef.value?.resetFields();
+};
+const handleQuery = () => {
+  queryParams.value.pageNum = 1;
+  getList();
+};
+const resetQuery = () => {
+  queryFormRef.value?.resetFields();
+  queryParams.value.dateRange = undefined;
+  queryParams.value.type = undefined;
+  queryParams.value.settingType = undefined;
+  queryParams.value.searchValue = undefined;
+  handleQuery();
+};
+const handleSelectionChange = (selection: NutritionSettingVO[]) => {
+  ids.value = selection.map((item) => item.id);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+};
+const handleAdd = () => {
+  dialog.visible = true;
+  dialog.title = '选择营养设定方式';
+};
+const handleUpdate = async (row?: NutritionSettingVO) => {
+  reset();
+  const _id = row?.id || ids.value[0];
+  const res = await getSetting(_id);
+  Object.assign(form.value, res.data);
+  dialog.visible = true;
+  dialog.title = '修改营养设定';
+};
 
-    const cancel = () => {
-        reset();
-        dialog.visible = false;
-    };
-    const handleCancel = () => {
-        type.value = 'list';
-    };
-    const handleCancelOne = () => {
-        getList();
-        type.value = 'list';
-    };
-    const reset = () => {
-        form.value = { ...initFormData };
-        NutritionSettingFormRef.value ?.resetFields();
-    };
-    const handleQuery = () => {
-        queryParams.value.pageNum = 1;
-        getList();
-    };
-    const resetQuery = () => {
-        queryFormRef.value ?.resetFields();
-        queryParams.value.dateRange = undefined;
-        queryParams.value.type = undefined;
-        queryParams.value.settingType = undefined;
-        queryParams.value.searchValue = undefined;
-        handleQuery();
-    };
-    const handleSelectionChange = (selection: NutritionSettingVO[]) => {
-        ids.value = selection.map(item => item.id);
-        single.value = selection.length != 1;
-        multiple.value = !selection.length;
-    };
-    const handleAdd = () => {
-        dialog.visible = true;
-        dialog.title = '选择营养设定方式';
-    };
-    const handleUpdate = async (row ? : NutritionSettingVO) => {
-        reset();
-        const _id = row ?.id || ids.value[0];
-        const res = await getSetting(_id);
-        Object.assign(form.value, res.data);
-        dialog.visible = true;
-        dialog.title = '修改营养设定';
-    };
+const getList = async () => {
+  loading.value = true;
+  //  这里补充你的获取数据逻辑
+  const res = await listSetting(queryParams.value);
+  settingList.value = res.rows || [];
+  total.value = res.total;
+  loading.value = false;
+};
 
-    const getList = async () => {
-        loading.value = true;
-        //  这里补充你的获取数据逻辑
-        const res = await listSetting(queryParams.value);
-        settingList.value = res.rows || [];
-        total.value = res.total;
-        loading.value = false;
-    };
-
-    onMounted(() => {
-        getList();
-    });
+onMounted(() => {
+  getList();
+});
 </script>
 <style scoped>
-    .nutrition-setting-dialog .setting-type-btn {
-        font-size: 18px;
-        border: 1.5px solid #409eff;
-        color: #409eff;
-        background: #fff;
-        transition:
-            background 0.2s,
-            color 0.2s;
-    }
+.nutrition-setting-dialog .setting-type-btn {
+  font-size: 18px;
+  border: 1.5px solid #409eff;
+  color: #409eff;
+  background: #fff;
+  transition:
+    background 0.2s,
+    color 0.2s;
+}
 
-    .nutrition-setting-dialog .setting-type-btn.active,
-    .nutrition-setting-dialog .setting-type-btn:active,
-    .nutrition-setting-dialog .setting-type-btn:focus {
-        background: #e6f0ff;
-        color: #409eff;
-        border-color: #409eff;
-    }
-</style>
+.nutrition-setting-dialog .setting-type-btn.active,
+.nutrition-setting-dialog .setting-type-btn:active,
+.nutrition-setting-dialog .setting-type-btn:focus {
+  background: #e6f0ff;
+  color: #409eff;
+  border-color: #409eff;
+}
+</style>

Plik diff jest za duży
+ 617 - 628
src/views/patients/screening/add.vue


+ 95 - 97
src/views/patients/screening/index.vue

@@ -1,14 +1,19 @@
 <template>
   <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter"
-      :leave-active-class="proxy?.animate.searchAnimate.leave">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form ref="queryFormRef" :model="queryParams" :inline="true">
             <el-form-item prop="screeningTime">
-              <el-date-picker v-model="screeningTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
-                range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
-                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"></el-date-picker>
+              <el-date-picker
+                v-model="screeningTime"
+                value-format="YYYY-MM-DD HH:mm:ss"
+                type="daterange"
+                range-separator="-"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
+              ></el-date-picker>
             </el-form-item>
             <el-form-item label="看诊类型" prop="visitType">
               <el-select v-model="queryParams.visitType" placeholder="请选择" clearable>
@@ -38,8 +43,7 @@
       <template #header>
         <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd"
-              v-hasPermi="['system:screening:add']">新增营养筛查</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:screening:add']">新增营养筛查</el-button>
           </el-col>
           <!-- <el-col :span="1.5">
             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
@@ -59,7 +63,7 @@
 
       <el-table v-loading="loading" border :data="screeningList" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="时间" align="center" prop="screeningTime"  />
+        <el-table-column label="时间" align="center" prop="screeningTime" />
         <el-table-column label="看诊类型" align="center" prop="visitType" />
         <el-table-column label="门诊/住院号" align="center" prop="patientNo" />
         <el-table-column label="营养筛查类型" align="center" prop="configName" />
@@ -76,42 +80,41 @@
               <el-button link type="primary" icon="Print" @click="handleUpdate(scope.row)">打印</el-button>
             </el-tooltip> -->
             <el-tooltip content="删除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
-                v-hasPermi="['system:screening:remove']">删除</el-button>
+              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:screening:remove']">删除</el-button>
             </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
 
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
-        v-model:limit="queryParams.pageSize" @pagination="getList" />
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
     <!-- 添加或修改营养筛查对话框 -->
     <el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
       <div class="screening-type-grid">
-            <el-button
-              v-for="item in screeningAssessmentConfigList"
-              :key="item.configId"
-              type="primary"
-              plain 
-              class="screening-type-btn"              
-              @click="handleScreeningSelect(item.configId)"
-              style="width: 350px;margin-left:0px">            
-              {{ item.name }}
-            </el-button>
-          </div>       
+        <el-button
+          v-for="item in screeningAssessmentConfigList"
+          :key="item.configId"
+          type="primary"
+          plain
+          class="screening-type-btn"
+          @click="handleScreeningSelect(item.configId)"
+          style="width: 350px; margin-left: 0px"
+        >
+          {{ item.name }}
+        </el-button>
+      </div>
     </el-dialog>
   </div>
 </template>
 
 <script setup name="Screening" lang="ts">
-import { listScreening, getScreening, delScreening, addScreening, updateScreening } from '@/api/patients/screening';
-import { ScreeningVO, ScreeningQuery, ScreeningForm } from '@/api/patients/screening/types';
-import { listScreeningAssessmentConfig } from '@/api/system/screeningAssessmentConfig';
-import { ScreeningAssessmentConfigQuery,ScreeningAssessmentConfigVO } from '@/api/system/screeningAssessmentConfig/types';
+import {listScreening, getScreening, delScreening, addScreening, updateScreening} from '@/api/patients/screening';
+import {ScreeningVO, ScreeningQuery, ScreeningForm} from '@/api/patients/screening/types';
+import {listScreeningAssessmentConfig} from '@/api/system/screeningAssessmentConfig';
+import {ScreeningAssessmentConfigQuery, ScreeningAssessmentConfigVO} from '@/api/system/screeningAssessmentConfig/types';
 
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { treatment_user_type } = toRefs<any>(proxy?.useDict('treatment_user_type'));
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {treatment_user_type} = toRefs<any>(proxy?.useDict('treatment_user_type'));
 
 const screeningTime = ref<[DateModelType, DateModelType]>(['', '']);
 const screeningList = ref<ScreeningVO[]>([]);
@@ -126,8 +129,8 @@ const screeningAssessmentConfigList = ref<ScreeningAssessmentConfigVO[]>([]);
 const router = useRouter();
 const queryFormRef = ref<ElFormInstance>();
 const screeningFormRef = ref<ElFormInstance>();
-const { patientInfo } = defineProps<{ patientInfo: any }>()
-const emit = defineEmits(['change'])
+const {patientInfo} = defineProps<{patientInfo: any}>();
+const emit = defineEmits(['change']);
 
 const dialog = reactive<DialogOption>({
   visible: false,
@@ -144,8 +147,8 @@ const initFormData: ScreeningForm = {
   screeningScore: undefined,
   screeningConclusion: undefined,
   paymentStatus: undefined,
-  status: undefined,
-}
+  status: undefined
+};
 const data = reactive<PageData<ScreeningForm, ScreeningQuery>>({
   form: {...initFormData},
   queryParams: {
@@ -160,103 +163,91 @@ const data = reactive<PageData<ScreeningForm, ScreeningQuery>>({
     screeningConclusion: undefined,
     paymentStatus: undefined,
     status: undefined,
-    params: {
-    }
+    params: {}
   },
   rules: {
-    id: [
-      { required: true, message: "主键ID不能为空", trigger: "blur" }
-    ],
-    configId: [
-      { required: true, message: "营养筛查类型不能为空", trigger: "blur" }
-    ],
-    screeningTime: [
-      { required: true, message: "筛查时间不能为空", trigger: "blur" }
-    ],
-    visitType: [
-      { required: true, message: "看诊类型不能为空", trigger: "change" }
-    ],
-    patientNo: [
-      { required: true, message: "门诊/住院号不能为空", trigger: "blur" }
-    ],
+    id: [{required: true, message: '主键ID不能为空', trigger: 'blur'}],
+    configId: [{required: true, message: '营养筛查类型不能为空', trigger: 'blur'}],
+    screeningTime: [{required: true, message: '筛查时间不能为空', trigger: 'blur'}],
+    visitType: [{required: true, message: '看诊类型不能为空', trigger: 'change'}],
+    patientNo: [{required: true, message: '门诊/住院号不能为空', trigger: 'blur'}]
   }
 });
 
-const { queryParams, form, rules } = toRefs(data);
+const {queryParams, form, rules} = toRefs(data);
 
 /** 查询筛查/评估配置列表 */
 const getScreeningConfigList = async () => {
-  let param=ref<ScreeningAssessmentConfigQuery>({
+  let param = ref<ScreeningAssessmentConfigQuery>({
     pageNum: 1,
     type: '1',
-    pageSize: -1,
+    pageSize: -1
   });
   const res = await listScreeningAssessmentConfig(param.value);
-  screeningAssessmentConfigList.value = res.rows;   
-}
+  screeningAssessmentConfigList.value = res.rows;
+};
 
 /** 查询营养筛查列表 */
 const getList = async () => {
-  loading.value = true;    
-  queryParams.value.patientId= patientInfo.id; 
+  loading.value = true;
+  queryParams.value.patientId = patientInfo.id;
   const res = await listScreening(proxy?.addDateRange(queryParams.value, screeningTime.value));
   screeningList.value = res.rows;
   total.value = res.total;
   loading.value = false;
-}
+};
 
 /** 取消按钮 */
 const cancel = () => {
   reset();
   dialog.visible = false;
-}
+};
 
 /** 表单重置 */
 const reset = () => {
   form.value = {...initFormData};
   screeningFormRef.value?.resetFields();
-}
+};
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
   queryParams.value.pageNum = 1;
   getList();
-}
+};
 
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
   handleQuery();
-}
+};
 
 /** 多选框选中数据 */
 const handleSelectionChange = (selection: ScreeningVO[]) => {
-  ids.value = selection.map(item => item.id);
+  ids.value = selection.map((item) => item.id);
   single.value = selection.length != 1;
   multiple.value = !selection.length;
-}
+};
 
 /** 新增按钮操作 */
 const handleAdd = () => {
   reset();
   dialog.visible = true;
-  dialog.title = "选择营养筛查";
-}
+  dialog.title = '选择营养筛查';
+};
 
 /** 修改按钮操作 */
 const handleUpdate = async (row?: ScreeningVO) => {
   reset();
-  const _id = row?.id || ids.value[0]
+  const _id = row?.id || ids.value[0];
   const res = await getScreening(_id);
   Object.assign(form.value, res.data);
   dialog.visible = true;
-  dialog.title = "修改营养筛查";
-}
+  dialog.title = '修改营养筛查';
+};
 
 const handleView = async (row?: ScreeningVO) => {
-  emit('change', 'nutritionScreeningAdd',window.btoa(row.id.toString()))
-}
-
+  emit('change', 'nutritionScreeningAdd', window.btoa(row.id.toString()));
+};
 
 /** 提交按钮 */
 const submitForm = () => {
@@ -264,52 +255,54 @@ const submitForm = () => {
     if (valid) {
       buttonLoading.value = true;
       if (form.value.id) {
-        await updateScreening(form.value).finally(() =>  buttonLoading.value = false);
+        await updateScreening(form.value).finally(() => (buttonLoading.value = false));
       } else {
-        await addScreening(form.value).finally(() =>  buttonLoading.value = false);
+        await addScreening(form.value).finally(() => (buttonLoading.value = false));
       }
-      proxy?.$modal.msgSuccess("操作成功");
+      proxy?.$modal.msgSuccess('操作成功');
       dialog.visible = false;
       await getList();
     }
   });
-}
+};
 
 /** 删除按钮操作 */
 const handleDelete = async (row?: ScreeningVO) => {
   const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除营养筛查编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
+  await proxy?.$modal.confirm('是否确认删除营养筛查编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
   await delScreening(_ids);
-  proxy?.$modal.msgSuccess("删除成功");
+  proxy?.$modal.msgSuccess('删除成功');
   await getList();
-}
+};
 
 /** 导出按钮操作 */
 const handleExport = () => {
-  proxy?.download('system/screening/export', {
-    ...queryParams.value
-  }, `screening_${new Date().getTime()}.xlsx`)
-}
+  proxy?.download(
+    'system/screening/export',
+    {
+      ...queryParams.value
+    },
+    `screening_${new Date().getTime()}.xlsx`
+  );
+};
 
-const handleScreeningSelect = (configId:number) => {   
-  emit('change', 'nutritionScreeningAdd',configId)
-} 
+const handleScreeningSelect = (configId: number) => {
+  emit('change', 'nutritionScreeningAdd', configId);
+};
 
 function formatDate(date) {
-  const pad = n => n < 10 ? '0' + n : n;
-  return date.getFullYear() + '-' +
-    pad(date.getMonth() + 1) + '-' +
-    pad(date.getDate())   ;
+  const pad = (n) => (n < 10 ? '0' + n : n);
+  return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate());
 }
 
 onMounted(() => {
   getList();
-  getScreeningConfigList(); 
-  
-  let now=new Date();
-  let start=formatDate(now);
-  let end=formatDate(new Date(now.getTime()-24*60*60*1000*30));
-  screeningTime.value=[end+' 00:00:00',start+' 23:59:59'];  
+  getScreeningConfigList();
+
+  let now = new Date();
+  let start = formatDate(now);
+  let end = formatDate(new Date(now.getTime() - 24 * 60 * 60 * 1000 * 30));
+  screeningTime.value = [end + ' 00:00:00', start + ' 23:59:59'];
 });
 </script>
 
@@ -323,6 +316,11 @@ onMounted(() => {
   font-weight: normal;
   font-size: 16px;
   height: 48px;
-  border-radius: 8px;  
+  border-radius: 8px;
+  white-space: normal;
+  word-wrap: break-word;
+  text-align: center;
+  line-height: 1.2;
+  padding: 8px 12px;
 }
 </style>

+ 147 - 108
src/views/system/screeningAssessmentConfig/add.vue

@@ -4,10 +4,11 @@
     <el-row type="flex" align="middle" justify="space-between" style="margin-bottom: 16px;">
       <el-col :span="4">
         <el-button type="primary" plain @click="close" style="margin-right: 20px;margin-left: 30px;">返回</el-button>
-        <span style="font-size: 14px;  vertical-align: middle;">新增量表</span>
+        <span style="font-size: 14px;  vertical-align: middle;">{{ isEdit ? '修改量表' : '新增量表' }}</span>
       </el-col>
       <el-col :span="4" style="text-align: right;">
         <!-- <el-button type="primary" plain @click="handlePreview" style="margin-right: 8px;">预览</el-button> -->
+        <el-button type="primary" @click="editConclusion" style="margin-right: 0px;" v-if="isEdit">编辑结论</el-button>
         <el-button type="primary" @click="submitForm" style="margin-right: 30px;">保存</el-button>
       </el-col>
     </el-row>
@@ -101,12 +102,12 @@
               <el-form label-width="100px" label-position="left" :model="form" ref="screeningAssessmentConfigFormRef">
                 <el-form-item label="量表类型:" required>
                   <el-radio-group v-model="form.type">
-                    <el-radio :label="item.label" :value="item.value" v-for="item in scale_type" :key="item.value"/>                     
+                    <el-radio :label="item.label" :value="item.value" v-for="item in scale_type" :key="item.value" />
                   </el-radio-group>
-            </el-form-item>             
+                </el-form-item>
                 <el-form-item label="适用条件:" required>
                   <!-- 可留空或加说明 -->
-            </el-form-item>            
+                </el-form-item>
                 <el-form-item label="性别:" style="margin-left: 20px;">
                   <el-radio-group v-model="form.gender" style="margin-left: -50px;">
                     <el-radio label="不限" value="-1">不限</el-radio>
@@ -126,9 +127,9 @@
                 <el-form-item label="备注:">
                   <el-input type="textarea" v-model="form.remark" maxlength="500" show-word-limit placeholder="请输入"
                     :rows="3" />
-            </el-form-item>
-          </el-form>
-      </div>
+                </el-form-item>
+              </el-form>
+            </div>
 
             <div v-if="baseInfo.questionType" @click="selectBaseInfo" :class="{ selectedDiv: baseInfo.selected }">
               <span>&nbsp;</span>
@@ -174,14 +175,14 @@
 
               <div style="border-bottom: 1px solid #e5e7eb;width: 98%;" v-if="other.questionChildType == 'matrixScale'">
 
-        <el-row :gutter="10" class="mb8">
+                <el-row :gutter="10" class="mb8">
                   <el-col :span="3" style="margin-top: 30px;">
-          </el-col>
+                  </el-col>
                   <template v-for="clt in other.contentList">
                     <template v-if="clt.optionFlag">
                       <el-col :span="1" align="center" style="margin-top: 30px;margin-left: 30px;">
                         {{ clt.optionContent }}
-          </el-col>
+                      </el-col>
                     </template>
                   </template>
                 </el-row>
@@ -192,7 +193,7 @@
                       <template v-if="clt.labelFlag">
                         标题{{ idx + 1 }}:{{ clt.label }}
                       </template>
-          </el-col>
+                    </el-col>
                     <template v-for="clt2, idx in other.contentList">
                       <el-col :span="1" align="center" style="margin-left: 30px;">
                         <template v-if="clt2.optionFlag && clt.labelFlag">
@@ -202,8 +203,8 @@
                         </template>
                       </el-col>
                     </template>
-        </el-row>
-      </template>
+                  </el-row>
+                </template>
               </div>
 
               <div style="border-bottom: 1px solid #e5e7eb;width: 98%;" :class="{ selectedDiv: other.selected }"
@@ -212,7 +213,7 @@
                 <template v-if="other.questionType != 'questionTypeSelection'">
                   <el-row :gutter="10" class="mb8">
                     <el-col :span="12">
-                      <el-form-item :label="(index + 1 + (baseInfo.contentList.length>0?1:0)) + '. 标题:'" required>
+                      <el-form-item :label="(index + 1 + (baseInfo.contentList.length > 0 ? 1 : 0)) + '. 标题:'" required>
                         <el-input readonly style="width: 100%;" v-model="other.title" size="large" />
                       </el-form-item>
                     </el-col>
@@ -225,11 +226,11 @@
                     <el-col :span="4">
                     </el-col>
                   </el-row>
-          </template>
+                </template>
                 <template v-if="other.questionType == 'questionTypeSelection'">
                   <el-row :gutter="10" class="mb8">
                     <el-col :span="12">
-                      <el-form-item :label="(index + 1 + (baseInfo.contentList.length>0?1:0)) + '. 标题:'" required>
+                      <el-form-item :label="(index + 1 + (baseInfo.contentList.length > 0 ? 1 : 0)) + '. 标题:'" required>
                         <el-input style="width: 100%;" v-model="other.title" placeholder="请输入标题" size="large"
                           show-word-limit maxlength="150" />
                       </el-form-item>
@@ -394,7 +395,7 @@
                               </el-input>
                             </el-radio>
                           </el-radio-group>
-        </el-form-item>
+                        </el-form-item>
                       </el-col>
                       <el-col :span="2" align="center" style="margin-top: -5px;">
                         <miniImageUpload :limit="1" v-model="ctl.img" />
@@ -431,7 +432,7 @@
                               <template #append><el-button
                                   @click="handleMatrixScaleDelete(index, idx, true)">-</el-button></template>
                             </el-input>
-        </el-form-item>
+                          </el-form-item>
                         </template>
                       </el-col>
                       <el-col :span="4" align="center" style="margin-top: -5px;">
@@ -447,7 +448,7 @@
                       <el-col :span="3" align="center" style="margin-top: -5px;">
                         <el-input style="width: 60px;" size="large" v-model="ctl.score" />
                       </el-col>
-                      <el-col :span="3" align="left" style="margin-top: -5px;">                        
+                      <el-col :span="3" align="left" style="margin-top: -5px;">
                         <el-checkbox v-model="ctl.allowFillBlank" />
                       </el-col>
                       <el-col :span="4" align="center">
@@ -468,7 +469,7 @@
                               <template #append><el-button
                                   @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
                             </el-input>
-        </el-form-item>
+                          </el-form-item>
                         </div>
                       </el-col>
                       <el-col :span="2" align="center" style="margin-top: -5px;">
@@ -500,7 +501,7 @@
                               </el-input>
                             </el-radio>
                           </el-radio-group>
-        </el-form-item>
+                        </el-form-item>
                       </el-col>
                       <el-col :span="2" align="center" style="margin-top: -5px;">
                         <el-input style="width: 60px;" v-model="ctl.score" size="large" />
@@ -530,7 +531,7 @@
                             <template #append><el-button
                                 @click="handleOtherBtnDelete(index, idx)">-</el-button></template>
                           </el-input>
-        </el-form-item>
+                        </el-form-item>
                       </el-col>
                       <el-col :span="2" align="center" style="margin-top: -5px;">
                         <el-input style="width: 60px;" v-model="ctl.score" size="large" />
@@ -589,37 +590,84 @@
                   <el-button type="primary" icon="Delete" plain @click="deleteOtherInfo(index)">删除</el-button>
                 </div>
                 <span>&nbsp;</span>
-        </div>
-      </template>
+              </div>
+            </template>
 
 
           </el-scrollbar>
         </el-main>
       </el-container>
     </el-container>
+
+
+    <!--  修改结论 -->
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="1000px" append-to-body>
+      <el-row style="margin-bottom: 5px;" v-for="(item, index) in conclusionList">
+        <el-col :span="4">
+          <el-input v-model="item.min" placeholder="请输入" />
+        </el-col>
+        <el-col :span="1">
+          <div style="margin-top: 5px;">分</div>
+        </el-col>
+        <el-col :span="1">
+          <div style="margin-top: 5px;">-</div>
+        </el-col>
+        <el-col :span="4">
+          <el-input v-model="item.max" placeholder="请输入" />
+        </el-col>
+        <el-col :span="1">
+          <div style="margin-top: 5px;">分</div>
+        </el-col>
+        <el-col :span="9">
+          <el-input v-model="item.text" placeholder="请输入结论" type="textarea" />
+        </el-col>
+        <el-col :span="1">
+        </el-col>
+        <el-col :span="2">
+          <div class="action-buttons">
+            <el-button class="icon-btn" @click="addRow()">
+              <el-icon>
+                <Plus />
+              </el-icon>
+            </el-button>
+            <el-button class="icon-btn" @click="delRow(index)">
+              <el-icon>
+                <Delete />
+              </el-icon>
+            </el-button>
+          </div>
+        </el-col>
+      </el-row>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitConclusionForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="ScreeningAssessmentConfig" lang="ts">
 import { ref, onMounted, onUnmounted } from 'vue';
-import { listScreeningAssessmentConfig, getScreeningAssessmentConfig, delScreeningAssessmentConfig, addScreeningAssessmentConfig, updateScreeningAssessmentConfig } from '@/api/system/screeningAssessmentConfig';
+import { updateConclusion, getScreeningAssessmentConfig, delScreeningAssessmentConfig, addScreeningAssessmentConfig, updateScreeningAssessmentConfig } from '@/api/system/screeningAssessmentConfig';
 import { ScreeningAssessmentConfigVO, ScreeningAssessmentConfigQuery, ScreeningAssessmentConfigForm, QuestionAttrVO, QuestionVO } from '@/api/system/screeningAssessmentConfig/types';
-import { fa } from 'element-plus/es/locale/index.mjs';
+
 
 const route = useRoute();
 const showSystemParam = ref(true);
 const showQuestionType = ref(true);
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { arrangement_method, score_method ,scale_type} = toRefs<any>(proxy?.useDict('scale_type','arrangement_method', 'score_method'));
+const { arrangement_method, score_method, scale_type } = toRefs<any>(proxy?.useDict('scale_type', 'arrangement_method', 'score_method'));
 
-const screeningAssessmentConfigList = ref<ScreeningAssessmentConfigVO[]>([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
 const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
+const conclusionList = ref([{ min: null, max: null, text: null }]);
+const isEdit = ref(false);
+
 
 const baseInfo = ref<QuestionVO>({
   questionId: '',
@@ -631,12 +679,11 @@ const baseInfo = ref<QuestionVO>({
 });
 const otherInfo = ref<QuestionVO[]>([]);
 
-const queryFormRef = ref<ElFormInstance>();
 const screeningAssessmentConfigFormRef = ref<ElFormInstance>();
 
 const dialog = reactive<DialogOption>({
   visible: false,
-  title: ''
+  title: '修改结论'
 });
 
 const initFormData: ScreeningAssessmentConfigForm = {
@@ -645,6 +692,7 @@ const initFormData: ScreeningAssessmentConfigForm = {
   gender: '-1',
   age: '-1',
   name: undefined,
+  conclusion: undefined,
   description: undefined,
   remark: undefined,
   status: undefined,
@@ -687,78 +735,68 @@ const { queryParams, form, rules } = toRefs(data);
 const getList = async () => {
   const eId = route.params && route.params.id;
   const vId = route.params && route.params.vid;
-  let id=undefined;
-  if(vId){    
-    id=vId;
-  }else{    
-    id=eId;
+  let id = undefined;
+  if (vId) {
+    id = vId;
+  } else {
+    id = eId;
   }
 
-  if (id&&id!='0') {
-  loading.value = true;
+  if (id && id != '0') {
+    isEdit.value = true;
+    loading.value = true;
     const res = await getScreeningAssessmentConfig(id as string);
     Object.assign(form.value, res.data);
-    if(res.data.baseInfo){
+    if(form.value.conclusion){
+      conclusionList.value=JSON.parse(form.value.conclusion);
+      form.value.conclusion=null;
+    }   
+
+    if (res.data.baseInfo) {
       baseInfo.value = res.data.baseInfo;
     }
-    if(res.data.otherInfo){
-      otherInfo.value = res.data.otherInfo;      
-      otherInfo.value.forEach(item=>{
-        item.increment = item.contentList.length;                 
+    if (res.data.otherInfo) {
+      otherInfo.value = res.data.otherInfo;
+      otherInfo.value.forEach(item => {
+        item.increment = item.contentList.length;
       });
     }
-  loading.value = false;
+    loading.value = false;
   }
 }
 
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
+const addRow = () => {
+  conclusionList.value.push({ min: null, max: null, text: null });
 }
 
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  screeningAssessmentConfigFormRef.value?.resetFields();
+const submitConclusionForm = async () => {
+  let param = ref<ScreeningAssessmentConfigForm>({});
+  param.value.conclusion = JSON.stringify(conclusionList.value);
+  param.value.configId=form.value.configId;
+  await updateConclusion(param.value);
+  proxy?.$modal.msgSuccess("操作成功");
+  dialog.visible = false;
 }
 
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.value.pageNum = 1;
-  getList();
-}
 
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value?.resetFields();
-  handleQuery();
-}
 
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: ScreeningAssessmentConfigVO[]) => {
-  ids.value = selection.map(item => item.configId);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
+const delRow = (index: number) => {
+  conclusionList.value.splice(index, 1);
 }
 
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = "添加筛查/评估配置";
+/** 取消按钮 */
+const cancel = () => {
+  dialog.visible = false;
 }
 
-/** 修改按钮操作 */
-const handleUpdate = async (row?: ScreeningAssessmentConfigVO) => {
-  reset();
-  const _configId = row?.configId || ids.value[0]
-  const res = await getScreeningAssessmentConfig(_configId);
-  Object.assign(form.value, res.data);
+/**  编辑结论  */
+const editConclusion = () => {
   dialog.visible = true;
-  dialog.title = "修改筛查/评估配置";
 }
 
+
+
+
 /** 提交按钮 */
 const submitForm = () => {
   screeningAssessmentConfigFormRef.value?.validate(async (valid: boolean) => {
@@ -768,8 +806,8 @@ const submitForm = () => {
         return;
       }
 
-      let baseNum=!baseInfo.value.questionType?0:1;
-      let lineNum=0;
+      let baseNum = !baseInfo.value.questionType ? 0 : 1;
+      let lineNum = 0;
       for (let item of otherInfo.value) {
         lineNum++;
         if (!item.title || item.title.trim().length < 1) {
@@ -793,10 +831,10 @@ const submitForm = () => {
         }
       }
 
-      if(baseInfo.value.questionType&&baseInfo.value.questionType.length>0){
+      if (baseInfo.value.questionType && baseInfo.value.questionType.length > 0) {
         form.value.baseInfo = baseInfo.value;
       }
-      if(otherInfo.value&&otherInfo.value.length>0){
+      if (otherInfo.value && otherInfo.value.length > 0) {
         form.value.otherInfo = otherInfo.value;
       }
       buttonLoading.value = true;
@@ -811,26 +849,7 @@ const submitForm = () => {
   });
 }
 
-/** 删除按钮操作 */
-const handleDelete = async (row?: ScreeningAssessmentConfigVO) => {
-  const _configIds = row?.configId || ids.value;
-  await proxy?.$modal.confirm('是否确认删除筛查/评估配置编号为"' + _configIds + '"的数据项?').finally(() => loading.value = false);
-  await delScreeningAssessmentConfig(_configIds);
-  proxy?.$modal.msgSuccess("删除成功");
-  await getList();
-}
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download('system/screeningAssessmentConfig/export', {
-    ...queryParams.value
-  }, `screeningAssessmentConfig_${new Date().getTime()}.xlsx`)
-}
 
-/** 预览按钮操作 */
-const handlePreview = () => {
-  // Implementation of handlePreview function
-}
 
 /** 关闭按钮操作 */
 const close = () => {
@@ -1381,7 +1400,7 @@ function handleMatrixScaleAdd(index: number, childIndex: number, isLeft: boolean
       nameEn: 'matrix' + other.increment.toString(),
       score: '0.0',
       optionContent: undefined,
-      optionFlag: !isLeft  ,
+      optionFlag: !isLeft,
     });
     return;
   }
@@ -1398,13 +1417,13 @@ function handleMatrixScaleAdd(index: number, childIndex: number, isLeft: boolean
 
   if (effectiveNum == other.contentList.length) {
     other.contentList.push({
-      labelFlag: isLeft  ,
+      labelFlag: isLeft,
       label: undefined,
       value: undefined,
       nameEn: 'matrix' + other.increment.toString(),
       score: '0.0',
       optionContent: undefined,
-      optionFlag: !isLeft  ,
+      optionFlag: !isLeft,
     });
   } else {
     let o = other.contentList[effectiveNum];
@@ -1445,7 +1464,7 @@ function handleMatrixScaleDelete(index: number, childIndex: number, isLeft: bool
       if (!child.optionFlag) {
         other.contentList = [];
       } else {
-        child.labelFlag = false;     
+        child.labelFlag = false;
       }
     } else {
       if (!child.labelFlag) {
@@ -1787,4 +1806,24 @@ ul .el-upload--picture-card {
 :deep(#jffs label) {
   font-weight: normal;
 }
+
+.action-buttons {
+  display: flex;
+  gap: 1px;
+
+  .icon-btn {
+    padding: 6px;
+    height: 32px;
+    border: 1px solid #dcdfe6;
+
+    &:hover {
+      border-color: var(--el-color-primary);
+      color: var(--el-color-primary);
+    }
+
+    .el-icon {
+      font-size: 14px;
+    }
+  }
+}
 </style>

+ 209 - 14
src/views/system/screeningAssessmentConfig/index.vue

@@ -1,17 +1,19 @@
 <template>
   <div class="p-2">
-    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter"
+      :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form ref="queryFormRef" :model="queryParams" :inline="true">
             <el-form-item label="模板类型" prop="type">
               <el-select v-model="queryParams.type" placeholder="请选择" clearable>
-                <el-option v-for="dict in scale_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+                <el-option v-for="dict in scale_type" :key="dict.value" :label="dict.label"
+                  :value="dict.value"></el-option>
               </el-select>
-            </el-form-item>             
+            </el-form-item>
             <el-form-item label="模板名称" prop="name">
               <el-input v-model="queryParams.name" placeholder="请输入" clearable @keyup.enter="handleQuery" />
-            </el-form-item>            
+            </el-form-item>
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
               <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -25,7 +27,12 @@
       <template #header>
         <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
-            <el-button type="primary"   icon="Plus" @click="handleAdd" v-hasPermi="['system:screeningAssessmentConfig:add']">新增量表</el-button>
+            <el-button type="primary" icon="Plus" @click="handleAdd"
+              v-hasPermi="['system:screeningAssessmentConfig:add']">新增量表</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="primary" plain icon="Upload" @click="handleImport"
+              v-hasPermi="['system:diseaseLabel:import']">快速导入JSON</el-button>
           </el-col>
           <!-- <el-col :span="1.5">
             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:screeningAssessmentConfig:edit']">修改</el-button>
@@ -40,14 +47,15 @@
         </el-row>
       </template>
 
-      <el-table v-loading="loading" border :data="screeningAssessmentConfigList" >
+      <el-table v-loading="loading" border :data="screeningAssessmentConfigList">
         <!-- <el-table-column type="selection" width="55" align="center" />        @selection-change="handleSelectionChange" -->
         <el-table-column label="模板名称" align="center" prop="name" />
-        <el-table-column label="模板类型" align="center" prop="typeName" />        
+        <el-table-column label="模板类型" align="center" prop="typeName" />
         <el-table-column label="创建人" align="center" prop="createByName" />
         <el-table-column label="状态" align="center" width="100">
           <template #default="scope">
-            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
+            <el-switch v-model="scope.row.status" active-value="0" inactive-value="1"
+              @change="handleStatusChange(scope.row)"></el-switch>
           </template>
         </el-table-column>
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -56,19 +64,22 @@
               <el-button link type="primary" icon="View" @click="handleView(scope.row)">预览</el-button>
             </el-tooltip> -->
             <el-tooltip content="编辑" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(false,scope.row)" v-hasPermi="['system:screeningAssessmentConfig:edit']">编辑</el-button>
+              <el-button link type="primary" icon="Edit" @click="handleUpdate(false,scope.row)"
+                v-hasPermi="['system:screeningAssessmentConfig:edit']">编辑</el-button>
             </el-tooltip>
             <el-tooltip content="删除" placement="top">
-              <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:screeningAssessmentConfig:remove']">删除</el-button>
+              <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"
+                v-hasPermi="['system:screeningAssessmentConfig:remove']">删除</el-button>
             </el-tooltip>
             <el-tooltip content="修改结论" placement="top">
-              <el-button link type="primary" icon="Edit" @click="handleReviseConclusion(scope.row)">修改结论</el-button>
+              <el-button link type="primary" icon="Edit" @click="editConclusion(scope.row)">修改结论</el-button>
             </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
 
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
     <!-- 添加或修改筛查/评估配置对话框 -->
     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
@@ -86,7 +97,7 @@
           <el-input v-model="form.description" placeholder="请输入量表说明" />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
-            <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -96,12 +107,83 @@
         </div>
       </template>
     </el-dialog>
+
+
+    <!--  修改结论 -->
+    <el-dialog :title="dialog2.title" v-model="dialog2.visible" width="1000px" append-to-body>
+      <el-row style="margin-bottom: 5px;" v-for="(item, index) in conclusionList">
+        <el-col :span="4">
+          <el-input v-model="item.min" placeholder="请输入" />
+        </el-col>
+        <el-col :span="1">
+          <div style="margin-top: 5px;">分</div>
+        </el-col>
+        <el-col :span="1">
+          <div style="margin-top: 5px;">-</div>
+        </el-col>
+        <el-col :span="4">
+          <el-input v-model="item.max" placeholder="请输入" />
+        </el-col>
+        <el-col :span="1">
+          <div style="margin-top: 5px;">分</div>
+        </el-col>
+        <el-col :span="9">
+          <el-input v-model="item.text" placeholder="请输入结论" type="textarea" />
+        </el-col>
+        <el-col :span="1">
+        </el-col>
+        <el-col :span="2">
+          <div class="action-buttons">
+            <el-button class="icon-btn" @click="addRow()">
+              <el-icon>
+                <Plus />
+              </el-icon>
+            </el-button>
+            <el-button class="icon-btn" @click="delRow(index)">
+              <el-icon>
+                <Delete />
+              </el-icon>
+            </el-button>
+          </div>
+        </el-col>
+      </el-row>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitConclusionForm">确 定</el-button>
+          <el-button @click="cancelConclusion">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+
+    <!-- 上传excel -->
+    <el-dialog :title="dialogFile.title" v-model="dialogFile.visible" width="700px" append-to-body>
+      <el-form-item label="量表类型:" required>
+        <el-radio-group v-model="uploadType">
+          <el-radio :label="item.label" :value="item.value" v-for="item in scale_type" :key="item.value" />
+        </el-radio-group>
+      </el-form-item>
+      <el-upload drag :action="uploadFileUrl" :headers="headers" :file-list="fileList" accept=".json"
+        ref="imageUploadRef" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload"
+        :data="{type: uploadType}"
+        :on-error="handleUploadError">
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+        <div class="el-upload__text">
+          将文件拖到此处,或 <em>点击上传</em>
+        </div>
+      </el-upload>
+      <div class="el-upload__tip">
+        请上传 .json 标准格式文件
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="ScreeningAssessmentConfig" lang="ts">
-import { listScreeningAssessmentConfig,changeConfigStatus, getScreeningAssessmentConfig, delScreeningAssessmentConfig, addScreeningAssessmentConfig, updateScreeningAssessmentConfig } from '@/api/system/screeningAssessmentConfig';
+import { updateConclusion,listScreeningAssessmentConfig,changeConfigStatus, getScreeningAssessmentConfig, delScreeningAssessmentConfig, addScreeningAssessmentConfig, updateScreeningAssessmentConfig } from '@/api/system/screeningAssessmentConfig';
 import { ScreeningAssessmentConfigVO, ScreeningAssessmentConfigQuery, ScreeningAssessmentConfigForm } from '@/api/system/screeningAssessmentConfig/types';
+import { globalHeaders } from '@/utils/request';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const {scale_type} = toRefs<any>(proxy?.useDict('scale_type'));
@@ -115,15 +197,71 @@ const single = ref(true);
 const multiple = ref(true);
 const total = ref(0);
 const router = useRouter();
+const configId = ref<string>('0');
 
 const queryFormRef = ref<ElFormInstance>();
 const screeningAssessmentConfigFormRef = ref<ElFormInstance>();
 
+const baseUrl = import.meta.env.VITE_APP_BASE_API;
+const uploadFileUrl = ref(baseUrl + '/system/screeningAssessmentConfig/importFile'); 
+const headers = ref(globalHeaders());
+const fileList = ref<any[]>([]);
+const imageUploadRef = ref<ElUploadInstance>();
+const uploadType = ref('1'); 
+
+const dialogFile = reactive<DialogOption>({
+  visible: false,
+  title: '请上传'
+});
+
+/** 导出按钮操作 */
+const handleImport = () => {
+  dialogFile.visible = true;
+  fileList.value = [];
+}
+
+// 上传失败
+const handleUploadError = () => {
+  proxy?.$modal.msgError('上传Excel失败');
+  proxy?.$modal.closeLoading();
+};
+
+// 上传成功回调
+const handleUploadSuccess = (res: any, file: UploadFile) => {
+  if (res.code === 200) {
+    dialogFile.visible = false;
+    fileList.value = [];
+    proxy?.$modal.closeLoading();
+    getList();
+  } else {
+    proxy?.$modal.msgError(res.msg);
+    proxy?.$modal.closeLoading();
+  }
+  fileList.value = [];
+};
+
+
+/** 上传前loading加载 */
+const handleBeforeUpload = (file: any) => {
+   const isLt = file.size / 1024 / 1024 < 10;
+    if (!isLt) {
+      proxy?.$modal.msgError(`上传文件大小不能超过10MB!`);
+      return false;
+    }       
+  proxy?.$modal.loading('正在上传文件,请稍候...');
+  return true;
+};
+
 const dialog = reactive<DialogOption>({
   visible: false,
   title: ''
 });
 
+const dialog2 = reactive<DialogOption>({
+  visible: false,
+  title: '修改结论'
+});
+
 const initFormData: ScreeningAssessmentConfigForm = {
   configId: undefined,
   type: undefined,
@@ -163,6 +301,42 @@ const data = reactive<PageData<ScreeningAssessmentConfigForm, ScreeningAssessmen
 
 const { queryParams, form, rules } = toRefs(data);
 
+const conclusionList = ref([{ min: null, max: null, text: null }]);
+
+const addRow = () => {
+  conclusionList.value.push({ min: null, max: null, text: null });
+}
+
+const submitConclusionForm = async () => {
+  let param = ref<ScreeningAssessmentConfigForm>({});
+  param.value.conclusion = JSON.stringify(conclusionList.value);
+  param.value.configId=configId.value;
+  await updateConclusion(param.value);
+  proxy?.$modal.msgSuccess("操作成功");
+  dialog2.visible = false;
+  getList();
+}
+
+/** 取消按钮 */
+const cancelConclusion = () => {
+  dialog2.visible = false;
+}
+
+const delRow = (index: number) => {
+  conclusionList.value.splice(index, 1);
+}
+
+/**  编辑结论  */
+const editConclusion = (row?: ScreeningAssessmentConfigVO) => {
+  dialog2.visible = true;
+  if(row.conclusion){
+      conclusionList.value=JSON.parse(row.conclusion);  
+      configId.value=row.configId.toString();     
+    }else{
+      conclusionList.value=[{ min: null, max: null, text: null }];      
+    }
+}
+
 /** 查询筛查/评估配置列表 */
 const getList = async () => {
   loading.value = true;
@@ -284,3 +458,24 @@ onMounted(() => {
   getList();
 });
 </script>
+<style scoped>
+.action-buttons {
+  display: flex;
+  gap: 1px;
+
+  .icon-btn {
+    padding: 6px;
+    height: 32px;
+    border: 1px solid #dcdfe6;
+
+    &:hover {
+      border-color: var(--el-color-primary);
+      color: var(--el-color-primary);
+    }
+
+    .el-icon {
+      font-size: 14px;
+    }
+  }
+}
+</style>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików