diff --git a/zhican/admin/docs/功能规划文档-v5.md b/zhican/admin/docs/功能规划文档-v5.md new file mode 100644 index 0000000..01bc29f --- /dev/null +++ b/zhican/admin/docs/功能规划文档-v5.md @@ -0,0 +1,224 @@ +# 智能餐养管理系统 — 功能完善规划文档(v5) + +## 核心理念:全链路溯源 + +``` +农田 ──→ 检测 ──→ 加工 ──→ 厨房 ──→ 餐桌 +绿色种养 卫生供应 卫生供应 健康生产 营养用餐 +(种从哪来) (检了什么) (怎么加工) (怎么做的) (谁吃了什么) +``` + +以"溯源"为灵魂,贯穿绿色种养→卫生供应→健康生产→营养用餐四大阶段,形成从农田到餐桌的完整数据闭环。每条数据都可沿此链路正向追踪或反向溯源。 + +--- + +## 一、项目现状 + +- 技术栈:Vue 3 + TypeScript + Ant Design Vue + Vite +- 已实现页面:8个(Dashboard、登录、土地环境、食安监控、食谱管理、用户管理、组织机构、业务流程图) +- 占位页面:34个(仅有框架,无实质内容) +- API:仅覆盖 4 个业务模块,大部分缺失 +- Mock 数据:有基础框架,需按模块扩展 + +--- + +## 二、数据采集架构 + +本系统数据来源分为三类,页面设计需区别对待: + +| 采集方式 | 说明 | 页面设计要点 | +|---|---|---| +| 硬件自动采集 | 物联网传感器、智能秤、气体传感器、环境传感器等设备自动上报 | 数据只读展示 + 设备状态监控 + 异常告警 + 数据刷新机制 | +| 专业设备检测 | 营养质谱仪、电子鼻/舌、质构仪、OCR识别等 | 设备直连/报告上传两种模式 + 检测结果结构化解析 | +| 人工录入/系统对接 | 人工补录、小程序填报、体检系统API对接 | 表单录入 + 批量导入 + 外部系统数据同步 | + +--- + +## 三、三级菜单结构与数据项 + +### 一级:数据概览 + +| 二级 | 三级页面 | 核心展示数据项 | +|---|---|---| +| — | 运营大屏 | KPI卡片、食堂运营数据、供应链状态、订单趋势、告警 | +| — | 溯源总览 | 全链路溯源可视化(输入批次号→展示从种养到用餐的完整链路) | +| — | 业务流程图 | 四大阶段流程关系图、模块关联矩阵 | + +--- + +### 一级:绿色种养 + +说明:土地环境、种养监控、收成入库直接作为二级菜单,不再归入"种养基地"三级分组。 + +| 二级 | 三级页面 | 核心展示数据项 | 数据来源 | +|---|---|---|---| +| 土地环境 | — | 地块编号、面积、土壤pH、水质指标、温湿度、传感器在线状态 | 物联网传感器 | +| 种养监控 | — | 批次号、地块、品种、播种日期、生长周期、当前状态、预计收成日期 | 传感器+人工 | +| 收成入库 | — | 批次号、品种、收成时间、入库重量(kg)、质量等级(优/良/一般/不合格)、入库人、库位 | 智能秤+人工 | +| 供商管理 | 自有供应商 | 名称、类型(种养公司/净菜公司/餐饮公司)、资质证照、有效期、诚信评分、交易总额 | 人工录入 | +| | 外部供应商 | 名称、资质证照、有效期、合作起始日、交易总额、最近交易、诚信评分 | 人工录入 | +| 采购管理 | 采购订单 | 订单号、供应商、品种、数量、单价、金额、下单时间、状态(待确认/已发货/已到货) | 系统生成+API对接 | +| | 到货验收 | 订单号、品种、实收重量、差异量、验收人、验收时间、是否合格 | 智能秤+人工确认 | + +--- + +### 一级:卫生供应 + +说明:净菜入库、净菜内供、净菜外售直接作为二级菜单,不再归入"净菜流通"三级分组。 + +| 二级 | 三级页面 | 核心展示数据项 | 数据来源 | +|---|---|---|---| +| 卫生检测 | 检测记录 | 批次号、品种、农残值、重金属值、化肥残留值、检测员、检测时间、结果(合格/不合格) | 设备直连 | +| | 检测报告 | 报告编号、关联批次、检测项明细、报告文件、上传方式(设备直连/OCR识别)、上传时间 | 设备/OCR | +| 毛菜管理 | 毛菜入库 | 批次号、品种、毛菜/净菜类型、称重重量(kg)、入库时间、关联检测报告、入库人 | 智能秤自动称重 | +| | 毛菜台账 | 品种、当前库存、入库总量、出库总量、最近入库时间、库龄 | 系统汇总 | +| 净菜加工 | 加工记录 | 加工批次、品种、毛菜重量(kg)、净菜重量(kg)、损耗率(%)、加工起止时间、操作员 | 双秤自动计算 | +| | 损耗统计 | 品种、平均损耗率、最高/最低损耗率、趋势图、异常标记 | 系统汇总 | +| 净菜入库 | — | 批次号、品种、净菜重量(kg)、入库时间、来源(自加工/外采)、库位 | 智能秤 | +| 净菜内供 | — | 出库单号、品种、数量(kg)、目标食堂、出库时间、领用人 | 系统记录 | +| 净菜外售 | — | 销售单号、客户、品种、数量(kg)、单价、金额、出库时间 | 系统+人工 | + +--- + +### 一级:健康生产 + +说明:健康生产模块采用扁平化结构,核心生产流程节点直接作为二级菜单;食安监控为二级菜单,其下设三级页面。 + +| 二级菜单 | 三级页面 | 核心展示数据项 | 数据来源 | +|---|---|---|---| +| 食安监控 | 食安视频 | 摄像头编号、位置、在线状态、违规事件(未戴帽/未戴口罩)、违规截图、时间、处理状态 | AI视频分析 | +| | 环境安全 | 天然气浓度(ppm)、报警状态、消防设施状态、各区域温度(℃)、湿度(%)、温湿度趋势图、超阈值告警、最近检查时间、告警历史 | 气体/消防/环境温湿度传感器 | +| | 餐品留样 | 留样菜品名、留样量(g)、留样时间、到期时间(48h)、留样柜编号、留样状态(留样中/已到期/已销毁)、留样照片 | 人工录入 | +| 食谱规划 | — | 日期、餐次(早/中/晚)、菜品列表、营养评分、反算原料需求(可选净菜需求或毛菜需求,毛菜需求=净菜需求÷(1-损耗率))、采购订单状态 | 人工编排+系统计算 | +| 净菜订单 | — | 订单号、来源食谱、品种、需求量(kg)、供应商、状态、到货时间 | 系统自动生成 | +| 净菜进柜 | — | 柜号、品种、订单量(kg)、实收量(kg)、差异量、校验结果、当前库存 | 智能秤校验 | +| 净菜组配 | — | 食谱菜品、所需食材清单、配比量(g)、实际领用量(g)、组配完成状态 | 系统+人工确认 | +| 按单烹制 | — | 菜品名、生重(kg)、熟重(kg)、生熟比、调料时间轴(盐/油/花椒时刻)、工艺动作(翻炒/颠勺)、烹饪时长、厨师;开餐/加餐自动化流转(上架记录"开餐"时间,加餐需求量基于消耗量自动触发);零售后效期自动预警(临期倒计时、过期自动锁定下架) | 智能秤+AI视频 | +| 上餐监控 | — | 菜品名、上餐时间、初始温度(℃)、当前温度、温度衰减曲线、上餐位置、剩余量(kg)、出品时间、保质时限、剩余有效期、过期预警状态 | 温度传感器 | +| 余量处置 | — | 菜品名、剩余量(kg)、处置方式(打折销售/回收/废弃)、打折比例、打折销售量、处置时间、处置人 | 智能秤+人工 | +| 生产统计 | 生产报表 | 日期范围、总产量、总损耗率、菜品产量排行、厨师效率排行、异常事件数、取餐结构分析(主食/荤菜/素菜/汤品分布饼图、各品类消耗趋势) | 系统汇总 | +| | 成本利润 | 原材料成本(系统自动计算:采购单价×用量,沿溯源链路自动关联)、人工成本(人工录入:厨师工时×时薪)、水电气成本(人工录入/抄表)、总成本、营收(来自消费管理)、毛利润、毛利率(%)、按日/周/月维度、趋势图、成本结构饼图 | 原材料=自动计算;人工/水电气=人工录入;营收=系统汇总 | + +> **原材料成本自动计算逻辑:** `原材料成本 = Σ(食材采购单价 × 实际使用量)`,采购单价自动关联「采购订单」,实际使用量自动关联「净菜组配」领用记录 + 「加工记录」损耗。 + +--- + +### 一级:营养用餐 + +说明:营养用餐采用扁平化结构,大部分功能直接作为二级菜单;仅"营养点餐"下设三级(个人点餐/团体点餐)。 + +| 二级 | 三级页面 | 核心展示数据项 | 数据来源 | +|---|---|---|---| +| 营养检验 | — | 菜品名、油(g)、盐(g)、糖(g)、蛋白质(g)、碳水(g)、脂肪(g)、矿物质(mg)、维生素(mg)、检测设备、检测时间 | 营养质谱仪等专业设备 | +| 食物成分 | — | 食材名、每100g:热量(kcal)、蛋白质、脂肪、碳水、膳食纤维、维生素、矿物质、数据来源(国标/检测) | 国标导入+检测补充 | +| 餐品总库 | — | 菜品名、主材(≤12)、辅材(≤4)、配比、工艺(炒/炖/煮/烤)、菜系、荤素、冷热、人群标签(低脂/高钙/低钠)、图片;支持批量导入(Excel/CSV模板:下载模板→填写→上传→校验反馈) | 人工录入+批量导入 | +| 算法标准 | 算法标准 | 人群(年龄/性别/孕期/老年)、每日推荐:热量(kcal)、蛋白质(g)、脂肪(g)、碳水(g)、维生素矿物质、来源(膳食指南版本)、动态算法接口配置;食物交换份标准化:每份90大卡为1份,系统自动将菜品拆解为主食份数/菜品份数/饮品份数/水果份数,界面显示每份热量占比 | 国标导入+API配置 | +| | 营养方案 | 两类方案并行:(1) 个性化方案——起始模板按人群(孕妇/少儿/老人/儿童/普通成人),基于BMI模型+体质健康问卷综合评估自动生成,支持用户人工干预+系统自动推荐结合,无营养师场景下系统可独立输出;(2) 大众方案——面向工厂/院校团体(含正餐/加班餐/夜宵),院校权限可按学段折算至营养方案 | 算法生成+人工调整 | +| 食谱管理 | — | (已实现) 补充营养均衡校验、与餐品总库联动 | 人工+系统校验 | +| 营养点餐 | 个人点餐 | 用户、个人营养画像、推荐菜品列表、营养匹配度(%)、禁忌过滤标记、已选菜品、本餐营养预估;分级管控:根据营养方案设定每餐各品类推荐份数,用户可手动调整(系统提示偏离度),界面显示每份热量占比、人群推荐占比对比 | 算法推荐+用户画像 | +| | 团体点餐 | 团体名称(部门/班级)、人数、人群特征分布、团体营养方案、菜品组合推荐、份量自动计算、预算控制、食物交换份展示、按团体人群结构自动分配各品类份数 | 算法推荐+团体画像 | +| | 熟餐订单 | (小程序端下单) 订单号、用户、餐次(早/中/晚)、菜品明细(成品菜)、份数、金额、下单时间、配送/自取方式、订单状态(待支付/已支付/制作中/待取餐/已完成/已取消)、取餐时间 | 小程序下单 | +| | 净菜订单 | (小程序端下单) 订单号、用户、净菜品种、规格(kg)、数量、金额、下单时间、配送/自取方式、订单状态(待支付/已支付/备货中/待取货/已完成/已取消)、取货时间 | 小程序下单 | +| 用户管理 | — | (已实现) 扩展五维信息:(1) 静态基础(年龄/身高/体重/活动水平);(2) 健康档案(疾病史/体检报告);(3) 口味偏好(酸甜苦辣/地域菜系);(4) 禁忌关联(糖尿病禁高糖等);(5) 动态生理数据(运动量/体重趋势/体脂率);基于五维信息自动生成个人推荐食谱(综合营养需求、口味偏好、禁忌过滤、热量目标),支持手动调整后确认 | 体脂秤/智能手表+小程序填报+体检系统API+算法生成 | +| 餐线管理 | — | 秤编号(CH00025)、当前菜品、更换序列(早→午→晚)、当前存量(kg)、补餐状态(正常/需补餐/禁加餐)、各时段取餐量;补餐阈值(存量<1/5);禁加餐时间(可配置,如13:30后);加餐提示(存量低于阈值自动推送提醒);实时取餐数据(当前取餐人数/取餐速率);餐线监控视频(关联摄像头实时画面、回放) | 智能秤上报+摄像头 | +| 取餐管理 | — | 用户、识别方式(人脸/RFID)、菜品、取餐重量(g)、取餐时间、秤编号、异常标记;AI取餐数据分析:自动统计每人取餐结构(主食/荤菜/素菜/汤品占比),饼图展示 | 人脸+RFID设备 | +| 消费管理 | — | 用户、日期、餐次、菜品明细、金额、支付方式、月度统计 | 系统记录 | +| 营养管理 | 营养管理 | 用户、日期范围、每日摄入(热量/蛋白质/脂肪/碳水) vs 推荐量对比、健康趋势图、异常提醒 | 系统汇总 | +| | 指标预警 | 用户、预警指标(BMI/体脂率/血糖/血压等)、当前值、正常范围、偏离度、预警等级(关注/警告/严重)、触发时间、处理状态、建议措施 | 设备采集+体检数据+系统计算 | +| | 慢病预警 | 用户、慢病类型(糖尿病/高血压/高血脂/痛风等)、风险评分、关联指标趋势、饮食风险项(如高糖/高钠摄入频次)、预警等级、干预建议(推荐食谱调整)、跟踪记录 | 系统算法评估+健康档案 | +| 餐材效益 | — | 食材名、采购成本、使用量、损耗量、产出菜品数、单位成本、效益评分 | 系统汇总 | +| 终端管理 | — | 秤编号、在线状态、故障代码、心跳周期、启用时长、最近上报时间 | 设备固件上报 | +| 模型管理 | — | 模型名、级别(大/专用/小)、版本、训练参数、API接口、准确率 | 人工配置+系统采集 | +| 风味创新 | — | 新菜品名、研发人、配方、电子鼻/电子舌评分、试吃评价、状态(研发中/试吃/上线/下线) | 设备检测+人工 | + +--- + +### 一级:系统管理 + +| 二级 | 核心展示数据项 | 数据来源 | +|---|---|---| +| 组织机构 | (已实现) 树形结构、部门详情 | 人工录入 | +| 员工管理 | 姓名、工号、部门、岗位、联系方式、状态 | 人工录入 | +| 角色管理 | 角色名、权限范围、关联员工数 | 人工配置 | +| 食堂管理 | 食堂名、地址、容纳人数、餐线数、运营状态 | 人工录入 | +| 字典配置 | 字典类型(质量等级/处置方式/加工工艺/菜系/人群标签等)、字典编码、字典名称、排序、状态(启用/停用)、备注 | 人工配置 | + +--- + +## 四、硬件数据接入页面设计规范 + +所有涉及硬件采集的页面统一增加以下设计元素: + +| 设计元素 | 说明 | +|---|---| +| 设备状态面板 | 展示关联设备的在线/离线/故障状态 | +| 数据同步指示 | 显示最近一次数据同步时间,标记"实时"或"延迟" | +| 异常告警区域 | 设备离线、数据中断、数值超阈值等异常自动高亮告警 | +| 数据只读标记 | 硬件自动采集字段标记为只读,与人工可编辑字段区分 | +| 手动补录入口 | 设备故障时提供人工补录通道,补录数据标记来源为"手动" | +| 数据来源标签 | 每条数据标注来源(自动采集/设备检测/人工录入/系统计算) | + +--- + +## 五、三大业务闭环 + +### 闭环1:食谱驱动反向采购 + +``` +食谱规划(周/日) → 系统自动反算原料需求(净菜需求 或 毛菜需求,毛菜=净菜÷(1-损耗率)) +→ 生成采购订单 → 推送加工端 → 净菜进柜(智能秤校验订单量 vs 实收量) +→ 厨房净菜柜库存动态表 → "送多少、用多少、产多少"数据一致 +``` + +涉及页面:食谱规划、净菜订单、净菜进柜、净菜组配 + +### 闭环2:按单烹饪与熟重计量 + +``` +生重(智能秤自动称) → 调料时间点(传感器采集) → 工艺动作(AI视频解析) +→ 熟重(智能秤自动称) → 上餐时间(系统记录) → 温度衰减(温度传感器) +→ 开餐/加餐自动流转 → 效期预警 +``` + +涉及页面:按单烹制、上餐监控 + +### 闭环3:餐线智能调度与取餐治理 + +``` +秤编号绑定菜品序列(设备自动上报) → 各时段取餐量(智能秤实时统计) +→ 补餐阈值触发(存量<1/5, 系统自动判断) → 时间过滤(可配置禁加餐时间,如13:30后) +→ 人脸+RFID双模取餐识别(硬件自动采集) → AI取餐结构分析(饼图) +``` + +涉及页面:餐线管理、取餐管理、消费管理 + +--- + +## 六、实施顺序(8步) + +| 步骤 | 模块 | 页面数 | 具体内容 | +|---|---|---|---| +| Step 1 | 系统管理 | 2新建+2已有 | 员工管理、角色管理、食堂管理、字典配置(基础数据先行,后续模块依赖字典) | +| Step 2 | 绿色种养 | 4新建+1补充 | 种养监控、收成入库、自有/外部供应商、采购订单、到货验收、土地环境补充 | +| Step 3 | 卫生供应 | 9新建 | 检测记录、检测报告、毛菜入库、毛菜台账、加工记录、损耗统计、净菜入库、净菜内供、净菜外售 | +| Step 4 | 健康生产-食安监控 | 3新建 | 食安视频、环境安全、餐品留样 | +| Step 5 | 健康生产-生产流程+闭环1&2 | 8新建+2三级 | 食谱规划、净菜订单、净菜进柜、净菜组配、按单烹制、上餐监控、余量处置、生产报表、成本利润 | +| Step 6 | 营养用餐-数据体系 | 6新建+1补充 | 营养检验、食物成分、餐品总库(含导入)、算法标准、营养方案、食谱管理补充、风味创新 | +| Step 7 | 营养用餐-用餐服务+闭环3 | 12新建+1扩展 | 个人/团体点餐、熟餐/净菜订单、用户管理扩展、餐线管理、取餐管理、消费管理、营养管理、指标预警、慢病预警、餐材效益、终端管理、模型管理 | +| Step 8 | 数据概览 | 1新建+2补充 | 溯源总览(新建)、运营大屏升级、业务流程图升级 | + +执行逻辑:Step 1 字典配置是所有模块的基础依赖 → Step 2-3 按溯源链路从上游开始 → Step 4-5 健康生产拆两步 → Step 6-7 营养用餐拆两步 → Step 8 数据概览最后做(需所有模块数据支撑)。 + +每步内部按「路由+菜单 → Mock数据 → API定义 → 页面实现」顺序逐页推进。 + +--- + +## 七、每个页面的标准实施内容 + +1. 顶部统计卡片(关键指标) +2. 筛选工具栏(搜索、时间范围、状态筛选) +3. 数据表格(分页、排序、导出) +4. 新增/编辑弹窗或抽屉(含表单校验) +5. 详情查看(抽屉或子页面) +6. Mock 数据扩展(覆盖该页面所有字段) +7. API 接口定义(CRUD + 统计接口) diff --git a/zhican/admin/src/api/index.ts b/zhican/admin/src/api/index.ts index 69d8a93..39b0365 100644 --- a/zhican/admin/src/api/index.ts +++ b/zhican/admin/src/api/index.ts @@ -31,6 +31,20 @@ export const userMgmtApi = { remove: (id: string) => request.delete(`/nutrition-dining/users/${id}`), } +// 系统管理 - 字典配置 +export const dictApi = { + // 字典类型 + typeList: (params?: any) => request.get('/system/dict-type', { params }), + typeCreate: (data: any) => request.post('/system/dict-type', data), + typeUpdate: (id: string, data: any) => request.put(`/system/dict-type/${id}`, data), + typeRemove: (id: string) => request.delete(`/system/dict-type/${id}`), + // 字典项 + itemList: (typeCode: string, params?: any) => request.get(`/system/dict-item/${typeCode}`, { params }), + itemCreate: (data: any) => request.post('/system/dict-item', data), + itemUpdate: (id: string, data: any) => request.put(`/system/dict-item/${id}`, data), + itemRemove: (id: string) => request.delete(`/system/dict-item/${id}`), +} + // 登录 export const authApi = { login: (data: { username: string; password: string }) => request.post('/auth/login', data), diff --git a/zhican/admin/src/components.d.ts b/zhican/admin/src/components.d.ts index 0f15aa8..9574c1e 100644 --- a/zhican/admin/src/components.d.ts +++ b/zhican/admin/src/components.d.ts @@ -26,7 +26,6 @@ declare module 'vue' { AForm: typeof import('ant-design-vue/es')['Form'] AFormItem: typeof import('ant-design-vue/es')['FormItem'] AInput: typeof import('ant-design-vue/es')['Input'] - AInputGroup: typeof import('ant-design-vue/es')['InputGroup'] AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] AInputSearch: typeof import('ant-design-vue/es')['InputSearch'] @@ -65,6 +64,7 @@ declare module 'vue' { ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATooltip: typeof import('ant-design-vue/es')['Tooltip'] ATree: typeof import('ant-design-vue/es')['Tree'] + AUpload: typeof import('ant-design-vue/es')['Upload'] ChartPanel: typeof import('./components/common/ChartPanel.vue')['default'] RelatedModules: typeof import('./components/common/RelatedModules.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] diff --git a/zhican/admin/src/layouts/MainLayout.vue b/zhican/admin/src/layouts/MainLayout.vue index 6df319b..3d7b223 100644 --- a/zhican/admin/src/layouts/MainLayout.vue +++ b/zhican/admin/src/layouts/MainLayout.vue @@ -12,7 +12,11 @@ mode="inline" > - 数据概览 + 运营大屏 + + + + 溯源总览 @@ -27,7 +31,7 @@ 种养监控 收成入库 供商管理 - 采供管理 + 采购管理 @@ -35,7 +39,7 @@ 卫生供应 卫生检测 - 毛菜入库 + 毛菜管理 净菜加工 净菜入库 净菜内供 @@ -72,7 +76,7 @@ 取餐管理 消费管理 营养管理 - 食材效益 + 餐材效益 终端管理 模型管理 味养创新 @@ -86,6 +90,7 @@ 员工管理 角色管理 食堂管理 + 字典配置 diff --git a/zhican/admin/src/mock/data.ts b/zhican/admin/src/mock/data.ts index 261db71..bcfa1a5 100644 --- a/zhican/admin/src/mock/data.ts +++ b/zhican/admin/src/mock/data.ts @@ -42,6 +42,7 @@ const materialNames = ['有机大米', '土鸡蛋', '新鲜猪肉', '活鱼', ' export function genLandEnvData(n = 12) { return Array.from({ length: n }, (_, i) => ({ id: randomId(), + code: 'LD' + String(i + 1).padStart(3, '0'), name: pick(landNames), area: randomFloat(5, 200, 0) + '亩', soilType: pick(soilTypes), @@ -52,6 +53,8 @@ export function genLandEnvData(n = 12) { status: pick(['normal', 'warning', 'error']), lastCheck: randomDate(7), crop: pick(cropTypes), + sensorStatus: pick(['online', 'online', 'online', 'offline', 'fault']), + lastSync: randomDate(1) + ' ' + randomTime(), })) } @@ -74,6 +77,7 @@ export function genPlantingMonitorData(n = 10) { } export function genHarvestData(n = 15) { + const qualityLevels = ['优等', '良好', '一般', '不合格'] return Array.from({ length: n }, () => ({ id: randomId(), batchNo: 'HV' + randomDate(30).replace(/-/g, '') + randomNum(100, 999), @@ -81,7 +85,7 @@ export function genHarvestData(n = 15) { land: pick(landNames), harvestDate: randomDate(30), quantity: randomFloat(100, 5000, 0) + 'kg', - quality: pick(['A', 'B', 'C']), + quality: pick(qualityLevels), status: pick(['stored', 'pending', 'processing']), inspector: pick(['张三', '李四', '王五']), warehouse: pick(['1号仓', '2号仓', '3号冷库']), @@ -121,7 +125,7 @@ export function genProcurementData(n = 12) { } // ==================== 卫生供应 ==================== -const testItems = ['农药残留', '重金属', '微生物', '添加剂', '兽药残留'] +const testItems = ['农药残留', '重金属', '化肥残留'] const vegetableNames = ['白菜', '萝卜', '番茄', '黄瓜', '茄子', '青椒', '芹菜', '菠菜', '土豆', '胡萝卜', '豆角', '西兰花'] const meatNames = ['猪里脊', '鸡胸肉', '牛腱子', '羊腿肉', '鱼片', '虾仁'] @@ -343,7 +347,7 @@ export function genSurplusData(n = 8) { mealType: pick(mealTypes), dish: pick(dishNames), surplusQty: randomFloat(1, 30, 0) + 'kg', - disposal: pick(['员工餐', '捐赠', '堆肥', '废弃']), + disposal: pick(['打折销售', '员工餐', '捐赠', '堆肥', '废弃']), handler: pick(['处置员A', '处置员B']), remark: '', })) @@ -498,6 +502,83 @@ export function genMealLineData() { })) } +// ==================== 系统管理 - 字典配置 ==================== +export interface DictType { + id: string + name: string + code: string + status: 'enabled' | 'disabled' + remark: string + createTime: string +} + +export interface DictItem { + id: string + typeCode: string + label: string + value: string + sort: number + status: 'enabled' | 'disabled' + remark: string +} + +// 预置字典类型 +export const dictTypes: DictType[] = [ + { id: 'd1', name: '质量等级', code: 'quality_level', status: 'enabled', remark: '收成入库质量等级', createTime: '2025-01-01' }, + { id: 'd2', name: '处置方式', code: 'disposal_method', status: 'enabled', remark: '余量处置方式', createTime: '2025-01-01' }, + { id: 'd3', name: '加工工艺', code: 'process_method', status: 'enabled', remark: '菜品加工工艺', createTime: '2025-01-01' }, + { id: 'd4', name: '菜系', code: 'cuisine_type', status: 'enabled', remark: '菜品菜系分类', createTime: '2025-01-01' }, + { id: 'd5', name: '人群标签', code: 'crowd_tag', status: 'enabled', remark: '适用人群标签', createTime: '2025-01-01' }, + { id: 'd6', name: '检测项类型', code: 'test_type', status: 'enabled', remark: '卫生检测项分类', createTime: '2025-01-01' }, + { id: 'd7', name: '供应商类型', code: 'supplier_type', status: 'enabled', remark: '供应商分类', createTime: '2025-01-01' }, + { id: 'd8', name: '订单状态', code: 'order_status', status: 'enabled', remark: '通用订单状态', createTime: '2025-01-01' }, +] + +// 预置字典项 +export const dictItems: DictItem[] = [ + // 质量等级 + { id: 'di01', typeCode: 'quality_level', label: '优等', value: 'excellent', sort: 1, status: 'enabled', remark: '' }, + { id: 'di02', typeCode: 'quality_level', label: '良好', value: 'good', sort: 2, status: 'enabled', remark: '' }, + { id: 'di03', typeCode: 'quality_level', label: '一般', value: 'normal', sort: 3, status: 'enabled', remark: '' }, + { id: 'di04', typeCode: 'quality_level', label: '不合格', value: 'unqualified', sort: 4, status: 'enabled', remark: '' }, + // 处置方式 + { id: 'di05', typeCode: 'disposal_method', label: '打折销售', value: 'discount', sort: 1, status: 'enabled', remark: '' }, + { id: 'di06', typeCode: 'disposal_method', label: '回收', value: 'recycle', sort: 2, status: 'enabled', remark: '' }, + { id: 'di07', typeCode: 'disposal_method', label: '废弃', value: 'discard', sort: 3, status: 'enabled', remark: '' }, + // 加工工艺 + { id: 'di08', typeCode: 'process_method', label: '炒', value: 'stir_fry', sort: 1, status: 'enabled', remark: '' }, + { id: 'di09', typeCode: 'process_method', label: '炖', value: 'stew', sort: 2, status: 'enabled', remark: '' }, + { id: 'di10', typeCode: 'process_method', label: '煮', value: 'boil', sort: 3, status: 'enabled', remark: '' }, + { id: 'di11', typeCode: 'process_method', label: '烤', value: 'roast', sort: 4, status: 'enabled', remark: '' }, + // 菜系 + { id: 'di12', typeCode: 'cuisine_type', label: '川菜', value: 'sichuan', sort: 1, status: 'enabled', remark: '' }, + { id: 'di13', typeCode: 'cuisine_type', label: '粤菜', value: 'cantonese', sort: 2, status: 'enabled', remark: '' }, + { id: 'di14', typeCode: 'cuisine_type', label: '鲁菜', value: 'shandong', sort: 3, status: 'enabled', remark: '' }, + { id: 'di15', typeCode: 'cuisine_type', label: '苏菜', value: 'jiangsu', sort: 4, status: 'enabled', remark: '' }, + { id: 'di16', typeCode: 'cuisine_type', label: '湘菜', value: 'hunan', sort: 5, status: 'enabled', remark: '' }, + // 人群标签 + { id: 'di17', typeCode: 'crowd_tag', label: '低脂', value: 'low_fat', sort: 1, status: 'enabled', remark: '' }, + { id: 'di18', typeCode: 'crowd_tag', label: '高钙', value: 'high_calcium', sort: 2, status: 'enabled', remark: '' }, + { id: 'di19', typeCode: 'crowd_tag', label: '低钠', value: 'low_sodium', sort: 3, status: 'enabled', remark: '' }, + { id: 'di20', typeCode: 'crowd_tag', label: '高蛋白', value: 'high_protein', sort: 4, status: 'enabled', remark: '' }, + { id: 'di21', typeCode: 'crowd_tag', label: '低糖', value: 'low_sugar', sort: 5, status: 'enabled', remark: '' }, + // 检测项类型 + { id: 'di22', typeCode: 'test_type', label: '农药残留', value: 'pesticide', sort: 1, status: 'enabled', remark: '' }, + { id: 'di23', typeCode: 'test_type', label: '重金属', value: 'heavy_metal', sort: 2, status: 'enabled', remark: '' }, + { id: 'di24', typeCode: 'test_type', label: '化肥残留', value: 'fertilizer', sort: 3, status: 'enabled', remark: '' }, + // 供应商类型 + { id: 'di25', typeCode: 'supplier_type', label: '种养公司', value: 'farming', sort: 1, status: 'enabled', remark: '' }, + { id: 'di26', typeCode: 'supplier_type', label: '净菜公司', value: 'clean_veg', sort: 2, status: 'enabled', remark: '' }, + { id: 'di27', typeCode: 'supplier_type', label: '餐饮公司', value: 'catering', sort: 3, status: 'enabled', remark: '' }, + { id: 'di28', typeCode: 'supplier_type', label: '外部供应商', value: 'external', sort: 4, status: 'enabled', remark: '' }, + // 订单状态 + { id: 'di29', typeCode: 'order_status', label: '待确认', value: 'pending', sort: 1, status: 'enabled', remark: '' }, + { id: 'di30', typeCode: 'order_status', label: '已确认', value: 'confirmed', sort: 2, status: 'enabled', remark: '' }, + { id: 'di31', typeCode: 'order_status', label: '已发货', value: 'shipped', sort: 3, status: 'enabled', remark: '' }, + { id: 'di32', typeCode: 'order_status', label: '已到货', value: 'arrived', sort: 4, status: 'enabled', remark: '' }, + { id: 'di33', typeCode: 'order_status', label: '已取消', value: 'cancelled', sort: 5, status: 'enabled', remark: '' }, +] + // ==================== Dashboard ==================== export function genDashboardData() { return { diff --git a/zhican/admin/src/router/index.ts b/zhican/admin/src/router/index.ts index b66ea7f..81cf424 100644 --- a/zhican/admin/src/router/index.ts +++ b/zhican/admin/src/router/index.ts @@ -4,6 +4,7 @@ import type { RouteRecordRaw } from 'vue-router' const modules: RouteRecordRaw[] = [ // ========== 数据概览 ========== { path: 'dashboard', name: 'dashboard', meta: { title: '数据概览', menuKey: 'dashboard' }, component: () => import('@/views/dashboard/index.vue') }, + { path: 'trace-overview', name: 'trace-overview', meta: { title: '溯源总览', menuKey: 'trace-overview' }, component: () => import('@/views/dashboard/trace/index.vue') }, { path: 'business-flow', name: 'business-flow', meta: { title: '业务流程', menuKey: 'business-flow' }, component: () => import('@/views/business-flow/index.vue') }, // ========== 绿色种采 ========== @@ -54,6 +55,7 @@ const modules: RouteRecordRaw[] = [ { path: 'employee-mgmt', name: 'employee-mgmt', meta: { title: '员工管理', menuKey: 'employee-mgmt' }, component: () => import('@/views/system/employee-mgmt/index.vue') }, { path: 'role-mgmt', name: 'role-mgmt', meta: { title: '角色管理', menuKey: 'role-mgmt' }, component: () => import('@/views/system/role-mgmt/index.vue') }, { path: 'canteen-mgmt', name: 'canteen-mgmt', meta: { title: '食堂管理', menuKey: 'canteen-mgmt' }, component: () => import('@/views/system/canteen-mgmt/index.vue') }, + { path: 'dict-config', name: 'dict-config', meta: { title: '字典配置', menuKey: 'dict-config' }, component: () => import('@/views/system/dict-config/index.vue') }, ] const routes: RouteRecordRaw[] = [ diff --git a/zhican/admin/src/views/dashboard/trace/index.vue b/zhican/admin/src/views/dashboard/trace/index.vue new file mode 100644 index 0000000..1d2494f --- /dev/null +++ b/zhican/admin/src/views/dashboard/trace/index.vue @@ -0,0 +1,82 @@ + + + + + \ No newline at end of file diff --git a/zhican/admin/src/views/green-planting/harvest-storage/index.vue b/zhican/admin/src/views/green-planting/harvest-storage/index.vue index f8b5211..9e9742a 100644 --- a/zhican/admin/src/views/green-planting/harvest-storage/index.vue +++ b/zhican/admin/src/views/green-planting/harvest-storage/index.vue @@ -12,10 +12,10 @@ - + - + @@ -51,8 +51,8 @@ >