diff --git a/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml b/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml
index 3e15a55d7..82feea188 100644
--- a/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml
+++ b/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml
@@ -82,6 +82,9 @@
     <update id="updateDishesDetail" parameterType="SysRecipesDailyDishes">
         update sys_customer_menu_dishes
         <trim prefix="SET" suffixOverrides=",">
+            <if test="menuId != null">menu_id = #{menuId},</if>
+            <if test="dishesId != null">dishes_id = #{dishesId},</if>
+            <if test="type != null">type = #{type},</if>
             <if test="detail != null">detail = #{detail, jdbcType=OTHER, typeHandler=com.stdiet.custom.typehandler.ArrayJsonHandler},</if>
         </trim>
         where id = #{id}
diff --git a/stdiet-ui/src/store/modules/recipes.js b/stdiet-ui/src/store/modules/recipes.js
index 6043be6c4..ff9381d34 100644
--- a/stdiet-ui/src/store/modules/recipes.js
+++ b/stdiet-ui/src/store/modules/recipes.js
@@ -37,11 +37,21 @@ const mutations = {
       obj => obj.id === payload.id
     );
     if (tarDishes) {
-      const tarIgd = tarDishes.igdList.find(obj => obj.id === payload.igdId);
-      if (tarIgd) {
-        payload.weight && (tarIgd.weight = payload.weight);
-        payload.cusWeight && (tarIgd.cusWeight = payload.cusWeight);
-        payload.cusUnit && (tarIgd.cusUnit = payload.cusUnit);
+      if (tarDishes.dishesId !== payload.dishesId) {
+        // 替换菜品
+        Object.keys(payload).forEach(key => {
+          if (key === "num") {
+            return;
+          }
+          tarDishes[key] = payload[key];
+        });
+      } else {
+        const tarIgd = tarDishes.igdList.find(obj => obj.id === payload.igdId);
+        if (tarIgd) {
+          payload.weight && (tarIgd.weight = payload.weight);
+          payload.cusWeight && (tarIgd.cusWeight = payload.cusWeight);
+          payload.cusUnit && (tarIgd.cusUnit = payload.cusUnit);
+        }
       }
     }
   },
@@ -49,6 +59,12 @@ const mutations = {
     state.recipesData[payload.num].dishes.push(payload.data);
   },
   setCurrentDay(state, payload) {
+    if (state.currentDay !== payload.currentDay) {
+      state.currentDay = payload.currentDay;
+    }
+  },
+  resetCurrentDay(state, payload) {
+    // console.log(payload);
     state.currentDay =
       payload.currentDay === state.currentDay ? -1 : payload.currentDay;
   },
@@ -267,11 +283,12 @@ const actions = {
   },
   async addDishes({ commit, state }, payload) {
     const tarDishesList = state.recipesData[payload.num].dishes.filter(
-      obj => obj.type === payload.type
+      obj => obj.type === payload.data.type
     );
-    if (tarDishesList.some(obj => obj.dishesId === payload.dishesId)) {
-      console.log("目标餐类已有相同的菜品");
-      throw new Error("目标餐类已有相同的菜品");
+    if (tarDishesList.some(obj => obj.dishesId === payload.data.dishesId)) {
+      return new Promise((res, rej) =>
+        rej(`目标餐类已有相同的菜品「${payload.data.name}」`)
+      );
     }
     if (state.recipesId) {
       const tarRecipesObj = state.recipesData[payload.num];
@@ -301,6 +318,47 @@ const actions = {
       commit("addRecipesDishes", payload);
     }
   },
+  async replaceDishes({ commit, state }, payload) {
+    // console.log(payload);
+    const tarDishesList = state.recipesData[payload.num].dishes.filter(
+      obj => obj.type === payload.data.type
+    );
+    if (tarDishesList.some(obj => obj.dishesId === payload.data.dishesId)) {
+      return new Promise((res, rej) =>
+        rej(`目标餐类已有相同的菜品「${payload.data.name}」`)
+      );
+    }
+    if (state.recipesId) {
+      const tarDishes = state.recipesData[payload.num].dishes.find(
+        obj => obj.id === payload.data.id
+      );
+      if (tarDishes) {
+        const params = {
+          id: tarDishes.id,
+          dishesId: payload.data.dishesId,
+          detail: payload.data.igdList.map(igd => ({
+            id: igd.id,
+            weight: igd.weight,
+            cus_unit: igd.cusUnit,
+            cus_weight: igd.cusWeight
+          }))
+        };
+        // console.log(params);
+        const result = await updateDishesDetailApi(params);
+        if (result.code === 200) {
+          commit("updateRecipesDishesDetail", {
+            num: payload.num,
+            ...payload.data
+          });
+        }
+      }
+    } else {
+      commit("updateRecipesDishesDetail", {
+        num: payload.num,
+        ...payload.data
+      });
+    }
+  },
   async updateDishes({ commit, state }, payload) {
     // console.log(payload);
     if (state.recipesId) {
diff --git a/stdiet-ui/src/utils/request.js b/stdiet-ui/src/utils/request.js
index 90df1b246..c26c01fa8 100644
--- a/stdiet-ui/src/utils/request.js
+++ b/stdiet-ui/src/utils/request.js
@@ -32,7 +32,7 @@ service.interceptors.response.use(res => {
     // 获取错误信息
     const msg = errorCode[code] || res.data.msg || errorCode['default']
     if (code === 401) {
-      console.log(code)
+      // console.log(code)
       MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
           confirmButtonText: '重新登录',
           cancelButtonText: '取消',
diff --git a/stdiet-ui/src/views/custom/dishes/index.vue b/stdiet-ui/src/views/custom/dishes/index.vue
index 8f0bb00d1..497b27e66 100644
--- a/stdiet-ui/src/views/custom/dishes/index.vue
+++ b/stdiet-ui/src/views/custom/dishes/index.vue
@@ -277,7 +277,6 @@
                         v-model="scope.row.weight"
                         size="mini"
                         controls-position="right"
-                        @change="handleInputChange"
                         :min="0"
                         :step="5"
                       />
@@ -749,12 +748,9 @@ export default {
         }, []);
       });
     },
-    handleInputChange(val) {
-      // console.log({ val, table: this.selTableData });
-    },
     getSummaries(param) {
       const { columns, data } = param;
-      console.log(data);
+      // console.log(data);
       return columns.reduce(
         (arr, cur, idx) => {
           if (idx > 1) {
diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/BarChart.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/BarChart.vue
index 531961636..6a06111b8 100644
--- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/BarChart.vue
+++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/BarChart.vue
@@ -68,7 +68,7 @@ export default {
       this.updateChart(this.data.length > 0 ? this.data : {});
     },
     updateChart(source) {
-      console.log(this.max);
+      // console.log(this.max);
       this.chart.clear();
       this.chart.setOption({
         title: {
@@ -141,10 +141,10 @@ export default {
             x: 0,
           },
           markLine: {
-            data: [{ name: "BMR", yAxis: this.max - 400 }],
+            data: [{ name: "BMR", yAxis: this.max ? this.max - 400 : 0 }],
             symbol: "none",
             lineStyle: {
-              color: "red",
+              color: "#d96969",
             },
           },
           itemStyle: {
diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/PieChart.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/PieChart.vue
index b2dceb9ca..329b44f4d 100644
--- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/PieChart.vue
+++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/PieChart.vue
@@ -87,7 +87,7 @@ export default {
           return obj;
         }, {}),
       }));
-      console.log(mData);
+      // console.log(mData);
       return mData;
     },
   },
diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/index.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/index.vue
index 65b73303b..8d4d713dd 100644
--- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/index.vue
+++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesAspectCom/index.vue
@@ -26,7 +26,6 @@
           slot="reference"
           size="mini"
           v-if="reviewStatus"
-          @click="handleReview"
           :type="reviewStatus === 1 ? 'danger' : 'success'"
         >
           {{ reviewStatus === 1 ? "未审核" : "已审核" }}
diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/SelectDishes.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/SelectDishes.vue
index 348ae2f45..3b74c2417 100644
--- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/SelectDishes.vue
+++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/SelectDishes.vue
@@ -17,6 +17,7 @@
       </el-form-item>
       <el-form-item label="菜品类型" prop="type">
         <el-select
+          :disabled="lockType"
           v-model="queryParams.type"
           placeholder="请选择菜品类型"
           clearable
@@ -98,6 +99,7 @@ export default {
   data() {
     return {
       loading: false,
+      lockType: false,
       total: 0,
       dishesList: [],
       queryParams: {
@@ -116,8 +118,12 @@ export default {
     ...mapState(["typeOptions"]),
   },
   methods: {
-    getList() {
+    getList({ type }) {
       // console.log('getList')
+      if (type) {
+        this.lockType = true;
+        this.queryParams.type = type;
+      }
       this.loading = true;
       listDishes(this.queryParams).then((result) => {
         this.dishesList = result.rows.map((d) => {
@@ -149,12 +155,21 @@ export default {
         this.loading = false;
       });
     },
+    clean() {
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        type: null,
+        reviewStatus: "yes",
+      };
+    },
     handleCurrentChange(data) {
       this.$emit("onChange", data);
     },
     handleQuery() {
       this.queryParams.pageNum = 1;
-      this.getList();
+      this.getList({});
     },
     resetQuery() {
       this.resetForm("queryForm");
diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/index.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/index.vue
index 1b57baf21..424927ea6 100644
--- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/index.vue
+++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/AddDishesDrawer/index.vue
@@ -1,6 +1,6 @@
 <template>
   <el-drawer
-    title="添加菜品"
+    :title="title"
     :visible.sync="visible"
     :close-on-press-escape="false"
     :before-close="handleOnClosed"
@@ -50,7 +50,7 @@
 </template>
 <script>
 import { createNamespacedHelpers } from "vuex";
-const { mapState } = createNamespacedHelpers("recipes");
+const { mapState, mapGetters } = createNamespacedHelpers("recipes");
 
 import SelectDishes from "./SelectDishes";
 import ConfigDishes from "./ConfigDishes";
@@ -63,7 +63,10 @@ export default {
   },
   data() {
     return {
+      id: "",
+      type: "",
       visible: false,
+      title: "",
       active: 0,
       dishesTypeOptions: [],
       selDishes: {
@@ -76,16 +79,30 @@ export default {
     };
   },
   computed: {
-    ...mapState(["typeOptions"]),
+    ...mapState(["typeOptions", "currentDay"]),
+    ...mapGetters(["typeDict"]),
   },
   methods: {
-    showDrawer() {
+    showDrawer({ data, type, numDay }) {
+      this.title = "添加菜品";
+      this.id = "";
+      this.type = "";
+      if (data) {
+        this.title = `替换第${numDay}天${this.typeDict[data.type]}的「${
+          data.name
+        }」`;
+        this.id = data.id;
+      } else if (type) {
+        this.title = `添加第${numDay}天${this.typeDict[type]}菜品`;
+        this.type = type;
+      }
       this.visible = true;
       this.$nextTick(() => {
-        this.$refs.dishesRef.getList();
+        this.$refs.dishesRef.getList({ type });
       });
     },
     handleOnClosed(done) {
+      this.$refs.dishesRef.clean();
       done();
     },
     handleCurrentChange(data) {
@@ -95,16 +112,18 @@ export default {
       // console.log(data);
       this.selDishes = data;
       this.active = 1;
-      this.dishesTypeOptions = data.type.split(",").reduce((arr, cur, idx) => {
-        if (idx === 0) {
-          this.selDishes.type = cur;
-        }
-        const tarOpt = this.typeOptions.find((obj) => obj.dictValue === cur);
-        if (tarOpt) {
-          arr.push(tarOpt);
-        }
-        return arr;
-      }, []);
+      this.dishesTypeOptions = (this.type || data.type)
+        .split(",")
+        .reduce((arr, cur, idx) => {
+          if (idx === 0) {
+            this.selDishes.type = cur;
+          }
+          const tarOpt = this.typeOptions.find((obj) => obj.dictValue === cur);
+          if (tarOpt) {
+            arr.push(tarOpt);
+          }
+          return arr;
+        }, []);
     },
     handleOnConfigChange(val) {
       Object.keys(val).forEach((key) => {
@@ -114,6 +133,7 @@ export default {
     handleOnCancelClick() {
       this.visible = false;
       this.active = 0;
+      this.$refs.dishesRef.clean();
     },
     handleOnLastStepClick() {
       this.active = 0;
@@ -132,14 +152,17 @@ export default {
         igdList,
       } = this.selDishes;
       this.$emit("onConfirm", {
-        id: new Date().getTime(),
-        dishesId: id,
-        methods,
-        name,
-        notRecTags,
-        recTags,
-        type,
-        igdList,
+        type: this.id ? "replace" : "add",
+        data: {
+          id: this.id || new Date().getTime(),
+          dishesId: id,
+          methods,
+          name,
+          notRecTags,
+          recTags,
+          type,
+          igdList,
+        },
       });
       // console.log(this.selDishes);
     },
diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue
index 026686988..271333801 100644
--- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue
+++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="recipes_com_wrapper">
+  <div class="recipes_com_wrapper" @click="handleParentClick">
     <el-table
       :data="mData"
       border
@@ -11,15 +11,23 @@
     >
       <el-table-column prop="type" :width="100" align="center">
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
-            <!-- <div>{{ name }}</div> -->
+          <div class="num_day" @click="handleOnResetCurrentDay">
             <div>{{ `第${numDay}天` }}</div>
           </div>
         </template>
         <template slot-scope="scope">
-          <span style="font-weight: bold; font-size: 14px">{{
-            typeFormatter(scope.row)
-          }}</span>
+          <el-tooltip
+            class="item"
+            effect="dark"
+            :content="`点击添加${typeFormatter(scope.row)}`"
+            placement="top"
+          >
+            <span
+              style="font-weight: bold; font-size: 14px; cursor: pointer"
+              @click="handleOnMenuTypeClick(scope.row)"
+              >{{ typeFormatter(scope.row) }}</span
+            >
+          </el-tooltip>
         </template>
       </el-table-column>
       <el-table-column label="菜品" prop="name" align="center" :width="180">
@@ -34,8 +42,17 @@
           </el-tooltip>
         </template>
         <template slot-scope="scope">
-          <el-popover placement="right" trigger="hover">
+          <el-popover placement="right" trigger="hover" :title="scope.row.name">
             <div>
+              <el-button
+                type="primary"
+                size="mini"
+                icon="el-icon-refresh"
+                class="fun_button"
+                @click="handleOnReplace(scope.row)"
+              >
+                替换
+              </el-button>
               <el-button
                 type="danger"
                 size="mini"
@@ -79,7 +96,7 @@
         align="center"
       >
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
+          <div class="num_day">
             <div>蛋白质</div>
             <div>/100g</div>
           </div>
@@ -92,7 +109,7 @@
         align="center"
       >
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
+          <div class="num_day">
             <div>脂肪</div>
             <div>/100g</div>
           </div>
@@ -105,7 +122,7 @@
         align="center"
       >
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
+          <div class="num_day">
             <div>碳水</div>
             <div>/100g</div>
           </div>
@@ -119,7 +136,7 @@
         :formatter="nutriFormatter"
       >
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
+          <div class="num_day">
             <div>蛋白质</div>
             <div>含量</div>
           </div>
@@ -133,7 +150,7 @@
         :formatter="nutriFormatter"
       >
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
+          <div class="num_day">
             <div>脂肪</div>
             <div>含量</div>
           </div>
@@ -147,7 +164,7 @@
         :formatter="nutriFormatter"
       >
         <template slot="header">
-          <div class="num_day" @click="handleOnOneDayAnalysis">
+          <div class="num_day">
             <div>碳水</div>
             <div>含量</div>
           </div>
@@ -299,6 +316,10 @@ export default {
     ...mapState(["currentDay"]),
   },
   methods: {
+    handleParentClick(e) {
+      // 校验某天
+      this.setCurrentDay({ currentDay: this.num });
+    },
     spanMethod({ row, column, rowIndex, columnIndex }) {
       if (columnIndex === 0) {
         return row.typeSpan;
@@ -314,13 +335,17 @@ export default {
     nutriFormatter(row, col) {
       return ((row.weight / 100) * row[col.property]).toFixed(1);
     },
-    handleOnOneDayAnalysis(e) {
-      // 校验某天
-      this.setCurrentDay({ currentDay: this.num });
+    handleOnResetCurrentDay(e) {
+      e.stopPropagation();
+      // 取消高亮
+      this.resetCurrentDay({ currentDay: this.num });
     },
     handleOnAdd() {
       // console.log(this.num);
-      this.$refs.drawerRef.showDrawer();
+      this.$refs.drawerRef.showDrawer({});
+    },
+    handleOnReplace(data) {
+      this.$refs.drawerRef.showDrawer({ data, numDay: this.numDay });
     },
     handleOnDelete(data) {
       // console.log(data);
@@ -347,17 +372,34 @@ export default {
         cusUnit,
       });
     },
-    handleOnDishesConfirm(data) {
+    handleOnDishesConfirm({ type, data }) {
       // console.log(data);
-      this.addDishes({
-        num: this.num,
-        data,
-      }).catch((err) => {
-        this.$message.error(err.message);
-      });
+      if (type === "add") {
+        this.addDishes({
+          num: this.num,
+          data,
+        }).catch((err) => {
+          this.$message.error(err);
+        });
+      } else if (type === "replace") {
+        this.replaceDishes({
+          num: this.num,
+          data,
+        }).catch((err) => {
+          this.$message.error(err);
+        });
+      }
     },
-    ...mapActions(["updateDishes", "addDishes", "deleteDishes"]),
-    ...mapMutations(["setCurrentDay"]),
+    handleOnMenuTypeClick(data) {
+      this.$refs.drawerRef.showDrawer({ type: data.type, numDay: this.numDay });
+    },
+    ...mapActions([
+      "updateDishes",
+      "addDishes",
+      "deleteDishes",
+      "replaceDishes",
+    ]),
+    ...mapMutations(["setCurrentDay", "resetCurrentDay"]),
   },
 };
 </script>