🍳 厨房出品操作文档

乐大都食堂管理系统 - 出品计划与调度管理

📋 功能概述

厨房出品功能用于规划下一天的菜品出品计划,按早、中、晚餐段进行分配,为厨房生产调度提供准确的制作依据。

🎯 核心功能

  • 按餐段规划出品菜品
  • 智能分词与菜品查重
  • 菜品批量核验与存库状态管理
  • 灵活的增删改操作
  • 数据完整性验证与保存限制
  • 数据持久化存储

💡 使用场景

  • 每日出品计划制定
  • 厨房生产调度安排
  • 菜品库存与采购规划
  • 出品数据分析

🚀 操作流程与数据流处理

厨房出品功能包含以下主要操作流程,每个操作都有独立的数据处理逻辑和用户交互界面。

📄 静态页面结构

页面文件:kitout/index.html

页面主要结构:
  • 导航区域:日期显示、母菜单、子菜单
  • 交互区域:输入示例、菜品显示区域(早餐/中餐/晚餐/未分类)
  • 输入条:命令输入框和发送按钮
  • 浮动按钮组:选菜、拖动、删除、保存四个操作按钮
  • 浮动按钮监听函数:menuOutput_handleFloatingButtonAction
  • 模态框:操作确认对话框
浮动按钮监听函数说明:

menuOutput_handleFloatingButtonAction函数:输入接收点击事件对象,处理过程检测按钮动作(保存/选菜/拖动/删除),对于保存按钮直接调用menuOutput_saveData,输出按钮处理结果。

📱 页面入口与总调

负责厨房出品功能的页面入口和总体调度,实现基于浮动按钮状态的菜品响应处理分发机制

对应JavaScript文件:kitout.js

完整时序处理流程

当用户打开厨房出品页面时,系统按照以下时序执行完整的初始化操作:

  1. 页面加载完成:浏览器完成DOM解析后,DOMContentLoaded事件触发
  2. 主初始化函数调用:menuOutput_init函数被调用,开始厨房出品模块初始化
  3. 前端向后端请求数据:menuOutput_init调用fetchKitchenOutputData函数,向/mobile/combo/api/kitout/dishes接口发送GET请求,包含日期参数20250501
  4. 后端处理数据请求:后端API接收日期参数,查询daily_dishes表获取该日期的菜品安排,按餐段分类后返回JSON格式的菜品数据
  5. 前端接收并处理数据:fetchKitchenOutputData接收后端返回的数据,menuOutput_init调用initializeGlobalVariables函数初始化window.kitchenData全局数据结构
  6. 数据获取阶段:menuOutput_init调用fetchKitchenOutputData函数从后端API获取菜品数据
  7. 页面渲染:menuOutput_init调用renderMealSections函数,将菜品数据按早餐、午餐、晚餐三个餐段分类显示在页面上
  8. 浮动按钮状态初始化:menuOutput_init调用menuOutput_initDefaultMode函数,设置默认选菜模式并绑定对应的监听处理程序
  9. 初始化完成:menuOutput_init函数执行完毕,页面进入可交互状态

📤 发送处理

编程要求:前端发送, 不同餐段 + 菜品, 前段用标点符号进行分词, 然后,对应页面餐段 结构, 先看是 餐段+菜品 是不是已经存在, 比如,要先看 餐段 + 馒头 是不是已经有了, 有了就不加, 要有一个加入结果的弹窗 早餐已经有馒头, 中餐已经有炒土豆丝, 这样对输入已经有的 加入提示字串ABC, 其它不提示, 新的各菜品, 送到服务端, 在 dishes 里查一下, 看每个菜品是不是有全匹配, 返回 全匹配的后的情况: 匹配不匹配, 匹配有 dish_id , 不匹配 dish_id = null 前端取到匹配结果, 加到餐段数据结构里, 对界面各餐段进行刷新, 新增 dish_id 有值的黄色框, dish_id =null 的显示绿色, 全部处理完成, 弹出ABC 内容提示 发送提交, 显示等待状态, 进行上述处理,处理完成出提示窗口, 窗口按确认退出, 页面加入标签 发送示例 : 午餐:宫保鸡丁 藜麦牛油果兔丁 晚餐:馒头 炝炒圆白菜 其中 藜麦牛油果兔丁 为新增 馒头 晚餐有了则弹窗提示:下列已有 晚餐 馒头 新标签 : 黄框 宫保鸡丁 炝炒圆白菜 绿框 藜麦牛油果兔丁 晚

对应JavaScript文件:p0kitout.js

操作描述

完整时序处理流程

当用户在输入框中输入菜品信息并点击发送按钮时,系统按照以下时序执行完整的发送处理操作:

  1. 用户输入菜品文本:用户在输入框中输入包含餐段和菜品的文本信息
  2. 发送按钮点击事件:用户点击发送按钮,触发menuOutput_handleKitchenOutputCommand函数
  3. 标点符号分词处理:menuOutput_handleKitchenOutputCommand调用menuOutput_tokenizeMenuText函数,使用标点符号进行文本分割
  4. 餐段+菜品查重对比:menuOutput_tokenizeMenuText对输入菜品与餐段已有菜品进行全匹配对比,检查餐段+菜品组合是否已存在(如早餐+馒头)
  5. 已存在菜品提示:对已存在的餐段+菜品组合进行提示(如早餐已有馒头,中餐已有炒土豆丝),其他不提示
  6. 新菜品服务端验证:menuOutput_displayTokenizedResult调用menuOutput_validateDishes函数,将所有新菜品发送到核验API
  7. 后端菜品全匹配验证:menuOutput_validateDishes向/mobile/combo/api/kitout/validate-dishes接口发送POST请求,包含新菜品列表
  8. 后端菜品库全匹配对比:后端validate_dishes_api函数接收菜品列表,在dishes表中进行全匹配验证
  9. 数据库全匹配查询处理:validate_dishes_api调用db.validate_dishes函数查询dishes表,匹配菜品返回dish_id,不匹配菜品返回dish_id=null
  10. 验证结果返回:后端返回已存库和未存库的菜品记录,包含菜品ID信息(匹配有dish_id,不匹配dish_id=null)
  11. 前端状态显示更新:menuOutput_validateDishes接收验证结果,前端用黄框表示dish_id有值的菜品,绿框表示dish_id=null的菜品
  12. 菜品分类存储:menuOutput_displayTokenizedResult将菜品按识别到的餐段分类到对应区域,新菜品按餐段分别写入
  13. 界面更新完成:所有菜品显示在对应餐段区域,发送处理操作完成

前端JavaScript处理流程

  • 标点符号分词:使用标点符号进行文本分割,识别餐段关键词(早餐/中餐/晚餐)
  • 餐段+菜品查重:对输入菜品与餐段已有菜品进行全匹配对比,检查餐段+菜品组合是否已存在
  • 已存在菜品提示:对已存在的餐段+菜品组合进行提示(如早餐已有馒头),其他不提示
  • 新菜品服务端验证:将所有新菜品发送到核验API进行全匹配验证
  • 状态显示:前端用黄框表示dish_id有值的菜品,绿框表示dish_id=null的菜品
  • 分类存储:将菜品按识别到的餐段分类到对应区域,新菜品按餐段分别写入

后端Python处理流程

  • 菜品全匹配验证:在dishes表中进行全匹配对比,匹配菜品返回dish_id,不匹配菜品返回dish_id=null
  • 状态返回:返回已存库和未存库的菜品记录,包含菜品ID信息(匹配有dish_id,不匹配dish_id=null)
  • 数据完整性:确保daily_dishes表包含完整的菜品ID信息

完整时序处理流程

当用户在输入框中输入菜品信息并点击发送按钮时,系统按照以下时序执行完整的发送处理操作:

  1. 用户输入菜品文本:用户在输入框中输入包含餐段和菜品的文本信息
  2. 发送按钮点击事件:用户点击发送按钮,触发menuOutput_handleKitchenOutputCommand函数
  3. 标点符号分词处理:menuOutput_handleKitchenOutputCommand调用menuOutput_tokenizeMenuText函数,使用标点符号进行文本分割
  4. 餐段+菜品查重对比:menuOutput_tokenizeMenuText对输入菜品与餐段已有菜品进行全匹配对比,检查餐段+菜品组合是否已存在(如早餐+馒头)
  5. 已存在菜品提示:对已存在的餐段+菜品组合进行提示(如早餐已有馒头,中餐已有炒土豆丝),其他不提示
  6. 新菜品服务端验证:menuOutput_displayTokenizedResult调用menuOutput_validateDishes函数,将所有新菜品发送到核验API
  7. 后端菜品全匹配验证:menuOutput_validateDishes向/mobile/combo/api/kitout/validate-dishes接口发送POST请求,包含新菜品列表
  8. 后端菜品库全匹配对比:后端validate_dishes_api函数接收菜品列表,在dishes表中进行全匹配验证
  9. 数据库全匹配查询处理:validate_dishes_api调用db.validate_dishes函数查询dishes表,匹配菜品返回dish_id,不匹配菜品返回dish_id=null
  10. 验证结果返回:后端返回已存库和未存库的菜品记录,包含菜品ID信息(匹配有dish_id,不匹配dish_id=null)
  11. 前端状态显示更新:menuOutput_validateDishes接收验证结果,前端用黄框表示dish_id有值的菜品,绿框表示dish_id=null的菜品
  12. 菜品分类存储:menuOutput_displayTokenizedResult将菜品按识别到的餐段分类到对应区域,新菜品按餐段分别写入
  13. 界面更新完成:所有菜品显示在对应餐段区域,发送处理操作完成

前端JavaScript处理流程

  • 标点符号分词:使用标点符号进行文本分割,识别餐段关键词(早餐/中餐/晚餐)
  • 餐段+菜品查重:对输入菜品与餐段已有菜品进行全匹配对比,检查餐段+菜品组合是否已存在
  • 已存在菜品提示:对已存在的餐段+菜品组合进行提示(如早餐已有馒头),其他不提示
  • 新菜品服务端验证:将所有新菜品发送到核验API进行全匹配验证
  • 状态显示:前端用黄框表示dish_id有值的菜品,绿框表示dish_id=null的菜品
  • 分类存储:将菜品按识别到的餐段分类到对应区域,新菜品按餐段分别写入

后端Python处理流程

  • 菜品全匹配验证:在dishes表中进行全匹配对比,匹配菜品返回dish_id,不匹配菜品返回dish_id=null
  • 状态返回:返回已存库和未存库的菜品记录,包含菜品ID信息(匹配有dish_id,不匹配dish_id=null)
  • 数据完整性:确保daily_dishes表包含完整的菜品ID信息

各函数的IPO处理

前端JavaScript函数(menu-output.js)

menuOutput_tokenizeMenuText函数:输入接收用户输入的菜品文本,处理过程识别餐段关键词进行智能分词,输出按餐段分类的菜品对象。

menuOutput_displayTokenizedResult函数:输入接收分类菜品数据,处理过程生成HTML内容并显示分词结果,输出渲染完成的菜品标签界面。

menuOutput_handleKitchenOutputCommand函数:输入接收用户命令输入,处理过程调用分词和显示功能,输出处理完成的菜品显示结果。

前端JavaScript函数(kitout.js)

menuOutput_validateDishes函数:输入接收未验证菜品列表,处理过程调用批量核验API验证菜品,输出验证结果状态信息。

后端Python函数(router.py)

validate_dishes_api函数:输入接收菜品名称列表,处理过程在dishes表中进行全匹配验证,输出已存库和未存库的菜品记录。

后端Python函数(db.py)

validate_dishes函数:输入接收菜品名称列表,处理过程查询dishes表进行菜品验证,输出验证结果数据。

相关API调用

🍽️ 获取所有菜品数据

接口地址:/mobile/combo/api/dishes/all

请求方法:GET

调用时机:用户输入菜品时进行对库验证,确保菜品名称正确

功能描述:获取系统中所有菜品的基础信息,用于菜品验证和智能匹配

🔍 菜品批量核验

接口地址:/mobile/combo/api/dishes/validate

请求方法:POST

调用时机:用户输入新菜品时,一次性核验所有未输入菜品

功能描述:批量验证菜品是否在菜品库中存在,返回已存库和未存库的菜品记录

🍽️ 选菜操作

在"选菜"模式下,用户通过点击菜品标签弹出下拉框选择菜品,通过浮动按钮状态分发机制绑定p1kitout.js中的监听处理程序

对应JavaScript文件:p1kitout.js

操作描述

  • 模式切换:通过浮动按钮切换到"选菜"模式,绑定p1kitout.js中的menuOutput_handleDishClick函数
  • 点击标签:在"选菜"模式下点击菜品标签弹出下拉框
  • 下拉选择:从下拉框中选择当前菜品或相关推荐菜品
  • 智能推荐:系统基于字符串相似度推荐相关菜品
  • 自动更新:选择菜品后自动更新标签内容和属性

完整时序处理流程

当用户在"选菜"模式下点击菜品标签时,系统按照以下时序执行完整的选菜操作:

  1. 模式切换触发:用户点击"选菜"浮动按钮,menuOutput_switchFloatingButtonState函数绑定p1kitout.js监听处理程序
  2. 用户点击菜品标签:在"选菜"模式下,用户点击菜品标签触发menuOutput_handleDishClick函数
  3. 检查当前模式:menuOutput_handleDishClick函数检查当前是否为"select"模式
  4. 显示下拉框:menuOutput_toggleDishList函数被调用,创建并显示菜品选择下拉框
  5. 获取相关菜品推荐:menuOutput_toggleDishList调用menuOutput_getRelatedDishes函数,基于字符串相似度计算相关菜品
  6. 生成下拉框内容:创建包含当前菜品和推荐菜品的下拉列表,当前菜品显示为已选中状态
  7. 定位下拉框位置:menuOutput_toggleDishList调用menuOutput_positionList函数,计算最佳显示位置
  8. 绑定点击事件:为下拉框中的每个菜品项添加点击事件监听器
  9. 用户选择菜品:用户从下拉框中选择目标菜品
  10. 菜品选择处理:menuOutput_selectDish函数被调用,更新菜品标签内容和data-dish属性
  11. 关闭下拉框:menuOutput_selectDish关闭菜品选择下拉框
  12. 界面状态更新:更新菜品显示,标签内容自动更新为选中的菜品
  13. 保存状态激活:设置保存按钮为可用状态,提示用户数据已变更
  14. 选菜操作完成:菜品标签内容成功更新,选菜操作完成

各函数的IPO处理

前端JavaScript函数(menu-output.js)

menuOutput_addTagClickEvents函数:输入接收所有标签容器元素,处理过程为标签添加触摸点击事件监听器,检查当前模式是否为"select",输出绑定完成的事件系统。

menuOutput_toggleDishList函数:输入接收菜品标签元素和当前菜品名称,处理过程创建并显示菜品选择下拉框,包含当前菜品和推荐菜品,输出菜品选择界面。

menuOutput_getRelatedDishes函数:输入接收当前菜品名称,处理过程基于字符串相似度计算相关菜品(使用预定义的菜品列表),输出推荐菜品列表。

menuOutput_selectDish函数:输入接收菜品标签元素和选中的菜品名称,处理过程更新标签文本内容和data-dish属性,关闭下拉框,输出更新后的菜品标签。

menuOutput_positionList函数:输入接收下拉框元素和标签元素,处理过程计算最佳显示位置(上方或下方),输出定位完成的下拉框。

menuOutput_closeAllLists函数:输入接收无参数,处理过程关闭所有已显示的菜品选择下拉框,输出清理完成的界面状态。

后端Python函数(router.py)

get_all_dishes_api函数:输入接收无参数,处理过程调用数据库函数获取所有菜品列表,输出包含所有菜品信息的JSON响应。

search_dishes_api函数:输入接收搜索关键词和数量限制参数,处理过程调用数据库搜索函数进行模糊匹配,输出搜索结果列表。

get_dish_by_id_api函数:输入接收菜品ID参数,处理过程调用数据库函数获取菜品详情,输出菜品详细信息。

get_similar_dishes_api函数:输入接收菜品名称和数量限制参数,处理过程基于字符串相似度计算相关菜品,输出相似菜品列表。

validate_dishes_api函数:输入接收菜品名称列表,处理过程验证菜品是否在菜品库中存在,输出验证结果状态。

后端Python函数(db.py)

get_all_dishes函数:输入接收无参数,处理过程查询dishes表获取所有菜品,输出菜品列表数据。

search_dishes函数:输入接收搜索关键词和数量限制参数,处理过程使用LIKE进行模糊匹配查询,输出搜索结果。

get_dish_by_id函数:输入接收菜品ID参数,处理过程根据ID查询菜品详情,输出菜品信息。

find_dish_id_by_name函数:输入接收菜品名称参数,处理过程进行精确匹配和模糊匹配查询,输出菜品ID。

validate_dishes函数:输入接收菜品名称列表,处理过程验证每个菜品是否存在,输出验证结果。

相关API调用

🍽️ 获取所有菜品数据

接口地址:/mobile/combo/api/dishes/all

请求方法:GET

调用时机:页面初始化时获取菜品列表,用于智能推荐和菜品验证

功能描述:获取系统中所有菜品的基础信息,用于菜品选择界面的智能匹配和推荐

🔍 菜品搜索

接口地址:/mobile/combo/api/dishes/search

请求方法:GET

调用时机:用户输入关键词时进行模糊搜索,提供相关菜品选项

功能描述:根据关键词模糊搜索菜品,返回匹配的菜品列表

🔗 获取相似菜品

接口地址:/mobile/combo/api/dishes/similar

请求方法:GET

调用时机:用户选择菜品时,基于当前菜品名称推荐相似菜品

功能描述:基于字符串相似度算法,推荐与当前菜品相关的其他菜品

🗑️ 删除操作

在"删除"模式下,用户通过点击菜品标签删除对应菜品,通过浮动按钮状态分发机制绑定p2kitout.js中的监听处理程序

对应JavaScript文件:p2kitout.js

操作描述

  • 模块初始化:页面加载时p2kitout_initDeleteModule函数初始化删除模块,设置浮动按钮监听器
  • 模式切换:通过浮动按钮切换到"删除"模式,p2kitout_setDeleteModeActive函数激活删除状态
  • 样式更新:删除按钮显示激活状态(红色背景),菜品元素变为可点击状态
  • 提示显示:p2kitout_showDeleteModeHint函数显示"删除模式已激活"提示信息
  • 监听器绑定:p2kitout_setupDishClickListeners函数为所有菜品添加点击监听器
  • 点击标签:在"删除"模式下点击菜品标签,p2kitout_handleDishClick函数触发删除确认
  • 选中效果:点击的菜品显示选中样式(红色边框和阴影)
  • 确认删除:p2kitout_showDeleteConfirmation函数弹出确认对话框,支持ESC键和外部点击关闭
  • 动画效果:用户确认后,p2kitout_deleteDish函数执行删除动画(淡出+缩放)
  • 数据同步:p2kitout_setDataModified函数标记数据已修改,更新保存按钮状态
  • 统计更新:p2kitout_updateUnstoredDishesCountAfterDelete函数更新未存库菜品数量
  • 成功提示:p2kitout_showDeleteSuccessMessage函数显示删除成功消息
  • 按钮检查:p2kitout_checkFloatingButtonsVisibility函数检查是否需要隐藏浮动按钮组
  • 状态恢复:退出删除模式时,p2kitout_removeDishClickListeners函数清除监听器

完整时序处理流程

当用户在"删除"模式下点击菜品标签时,系统按照以下时序执行完整的删除操作:

  1. 模式切换触发:用户点击"删除"浮动按钮,menuOutput_switchFloatingButtonState函数绑定p2kitout.js监听处理程序
  2. 用户点击菜品标签:在"删除"模式下,用户点击菜品标签触发p2kitout_handleDishClick函数
  3. 检查当前模式:p2kitout_handleDishClick函数检查当前是否为"delete"模式
  4. 显示确认对话框:menuOutput_confirmDelete函数被调用,显示删除确认对话框
  5. 用户确认删除:用户点击确认按钮确认删除操作
  6. 执行删除操作:menuOutput_deleteDish函数被调用,从菜品列表中移除对应菜品
  7. 视觉反馈开始:menuOutput_deleteDish调用menuOutput_showDeletingFeedback函数,显示删除动画
  8. 更新菜品列表:从DOM中移除对应的菜品标签元素
  9. 视觉反馈结束:删除动画完成后,视觉反馈结束
  10. 保存状态激活:设置保存按钮为可用状态,提示用户数据已变更
  11. 删除操作完成:菜品成功从列表中移除,删除操作完成

各函数的IPO处理

前端JavaScript函数(p2kitout.js - 删除操作核心模块)

p2kitout_initDeleteModule函数:输入无参数,处理过程初始化删除模块,设置浮动按钮监听器和删除模式状态,输出删除模块初始化完成状态。

p2kitout_setupFloatingButtonListeners函数:输入无参数,处理过程为删除按钮设置点击监听器,实现删除模式切换功能,输出监听器绑定完成状态。

p2kitout_setDeleteModeActive函数:输入接收布尔值active参数,处理过程设置删除模式激活状态,更新按钮样式和显示提示信息,输出删除模式状态更新结果。

p2kitout_setupDishClickListeners函数:输入无参数,处理过程为所有菜品元素添加点击监听器和选中样式,输出监听器设置完成状态。

p2kitout_removeDishClickListeners函数:输入无参数,处理过程清除所有菜品的点击事件监听器,输出监听器清除完成状态。

p2kitout_handleDishClick函数:输入接收菜品点击事件对象,处理过程检查删除模式状态,显示删除确认对话框,输出用户操作结果。

p2kitout_showDeleteConfirmation函数:输入接收菜品元素和菜品名称,处理过程显示删除确认模态框,支持ESC键和外部点击关闭,输出用户确认结果。

p2kitout_deleteDish函数:输入接收菜品元素和菜品名称,处理过程执行删除动画效果,移除DOM元素,更新数据状态,输出删除操作完成状态。

p2kitout_setDataModified函数:输入接收布尔值modified参数,处理过程标记数据修改状态,更新保存按钮样式,输出数据状态更新结果。

p2kitout_checkFloatingButtonsVisibility函数:输入无参数,处理过程检查菜品数量,控制浮动按钮组的显示/隐藏,输出按钮可见性状态。

p2kitout_updateUnstoredDishesCountAfterDelete函数:输入无参数,处理过程重新计算未存库菜品数量,更新统计信息,输出数量更新结果。

p2kitout_showDeleteSuccessMessage函数:输入接收菜品名称,处理过程显示删除成功提示信息,3秒后自动消失,输出提示显示状态。

p2kitout_showDeleteModeHint函数:输入无参数,处理过程显示删除模式激活提示信息,5秒后自动隐藏,输出提示显示状态。

p2kitout_hideDeleteModeHint函数:输入无参数,处理过程隐藏删除模式提示信息,输出提示隐藏状态。

前端JavaScript函数(kitout.js)

menuOutput_showDeleteConfirmation函数:输入接收菜品元素和菜品名称,处理过程显示删除确认对话框,输出用户确认结果。

menuOutput_deleteDish函数:输入接收菜品元素,处理过程从界面删除菜品并更新状态,输出更新后的菜品列表。

menuOutput_showModal函数:输入接收标题、内容和回调函数,处理过程显示模态对话框,输出用户操作结果。

前端JavaScript函数(menu-output.js)

menuOutput_handleDelete函数:输入接收菜品标签元素,处理过程删除菜品并更新界面,输出更新后的菜品显示。

后端Python函数(router.py)

delete_dish_api函数:输入接收菜品ID和日期参数,处理过程从daily_dishes表删除菜品记录,输出删除操作结果。

后端Python函数(db.py)

delete_dish函数:输入接收菜品ID和日期参数,处理过程执行数据库删除操作,输出删除结果状态。

相关API调用

🗑️ 删除菜品

接口地址:/mobile/combo/api/kitout/delete-dish

请求方法:DELETE

调用时机:用户确认删除菜品时,从出品计划中移除指定菜品

功能描述:删除指定日期和菜品ID的出品记录,支持单个和批量删除操作

💾 保存操作

点击"保存"按钮将整理好的出品计划数据持久化存储到数据库中

对应JavaScript文件:p3kitout.js

操作描述

  • 数据完整性检查:保存前检查菜品ID信息是否完整
  • 未存库菜品限制:存在未存库菜品时禁止保存,提示用户先处理未存库菜品
  • 全量更新:采用先删除后插入的方式,确保数据一致性
  • 事务处理:确保删除和插入操作在一个事务中完成
  • 保存确认:保存成功后显示操作结果提示

完整时序处理流程

当用户点击保存按钮时,系统按照以下时序执行完整的保存操作:

  1. 用户触发保存操作:用户点击"保存"按钮,触发menuOutput_handleFloatingButtonAction函数
  2. 浮动按钮监听处理:menuOutput_handleFloatingButtonAction检测到action为"保存",直接调用menuOutput_saveData函数
  3. 数据完整性检查:menuOutput_saveData调用menuOutput_canSave函数检查是否存在未存库菜品
  4. 未存库菜品验证:menuOutput_canSave遍历所有菜品,检查菜品ID是否完整,返回验证结果
  5. 保存权限判断:如果存在未存库菜品,显示提示信息并阻止保存操作
  6. 数据收集准备:通过验证后,menuOutput_saveData调用menuOutput_collectAllDishes函数收集菜品数据
  7. 餐段数据收集:menuOutput_collectAllDishes遍历早餐、午餐、晚餐和未分类餐段,收集所有菜品信息
  8. 数据结构组织:将收集的菜品数据按餐段分类,构建完整的保存数据结构
  9. API保存调用:menuOutput_saveData调用menuOutput_saveToAPI函数,向/mobile/combo/api/kitchen-output/save接口发送POST请求
  10. 后端保存处理:后端save_kitchen_output函数接收保存请求,验证数据格式和权限
  11. 数据库事务开始:save_kitchen_output调用db.save_kitchen_output_data函数,开始数据库事务
  12. 历史数据清理:先删除指定日期的所有现有菜品记录,确保数据一致性
  13. 新数据插入:将新的菜品数据批量插入到daily_dishes表中
  14. 事务提交:数据库操作完成后提交事务,确保数据完整性
  15. 保存结果返回:后端返回保存操作结果状态给前端
  16. 界面状态更新:menuOutput_saveData接收保存结果,显示保存成功提示
  17. 保存操作完成:菜品数据成功持久化到数据库,保存操作完成

各函数的IPO处理

前端JavaScript函数(kitout.js)

menuOutput_saveData函数:输入接收无参数,处理过程检查数据完整性、收集菜品数据、调用保存API,输出保存操作结果。

menuOutput_canSave函数:输入接收无参数,处理过程检查是否存在未存库菜品,输出是否允许保存的布尔值。

menuOutput_collectAllDishes函数:输入接收无参数,处理过程收集所有餐段的菜品数据,输出完整的菜品数据结构。

menuOutput_saveToAPI函数:输入接收菜品数据,处理过程发送保存请求到后端API,输出保存结果状态。

前端JavaScript函数(menu-output.js)

menuOutput_saveData函数:输入接收无参数,处理过程收集当前界面数据并调用globalmeal API保存,输出保存操作结果。

menuOutput_collectCurrentData函数:输入接收无参数,处理过程收集所有餐段的菜品数据,输出当前界面数据对象。

后端Python函数(router.py)

save_kitchen_output函数:输入接收菜品数据和日期参数,处理过程调用数据库保存函数,输出保存操作结果。

后端Python函数(db.py)

save_kitchen_output_data函数:输入接收菜品数据和日期参数,处理过程执行事务性保存操作,输出数据库操作结果。

相关API调用

💾 保存厨房出品数据

接口地址:/mobile/combo/api/kitchen-output/save

请求方法:POST

调用时机:用户点击保存按钮时,将整理好的出品计划数据持久化存储

功能描述:采用事务性保存方式,先删除历史数据再插入新数据,确保数据一致性

🔄 拖动操作

在"拖动"模式下,用户通过拖动菜品调整出品顺序和餐段分配,通过浮动按钮状态分发机制绑定p4kitout.js中的监听处理程序

对应JavaScript文件:p4kitout.js

操作描述

  • 模式切换:通过浮动按钮切换到"拖动"模式,绑定p4kitout.js中的p4kitout_handleDishClick函数
  • 点击提示:点击菜品显示拖拽提示,指导用户进行拖拽操作
  • 顺序调整:拖动菜品在同一个餐段内调整出品顺序
  • 餐段转移:将菜品从一个餐段拖动到另一个餐段
  • 视觉反馈:拖动过程中显示拖拽状态和位置提示
  • 状态同步:拖动完成后自动保存新的排列顺序

完整时序处理流程

当用户在"拖动"模式下点击菜品标签时,系统按照以下时序执行完整的拖动操作:

  1. 模式切换触发:用户点击"拖动"浮动按钮,menuOutput_switchFloatingButtonState函数绑定p4kitout.js监听处理程序
  2. 用户点击菜品标签:在"拖动"模式下,用户点击菜品标签触发p4kitout_handleDishClick函数
  3. 检查当前模式:p4kitout_handleDishClick函数检查当前是否为"drag"模式
  4. 显示拖拽提示:menuOutput_showDragHint函数被调用,显示拖拽操作提示信息
  5. 拖拽功能初始化:页面加载时menuOutput_initDragDrop函数被调用,初始化拖拽事件监听器
  6. 用户开始拖拽:用户触摸或点击菜品元素,触发menuOutput_handleTouchStart或menuOutput_handleDragStart函数
  7. 拖拽状态记录:记录拖拽开始位置、时间戳和拖拽元素信息,设置拖拽样式
  8. 拖拽移动处理:用户移动手指或鼠标,触发menuOutput_handleTouchMove或menuOutput_handleDragOver函数
  9. 位置计算更新:实时计算拖拽距离、方向和当前位置,更新拖拽元素位置
  10. 放置区域检测:检测拖拽元素是否进入有效的放置区域(其他餐段或同餐段不同位置)
  11. 视觉反馈显示:在有效的放置区域显示放置提示效果,提供视觉反馈
  12. 拖拽结束处理:用户释放触摸或鼠标,触发menuOutput_handleTouchEnd或menuOutput_handleDrop函数
  13. 拖拽有效性判断:判断拖拽距离和时间是否满足有效拖拽条件
  14. 放置位置计算:计算拖拽元素应该放置的目标位置索引
  15. 菜品移动执行:menuOutput_handleTouchDrop或menuOutput_handleDrop函数执行菜品移动操作
  16. DOM元素重排:menuOutput_updateDishOrder函数更新DOM元素顺序,重新排列菜品显示
  17. 餐段归属更新:如果菜品被拖动到不同餐段,更新菜品的餐段归属信息
  18. 界面状态同步:更新菜品顺序和餐段信息,同步界面显示状态
  19. 自动保存触发:拖动完成后自动触发保存操作,将新的排列顺序持久化到数据库
  20. 拖动操作完成:菜品成功移动到新位置,拖动操作完成

各函数的IPO处理

前端JavaScript函数(menu-output.js)

menuOutput_handleTouchStart函数:输入接收触摸事件对象,处理过程记录拖拽开始位置和时间,输出拖拽状态信息。

menuOutput_handleTouchMove函数:输入接收触摸事件对象,处理过程计算拖拽距离和方向,输出拖拽位置更新。

menuOutput_handleTouchEnd函数:输入接收触摸事件对象,处理过程判断是否为有效拖拽并处理放置逻辑,输出拖拽操作结果。

menuOutput_handleTouchDrop函数:输入接收拖拽元素和目标位置,处理过程移动菜品到新位置,输出更新后的菜品顺序。

menuOutput_updateDishOrder函数:输入接收菜品元素和新位置索引,处理过程更新DOM元素顺序,输出重新排序的菜品列表。

前端JavaScript函数(kitout.js)

menuOutput_initDragDrop函数:输入接收无参数,处理过程初始化拖拽事件监听器,输出拖拽功能就绪状态。

menuOutput_handleDragStart函数:输入接收拖拽事件对象,处理过程设置拖拽数据和样式,输出拖拽开始状态。

menuOutput_handleDragOver函数:输入接收拖拽事件对象,处理过程阻止默认行为并设置放置效果,输出拖拽悬停状态。

menuOutput_handleDrop函数:输入接收拖拽事件对象,处理过程获取拖拽数据并移动菜品,输出拖拽完成结果。

相关API调用

💾 保存厨房出品数据

接口地址:/mobile/combo/api/kitchen-output/save

请求方法:POST

调用时机:拖动操作完成后自动触发保存,将新的菜品排列顺序持久化存储

功能描述:拖动操作完成后自动调用保存接口,确保菜品顺序和餐段分配的变更被及时保存

🌐 全局结构与变量

相关文件: kitout.js

厨房出品功能采用全局数据管理策略,通过window.kitchenData对象统一管理所有菜品数据和操作状态,确保前端与后端数据库的完整对应关系。

前端全局数据结构

window.kitchenData 核心对象

实际数据结构(基于代码实现):

window.kitchenData = {
    // 餐段菜品数据 - 直接存储菜品对象数组
    breakfast: [
        {
            name: "菜品名称",     // 菜品名称
            dish_id: 123          // 菜品ID(已存库菜品有ID,未存库菜品为null)
        },
        // 更多早餐菜品...
    ],
    lunch: [
        {
            name: "菜品名称",
            dish_id: 456
        }
    ],
    dinner: [
        {
            name: "菜品名称", 
            dish_id: 789
        }
    ],
    uncategorized: [
        {
            name: "未分类菜品",
            dish_id: null        // 未存库菜品dish_id为null
        }
    ],
    
    // 统计信息(动态计算)
    statistics: {
        totalDishes: 0,          // 菜品总数
        storedDishes: 0,         // 已存库菜品数
        unstoredDishes: 0,       // 未存库菜品数
        mealCounts: {             // 各餐段菜品数
            breakfast: 0,
            lunch: 0, 
            dinner: 0,
            uncategorized: 0
        }
    },
    
    // 操作状态
    operationState: {
        isEditing: false,         // 是否处于编辑状态
        hasUnsavedChanges: false, // 是否有未保存的修改
        currentDate: "20250501"   // 当前操作日期
    }
};

数据结构说明

  • 餐段数组结构:每个餐段(breakfast/lunch/dinner/uncategorized)直接存储菜品对象数组,而非嵌套在mealSections对象中
  • 菜品对象字段:每个菜品包含name(菜品名称)和dish_id(菜品ID)两个核心字段
  • 存库状态标识:dish_id为null表示未存库菜品,有有效ID表示已存库菜品
  • 数据来源:通过menuOutput_collectAllDishes()函数从DOM元素收集,包含data-dish和data-dish-id属性

全局控制变量

🔄 操作状态变量

  • window.isKitchenOutputInitialized: 页面初始化完成标志
  • window.currentDragElement: 当前拖拽的菜品元素
  • window.dragStartPosition: 拖拽开始位置坐标
  • window.isDragging: 是否正在拖拽状态

📊 数据管理变量

  • window.originalKitchenData: 原始菜品数据备份
  • window.dishCache: 菜品数据缓存,减少API调用
  • window.mealTypeMapping: 餐段类型映射关系
  • window.validationCache: 验证结果缓存

⚙️ 配置变量

  • window.kitchenConfig: 系统配置参数
  • window.apiEndpoints: API接口地址配置
  • window.uiConstants: 界面常量定义
  • window.errorMessages: 错误消息配置

🎛️ 浮动按钮状态切换机制

相关文件: kitout.js

厨房出品功能提供四种操作模式,通过浮动按钮组进行状态切换,实现选菜、删除、拖动、保存等核心功能。

四种操作模式说明

🍽️ 选菜模式

功能描述:点击菜品标签弹出下拉框,选择当前菜品或相关推荐菜品

按钮样式:红字红圈选中状态

交互方式:点击菜品标签触发选择操作

🗑️ 删除模式

功能描述:点击菜品标签删除对应菜品,弹出确认对话框

按钮样式:红字红圈选中状态

交互方式:点击菜品标签触发删除确认

↔️ 拖动模式

功能描述:拖拽菜品标签在不同餐段之间移动菜品

按钮样式:红字红圈选中状态

交互方式:拖拽菜品标签进行位置调整

💾 保存模式

功能描述:保存当前所有菜品数据到后端数据库

按钮样式:独立操作按钮,不参与状态切换

交互方式:点击按钮触发保存操作

状态切换流程

  1. 用户点击浮动按钮:用户点击选菜、拖动、删除、保存四个按钮之一
  2. 状态切换函数调用:menuOutput_handleFloatingButtonAction函数被触发
  3. 当前状态检查:检查当前是否已处于目标状态,避免重复切换
  4. 按钮状态更新:更新按钮的active状态,高亮显示当前模式
  5. 事件监听器绑定:根据当前模式绑定对应的监听处理程序
  6. 界面状态同步:更新界面显示,反映当前操作模式

各函数的IPO处理

前端JavaScript函数(kitout.js)

menuOutput_handleFloatingButtonAction函数:输入接收点击事件对象,处理过程切换按钮状态并绑定对应监听器,输出更新后的界面状态。

menuOutput_bindFloatingButtonEvents函数:输入接收无参数,处理过程绑定浮动按钮点击事件监听器,输出事件绑定完成状态。

menuOutput_globalDishClickListener函数:输入接收菜品点击事件,处理过程根据当前模式调用相应的处理函数,输出菜品操作结果。

相关API调用

💾 保存厨房出品数据

接口地址:/mobile/combo/api/kitchen-output/save

请求方法:POST

调用时机:保存按钮点击时调用,将当前所有菜品数据持久化存储

功能描述:保存按钮触发时调用保存接口,确保菜品数据的变更被及时保存

样式定义

CSS样式定义(kitout.css)

/* 选菜浮动按钮样式 - 重新组织选中和未选两种样式 */

/* 未选状态 - 默认样式 */
.menuOutput_icon-btn[data-action="选菜"] {
    background-color: rgba(255, 255, 255, 0.9); /* 白色背景 */
    color: #333; /* 黑色文字 */
    border: 1px solid #e0e0e0; /* 浅灰色边框 */
}

/* 选中状态 - 红字红圈 */
.menuOutput_icon-btn[data-action="选菜"].active {
    background-color: transparent !important; /* 透明背景 */
    color: #dc3545 !important; /* 红色文字 */
    border: 2px solid #dc3545 !important; /* 红色边框 */
    box-shadow: 0 0 10px rgba(220, 53, 69, 0.3) !important; /* 红色阴影 */
}

🔌 API调用

📡 获取厨房出品数据

接口地址:/mobile/combo/api/kitchen-output?date=YYYYMMDD

请求方法:GET

功能描述:获取指定日期的厨房出品数据,按早餐、午餐、晚餐和未分类四个餐段组织菜品

调用时机:页面加载时自动调用,用于初始化菜品显示

🍽️ 获取所有菜品数据

接口地址:/mobile/combo/api/dishes/all

请求方法:GET

功能描述:获取系统中所有菜品的基础信息,用于菜品验证和智能匹配

调用时机:用户输入菜品时进行对库验证,确保菜品名称正确

🔍 菜品批量核验

接口地址:/mobile/combo/api/dishes/validate

请求方法:POST

功能描述:批量验证菜品是否在菜品库中存在,返回已存库和未存库的菜品记录

调用时机:用户输入新菜品时,一次性核验所有未输入菜品

💾 保存厨房出品数据

接口地址:/mobile/combo/api/kitchen-output/save

请求方法:POST

功能描述:保存用户修改后的厨房出品数据到数据库

调用时机:用户点击保存按钮时调用,持久化菜品安排

← 返回乐大都系统文档