浏览代码

膳食管理

chenying2100 1 月之前
父节点
当前提交
6910608e1d
共有 6 个文件被更改,包括 285 次插入157 次删除
  1. 24 0
      info.txt
  2. 11 0
      src/api/system/foodIngredient/types.ts
  3. 1 0
      src/types/global.d.ts
  4. 1 1
      src/utils/dict.ts
  5. 247 155
      src/views/system/recipe/add.vue
  6. 1 1
      vite.config.ts

+ 24 - 0
info.txt

@@ -133,3 +133,27 @@ CREATE TABLE sys_food_ingredient (
 
 
 
+{ "calories": "kcal", "protein": "g", "fat": "g", "carbohydrate": "g", "water": "ml", "vitamin_a": "μg", "vitamin_b2": "mg", "vitamin_c": "mg", "sodium": "mg", "iron": "mg", "phosphorus": "mg", "dietary_fiber": "g", "vitamin_b1": "mg", "niacin": "mg", "vitamin_e": "mg", "calcium": "mg", "potassium": "mg", "cholesterol": "g" }
+
+[
+  { "name": "calories", "unit": "kcal", "remark": "热量" },
+  { "name": "protein", "unit": "g", "remark": "蛋白质" },
+  { "name": "fat", "unit": "g", "remark": "脂肪" },
+  { "name": "carbohydrate", "unit": "g", "remark": "碳水化合物" },
+  { "name": "water", "unit": "ml", "remark": "水分" },
+  { "name": "vitamin_a", "unit": "μg", "remark": "维生素A" },
+  { "name": "vitamin_b2", "unit": "mg", "remark": "维生素B2" },
+  { "name": "vitamin_c", "unit": "mg", "remark": "维生素C" },
+  { "name": "sodium", "unit": "mg", "remark": "钠" },
+  { "name": "iron", "unit": "mg", "remark": "铁" },
+  { "name": "phosphorus", "unit": "mg", "remark": "磷" },
+  { "name": "dietary_fiber", "unit": "g", "remark": "膳食纤维" },
+  { "name": "vitamin_b1", "unit": "mg", "remark": "维生素B1" },
+  { "name": "niacin", "unit": "mg", "remark": "烟酸" },
+  { "name": "vitamin_e", "unit": "mg", "remark": "维生素E" },
+  { "name": "calcium", "unit": "mg", "remark": "钙" },
+  { "name": "potassium", "unit": "mg", "remark": "钾" },
+  { "name": "cholesterol", "unit": "g", "remark": "胆固醇" }
+]
+
+

+ 11 - 0
src/api/system/foodIngredient/types.ts

@@ -157,6 +157,17 @@ export interface FoodIngredientVO {
 
   quantity: number;
 
+  bigCategory: string;
+
+  subCategory: string;
+
+  nutrientName: string;
+
+  nutrientQuantity: number;
+
+  nutrientRatio: string;
+
+  nutrientRefVal: string;
 }
 
 export interface FoodIngredientForm extends BaseEntity {

+ 1 - 0
src/types/global.d.ts

@@ -60,6 +60,7 @@ declare global {
    */
   declare interface DictDataOption {
     label: string;
+    remark: string;
     value: string;
     elTagType?: ElTagType;
     elTagClass?: string;

+ 1 - 1
src/utils/dict.ts

@@ -16,7 +16,7 @@ export const useDict = (...args: string[]): { [key: string]: DictDataOption[] }
     } else {
       await getDicts(dictType).then((resp) => {
         res.value[dictType] = resp.data.map(
-          (p): DictDataOption => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass })
+          (p): DictDataOption => ({ label: p.dictLabel, value: p.dictValue, elTagType: p.listClass, elTagClass: p.cssClass,remark: p.remark})
         );
         useDictStore().setDict(dictType, res.value[dictType]);
       });

+ 247 - 155
src/views/system/recipe/add.vue

@@ -20,7 +20,7 @@
               <el-form-item label="基本膳食" prop="baseDiet">
                 <el-radio-group v-model="form.baseDiet" :disabled="isView">
                   <el-radio v-for="item in dietary_types" :key="item.value" :label="item.value">{{ item.label
-                    }}</el-radio>
+                  }}</el-radio>
                 </el-radio-group>
               </el-form-item>
             </el-col>
@@ -152,8 +152,8 @@
         <el-divider />
         <div style="font-size: 14px;margin-top: -10px;margin-bottom: -10px;">食材组成</div>
         <el-divider />
-        <div style="margin-top: 10px; margin-bottom: 20px;"><span>食材总量:{{quantitySum}} g</span><span
-            style="margin-left: 100px;">膳食总热量:{{caloriesSum}}kcal</span></div>
+        <div style="margin-top: 10px; margin-bottom: 20px;"><span>食材总量:{{ quantitySum }} g</span><span
+            style="margin-left: 100px;">膳食总热量:{{ caloriesSum }}kcal</span></div>
 
 
         <el-table border :data="selectedIngredientListBak">
@@ -163,7 +163,7 @@
             <template #default="scope">
               <el-input v-model="scope.row.quantity" placeholder="请输入" :disabled="isView"
                 @input="editFoodquantity(scope.row)">
-                <template #append><span>{{scope.row.unitName}}</span></template>
+                <template #append><span>{{ scope.row.unitName }}</span></template>
               </el-input>
             </template>
           </el-table-column>
@@ -472,50 +472,53 @@
 
 
   <!-- 营养数据分析 -->
-  <el-dialog :title="dialog4.title" v-model="dialog4.visible" width="70%" append-to-body  >
+  <el-dialog :title="dialog4.title" v-model="dialog4.visible" width="70%" append-to-body>
     <div class="p-2">
       <el-menu class="el-menu-demo" mode="horizontal" @select="handleMenumSelect" :default-active="currentIndex">
         <el-menu-item index="1">三大营养素分析</el-menu-item>
         <el-menu-item index="2">营养数据分析</el-menu-item>
       </el-menu>
-    </div> 
+    </div>
 
-    <el-row :gutter="10" class="mb8" v-show="leftIndex==currentIndex">
+    <el-row :gutter="10" class="mb8" v-show="leftIndex == currentIndex">
       <el-col :span="14">
-        <div style="margin-top: 20px;margin-bottom: 20px;">实际热量:26.90kcal/d</div>
+        <div style="margin-top: 20px;margin-bottom: 20px;">实际热量:{{ leftCalories }}kcal/d</div>
         <div style="height: 300px;">
-          <el-table border stripe :data="diseaseLabelList" @select-all="handleSelectAllChange"
-            @select="handleSelectChange" ref="diseaseLabelRef" @selection-change="handleSelectionChange">             
-            <el-table-column label="三大营养素" align="center" prop="labelName" />
-            <el-table-column label="质量(g)" align="center" prop="labelCode" />
-            <el-table-column label="热量占比" align="center" prop="categoryName" />
-            <el-table-column label="参考值" align="center"/>             
+          <el-table border stripe :data="leftList">
+            <el-table-column label="三大营养素" align="center" prop="nutrientName" />
+            <el-table-column label="质量(g)" align="center" prop="nutrientQuantity" >
+              <template #default="scope">
+                {{ scope.row.nutrientQuantity.toFixed(4)}}
+              </template>
+            </el-table-column>
+            <el-table-column label="热量占比" align="center" prop="nutrientRatio" />
+            <el-table-column label="参考值" align="center" prop="nutrientRefVal" />
           </el-table>
-        </div>         
+        </div>
       </el-col>
       <el-col :span="10" align="center">
         <div style="height: 300px;">
           <v-chart :option="pieOption" style="width: 400px; height: 200px;" class="chart-center" />
-        </div>         
+        </div>
       </el-col>
     </el-row>
 
-    <el-row :gutter="10" class="mb8" v-show="rightIndex==currentIndex">
+    <el-row :gutter="10" class="mb8" v-show="rightIndex == currentIndex">
       <el-col :span="24">
         <div style="height: 400px;overflow-y: scroll;">
-          <el-table border stripe :data="diseaseLabelList" @select-all="handleSelectAllChange"
-            @select="handleSelectChange" ref="diseaseLabelRef" @selection-change="handleSelectionChange">
-            <el-table-column label="元素名称" align="center" prop="labelName" />
-            <el-table-column label="单位" align="center" prop="labelCode" />
-            <el-table-column label="食谱营养素含量" align="center" prop="categoryName" />
+          <el-table border stripe :data="rightList">
+            <el-table-column label="元素名称" align="center" prop="nutrientName" />
+            <el-table-column label="单位" align="center" prop="nutrientUnit" />
+            <el-table-column label="食谱营养素含量" align="center" prop="nutrientQuantity" />
           </el-table>
-        </div>         
-      </el-col>       
+        </div>
+      </el-col>
     </el-row>
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="24" align="center">
-        <el-button type="primary" @click="handleSelectedconfirm">&nbsp;&nbsp;&nbsp;确定&nbsp;&nbsp;&nbsp;</el-button>         
+        <el-button type="primary"
+          @click="dialog4.visible = !dialog4.visible">&nbsp;&nbsp;&nbsp;确定&nbsp;&nbsp;&nbsp;</el-button>
       </el-col>
     </el-row>
   </el-dialog>
@@ -526,20 +529,20 @@ import { listTree } from '@/api/system/foodCategory';
 import { FoodCategoryVO } from '@/api/system/foodCategory/types';
 import { listDiseaseLabel, getDiseaseLabel, delDiseaseLabel, addDiseaseLabel, updateDiseaseLabel } from '@/api/system/diseaseLabel';
 import { DiseaseLabelVO, DiseaseLabelQuery, DiseaseLabelForm } from '@/api/system/diseaseLabel/types';
-import { listRecipe, getRecipe, delRecipe, addRecipe, updateRecipe,nutrientAnalysis } from '@/api/system/recipe';
+import { listRecipe, getRecipe, delRecipe, addRecipe, updateRecipe, nutrientAnalysis } from '@/api/system/recipe';
 import { RecipeVO, RecipeQuery, RecipeForm } from '@/api/system/recipe/types';
 import { listRecipeCategory, getRecipeCategory, delRecipeCategory, addRecipeCategory, updateRecipeCategory } from '@/api/system/recipeCategory';
 import { RecipeCategoryVO, RecipeCategoryQuery, RecipeCategoryForm } from '@/api/system/recipeCategory/types';
 import { DeptTreeVO } from '@/api/system/dept/types';
 import api from '@/api/system/user';
-import { FoodIngredientVO,FoodIngredientQuery } from '@/api/system/foodIngredient/types';
+import { FoodIngredientVO, FoodIngredientQuery } from '@/api/system/foodIngredient/types';
 import { listFoodIngredient, getFoodIngredient, delFoodIngredient, addFoodIngredient, updateFoodIngredient } from '@/api/system/foodIngredient';
- 
-  
+
+
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { intelligent_recommendation, meal_times, dietary_types, disease_label } = toRefs<any>(
-  proxy?.useDict('intelligent_recommendation', 'meal_times', 'dietary_types', 'disease_label'));
+const { intelligent_recommendation, meal_times, dietary_types, disease_label, nutrient_reference } = toRefs<any>(
+  proxy?.useDict('intelligent_recommendation', 'meal_times', 'dietary_types', 'disease_label', 'nutrient_reference'));
 
 const foodCategoryList = ref<FoodCategoryVO[]>([]);
 const diseaseLabelFormRef = ref<ElFormInstance>();
@@ -564,25 +567,31 @@ const foodIngredientList = ref<FoodIngredientVO[]>([]);
 const selectedIngredientList = ref<FoodIngredientVO[]>([]);
 const selectedIngredientListBak = ref<FoodIngredientVO[]>([]);
 const foodIngredienRef = ref<ElTableInstance>();
-   
+
+const leftList = ref<FoodIngredientVO[]>([]);
+const leftCalories = ref<number>(0.0);
+const rightList = ref<FoodIngredientVO[]>([]);
+
 const caloriesSum = ref('0.0000');
 const quantitySum = ref('0.00');
 
 const leftIndex = ref('1')
-const rightIndex  = ref('2')
-const currentIndex  = ref('1')
+const rightIndex = ref('2')
+const currentIndex = ref('1')
+
+
 const pieOption = ref({
   legend: {
     orient: 'horizontal',
-    bottom:'bottom',
-    data: ['蛋白质 30%', '脂肪 20%', '碳水化合物 50%']    
+    bottom: 'bottom',
+    data: ['蛋白质 30%', '脂肪 20%', '碳水化合物 50%']
   },
-  title:{
-    text:'三大营养素元素质量占比',     
-    left:'center'    
+  title: {
+    text: '三大营养素元素质量占比',
+    left: 'center'
   },
   series: [
-    {      
+    {
       type: 'pie',
       radius: ['50%', '70%'],
       avoidLabelOverlap: false,
@@ -603,7 +612,7 @@ const pieOption = ref({
       data: [
         { value: 30, name: '蛋白质 30%' },
         { value: 20, name: '脂肪 20%' },
-        { value: 50, name: '碳水化合物 50%' },        
+        { value: 50, name: '碳水化合物 50%' },
       ]
     }
   ]
@@ -747,17 +756,17 @@ const data = reactive<PageData<RecipeForm, RecipeQuery>>({
     ],
     price: [
       { required: true, message: "食谱价格不能为空", trigger: "blur" }
-    ],    
+    ],
   }
 });
 
 const { queryParams, form, rules } = toRefs(data);
 
 /** 查询食材分类列表 */
-const getListTree = async () => {   
-  const res = await listTree();  
+const getListTree = async () => {
+  const res = await listTree();
   foodCategoryList.value = res.rows;
-   
+
 }
 
 /** 关闭按钮 */
@@ -893,7 +902,7 @@ const handleSelectChange2 = (selection: DiseaseLabelVO[], row: DiseaseLabelVO) =
     selecteddiseaseLabelList2.value = tList.value;
   }
 }
- 
+
 
 /** 多选框选中数据 */
 const handleSelectAllChange3 = (selection: FoodIngredientVO[]) => {
@@ -928,7 +937,7 @@ const handleSelectChange3 = (selection: FoodIngredientVO[], row: FoodIngredientV
     selectedIngredientList.value.push(row);
   } else {
     let tList = ref<FoodIngredientVO[]>([]);
-      selectedIngredientList.value.forEach(item => {
+    selectedIngredientList.value.forEach(item => {
       if (item.foodIngredientId != row.foodIngredientId) {
         tList.value.push(item);
       }
@@ -969,7 +978,7 @@ const handleSelectedDelete2 = (row?: DiseaseLabelVO[]) => {
   }
 }
 
- 
+
 
 /** 查询食谱管理列表 */
 const getRecipeCategoryList = async () => {
@@ -1054,10 +1063,10 @@ const handleSelectedconfirm2 = async () => {
 }
 
 const handleSelectedconfirm3 = async () => {
-  dialog3.visible = false;   
-  selectedIngredientListBak.value = selectedIngredientList.value; 
-  selectedIngredientList.value=[];  
-  foodIngredienRef.value?.clearSelection();  
+  dialog3.visible = false;
+  selectedIngredientListBak.value = selectedIngredientList.value;
+  selectedIngredientList.value = [];
+  foodIngredienRef.value?.clearSelection();
 }
 
 const addDiseaseLabelDialog = async () => {
@@ -1162,40 +1171,40 @@ const diseaseLabelSubmitForm2 = async () => {
 
 /** 查询食材管理列表 */
 const getListFoodIngredient = async () => {
-  const res = await listFoodIngredient(foodIngredientQuery.value);  
+  const res = await listFoodIngredient(foodIngredientQuery.value);
   foodIngredientList.value = res.rows;
-  totalFood.value = res.total; 
-  if (res.rows&&res.rows.length>0&&selectedIngredientList.value&&selectedIngredientList.value.length>0) {
+  totalFood.value = res.total;
+  if (res.rows && res.rows.length > 0 && selectedIngredientList.value && selectedIngredientList.value.length > 0) {
     setTimeout(() => {
       let tJson = ref({})
-    selectedIngredientList.value.forEach(item => {
-      tJson.value[item.foodIngredientId] = true;
-    })
-    
-    foodIngredientList.value.forEach(item => {
-      if (tJson.value[item.foodIngredientId]) {        
-        foodIngredienRef.value.toggleRowSelection(item, true);
-      }
-    })
-    }, 500);  
+      selectedIngredientList.value.forEach(item => {
+        tJson.value[item.foodIngredientId] = true;
+      })
+
+      foodIngredientList.value.forEach(item => {
+        if (tJson.value[item.foodIngredientId]) {
+          foodIngredienRef.value.toggleRowSelection(item, true);
+        }
+      })
+    }, 500);
   }
 }
 
 const handleNodeClick = async (data: FoodCategoryVO) => {
-  if(foodIngredientQuery.value.foodCategoryId!=data.foodCategoryId){
-    foodIngredientQuery.value.foodCategoryId=data.foodCategoryId;
-    await getListFoodIngredient(); 
+  if (foodIngredientQuery.value.foodCategoryId != data.foodCategoryId) {
+    foodIngredientQuery.value.foodCategoryId = data.foodCategoryId;
+    await getListFoodIngredient();
   }
 }
 
 const openAddFoodDialog = async () => {
   dialog3.visible = true;
   dialog3.title = '添加食材';
-  foodIngredientQuery.value.name=undefined;
-  foodIngredientQuery.value.foodCategoryId=undefined;
+  foodIngredientQuery.value.name = undefined;
+  foodIngredientQuery.value.foodCategoryId = undefined;
   await getListTree();
   await getListFoodIngredient();
- 
+
   if (selectedIngredientListBak.value && selectedIngredientListBak.value.length > 0) {
     let dataMap = ref({});
     selectedIngredientListBak.value.forEach(item => {
@@ -1212,41 +1221,41 @@ const openAddFoodDialog = async () => {
 }
 
 const editFoodquantity = async (data: FoodIngredientVO) => {
-   let quantity=Number(data.quantity)/100;
-   let calories=Number(data.calories); 
-   data.caloriesForInput=Math.floor(quantity*calories*100)/100;
-
-   let qSum=ref(0.0);
-   let cSum=ref(0.0);
-   selectedIngredientListBak.value.forEach(item=>{
-    if(item.caloriesForInput){
-      cSum.value+=item.caloriesForInput;
+  let quantity = Number(data.quantity) / 100;
+  let calories = Number(data.calories);
+  data.caloriesForInput = Math.floor(quantity * calories * 100) / 100;
+
+  let qSum = ref(0.0);
+  let cSum = ref(0.0);
+  selectedIngredientListBak.value.forEach(item => {
+    if (item.caloriesForInput) {
+      cSum.value += item.caloriesForInput;
     }
-    if(item.quantity){
-      qSum.value+=Number(item.quantity);
+    if (item.quantity) {
+      qSum.value += Number(item.quantity);
     }
-   });    
-   caloriesSum.value=(Math.floor(cSum.value*100)/100).toString();
-   quantitySum.value=(Math.floor(qSum.value*100)/100).toString();
+  });
+  caloriesSum.value = (Math.floor(cSum.value * 100) / 100).toString();
+  quantitySum.value = (Math.floor(qSum.value * 100) / 100).toString();
 }
 
 const deleteFoodquantity = async (data: FoodIngredientVO) => {
   let tList = ref<FoodIngredientVO[]>([]);
   selectedIngredientListBak.value.forEach(item => {
-    if(data.foodIngredientId!=item.foodIngredientId){
+    if (data.foodIngredientId != item.foodIngredientId) {
       tList.value.push(item);
     }
   });
-  selectedIngredientListBak.value= tList.value
-  selectedIngredientList.value=[];
-  foodIngredienRef.value?.clearSelection(); 
+  selectedIngredientListBak.value = tList.value
+  selectedIngredientList.value = [];
+  foodIngredienRef.value?.clearSelection();
 }
 
 /** 提交按钮 */
-const submitForm = () => {  
+const submitForm = () => {
   foodIngredientFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
-      if(!selectedIngredientListBak.value||selectedIngredientListBak.value.length==0){
+      if (!selectedIngredientListBak.value || selectedIngredientListBak.value.length == 0) {
         proxy?.$modal.msgError("请先添加【食材组成】部分的信息");
         return;
       }
@@ -1255,23 +1264,23 @@ const submitForm = () => {
       Object.assign(params.value, form.value);
       params.value.suitableDept = form.value.suitableDeptList.join(',')
       params.value.suitableDisease = selecteddiseaseLabelList.value.map(v => v.labelId).join(',')
-      params.value.avoidDisease = selecteddiseaseLabelList2.value.map(v => v.labelId).join(',')       
+      params.value.avoidDisease = selecteddiseaseLabelList2.value.map(v => v.labelId).join(',')
       params.value.mealTime = params.value.mealTimes.join(',')
-      params.value.foodList=[];
+      params.value.foodList = [];
 
-      for(let item of selectedIngredientListBak.value){
-        let dataJSon={};
-        dataJSon['foodIngredientId']=item.foodIngredientId;
-        dataJSon['quantity']=item.quantity;
-        if(!item.quantity){
+      for (let item of selectedIngredientListBak.value) {
+        let dataJSon = {};
+        dataJSon['foodIngredientId'] = item.foodIngredientId;
+        dataJSon['quantity'] = item.quantity;
+        if (!item.quantity) {
           buttonLoading.value = false;
           proxy?.$modal.msgError("【食材用量】不能为空");
           return;
         }
-        dataJSon['calories']=item.caloriesForInput;
-        dataJSon['remark']=item.remark;
+        dataJSon['calories'] = item.caloriesForInput;
+        dataJSon['remark'] = item.remark;
         params.value.foodList.push(dataJSon);
-      }       
+      }
 
       if (form.value.recipeId) {
         await updateRecipe(params.value).finally(() => buttonLoading.value = false);
@@ -1279,7 +1288,7 @@ const submitForm = () => {
         await addRecipe(params.value).then(res => {
           form.value.recipeId = res.data;
         }).finally(() => buttonLoading.value = false);
-      }      
+      }
       proxy?.$modal.msgSuccess("操作成功");
       close();
     }
@@ -1290,77 +1299,154 @@ const submitForm = () => {
 const getList = async () => {
   const recipeId = route.params && route.params.id;
   const vRecipeId = route.params && route.params.vid;
-  let id=undefined;
-  if(vRecipeId){
-    isView.value=true;
-    id=vRecipeId;
-  }else{
-    isView.value=false ;
-    id=recipeId;
+  let id = undefined;
+  if (vRecipeId) {
+    isView.value = true;
+    id = vRecipeId;
+  } else {
+    isView.value = false;
+    id = recipeId;
   }
-  
-  if (id&&id!='0') {
+
+  if (id && id != '0') {
     dataLoading.value = true;
     const res = await getRecipe(id as string);
     Object.assign(form.value, res.data);
-     
-    if(res.data.suitableDept&&res.data.suitableDept.length>0){
-      form.value.suitableDeptList=res.data.suitableDept.split(',');
-    } 
-    if(res.data.avoidDiseaseList&&res.data.avoidDiseaseList.length>0){
-      selecteddiseaseLabelListBak2.value=res.data.avoidDiseaseList;
-      selecteddiseaseLabelList2.value=res.data.avoidDiseaseList;
+
+    if (res.data.suitableDept && res.data.suitableDept.length > 0) {
+      form.value.suitableDeptList = res.data.suitableDept.split(',');
+    }
+    if (res.data.avoidDiseaseList && res.data.avoidDiseaseList.length > 0) {
+      selecteddiseaseLabelListBak2.value = res.data.avoidDiseaseList;
+      selecteddiseaseLabelList2.value = res.data.avoidDiseaseList;
       form.value.avoidDisease = selecteddiseaseLabelList2.value.map(v => v.labelName).join(',')
-    }  
-    if(res.data.suitableDiseaseList&&res.data.suitableDiseaseList.length>0){
-      selecteddiseaseLabelListBak.value=res.data.suitableDiseaseList;
-      selecteddiseaseLabelList.value=res.data.suitableDiseaseList;
+    }
+    if (res.data.suitableDiseaseList && res.data.suitableDiseaseList.length > 0) {
+      selecteddiseaseLabelListBak.value = res.data.suitableDiseaseList;
+      selecteddiseaseLabelList.value = res.data.suitableDiseaseList;
       form.value.suitableDisease = selecteddiseaseLabelList.value.map(v => v.labelName).join(',')
-    } 
-    if(res.data.mealTime&&res.data.mealTime.length>0){      
+    }
+    if (res.data.mealTime && res.data.mealTime.length > 0) {
       form.value.mealTimes = res.data.mealTime.split(',')
-    }     
-    if(res.data.foodList&&res.data.foodList.length>0){
-      selectedIngredientListBak.value=res.data.foodList;       
-      let qSum=ref(0.0);
-      let cSum=ref(0.0);
-      selectedIngredientListBak.value.forEach(item=>{
-        let quantity=Number(item.quantity)/100;
-        let calories=Number(item.calories);
-        item.caloriesForInput=Math.floor(quantity*calories*100)/100;
-
-        if(item.caloriesForInput){
-          cSum.value+=item.caloriesForInput;
+    }
+    if (res.data.foodList && res.data.foodList.length > 0) {
+      selectedIngredientListBak.value = res.data.foodList;
+      let qSum = ref(0.0);
+      let cSum = ref(0.0);
+      selectedIngredientListBak.value.forEach(item => {
+        let quantity = Number(item.quantity) / 100;
+        let calories = Number(item.calories);
+        item.caloriesForInput = Math.floor(quantity * calories * 100) / 100;
+
+        if (item.caloriesForInput) {
+          cSum.value += item.caloriesForInput;
         }
-        if(item.quantity){
-          qSum.value+=Number(item.quantity);
+        if (item.quantity) {
+          qSum.value += Number(item.quantity);
         }
       });
-      caloriesSum.value=(Math.floor(cSum.value*100)/100).toString();
-      quantitySum.value=(Math.floor(qSum.value*100)/100).toString();
-    }     
-    
+      caloriesSum.value = (Math.floor(cSum.value * 100) / 100).toString();
+      quantitySum.value = (Math.floor(qSum.value * 100) / 100).toString();
+    }
+
     dataLoading.value = false;
-  }  
+  }
 }
 
 const handleMenumSelect = async (key: string, keyPath: string[]) => {
-  currentIndex.value=key.toString()
+  currentIndex.value = key.toString()
 }
 
-const showNutrientAnalysisDialog =async ( ) => {
-  dialog4.visible=true;
-  dialog4.title='营养数据分析';   
+const nutrientAnalysisLeftData = async () => {
+  let dataTemplate = JSON.stringify({
+    nutrientName: '',
+    nutrientQuantity: 0,
+    nutrientRatio: 0,
+    nutrientRefVal: ''
+  })
+
+  leftList.value=[];
+  let protein = ref<FoodIngredientVO>();
+  let fat = ref<FoodIngredientVO>();
+  let carbohydrate = ref<FoodIngredientVO>();
+  protein.value = JSON.parse(dataTemplate);
+  fat.value = JSON.parse(dataTemplate);
+  carbohydrate.value = JSON.parse(dataTemplate);
+  leftList.value.push(protein.value);
+  leftList.value.push(fat.value);
+  leftList.value.push(carbohydrate.value);
+
+  let nrJson = {};
+  nutrient_reference.value.forEach(nr => {
+    nrJson[nr.label] = nr;
+  })
+  protein.value.nutrientRefVal = nrJson['nutrient_protein'].value;
+  fat.value.nutrientRefVal = nrJson['nutrient_fat'].value;
+  carbohydrate.value.nutrientRefVal = nrJson['nutrient_carbohydrate'].value;
+  protein.value.nutrientName = '蛋白质';
+  fat.value.nutrientName = '脂肪';
+  carbohydrate.value.nutrientName = '碳水化合物';
+
+  let sum: number = 0.0; 
+
+  selectedIngredientListBak.value.forEach(item => {
+    protein.value.nutrientQuantity += Number(item.protein);
+    fat.value.nutrientQuantity += Number(item.fat);
+    carbohydrate.value.nutrientQuantity += Number(item.carbohydrate);
+    sum += protein.value.nutrientQuantity + fat.value.nutrientQuantity + carbohydrate.value.nutrientQuantity;
+    leftCalories.value += Number(item.caloriesForInput);
+  })  
+
+  protein.value.nutrientRatio = (sum > 0 ? (protein.value.nutrientQuantity / sum * 100).toFixed(2) : '0.00') + '%';
+  fat.value.nutrientRatio = (sum > 0 ? (fat.value.nutrientQuantity / sum * 100).toFixed(2) : '0.00') + '%';
+  carbohydrate.value.nutrientRatio = (sum > 0 ? (carbohydrate.value.nutrientQuantity / sum * 100).toFixed(2) : '0.00') + '%';
+ 
+  pieOption.value.legend.data = []
+  pieOption.value.series[0].data = []
+  leftList.value.forEach(item => {
+    pieOption.value.series[0].data.push({ value: Number(item.nutrientRatio.replace('%', '')), name: item.nutrientName + ' ' + item.nutrientRatio })
+    pieOption.value.legend.data.push(item.nutrientName + ' ' + item.nutrientRatio);
+  });
+
+  return nrJson['nutritional_data_analysis'].remark
 }
 
-// nutrientAnalysis
+
+const nutrientAnalysisRightData = async (jsonStr:string) => {
+  let nutritionalDataAnalysis =  JSON.parse(jsonStr);
+  nutritionalDataAnalysis.forEach((na:any) => {
+    let showData={}
+    selectedIngredientListBak.value.forEach(item => {
+      if(!showData['nutrientName']){
+        showData['nutrientUnit'] =na.unit;
+        showData['nutrientName'] = na.remark;
+        showData['nutrientQuantity'] = item[na.name]?Number(item[na.name]) : 0;
+      } else{
+        showData['nutrientQuantity'] = (item[na.name]?Number(item[na.name]):0)+showData['nutrientQuantity'];
+      }       
+  });
+   
+   rightList.value.push(JSON.parse(JSON.stringify(showData)));
+  });  
+}
+
+const nutrientAnalysisData = async () => {
+  let jsonStr:string=await nutrientAnalysisLeftData();
+  await nutrientAnalysisRightData(jsonStr);  
+}
+
+const showNutrientAnalysisDialog = async () => {
+  dialog4.visible = true;
+  dialog4.title = '营养数据分析';
+  nutrientAnalysisData();
+}
 
 
 onMounted(() => {
   getDiseaseLabelList()
   getDeptTree();
-  getRecipeCategoryList(); 
-  getList();  
+  getRecipeCategoryList();
+  getList();
 });
 </script>
 
@@ -1402,12 +1488,18 @@ onMounted(() => {
 .el-pagination__sizes {
   width: 100px;
 }
+
 .chart-center {
   display: flex;
-  flex-direction: column;      /* 垂直方向排列 */
-  justify-content: center;     /* 垂直居中 */
-  align-items: center;         /* 水平居中 */
-  height: 100%;                /* 父容器需有高度 */
-  min-height: 300px;           /* 可根据需要设置 */
+  flex-direction: column;
+  /* 垂直方向排列 */
+  justify-content: center;
+  /* 垂直居中 */
+  align-items: center;
+  /* 水平居中 */
+  height: 100%;
+  /* 父容器需有高度 */
+  min-height: 300px;
+  /* 可根据需要设置 */
 }
 </style>

+ 1 - 1
vite.config.ts

@@ -29,7 +29,7 @@ export default defineConfig(({ mode, command }) => {
       open: true,
       proxy: {
         [env.VITE_APP_BASE_API]: {
-          target: 'http://localhost:8080',
+          target: 'http://localhost:8081',
           changeOrigin: true,
           ws: true,
           rewrite: (path) => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')