营养信息类别

This commit is contained in:
zzyuan 2025-04-10 13:36:23 +08:00
parent 0fee0f0979
commit b74ec8b1a9
3 changed files with 468 additions and 123 deletions

View File

@ -1,9 +1,9 @@
import request from '@/utils/request'
// 原料类别
// 原料类别
export function systemMaterialTreeApi(data) {
return request({
url: '/smart-canteen/api/v1/menumaterialcategory/tree/list',
url: '/smart-canteen/menu_material_category/getTree',
method: 'post',
headers: {
"merchant-id":"378915229716713472",

View File

@ -1,36 +1,64 @@
import request from '@/utils/request'
// 获取营养信息类别
export function typeListApi(data) {
// 获取营养信息类别-树
export function nutritionTypeListApi(data) {
return request({
url: '/smart-canteen/menu_nutrition_type/nutritionTypeList',
method: 'post',
data: data
})
}
// 新增营养类别接口-树
export function nutritionTypeAddApi(data) {
return request({
url: '/smart-canteen/menu_nutrition_type/add',
method: 'post',
data: data
})
}
// 修改营养类别接口-树
export function nutritionTypeEditApi(data) {
return request({
url: '/smart-canteen/menu_nutrition_type/edit',
method: 'post',
data: data
})
}
// 删除营养类别接口-树
export function nutritionTypeDelApi(data) {
return request({
url: '/smart-canteen/menu_nutrition_type/del',
method: 'post',
data: data
})
}
// 查询获取所有营养信息
export function listNutrition(query) {
return request({
url: '/smart-canteen/menu_nutrition/list',
method: 'get',
param: query
method: 'post',
data: query
})
}
// 查询详细
export function getNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/oneMaterial',
method: 'post',
data: data
url: '/smart-canteen/menu_nutrition_type/getInfo',
method: 'get',
params: data
})
}
// 新增
export function addMenuNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/addMenuNutrition',
url: '/smart-canteen/menu_nutrition/add',
method: 'post',
data: data
})
@ -39,7 +67,7 @@ export function addMenuNutrition(data) {
// 修改
export function updateNutrition(data) {
return request({
url: '/smart-canteen/api/v1/menunutrition/updateMenuNutrition',
url: '/smart-canteen/menu_nutrition/edit',
method: 'post',
data: data
})

View File

@ -1,92 +1,177 @@
<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="type" >
<el-cascader
v-model="typeSelected" clearable
:options="cascaderOptions"
@change="handleChange"
></el-cascader>
</el-form-item>
<el-row :gutter="20">
<!--树数据-->
<el-col :span="4" :xs="24">
<div class="head-container">
<div style="width: 96%;display: flex;align-items: center;justify-content: space-between;">
<span>营养信息分类</span>
<span style="font-size: 24px;font-weight: 600;cursor: pointer;" @click.stop="() => appendTreeNode()">+</span>
</div>
<el-input
v-model="keyWord"
placeholder="请输入关键字进行搜索"
clearable
maxlength="50"
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
</div>
<el-form-item label="食材编码" prop="nutritionCode">
<el-input
v-model="queryParams.nutritionCode"
placeholder="请输入食材编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<div class="head-container" style>
<el-tree style="height: 700px; overflow: scroll"
:data="cascaderOptions" :props="defaultProps"
:show-checkbox="true" :default-expand-all="true"
:expand-on-click-node="false" :filter-node-method="filterNode"
ref="typeTree" node-key="id" highlight-current @node-click="handleNodeClick"
>
<span class="custom-tree-node" slot-scope="{ node, data }" @mousemove="onMousemove(data)" @mouseleave="onMouseleave()">
<span v-if="isMousemoveId === data.value && node.label.length > 10">{{
node.label.slice(0, 10) + "..."
}}</span>
<span v-else>{{ node.label }}</span>
<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>
<span class="btn-items" v-if="isMousemoveId === data.value">
<el-button
type="text"
size="mini"
icon="el-icon-plus" v-if="data.level<2"
@click.stop="() => appendTreeNode(data)"
>
</el-button>
<el-button
type="text"
size="mini"
icon="el-icon-edit-outline"
style="color: #67c23a"
@click.stop="() => editTreeNode(data)"
>
</el-button>
<el-button
type="text"
size="mini"
icon="el-icon-delete"
style="color: #f56c6c" v-if="!data.children||data.children.length==0"
@click.stop="() => removeTreeNode(data)"
>
</el-button>
</span>
</span>
</el-tree>
</div>
</el-col>
<!--用户数据-->
<el-col :span="20" :xs="24">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="98px">
<el-form-item label="营养信息类别" prop="type" >
<el-cascader
v-model="typeSelected" clearable
: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" height="650">
<el-table-column label="序号" align="center" width="80" type="index">
<template slot-scope="scope">
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
</template>
</el-table-column>
<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.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="menuNutritionList" height="650">
<el-table-column label="序号" align="center" width="80" type="index">
<template slot-scope="scope">
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
</template>
</el-table-column>
<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.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改岗位对话框 -->
<el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
<!-- 添加或修改类别对话框 -->
<el-dialog :title="title+'-营养信息类别'" :visible.sync="openType" width="500px" append-to-body :close-on-click-modal="false">
<el-form ref="typeForm" :model="typeForm" :rules="typeRules" label-width="120px">
<el-form-item label="父节点名称" prop="parentName" v-if="typeForm.parentName">
<el-input v-model="typeForm.parentName" placeholder="请输入父节点名称" maxlength="30" disabled/>
</el-form-item>
<el-form-item label="类别名称" prop="name">
<el-input v-model="typeForm.name" placeholder="请输入类别名称" maxlength="30"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleSubmit"> </el-button>
<el-button @click="openType=false"> </el-button>
</div>
</el-dialog>
<!-- 添加或修改对话框 -->
<el-dialog :title="title+'-营养信息'" :visible.sync="open" width="1000px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="180px" label-position="right">
<el-row>
@ -465,7 +550,8 @@
</template>
<script>
import { listNutrition, getNutrition, delNutrition, addMenuNutrition, updateNutrition, typeListApi } from "@/api/dish/nutritionInfo";
import { nutritionTypeListApi,nutritionTypeAddApi, nutritionTypeEditApi, nutritionTypeDelApi } from "@/api/dish/nutritionInfo";
import { listNutrition, getNutrition, delNutrition, addMenuNutrition, updateNutrition } from "@/api/dish/nutritionInfo";
import { cascaderMixin } from './cascaderMixin';
export default {
@ -532,9 +618,9 @@ export default {
},
//
rules: {
nutritionCategory: [
{ required: true, message: "请选择营养信息类别", trigger: "change" }
],
// nutritionCategory: [
// { required: true, message: "", trigger: "change" }
// ],
nutritionName: [
{ required: true, message: "营养信息名称不能为空", trigger: "blur" }
],
@ -544,22 +630,43 @@ export default {
},
typeSelected: [], //
typeTreeData:[],//
cascaderOptions: [] //
cascaderOptions: [], //
defaultProps: {
children: "children",
label: "label",
id: "value"
},
keyWord:"",//-
isMousemoveId: null,
openType:false,
typeForm:{},
typeRules: {
name: [
{ required: true, message: "类别名称不能为空", trigger: "change" }
],
// nutritionName: [
// { required: true, message: "", trigger: "blur" }
// ],
// nutritionCode: [
// { required: true, message: "", trigger: "blur" }
// ]
},
};
},
created() {
this.getFoodType();
this.getNutritionTypeList();
this.getList();
},
methods: {
/**
* 获取所有食材类别
* @returns {Promise<void>}
*/
getFoodType() {
typeListApi().then(response => {
watch: {
//
keyWord(val) {
this.$refs.typeTree.filter(val);
},
},
methods: {
//
getNutritionTypeList() {
nutritionTypeListApi().then(response => {
this.typeTreeData = response.data;
this.cascaderOptions = this.cascaderOptionsMethod();
console.log(this.cascaderOptions)
@ -567,26 +674,106 @@ export default {
}).catch(error => {
console.error("Failed to fetch food types:", error);
});
},
/**
* 生成级联选择器的选项数据
* @returns {Array<{value: string, label: string, children: Array<{value: string, label: string}>}>}
*/
},
//
cascaderOptionsMethod() {
if (this.typeTreeData.length==0) {
return [];
}
return this.typeTreeData.map(item => ({
value: item.bigType,
value: item.id,
label: item.bigType,
parentId:0,
level:1,
children: item.littleTypeList.map(subItem => ({
value: '#'+subItem,//value#
label: subItem
value: subItem.id,//value#
label: subItem.bigType,
parentId:item.id,
level:2
}))
}));
},
// -
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
// -
async handleNodeClick(data, node) {
console.log(data)
// this.handleQuery();
},
/* 树节点增加 */
appendTreeNode(data) {
console.log(data)
if(data&&data.level==1){
this.typeForm={}
this.typeForm.parentId = data.value;
this.typeForm.parentName = data.label;
}else{
this.typeForm={}
this.typeForm.parentId = 0;
}
this.resetForm("typeForm");
this.openType = true;
this.title = "新增";
},
/* 树节点修改 */
editTreeNode(data) {
console.log(data)
this.typeForm={}
this.resetForm("typeForm");
this.$set(this.typeForm,"id",data.value)
this.$set(this.typeForm,"name",data.label)
// this.typeForm = {
// ...data
// };
this.openType = true;
this.title = "修改";
},
/* 树节点删除 */
removeTreeNode(data) {
console.log(data, "删除时的数据源--");
this.$modal
.confirm("是否确认删除数据项?")
.then(function () {
return nutritionTypeDelApi({ids:[data.value]});
})
.then(() => {
this.$modal.msgSuccess("删除成功");
// this.getList();
this.getNutritionTypeList();
})
.catch(() => {});
},
onMousemove(data) {
this.isMousemoveId = data.value;
},
onMouseleave() {
this.isMousemoveId = null;
},
handleSubmit(){
console.log(this.typeForm)
this.$refs.typeForm.validate(valid => {
if (valid) {
if (this.typeForm.id != undefined) {
console.log('修改')
nutritionTypeEditApi(this.typeForm).then(response => {
this.$modal.msgSuccess("修改成功");
this.openType = false;
this.getNutritionTypeList();
});
} else {
console.log('新增')
nutritionTypeAddApi(this.typeForm).then(response => {
this.$modal.msgSuccess("新增成功");
this.openType = false;
this.getNutritionTypeList();
});
}
}
});
},
/**
* 处理级联选择器值变化
* @param {Array<string>} value - 选中的值数组
@ -600,11 +787,11 @@ export default {
this.queryParams.bigType = undefined;
this.queryParams.littleType = undefined;
}
},
},
/** 查询岗位列表 */
getList() {
this.loading = true;
console.log(this.queryParams)
listNutrition(this.queryParams).then(response => {
this.menuNutritionList = response.rows;
this.total = Number(response.total);
@ -678,9 +865,9 @@ export default {
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.nutritionId;
// const id = row.nutritionId;
var data = {
nutritionId: id
id: row.id
}
getNutrition(data).then(response => {
this.form = response.data;
@ -700,8 +887,8 @@ export default {
//
if (formData.nutritionCategory && formData.nutritionCategory.length >= 2) {
formData.bigType = formData.nutritionCategory[0];
formData.littleType = formData.nutritionCategory[1].split("#")[1];
}
formData.littleType = formData.nutritionCategory[1].split("#")[1];
}
delete formData.nutritionCategory; //
if (formData.id != undefined) {
@ -793,10 +980,140 @@ export default {
};
</script>
<style scoped>
<style lang="scss" scoped>
::v-deep .el-dialog__body {
max-height: calc(90vh - 120px);
overflow-y: auto;
padding: 20px;
}
::v-deep.el-table .fixed-width .el-button--mini {
width: 60px !important;
margin-bottom: 10px;
}
::v-deep .btn-items .el-button + .el-button {
margin-left: 6px;
}
.btn-items {
margin-left: 4px;
.el-button--text {
font-size: 16px;
}
}
// ::v-deep .el-tree .el-tree-node__expand-icon.expanded {
// -webkit-transform: rotate(0deg);
// transform: rotate(0deg);
// }
// ::v-deep .el-tree .el-icon-caret-right:before {
// content: "\e783";
// font-size: 16px;
// }
// ::v-deep
// .el-tree
// .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
// content: "\e781";
// font-size: 16px;
// color: #1890ff;
// }
// ::v-deep .el-tree-node__content > .el-tree-node__expand-icon {
// color: #1890ff !important;
// }
// ::v-deep .el-tree-node__expand-icon.is-leaf {
// color: transparent !important;
// }
// ::v-deep
// .el-tree--highlight-current
// .el-tree-node.is-current
// > .el-tree-node__content {
// background-color: #8decf1;
// }
::v-deep .el-dialog .material-dialog {
//
.el-form-item__label {
font-size: 14px;
color: #606266;
font-weight: 500;
line-height: 1.5;
}
//
.el-input__inner {
font-size: 14px;
color: #303133;
&::placeholder {
font-size: 13px;
color: #c0c4cc;
}
}
//
span {
font-size: 14px;
// color: #606266;
margin-left: 8px;
}
//
.el-select {
.el-input__inner {
font-size: 14px;
color: #303133;
}
}
//
.el-input.is-disabled .el-input__inner {
background-color: #f5f7fa;
border-color: #e4e7ed;
color: #606266;
cursor: not-allowed;
}
}
//
::v-deep .el-table {
font-size: 14px;
th {
font-weight: 500;
color: #303133;
}
td {
color: #606266;
}
}
//
::v-deep .el-button {
font-size: 14px;
&--text {
font-size: 13px;
}
}
//
::v-deep .el-tree-node__label {
font-size: 14px;
color: #606266;
}
//
::v-deep .el-input--small {
.el-input__inner {
font-size: 13px;
&::placeholder {
font-size: 13px;
color: #c0c4cc;
}
}
}
</style>