菜品菜谱-营养信息

This commit is contained in:
lSun 2025-03-05 09:46:58 +08:00
parent a9c0c1316c
commit dcec89674b
3 changed files with 907 additions and 0 deletions

View File

@ -0,0 +1,56 @@
import request from '@/utils/request'
// 查询获取所有食材营养信息
export function listNutrition(query) {
return request({
url: '/smart-canteen/api/v1/menunutrition/getMenuNutritionPage',
method: 'post',
data: query
})
}
// 查询详细
export function getNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/oneMaterial',
method: 'post',
data: data
})
}
// 新增
export function addMenuNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/addMenuNutrition',
method: 'post',
data: data
})
}
// 修改
export function updateNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/updateMenuNutrition',
method: 'post',
data: data
})
}
// 删除
export function delNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/remove',
method: 'post',
data: data
})
}
// 获取所有食材类别
export function typeList(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/all/type/list',
method: 'post',
data: data
})
}

View File

@ -0,0 +1,46 @@
/**
* 级联选择器相关方法
*/
export const cascaderMixin = {
methods: {
/**
* 更新级联选择器选项
* @returns {void}
*/
updateCascaderOptions() {
this.cascaderOptions = this.cascaderOptionsMethod();
},
/**
* 生成级联选择器的选项数据
* @returns {Array<{value: string, label: string, children: Array<{value: string, label: string}>}>}
*/
cascaderOptionsMethod() {
if (!this.queryParams.status) {
return [];
}
return this.queryParams.status.map(item => ({
value: item.bigType,
label: item.bigType,
children: item.littleTypeList.map(subItem => ({
value: subItem,
label: subItem
}))
}));
},
/**
* 处理级联选择器值变化
* @param {Array<string>} value - 选中的值数组
*/
handleChange(value) {
if (value && value.length >= 2) {
this.queryParams.bigType = value[0];
this.queryParams.littleType = value[1];
} else {
this.queryParams.bigType = undefined;
this.queryParams.littleType = undefined;
}
}
}
};

View File

@ -0,0 +1,805 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="98px">
<el-form-item label="营养信息类别" prop="status" >
<el-cascader
v-model="selectedOptions"
:options="cascaderOptions"
@change="handleChange"
></el-cascader>
</el-form-item>
<el-form-item label="食材编码" prop="nutritionCode">
<el-input
v-model="queryParams.nutritionCode"
placeholder="请输入食材编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="营养信息名称" prop="nutritionName">
<el-input
v-model="queryParams.nutritionName"
placeholder="请输入营养信息名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['dish:nutritionInfo:add']"
>新增</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="menuNutritionList" >
<el-table-column type="index" label="序号" width="50" align="center" />
<el-table-column label="食材编码" align="center" prop="nutritionCode" />
<el-table-column label="营养信息名称" align="center" prop="nutritionName" />
<el-table-column label="食材大类" align="center" prop="bigType" />
<el-table-column label="食材小类" align="center" prop="littleType" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['dish:nutritionInfo:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['dish:nutritionInfo:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.current"
:limit.sync="queryParams.size"
@pagination="getList"
/>
<!-- 添加或修改岗位对话框 -->
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="190px">
<el-row>
<el-col :span="12">
<el-form-item label="营养信息类别" prop="nutritionCategory" required>
<el-cascader
v-model="form.nutritionCategory"
:options="cascaderOptions"
:props="{
checkStrictly: false,
emitPath: true
}"
placeholder="请选择营养信息类别"
clearable
style="width: 100%;"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="营养信息名称" prop="nutritionName" required>
<el-input
v-model="form.nutritionName"
placeholder="请输入营养信息名称"
maxlength="30"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="食材编码" prop="nutritionCode" required>
<el-input
v-model="form.nutritionCode"
placeholder="请输入食材编码"
maxlength="30"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="加工时间min">
<el-input
v-model="form.processingTime"
@input="handleNumericInput('processingTime')"
@blur="formatNumericValue('processingTime')"
placeholder="请输入加工时间"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="可食部分g/100g" prop="edible">
<el-input
v-model="form.edible"
@input="handleNumericInput('edible')"
@blur="formatNumericValue('edible')"
placeholder="请输入可食部分"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="水分g/100g" prop="water">
<el-input
v-model="form.water"
@input="handleNumericInput('water')"
@blur="formatNumericValue('water')"
placeholder="请输入水分"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="热量(千卡/100g" prop="calories">
<el-input
v-model="form.calories"
@input="handleNumericInput('calories')"
@blur="formatNumericValue('calories')"
placeholder="请输入热量"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="蛋白质g/100g" prop="protein">
<el-input
v-model="form.protein"
@input="handleNumericInput('protein')"
@blur="formatNumericValue('protein')"
placeholder="请输入蛋白质"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="脂肪g/100g" prop="fat">
<el-input
v-model="form.fat"
@input="handleNumericInput('fat')"
@blur="formatNumericValue('fat')"
placeholder="请输入脂肪"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="碳水化合物g/100g" prop="carbohydrate">
<el-input
v-model="form.carbohydrate"
@input="handleNumericInput('carbohydrate')"
@blur="formatNumericValue('carbohydrate')"
placeholder="请输入碳水化合物"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="膳食纤维g/100g" prop="dietaryFiber">
<el-input
v-model="form.dietaryFiber"
@input="handleNumericInput('dietaryFiber')"
@blur="formatNumericValue('dietaryFiber')"
placeholder="请输入膳食纤维"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="胆固醇mg/100g" prop="cholesterol">
<el-input
v-model="form.cholesterol"
@input="handleNumericInput('cholesterol')"
@blur="formatNumericValue('cholesterol')"
placeholder="请输入胆固醇"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="灰分g/100g" prop="ash">
<el-input
v-model="form.ash"
@input="handleNumericInput('ash')"
@blur="formatNumericValue('ash')"
placeholder="请输入灰分"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="维生素Aμg/100g" prop="vitaminA">
<el-input
v-model="form.vitaminA"
@input="handleNumericInput('vitaminA')"
@blur="formatNumericValue('vitaminA')"
placeholder="请输入维生素A"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="胡萝卜素μg/100g" prop="carotene">
<el-input
v-model="form.carotene"
@input="handleNumericInput('carotene')"
@blur="formatNumericValue('carotene')"
placeholder="请输入胡萝卜素"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="视黄醇μg/100g" prop="retinol">
<el-input
v-model="form.retinol"
@input="handleNumericInput('retinol')"
@blur="formatNumericValue('retinol')"
placeholder="请输入视黄醇"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="硫胺素mg/100g" prop="thiamine">
<el-input
v-model="form.thiamine"
@input="handleNumericInput('thiamine')"
@blur="formatNumericValue('thiamine')"
placeholder="请输入硫胺素"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="核黄素mg/100g" prop="riboflavin">
<el-input
v-model="form.riboflavin"
@input="handleNumericInput('riboflavin')"
@blur="formatNumericValue('riboflavin')"
placeholder="请输入核黄素"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label=" 烟酸/尼克酸mg/100g" prop="niacin">
<el-input
v-model="form.niacin"
@input="handleNumericInput('niacin')"
@blur="formatNumericValue('niacin')"
placeholder="请输入烟酸/尼克酸"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="维生素Cmg/100g" prop="vitaminC">
<el-input
v-model="form.vitaminC"
@input="handleNumericInput('vitaminC')"
@blur="formatNumericValue('vitaminC')"
placeholder="请输入维生素C"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="维生素Dμg/100g" prop="vitaminD">
<el-input
v-model="form.vitaminD"
@input="handleNumericInput('vitaminD')"
@blur="formatNumericValue('vitaminD')"
placeholder="请输入维生素D"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="维生素Emg/100g" prop="vitaminE">
<el-input
v-model="form.vitaminE"
@input="handleNumericInput('vitaminE')"
@blur="formatNumericValue('vitaminE')"
placeholder="请输入维生素E"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="钙mg/100g" prop="calcium">
<el-input
v-model="form.calcium"
@input="handleNumericInput('calcium')"
@blur="formatNumericValue('calcium')"
placeholder="请输入钙"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="磷mg/100g" prop="phosphorus">
<el-input
v-model="form.phosphorus"
@input="handleNumericInput('phosphorus')"
@blur="formatNumericValue('phosphorus')"
placeholder="请输入磷"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label=" 钾mg/100g" prop="kalium">
<el-input
v-model="form.kalium"
@input="handleNumericInput('kalium')"
@blur="formatNumericValue('kalium')"
placeholder="请输入钾"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="钠 mg/100g" prop="sodium">
<el-input
v-model="form.sodium"
@input="handleNumericInput('sodium')"
@blur="formatNumericValue('sodium')"
placeholder="请输入钠"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label=" 镁mg/100g" prop="magnesium">
<el-input
v-model="form.magnesium"
@input="handleNumericInput('magnesium')"
@blur="formatNumericValue('magnesium')"
placeholder="请输入镁"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="铁 mg/100g" prop="iron">
<el-input
v-model="form.iron"
@input="handleNumericInput('iron')"
@blur="formatNumericValue('iron')"
placeholder="请输入铁"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="锌mg/100g" prop="zinc">
<el-input
v-model="form.zinc"
@input="handleNumericInput('zinc')"
@blur="formatNumericValue('zinc')"
placeholder="请输入锌"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="硒μg/100g" prop="selenium">
<el-input
v-model="form.selenium"
@input="handleNumericInput('selenium')"
@blur="formatNumericValue('selenium')"
placeholder="请输入硒"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listNutrition, getNutrition, delNutrition, addMenuNutrition, updateNutrition, typeList } from "@/api/dish/nutritionInfo";
import { cascaderMixin } from './cascaderMixin';
export default {
name: "NutritionInfo",
mixins: [cascaderMixin],
/** @type {import('vue').ComponentOptions} */
data() {
return {
//
loading: true,
//
showSearch: true,
//
total: 0,
//
menuNutritionList: [],
//
title: "",
//
open: false,
//
queryParams: {
current: 1,
size: 10,
nutritionCode: undefined,
nutritionName: undefined,
status: undefined,
bigType: undefined,
littleType: undefined
},
//
form: {
nutritionCategory: [], //
nutritionName: undefined, //
nutritionCode: undefined, //
processingTime: undefined, //
edible: undefined, //
water: undefined, //
calories: undefined, //
protein: undefined, //
fat: undefined, //
carbohydrate: undefined, //
dietaryFiber: undefined, //
cholesterol: undefined, //
ash: undefined, //
vitaminA: undefined, // A
carotene: undefined, //
retinol: undefined, //
thiamine: undefined, //
riboflavin: undefined, //
niacin: undefined, // /
vitaminC: undefined, // C
vitaminD: undefined, // D
vitaminE: undefined, // E
calcium: undefined, //
phosphorus: undefined, //
kalium: undefined, //
sodium: undefined, //
magnesium: undefined, //
iron: undefined, //
zinc: undefined, //
selenium: undefined, //
},
//
rules: {
nutritionCategory: [
{ required: true, message: "请选择营养信息类别", trigger: "change" }
],
nutritionName: [
{ required: true, message: "营养信息名称不能为空", trigger: "blur" }
],
nutritionCode: [
{ required: true, message: "食材编码不能为空", trigger: "blur" }
]
},
selectedOptions: [], //
cascaderOptions: [] //
};
},
created() {
this.getFoodType();
this.getList();
},
methods: {
/**
* 获取所有食材类别
* @returns {Promise<void>}
*/
getFoodType() {
typeList().then(response => {
this.queryParams.status = response.data;
this.updateCascaderOptions(); //
}).catch(error => {
console.error("Failed to fetch food types:", error);
});
},
/**
* 更新级联选择器选项
* @returns {void}
*/
updateCascaderOptions() {
this.cascaderOptions = this.cascaderOptionsMethod();
},
/**
* 生成级联选择器的选项数据
* @returns {Array<{value: string, label: string, children: Array<{value: string, label: string}>}>}
*/
cascaderOptionsMethod() {
if (!this.queryParams.status) {
return [];
}
return this.queryParams.status.map(item => ({
value: item.bigType,
label: item.bigType,
children: item.littleTypeList.map(subItem => ({
value: subItem,
label: subItem
}))
}));
},
/**
* 处理级联选择器值变化
* @param {Array<string>} value - 选中的值数组
*/
handleChange(value) {
if (value && value.length >= 2) {
this.queryParams.bigType = value[0];
this.queryParams.littleType = value[1];
} else {
this.queryParams.bigType = undefined;
this.queryParams.littleType = undefined;
}
},
/** 查询岗位列表 */
getList() {
this.loading = true;
listNutrition(this.queryParams).then(response => {
this.menuNutritionList = response.data.records;
this.total = Number(response.data.total);
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
nutritionCategory: [], //
nutritionName: undefined, //
nutritionCode: undefined, //
processingTime: undefined, //
edible: undefined, //
water: undefined, //
calories: undefined, //
protein: undefined, //
fat: undefined, //
carbohydrate: undefined, //
dietaryFiber: undefined, //
cholesterol: undefined, //
ash: undefined, //
vitaminA: undefined, // A
carotene: undefined, //
retinol: undefined, //
thiamine: undefined, //
riboflavin: undefined, //
niacin: undefined, // /
vitaminC: undefined, // C
vitaminD: undefined, // D
vitaminE: undefined, // E
calcium: undefined, //
phosphorus: undefined, //
kalium: undefined, //
sodium: undefined, //
magnesium: undefined, //
iron: undefined, //
zinc: undefined, //
selenium: undefined, //
};
this.resetForm("form");
},
/**
* 搜索按钮操作
* @method handleQuery
* @description 重置页码为1并获取列表数据
*/
handleQuery() {
this.queryParams.current = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.selectedOptions = []; //
this.queryParams.bigType = undefined;
this.queryParams.littleType = undefined;
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加营养信息";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.nutritionId;
var data = {
nutritionId: id
}
getNutrition(data).then(response => {
this.form = response.data;
//
if (response.data.bigType && response.data.littleType) {
this.form.nutritionCategory = [response.data.bigType, response.data.littleType];
}
this.open = true;
this.title = "修改营养信息";
});
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
const formData = { ...this.form };
//
if (formData.nutritionCategory && formData.nutritionCategory.length >= 2) {
formData.bigType = formData.nutritionCategory[0];
formData.littleType = formData.nutritionCategory[1];
}
delete formData.nutritionCategory; //
if (formData.id != undefined) {
updateNutrition(formData).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addMenuNutrition(formData).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const nutritionIds = row.nutritionId;
var data = {
nutritionId:nutritionIds
}
this.$modal.confirm('是否确认删除数据项?').then(function() {
return delNutrition(data);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/**
* 处理数值输入
* @param {string} field - 字段名
* @param {Event} event - 输入事件
*/
handleNumericInput(field, event) {
const value = event.target.value;
//
let newValue = value.replace(/[^\d.]/g, '');
//
const parts = newValue.split('.');
if (parts.length > 2) {
newValue = parts[0] + '.' + parts.slice(1).join('');
}
//
if (parts.length === 2 && parts[1].length > 2) {
newValue = parts[0] + '.' + parts[1].substring(0, 2);
}
// 100
if (parseFloat(newValue) > 100) {
newValue = '100.00';
}
this.form[field] = newValue;
},
/**
* 格式化数值
* @param {string} field - 字段名
*/
formatNumericValue(field) {
let value = this.form[field];
if (!value || value === '' || value === '.') {
this.form[field] = '0.00';
return;
}
value = parseFloat(value);
if (isNaN(value)) {
value = 0;
}
// 100
if (value > 100) {
value = 100;
}
//
this.form[field] = value.toFixed(2);
}
}
};
</script>
<style scoped>
::v-deep .el-dialog__body {
max-height: calc(90vh - 120px);
overflow-y: auto;
padding: 20px;
}
</style>