<template>
<a-row :gutter="16">
<a-col :span="6">
<div class="left">
<a-form :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item style="margin-bottom: 8px">
<template #label><span title="库">库选择</span></template>
<j-dict-select-tag
v-model:value="selectedLibrary"
placeholder="请选择库"
allow-clear
:options="libraryOptions"
@change="handleLibraryChange"
/>
</a-form-item>
<a-form-item>
<template #label><span title="类别">类别</span></template>
<j-dict-select-tag
v-model:value="selectedCategory"
placeholder="请选择类别"
allow-clear
:options="categoryOptions"
@change="handleCategoryChange"
:disabled="!selectedLibrary"
/>
</a-form-item>
<a-form>
<a-form-item style="width: 100%">
<a-input v-model:value="dishName" placeholder="请输入菜肴名" allow-clear @change="handleSearch"></a-input>
</a-form-item>
</a-form>
</a-form>
<div class="dishes">
<a-list :data-source="dishList" :pagination="pagination" bordered class="dish-list">
<template #renderItem="{ item }">
<a-list-item class="dish-item" @click="handleDishClick(item)" :class="{ 'active-dish': selectedDishId === item.id }">
{{ item.name }}
</a-list-item>
</template>
</a-list>
</div>
</div>
</a-col>
<a-col :span="18">
<div class="right">
<div style="display: flex; justify-content: space-between; height: 30px; margin-top: 5px">
<div style="width: 200px"
><a-form :label-col="labelCol1" :wrapper-col="wrapperCol1">
<a-form-item>
<template #label><span title="餐次">餐次</span></template>
<j-dict-select-tag v-model:value="status" placeholder="请选择" allow-clear dictCode="medical.foodplan.type" />
</a-form-item> </a-form
></div>
<div style="display: flex; flex-direction: row-reverse; color: #fff">
<button style="margin-left: 5px; background-color: green; padding: 0 15px; border-radius: 5px" @click="handleIssue">下达</button>
<!-- <button style="margin-left: 5px; background-color: blueviolet; padding: 0 15px; border-radius: 5px">分析报告</button>
<button style="margin-left: 5px; background-color: blue; padding: 0 15px; border-radius: 5px">设为经典</button>
<button style="margin-left: 5px; background-color: blue; padding: 0 15px; border-radius: 5px">调用经典</button>
<button style="margin-left: 5px; background-color: skyblue; padding: 0 15px; border-radius: 5px">食谱推荐</button> -->
</div>
</div>
<div style="display: flex; height: 30px; margin-top: 7px; margin-left: 5px">
<button
v-for="day in 7"
:key="day"
@click="changeDay(day)"
:style="{
backgroundColor: selectedDay === day ? '#e6f7ff' : '#fff',
border: `1px solid ${selectedDay === day ? '#1890ff' : '#eee'}`,
color: selectedDay === day ? '#1890ff' : 'inherit',
borderRadius: '20px',
padding: '0 15px',
marginRight: '5px',
cursor: 'pointer',
}"
>
第{{ day }}天
</button>
<button style="background-color: #fff; border-radius: 20px; border: 1px solid red; padding: 0 15px; color: red" @click="handleReset">
重置
</button>
</div>
<div class="table-container">
<a-table
:columns="columns"
:data-source="dailyData[selectedDay].dishes"
:pagination="false"
bordered
size="small"
class="full-width-table"
:scroll="{ y: 470 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'meal'">
{{ getMealTypeName(record.meal) }}
</template>
<template v-if="column.key === 'weight'">
<a-input v-model:value="record.weight" @change="handleWeightChange(record)" style="width: 100%" size="small" />
</template>
<template v-if="column.key === 'operation'">
<a-popconfirm title="确定要删除这条记录吗?" ok-text="确定" cancel-text="取消" @confirm="handleDelete(record)">
<a-button type="link" size="small" danger>删除</a-button>
</a-popconfirm>
</template>
</template>
</a-table>
</div>
</div>
</a-col>
</a-row>
<!-- <a-row>
<a-col :span="24">
<div class="bottom">
<div class="energy">
<div style="width: 10%; height: 70px; display: flex; flex-direction: column; justify-content: space-between; margin-left: 15px">
<button
@click="analysisType = 'daily'"
:style="{
backgroundColor: analysisType === 'daily' ? '#e6f7ff' : '#fff',
color: analysisType === 'daily' ? '#1890ff' : 'inherit',
border: `1px solid ${analysisType === 'daily' ? '#1890ff' : '#eee'}`,
}"
style="border-radius: 4px"
>按日分析</button
>
<button
@click="analysisType = 'average'"
:style="{
backgroundColor: analysisType === 'average' ? '#e6f7ff' : '#fff',
color: analysisType === 'average' ? '#1890ff' : 'inherit',
border: `1px solid ${analysisType === 'average' ? '#1890ff' : '#eee'}`,
}"
style="border-radius: 4px"
>多日均值</button
>
</div>
<div class="energy-one">
<button class="energy-btn">能量</button>
<span>{{ currentNutrition.energy.toFixed(2) }}</span>
<span>1291.5~1427.5</span>
</div>
<div class="energy-one">
<button class="energy-btn">蛋白质</button>
<span>{{ currentNutrition.protein.toFixed(2) }}</span>
<span>55.1~67.3</span>
</div>
<div class="energy-one">
<button class="energy-btn">碳水化合物</button>
<span>{{ currentNutrition.carbohydrate.toFixed(2) }}</span>
<span>174.2~213</span>
</div>
<div class="energy-one" style="border-right: none">
<button class="energy-btn">脂肪</button>
<span>{{ currentNutrition.fat.toFixed(2) }}</span>
<span>34~41.6</span>
</div>
<div style="width: 20%; text-align: center"> 三大产能营养素供能比: </div>
<div class="energy-one">
<button class="energy-btn">脂肪</button>
<span>{{ calculateEnergyRatio().fat }}%</span>
</div>
<div class="energy-one">
<button class="energy-btn">蛋白质</button>
<span>{{ calculateEnergyRatio().protein }}%</span>
</div>
<div class="energy-one" style="border-right: none">
<button class="energy-btn">碳水化合物</button>
<span>{{ calculateEnergyRatio().carbohydrate }}%</span>
</div>
</div>
<div class="energy">
<div
style="
width: 10%;
height: 70px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 15px;
align-items: center;
"
>
<span style="padding-top: 25px">摄入量:</span>
<span>推荐量:</span>
</div>
<div class="energy-scroll">
<div class="energy-one1">
<button class="mg">钙(mg)</button>
<span>{{ currentNutrition.ca.toFixed(2) }}</span>
<span>900~1100</span>
</div>
<div class="energy-one1">
<button class="mg">锌(mg)</button>
<span>{{ currentNutrition.zn.toFixed(2) }}</span>
<span>6.8~8.3</span>
</div>
<div class="energy-one1">
<button class="mg">铁(mg)</button>
<span>{{ currentNutrition.fe.toFixed(2) }}</span>
<span>10.8~13.2</span>
</div>
<div class="energy-one1">
<button class="mg">硒(mg)</button>
<span>{{ currentNutrition.se.toFixed(2) }}</span>
<span>54~66</span>
</div>
<div class="energy-one1">
<button class="mg">钾(mg)</button>
<span>{{ currentNutrition.kk.toFixed(2) }}</span>
<span>1800~2200</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维A(ugRAE)</button>
<span>{{ currentNutrition.vita.toFixed(2) }}</span>
<span>630~770</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维B1(mg)</button>
<span>{{ currentNutrition.vitb1.toFixed(2) }}</span>
<span>1.1~1.3</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维B2(mg)</button>
<span>{{ currentNutrition.vitb2.toFixed(2) }}</span>
<span>1.1~1.3</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维B6(mg)</button>
<span>{{ currentNutrition.vitb6.toFixed(2) }}</span>
<span>1.4~1.8</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维B12(mg)</button>
<span>{{ currentNutrition.vitb12.toFixed(2) }}</span>
<span>2.2~2.6</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维C(mg)</button>
<span>{{ currentNutrition.vitc.toFixed(2) }}</span>
<span>90~110</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维D(mg)</button>
<span>{{ currentNutrition.vitd.toFixed(2) }}</span>
<span>13.5~16.5</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维E(mg)</button>
<span>{{ currentNutrition.vite.toFixed(2) }}</span>
<span>12.6~15.4</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">铜(mg)</button>
<span>{{ currentNutrition.cu.toFixed(2) }}</span>
<span>0.7~0.9</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">Folicacid(mg)</button>
<span>{{ currentNutrition.folate.toFixed(2) }}</span>
<span>360~440</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维K(mg)</button>
<span>{{ currentNutrition.vitk.toFixed(2) }}</span>
<span>72~88</span>
</div>
<div class="energy-one1">
<button style="width: 90px" class="mg">维PP(mg)</button>
<span>{{ currentNutrition.pp.toFixed(2) }}</span>
<span>9.9~12.1</span>
</div>
<div class="energy-one1" style="border: none">
<button style="width: 90px" class="mg">Pa(mg)</button>
<span>{{ currentNutrition.pa.toFixed(2) }}</span>
<span>630~770</span>
</div>
</div>
</div>
</div>
</a-col>
</a-row> -->
<a-row>
<a-col :span="24">
<div class="energy1">
<div style="width: 20%; height: 70px; display: flex; flex-direction: column; justify-content: space-between; margin-left: 15px">
<button
@click="analysisType = 'daily'"
:style="{
backgroundColor: analysisType === 'daily' ? '#e6f7ff' : '#fff',
color: analysisType === 'daily' ? '#1890ff' : 'inherit',
border: `1px solid ${analysisType === 'daily' ? '#1890ff' : '#eee'}`,
}"
style="border-radius: 4px"
>按日分析</button
>
<button
@click="analysisType = 'average'"
:style="{
backgroundColor: analysisType === 'average' ? '#e6f7ff' : '#fff',
color: analysisType === 'average' ? '#1890ff' : 'inherit',
border: `1px solid ${analysisType === 'average' ? '#1890ff' : '#eee'}`,
}"
style="border-radius: 4px"
>多日均值</button
>
</div>
<div class="energy-one">
<button class="energy-btn">能量</button>
<span>{{ currentNutrition.energy.toFixed(2) }}</span>
<span>1291.5~1427.5</span>
</div>
<div class="energy-one">
<button class="energy-btn">蛋白质</button>
<span>{{ currentNutrition.protein.toFixed(2) }}</span>
<span>55.1~67.3</span>
</div>
<div class="energy-one" style="border-right: none">
<button class="energy-btn">脂肪</button>
<span>{{ currentNutrition.fat.toFixed(2) }}</span>
<span>34~41.6</span>
</div>
<div class="energy-one">
<button class="energy-btn" style="width: 100px">碳水化合物</button>
<span>{{ currentNutrition.carbohydrate.toFixed(2) }}</span>
<span>174.2~213</span>
</div>
</div>
<div class="element">
<div class="echarts" style="width: 40%"> </div>
<div class="table" style="width: 60%; padding: 10px">
<a-table :columns="nutritionColumns" :data-source="nutritionData" :pagination="false" :show-header="false" bordered size="small">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'value'">
{{ record.value }}
</template>
</template>
</a-table>
</div>
</div>
</a-col>
</a-row>
</template>
<script lang="ts" name="nutrition-EducationTabs" setup>
import { ref, reactive, onMounted, computed } from 'vue';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { pidAndName, list, planAdd } from './MedicalRecordPairing.api';
import { Modal } from 'ant-design-vue';
import { defHttp } from '/@/utils/http/axios';
const nutritionColumns = ref([
{
title: 'Category',
dataIndex: 'category',
key: 'category',
width: '20%',
},
{
title: 'Category',
dataIndex: 'category2',
key: 'category2',
width: '20%',
},
{
title: 'Category',
dataIndex: 'category3',
key: 'category3',
width: '20%',
},
{
title: 'Category',
dataIndex: 'category4',
key: 'category4',
width: '20%',
},
{
title: 'Category',
dataIndex: 'category5',
key: 'category5',
width: '20%',
},
]);
const nutritionData = computed(() => {
return [
{
category: '能量:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
category2: '蛋白质:' + `${currentNutrition.value.protein.toFixed(2)} g`,
category3: '脂肪:' + `${currentNutrition.value.fat.toFixed(2)} g`,
category4: '碳水化合物:' + `${currentNutrition.value.carbohydrate.toFixed(2)} g`,
category5: '膳食纤维:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
},
{
category: 'EPA:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
category2: 'EPA:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
category3: 'DHA:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
category4: '亚油酸:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
category5: '亚麻酸:' + `${currentNutrition.value.energy.toFixed(2)} kcal`,
},
{
category: '钙:' + `${currentNutrition.value.ca.toFixed(2)} mg`,
category2: '铁:' + `${currentNutrition.value.fe.toFixed(2)} mg`,
category3: '锌:' + `${currentNutrition.value.zn.toFixed(2)} mg`,
category4: '硒:' + `${currentNutrition.value.se.toFixed(2)} mg`,
category5: '钠:' + `${currentNutrition.value.na.toFixed(2)} mg`,
},
{
category: '氯:' + `${currentNutrition.value.energy.toFixed(2)} mg`,
category2: '钾:' + `${currentNutrition.value.kk.toFixed(2)} mg`,
category3: '磷:' + `${currentNutrition.value.energy.toFixed(2)} mg`,
category4: '叶酸:' + `${currentNutrition.value.energy.toFixed(2)} mg`,
category5: '维生素A:' + `${currentNutrition.value.vita.toFixed(2)} mg`,
},
{
category: '维生素B1:' + `${currentNutrition.value.vitb1.toFixed(2)} mg`,
category2: '维生素B2:' + `${currentNutrition.value.vitb2.toFixed(2)} mg`,
category3: '维生素B6:' + `${currentNutrition.value.vitb6.toFixed(2)} mg`,
category4: '维生素B12:' + `${currentNutrition.value.vitb12.toFixed(2)} mg`,
category5: '维生素C:' + `${currentNutrition.value.vitc.toFixed(2)} mg`,
},
{
category: '维生素D:' + `${currentNutrition.value.vitd.toFixed(2)} mg`,
category2: '维生素K1:' + `${currentNutrition.value.vitk.toFixed(2)} mg`,
},
];
});
const props = defineProps({
patientData: { type: Object, default: () => ({}) },
});
const labelCol = reactive({
span: 4,
});
const wrapperCol = reactive({
span: 18,
});
const labelCol1 = reactive({
span: 6,
});
const wrapperCol1 = reactive({
span: 12,
});
// 数据状态
const selectedLibrary = ref<string>('');
const selectedCategory = ref<string>('');
const dishName = ref<string>('');
const status = ref<string>('1');
const libraryOptions = ref<any[]>([]);
const categoryOptions = ref<any[]>([]);
const dishList = ref<any[]>([]);
const analysisType = ref<string>('daily');
const selectedDishId = ref<string | number | null>(null);
const selectedDay = ref<number>(1); // 默认选择第1天
// 创建空的营养值对象
const createEmptyNutrition = () => ({
energy: 0,
protein: 0,
fat: 0,
carbohydrate: 0,
ca: 0,
zn: 0,
fe: 0,
se: 0,
kk: 0,
vita: 0,
vitb1: 0,
vitb2: 0,
vitb6: 0,
vitb12: 0,
vitc: 0,
vitd: 0,
vite: 0,
vitk: 0,
vitpp: 0,
pa: 0,
pp: 0,
folate: 0,
cu: 0,
mg: 0,
na: 0,
});
// 每日数据,包含菜品和营养值
const dailyData = ref<Record<number, { dishes: any[]; nutrition: any }>>({
1: { dishes: [], nutrition: createEmptyNutrition() },
2: { dishes: [], nutrition: createEmptyNutrition() },
3: { dishes: [], nutrition: createEmptyNutrition() },
4: { dishes: [], nutrition: createEmptyNutrition() },
5: { dishes: [], nutrition: createEmptyNutrition() },
6: { dishes: [], nutrition: createEmptyNutrition() },
7: { dishes: [], nutrition: createEmptyNutrition() },
});
// 计算当前选择的营养值
const currentNutrition = computed(() => {
if (analysisType.value === 'daily') {
return dailyData.value[selectedDay.value].nutrition;
} else {
// 计算多日均值
const averageNutrition = createEmptyNutrition();
const dayCount = 7; // 7天平均值
// 累加所有天的营养值
for (let day = 1; day <= dayCount; day++) {
const dayNutrition = dailyData.value[day].nutrition;
Object.keys(averageNutrition).forEach((key) => {
averageNutrition[key] += dayNutrition[key];
});
}
// 计算平均值
Object.keys(averageNutrition).forEach((key) => {
averageNutrition[key] = averageNutrition[key] / dayCount;
});
return averageNutrition;
}
});
// 餐次类型映射
const mealTypeMap = ref<Record<string, string>>({
'1': '早餐',
'2': '早点',
'3': '午餐',
'4': '午点',
'5': '晚餐',
'6': '晚点',
});
// 获取餐次中文名称
const getMealTypeName = (mealCode: string) => {
return mealTypeMap.value[mealCode] || mealCode;
};
// 重置操作
const handleReset = () => {
Modal.confirm({
title: '确认重置',
content: '是否重置所选菜品?',
okText: '确定',
cancelText: '取消',
onOk: () => {
// 重置所有天的数据
for (let day = 1; day <= 7; day++) {
dailyData.value[day] = {
dishes: [],
nutrition: createEmptyNutrition(),
};
}
},
});
};
// 表格列定义
const columns = ref([
{
title: '餐次',
dataIndex: 'meal',
key: 'meal',
width: '15%',
align: 'center',
},
{
title: '品名',
dataIndex: 'ingredients',
key: 'ingredients',
width: '25%',
align: 'center',
},
{
title: '食材',
dataIndex: 'name',
key: 'name',
width: '30%',
align: 'center',
},
{
title: '重量(g)',
dataIndex: 'weight',
key: 'weight',
width: '15%',
align: 'center',
},
{
title: '操作',
key: 'operation',
width: '15%',
align: 'center',
},
]);
// 切换天数
const changeDay = (day: number) => {
selectedDay.value = day;
};
// 计算菜肴营养值
const calculateDishNutrition = (dish: any) => {
const weight = parseFloat(dish.weight) || 0;
return {
energy: dish.energy || 0,
protein: dish.protein || 0,
fat: dish.fat || 0,
carbohydrate: dish.carbohydrate || 0,
ca: dish.ca || 0,
zn: dish.zn || 0,
fe: dish.fe || 0,
se: dish.se || 0,
kk: dish.kk || 0,
vita: dish.vita || 0,
vitb1: dish.vitb1 || 0,
vitb2: dish.vitb2 || 0,
vitb6: dish.vitb6 || 0,
vitb12: dish.vitb12 || 0,
vitc: dish.vitc || 0,
vitd: dish.vitd || 0,
vite: dish.vite || 0,
vitk: dish.vitk || 0,
vitpp: dish.vitpp || 0,
pa: dish.pa || 0,
folate: dish.folate || 0,
cu: dish.cu || 0,
mg: dish.mg || 0,
na: dish.na || 0,
};
};
// 操作方法
const handleDishClick = (dish: any) => {
selectedDishId.value = dish.id;
const currentDay = dailyData.value[selectedDay.value];
const existingDishIndex = currentDay.dishes.findIndex(
(item) => item.name === dish.ingredient && item.ingredients === dish.name && item.meal === status.value
);
if (existingDishIndex >= 0) {
// 如果已存在相同菜品,则累加重量
const existingDish = currentDay.dishes[existingDishIndex];
const oldWeight = parseFloat(existingDish.weight) || 0;
const newWeight = oldWeight + (parseFloat(dish.weight) || 0);
// 先减去旧的营养值
const oldNutrition = calculateDishNutrition({
...dish,
weight: oldWeight,
});
Object.keys(oldNutrition).forEach((key) => {
currentDay.nutrition[key] -= oldNutrition[key];
});
// 更新菜品重量
currentDay.dishes = [
...currentDay.dishes.slice(0, existingDishIndex),
{
...existingDish,
weight: newWeight.toFixed(2),
},
...currentDay.dishes.slice(existingDishIndex + 1),
];
// 加上新的营养值
const newNutrition = calculateDishNutrition({
...dish,
weight: newWeight,
});
Object.keys(newNutrition).forEach((key) => {
currentDay.nutrition[key] += newNutrition[key];
});
} else {
// 如果不存在,则添加新菜品
const newRow = {
key: Date.now().toString(),
meal: status.value + '',
name: dish.ingredient,
ingredients: dish.name,
weight: dish.weight,
};
currentDay.dishes = [...currentDay.dishes, newRow];
// 添加营养值
const nutritionToAdd = calculateDishNutrition(dish);
Object.keys(nutritionToAdd).forEach((key) => {
currentDay.nutrition[key] += nutritionToAdd[key];
});
}
};
// 计算三大产能营养素供能比
const calculateEnergyRatio = () => {
const nutrition = currentNutrition.value;
const totalEnergy = nutrition.energy;
if (totalEnergy <= 0) return { fat: 0, protein: 0, carbohydrate: 0 };
// 1g脂肪=9kcal, 1g蛋白质=4kcal, 1g碳水化合物=4kcal
const fatEnergy = nutrition.fat * 9;
const proteinEnergy = nutrition.protein * 4;
const carbEnergy = nutrition.carbohydrate * 4;
return {
fat: ((fatEnergy / totalEnergy) * 100).toFixed(2),
protein: ((proteinEnergy / totalEnergy) * 100).toFixed(2),
carbohydrate: ((carbEnergy / totalEnergy) * 100).toFixed(2),
};
};
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: false,
showQuickJumper: true,
showLessItems: true,
size: 'small',
onChange: (page: number, pageSize: number) => {
pagination.current = page;
pagination.pageSize = pageSize;
fetchDishes();
},
});
// 重量修改操作
const handleWeightChange = (record: any) => {
const currentDay = dailyData.value[selectedDay.value];
const dishIndex = currentDay.dishes.findIndex((item) => item.key === record.key);
if (dishIndex >= 0) {
// 找到原始菜品数据
const originalDish = dishList.value.find((dish) => dish.name === record.ingredients && dish.ingredient === record.name);
if (originalDish) {
const oldWeight = parseFloat(currentDay.dishes[dishIndex].weight) || 0;
const newWeight = parseFloat(record.weight) || 0;
// 先减去旧的营养值
const oldNutrition = calculateDishNutrition({
...originalDish,
weight: oldWeight,
});
Object.keys(oldNutrition).forEach((key) => {
currentDay.nutrition[key] -= oldNutrition[key];
});
// 更新重量
currentDay.dishes[dishIndex].weight = newWeight;
// 加上新的营养值
const newNutrition = calculateDishNutrition({
...originalDish,
weight: newWeight,
});
Object.keys(newNutrition).forEach((key) => {
currentDay.nutrition[key] += newNutrition[key];
});
}
}
};
// 删除操作
const handleDelete = (record: any) => {
const currentDay = dailyData.value[selectedDay.value];
// 查找对应的原始菜肴数据
const originalDish = dishList.value.find((dish) => dish.name === record.ingredients && dish.ingredient === record.name);
if (originalDish) {
// 计算要减去的营养值
const nutritionToSubtract = calculateDishNutrition({
...originalDish,
weight: record.weight,
});
// 减去营养值
Object.keys(nutritionToSubtract).forEach((key) => {
currentDay.nutrition[key] = Math.max(0, currentDay.nutrition[key] - nutritionToSubtract[key]);
});
}
// 删除记录
currentDay.dishes = currentDay.dishes.filter((item) => item.key !== record.key);
};
// 初始化加载库列表和默认值
onMounted(async () => {
await fetchLibraries();
// 设置默认选择的库(第一个选项)
if (libraryOptions.value.length > 0) {
selectedLibrary.value = libraryOptions.value[0].value;
handleLibraryChange(selectedLibrary.value);
}
});
// 获取库列表
const fetchLibraries = async () => {
try {
const res = await pidAndName({ parentId: 0 });
libraryOptions.value = res.map((item: any) => ({
label: item.name,
value: item.id,
}));
} catch (error) {
console.error('获取库列表失败:', error);
}
};
// 库选择变化时获取类别
const handleLibraryChange = async (value: string) => {
selectedLibrary.value = value;
selectedCategory.value = '';
dishList.value = [];
if (value) {
try {
const res = await pidAndName({ parentId: value });
categoryOptions.value = res.map((item: any) => ({
label: item.name,
value: item.id,
}));
// 加载该库下的所有菜肴
pagination.current = 1;
fetchDishes();
} catch (error) {
console.error('获取类别列表失败:', error);
}
} else {
categoryOptions.value = [];
}
};
// 类别选择变化时搜索菜肴
const handleCategoryChange = () => {
pagination.current = 1;
fetchDishes();
};
// 输入变化时搜索菜肴
const handleSearch = () => {
pagination.current = 1;
fetchDishes();
};
// 获取菜肴列表
const fetchDishes = async () => {
if (!selectedLibrary.value) {
dishList.value = [];
return;
}
try {
const params: any = {
pageNo: pagination.current,
pageSize: pagination.pageSize,
};
if (selectedCategory.value) {
params.categoryId = selectedCategory.value;
}
if (dishName.value) {
params.name = dishName.value;
}
const res = await list(params);
dishList.value = res.records || [];
pagination.total = res.total || 0;
} catch (error) {
console.error('获取菜肴列表失败:', error);
}
};
// 在组件中添加下达方法
const handleIssue = async () => {
try {
const planData = {
recordId: props.patientData.id, // 就诊记录ID
flowNo: props.patientData.flowNo, // 就诊流水号
patientId: props.patientData.patientId, // 患者ID
patientNo: props.patientData.patientNo, // 患者号
patientName: props.patientData.patientName, // 患者姓名
// 营养数据 - 使用多日均值
energy: currentNutrition.value.energy,
protein: currentNutrition.value.protein,
carbs: currentNutrition.value.carbohydrate,
fat: currentNutrition.value.fat,
proteinRate: parseFloat(calculateEnergyRatio().protein),
carbsRate: parseFloat(calculateEnergyRatio().carbohydrate),
fatRate: parseFloat(calculateEnergyRatio().fat),
ca: currentNutrition.value.ca,
zn: currentNutrition.value.zn,
fe: currentNutrition.value.fe,
se: currentNutrition.value.se,
kk: currentNutrition.value.kk,
cu: currentNutrition.value.cu,
vita: currentNutrition.value.vita,
vitb1: currentNutrition.value.vitb1,
vitb2: currentNutrition.value.vitb2,
vitb6: currentNutrition.value.vitb6,
vitb12: currentNutrition.value.vitb12,
vitc: currentNutrition.value.vitc,
vitd: currentNutrition.value.vitd,
vite: currentNutrition.value.vite,
vitk: currentNutrition.value.vitk,
folate: currentNutrition.value.folate,
pa: currentNutrition.value.pa,
vitpp: currentNutrition.value.pp,
};
const details = [];
for (let day = 1; day <= 7; day++) {
const dayDishes = dailyData.value[day].dishes;
if (dayDishes.length > 0) {
dayDishes.forEach((dish) => {
// 查找原始菜品数据以获取完整的营养信息
const originalDish = dishList.value.find((d) => d.name === dish.ingredients && d.ingredient === dish.name);
if (originalDish) {
details.push({
day: day,
type: parseInt(dish.meal),
categoryId: selectedCategory.value,
foodId: originalDish.id,
name: dish.ingredients,
ingredient: dish.name,
weight: parseFloat(dish.weight) || 0,
energy: originalDish.energy,
protein: originalDish.protein,
carbs: originalDish.carbohydrate,
fat: originalDish.fat,
ca: originalDish.ca,
zn: originalDish.zn,
fe: originalDish.fe,
se: originalDish.se,
kk: originalDish.kk,
cu: originalDish.cu,
vita: originalDish.vita,
vitb1: originalDish.vitb1,
vitb2: originalDish.vitb2,
vitb6: originalDish.vitb6,
vitb12: originalDish.vitb12,
vitc: originalDish.vitc,
vitd: originalDish.vitd,
vite: originalDish.vite,
vitk: originalDish.vitk,
folate: originalDish.folate,
pa: originalDish.pa,
vitpp: originalDish.pp,
});
}
});
}
}
if (details.length === 0) {
Modal.warning({
title: '提示',
content: '请至少选择一道菜品',
});
return;
}
const requestData = {
plan: planData,
details: details,
};
const res = await planAdd({
data: requestData,
});
if (res) {
Modal.success({
title: '成功',
content: '营养配餐下达成功',
});
} else {
Modal.error({
title: '错误',
content: res.message || '营养配餐下达失败',
});
}
} catch (error) {
console.error('下达营养配餐失败:', error);
Modal.error({
title: '错误',
content: '下达营养配餐失败,请稍后重试',
});
}
};
</script>
<style scoped>
.left {
height: 600px;
padding: 0 5px;
}
.ant-form {
width: 100%;
}
.ant-form-item {
margin-bottom: 9px;
}
.dishes {
min-height: 475px;
display: flex;
flex-direction: column;
}
.dish-list {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
}
.dish-list :deep(.ant-list-items) {
overflow-y: auto;
flex: 1;
}
.dish-item {
padding: 8px 12px !important;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: background-color 0.3s;
}
.dish-item:hover {
background-color: rgba(144, 238, 144, 0.3) !important; /* 淡绿色悬停效果 */
}
.dish-item.active-dish {
background-color: rgba(144, 238, 144, 0.5) !important; /* 点击时更明显的淡绿色 */
}
.dish-item:last-child {
border-bottom: none;
}
.right {
height: 600px;
display: flex;
flex-direction: column;
}
.table-container {
flex: 1;
margin-top: 10px;
border: 1px solid #eee;
overflow: hidden;
}
.full-width-table {
width: 100% !important;
height: 100%;
}
.full-width-table :deep(.ant-table) {
height: 100%;
}
.full-width-table :deep(.ant-table-container) {
height: 100%;
display: flex;
flex-direction: column;
}
.full-width-table :deep(.ant-table-body) {
flex: 1;
overflow: auto;
}
.bottom {
height: 200px;
border: 1px solid #eee;
margin-top: 9px;
border-radius: 5px;
}
.energy {
height: 99px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
}
.energy1 {
height: 98px;
border: 1px solid #eee;
display: flex;
align-items: center;
margin-top: 10px;
}
.element {
height: 298px;
border: 1px solid #eee;
display: flex;
align-items: center;
}
.energy-one {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 20%;
height: 80px;
/* border-right: 2px solid #eee; */
}
.energy-scroll {
display: flex;
align-items: center;
width: 90%;
overflow-x: auto;
white-space: nowrap;
padding: 7px 0;
}
.energy-one1 {
display: inline-flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 7%;
height: 75px;
border-right: 2px solid #eee;
flex-shrink: 0; /* 防止被压缩 */
}
.mg {
width: 70px;
height: 30px;
background: #e6f7ff;
color: #1890ff;
border: 1px solid #1890ff;
border-radius: 4px;
}
.energy-btn {
width: auto;
height: 30px;
background: rgba(144, 238, 144, 0.3);
color: #333; /* Dark text color */
border: 1px solid rgba(144, 238, 144, 0.5);
border-radius: 4px;
}
.energy-one:nth-child(2) .energy-btn {
width: 50px;
} /* 能量 */
.energy-one:nth-child(3) .energy-btn {
width: 70px;
} /* 蛋白质 */
.energy-one:nth-child(4) .energy-btn {
width: 100px;
} /* 碳水化合物 */
.energy-one:nth-child(5) .energy-btn {
width: 50px;
} /* 脂肪 */
</style>
使用echarts,在<div class="echarts" style="width: 40%"> </div>用圆饼显示三大产能营养素供能比