From 144e3550aacefc225ac927282f8cb9107bc18960 Mon Sep 17 00:00:00 2001
From: huangdeliang <huangdeliang@skieer.com>
Date: Fri, 19 Mar 2021 17:08:21 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B7=9F=E6=8D=A2=E8=8F=9C=E5=93=81=E6=8E=A7?=
 =?UTF-8?q?=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../IngredientListView/index.vue              | 131 ++++
 .../custom/dishes/EditDishesDrawer/index.vue  | 507 +++++++++++++++
 stdiet-ui/src/views/custom/dishes/index.vue   | 581 +-----------------
 .../src/views/custom/ingredient/index.vue     |  10 +
 4 files changed, 668 insertions(+), 561 deletions(-)
 create mode 100644 stdiet-ui/src/views/custom/dishes/EditDishesDrawer/IngredientListView/index.vue
 create mode 100644 stdiet-ui/src/views/custom/dishes/EditDishesDrawer/index.vue

diff --git a/stdiet-ui/src/views/custom/dishes/EditDishesDrawer/IngredientListView/index.vue b/stdiet-ui/src/views/custom/dishes/EditDishesDrawer/IngredientListView/index.vue
new file mode 100644
index 000000000..60cff0173
--- /dev/null
+++ b/stdiet-ui/src/views/custom/dishes/EditDishesDrawer/IngredientListView/index.vue
@@ -0,0 +1,131 @@
+<template>
+  <div>
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入食材名称"
+          clearable
+          size="mini"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="类别" prop="type">
+        <el-select
+          v-model="queryParams.type"
+          placeholder="请选择食材类别"
+          clearable
+          size="mini"
+        >
+          <el-option
+            v-for="dict in typeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button
+          type="cyan"
+          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-table
+      v-loading="loading"
+      border
+      :data="ingredientList"
+      :cell-style="{ padding: 0 }"
+      :header-cell-style="{ padding: 0, height: 'unset' }"
+      @current-change="handleCurrentChange"
+    >
+      <el-table-column label="食材名称" align="center" prop="name" />
+      <el-table-column
+        label="食材类别"
+        align="center"
+        prop="type"
+        :formatter="typeFormat"
+      />
+      <el-table-column prop="proteinRatio" label="蛋白质/100g" align="center" />
+      <el-table-column prop="fatRatio" label="脂肪/100g" align="center" />
+      <el-table-column prop="carbonRatio" label="碳水/100g" align="center" />
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :background="false"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+      layout="total, prev, pager, next"
+    />
+  </div>
+</template>
+<script>
+import { listIngredient } from "@/api/custom/ingredient";
+export default {
+  name: "IngredientListView",
+  data() {
+    return {
+      loading: false,
+      total: 0,
+      ingredientList: [],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        type: null,
+        area: null,
+        reviewStatus: "yes",
+      },
+    };
+  },
+  props: ["typeOptions", "visible"],
+  watch: {},
+  methods: {
+    getList() {
+      this.loading = true;
+      listIngredient(this.queryParams).then((response) => {
+        this.ingredientList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    reset() {
+      this.resetForm("queryForm");
+    },
+    // 食材类别字典翻译
+    typeFormat(row, column) {
+      return this.selectDictLabel(this.typeOptions, row.type);
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    handleCurrentChange(data) {
+      this.$emit("onSelect", data);
+    },
+  },
+};
+</script>
diff --git a/stdiet-ui/src/views/custom/dishes/EditDishesDrawer/index.vue b/stdiet-ui/src/views/custom/dishes/EditDishesDrawer/index.vue
new file mode 100644
index 000000000..7ee9b0666
--- /dev/null
+++ b/stdiet-ui/src/views/custom/dishes/EditDishesDrawer/index.vue
@@ -0,0 +1,507 @@
+<template>
+  <el-drawer
+    :title="title"
+    :visible.sync="open"
+    :wrapperClosable="false"
+    :before-close="handleClose"
+    size="50%"
+    :close-on-press-escape="false"
+  >
+    <div class="edit_dishes_drawer_wrapper">
+      <el-row class="content_detail" v-loading="entireLoading">
+        <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+          <el-col :span="12">
+            <el-form-item label="菜品名称" prop="name">
+              <el-input v-model="form.name" placeholder="请输入菜品名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="审核状态" prop="reviewStatus">
+              <el-select
+                v-model="form.reviewStatus"
+                placeholder="请选择审核状态"
+                clearable
+              >
+                <el-option
+                  v-for="dict in reviewStatusOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="菜品种类" prop="dishClass">
+              <el-cascader
+                filterable
+                v-model="form.dishClass"
+                :options="dishClassOptions"
+                :props="{ expandTrigger: 'hover' }"
+                placeholder="请选择菜品种类"
+              ></el-cascader>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="菜品类型" prop="type">
+              <el-select
+                v-model="form.type"
+                placeholder="请选择菜品类型"
+                multiple
+              >
+                <el-option
+                  v-for="dict in typeOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="dict.dictValue"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="是否主食" prop="isMain">
+              <el-radio-group v-model="form.isMain">
+                <el-radio :label="0">是</el-radio>
+                <el-radio :label="1">否</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="待选食材">
+              <IngredientListView
+                ref="igdRef"
+                :typeOptions="ingTypeOptions"
+                @onSelect="handleOnIgdSelect"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="已选食材" prop="igdList">
+              <el-table
+                :data="form.igdList"
+                border
+                show-summary
+                :cell-style="{ padding: 0 }"
+                :header-cell-style="{ padding: 0, height: 'unset' }"
+                :summary-method="getSummaries"
+              >
+                <el-table-column prop="name" label="食材" align="center" />
+                <el-table-column label="通俗计量" align="center">
+                  <template slot-scope="scope">
+                    <span class="cus-unit">
+                      <el-select size="mini" v-model="scope.row.cusWeight">
+                        <el-option
+                          v-for="dict in cusWeightOptions"
+                          :key="dict.dictValue"
+                          :label="dict.dictLabel"
+                          :value="parseInt(dict.dictValue)"
+                        />
+                      </el-select>
+                      <el-select size="mini" v-model="scope.row.cusUnit">
+                        <el-option
+                          v-for="dict in cusUnitOptions"
+                          :key="dict.dictValue"
+                          :label="dict.dictLabel"
+                          :value="parseInt(dict.dictValue)"
+                        />
+                      </el-select>
+                    </span>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="weight" label="重量(g)" align="center">
+                  <template slot-scope="scope">
+                    <el-input-number
+                      class="weight"
+                      v-model="scope.row.weight"
+                      size="mini"
+                      controls-position="right"
+                      :min="0"
+                      :step="5"
+                    />
+                  </template>
+                </el-table-column>
+                <el-table-column
+                  prop="proteinRatio"
+                  label="蛋白质/100g"
+                  align="center"
+                />
+                <el-table-column
+                  prop="fatRatio"
+                  label="脂肪/100g"
+                  align="center"
+                />
+                <el-table-column
+                  prop="carbonRatio"
+                  label="碳水/100g"
+                  align="center"
+                />
+                <el-table-column label="热量(kcal)" align="center">
+                  <template slot-scope="scope">
+                    {{
+                      `${(
+                        ((scope.row.proteinRatio * scope.row.weight) / 100) *
+                          4 +
+                        ((scope.row.fatRatio * scope.row.weight) / 100) * 9 +
+                        ((scope.row.carbonRatio * scope.row.weight) / 100) * 4
+                      ).toFixed(1)}`
+                    }}
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center">
+                  <template slot-scope="scope">
+                    <el-button type="text" @click="handleOnDelete(scope.row)"
+                      >删除</el-button
+                    >
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="推荐人群" v-if="!!selRec.length">
+              <el-tag
+                style="margin-right: 4px"
+                v-for="rec in selRec"
+                :key="rec"
+                type="success"
+              >
+                {{ rec }}
+              </el-tag>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="忌口人群" v-if="!!selNotRec.length">
+              <el-tag
+                style="margin-right: 4px"
+                v-for="notRec in selNotRec"
+                :key="notRec"
+                type="danger"
+              >
+                {{ notRec }}
+              </el-tag>
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="24">
+            <el-form-item label="做法" prop="methods">
+              <el-input
+                v-model="form.methods"
+                type="textarea"
+                placeholder="请输入内容"
+                rows="4"
+              />
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </el-row>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </div>
+  </el-drawer>
+</template>
+<script>
+import { addDishes, updateDishes, getDishes } from "@/api/custom/dishes";
+import IngredientListView from "./IngredientListView";
+
+export default {
+  name: "EditDishesDrawer",
+  components: {
+    IngredientListView,
+  },
+  created() {
+    this.getDicts("cus_ing_type").then((response) => {
+      this.ingTypeOptions = response.data;
+    });
+    this.getDicts("cus_cus_unit").then((response) => {
+      this.cusUnitOptions = response.data;
+    });
+    this.getDicts("cus_cus_weight").then((response) => {
+      this.cusWeightOptions = response.data;
+    });
+  },
+  data() {
+    return {
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 通俗单位
+      cusUnitOptions: [],
+      //
+      cusWeightOptions: [],
+      // 食材类别字典
+      ingTypeOptions: [],
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        name: [
+          { required: true, message: "菜品名称不能为空", trigger: "blur" },
+        ],
+        type: [
+          { required: true, message: "菜品类型不能为空", trigger: "blur" },
+        ],
+        igdList: [{ required: true, message: "食材不能为空", trigger: "blur" }],
+      },
+      //
+      entireLoading: false,
+      // 选中的食材分量列表
+      //
+      selRec: [],
+      selNotRec: [],
+    };
+  },
+  props: [
+    "typeOptions",
+    "reviewStatusOptions",
+    "dishClassBigOptions",
+    "dishClassOptions",
+    "dishClassSmallOptions",
+  ],
+  watch: {
+    "form.igdList": function (val) {
+      const selRec = [];
+      const selNotRec = [];
+      val.forEach((obj) => {
+        if (obj.rec) {
+          obj.rec.split(",").forEach((rec) => {
+            if (!selRec.includes(rec)) {
+              selRec.push(rec);
+            }
+          });
+        }
+        if (obj.notRec) {
+          obj.notRec.split(",").forEach((notRec) => {
+            if (!selNotRec.includes(notRec)) {
+              selNotRec.push(notRec);
+            }
+          });
+        }
+      });
+      this.selRec = selRec;
+      this.selNotRec = selNotRec;
+    },
+
+    showNotRec() {
+      return !!this.selNotRec.length;
+    },
+  },
+  methods: {
+    showDrawer(id) {
+      this.open = true;
+      this.title = id ? "修改菜品" : "新建菜品";
+      this.reset();
+      if (id) {
+        this.fetchDishesDetail(id);
+      }
+      this.$nextTick(() => {
+        this.$refs.igdRef.getList();
+      });
+    },
+    fetchDishesDetail(id) {
+      getDishes(id).then((response) => {
+        this.form = response.data;
+        this.form.dishClass = [this.form.bigClass, this.form.smallClass];
+        this.form.type = this.form.type ? this.form.type.split(",") : [];
+      });
+    },
+    handleOnIgdSelect(data) {
+      if (this.form.igdList.some((obj) => obj.id === data.id)) {
+        this.$message.error(`已存在食材${data.name}`);
+        return;
+      }
+      this.form.igdList.push({
+        ...data,
+        weight: 100,
+        cusUnit: 1,
+        cusWeight: 1,
+      });
+    },
+    handleOnDelete(data) {
+      this.form.igdList = this.form.igdList.filter((obj) => obj.id !== data.id);
+    },
+    cusUnitFormat(row, column) {
+      return this.selectDictLabel(this.cusUnitOptions, row.type);
+    },
+    cusWeightFormat(row, column) {
+      return this.selectDictLabel(this.cusWeightOptions, row.cusWeight);
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        name: null,
+        type: [],
+        dishClass: [],
+        methods: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null,
+        igdList: [],
+        isMain: 1,
+      };
+      this.selRec = [];
+      this.selNotRec = [];
+      this.resetForm("form");
+      this.$nextTick(() => {
+        this.$refs.igdRef.reset();
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          const data = JSON.parse(JSON.stringify(this.form));
+          // console.log({ data });
+          data.type = data.type.join(",");
+          if (data.id != null) {
+            updateDishes(data).then((response) => {
+              if (response.code === 200) {
+                this.msgSuccess("修改成功");
+                this.open = false;
+                this.$emit("onSuccess");
+              }
+            });
+          } else {
+            addDishes(data).then((response) => {
+              if (response.code === 200) {
+                this.msgSuccess("新增成功");
+                this.open = false;
+                this.$emit("onSuccess");
+              }
+            });
+          }
+        }
+      });
+    },
+
+    getSummaries(param) {
+      const { columns, data } = param;
+      // console.log(data);
+      return columns.reduce(
+        (arr, cur, idx) => {
+          if (idx > 1 && idx !== 7) {
+            if (idx === 6) {
+              arr[6] = (arr[3] * 4 + arr[4] * 9 + arr[5] * 4).toFixed(1);
+            } else {
+              arr[idx] = data.reduce((acc, dAcc) => {
+                if (idx === 2) {
+                  return acc + parseFloat(dAcc.weight);
+                }
+                return parseFloat(
+                  (
+                    acc +
+                    (dAcc[cur.property] * parseFloat(dAcc.weight)) / 100
+                  ).toFixed(1)
+                );
+              }, 0);
+            }
+          }
+          return arr;
+        },
+        ["合计"]
+      );
+    },
+    handleClose(done) {
+      this.reset();
+      done();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.edit_dishes_drawer_wrapper {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+
+  .content_detail {
+    flex: 1 1 0;
+    padding: 12px;
+    overflow: auto;
+  }
+
+  .dialog-footer {
+    flex: 0 0 45px;
+    display: inline-flex;
+    align-items: center;
+    justify-content: flex-end;
+    padding: 0 12px;
+  }
+}
+</style>
+
+<style lang="scss">
+#el-drawer__title {
+  & > span:focus {
+    outline: 0;
+  }
+}
+
+.el-transfer-panel__filter {
+  margin: 2px;
+}
+
+.el-transfer-panel__list.is-filterable {
+  padding-bottom: 28px;
+}
+
+.cus-unit {
+  display: inline-flex;
+  .el-input-number--mini {
+    width: 38px;
+  }
+
+  .el-input-number {
+    .el-input-number__decrease {
+      display: none;
+    }
+    .el-input-number__increase {
+      display: none;
+    }
+
+    .el-input {
+      width: 38px;
+    }
+
+    .el-input .el-input__inner {
+      padding: 0;
+      border-radius: 0;
+      border: unset;
+      border-bottom: 1px solid #dcdfe6;
+    }
+  }
+
+  .el-select {
+    .el-input__suffix {
+      display: none;
+    }
+
+    .el-input__inner {
+      padding: 0 4px;
+      /* border: unset; */
+      text-align: center;
+    }
+  }
+}
+
+.weight {
+  width: 70px;
+
+  .el-input .el-input__inner {
+    padding: 0 32px 0 4px;
+  }
+}
+
+.pagination-container {
+  margin-top: 0;
+}
+</style>
diff --git a/stdiet-ui/src/views/custom/dishes/index.vue b/stdiet-ui/src/views/custom/dishes/index.vue
index b01a02a5b..532a79f82 100644
--- a/stdiet-ui/src/views/custom/dishes/index.vue
+++ b/stdiet-ui/src/views/custom/dishes/index.vue
@@ -97,11 +97,7 @@
         @queryTable="getList"
       ></right-toolbar>
     </el-row>
-    <el-table
-      v-loading="loading"
-      :data="dishesList"
-      @selection-change="handleSelectionChange"
-    >
+    <el-table v-loading="loading" :data="dishesList">
       <el-table-column label="审核状态" align="center" width="80">
         <template slot-scope="scope">
           <el-tag
@@ -177,247 +173,28 @@
     />
 
     <!-- 添加或修改菜品对话框 -->
-    <el-drawer
-      :title="title"
-      :visible.sync="open"
-      :wrapperClosable="false"
-      size="50%"
-      :close-on-press-escape="false"
-    >
-      <div class="drawer_content">
-        <el-row class="content_detail">
-          <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-            <el-col :span="24">
-              <el-form-item label="菜品名称" prop="name">
-                <el-input v-model="form.name" placeholder="请输入菜品名称" />
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="菜品种类" prop="dishClass">
-                <el-cascader
-                  filterable
-                  v-model="form.dishClass"
-                  :options="dishClassOptions"
-                  :props="{ expandTrigger: 'hover' }"
-                  placeholder="请选择菜品种类"
-                ></el-cascader>
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="菜品类型" prop="type">
-                <el-select
-                  v-model="form.type"
-                  placeholder="请选择菜品类型"
-                  multiple
-                >
-                  <el-option
-                    v-for="dict in typeOptions"
-                    :key="dict.dictValue"
-                    :label="dict.dictLabel"
-                    :value="dict.dictValue"
-                  ></el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="是否主食" prop="isMain">
-                <el-radio-group v-model="form.isMain">
-                  <el-radio :label="0">是</el-radio>
-                  <el-radio :label="1">否</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="食材" prop="ingIds">
-                <el-transfer
-                  style="text-align: left; display: inline-block"
-                  v-model="selIngIds"
-                  size="mini"
-                  filterable
-                  :titles="['备选', '已选']"
-                  :button-texts="['', '']"
-                  :format="{
-                    noChecked: '${total}',
-                    hasChecked: '${checked}/${total}',
-                  }"
-                  @change="handleChange"
-                  :data="ingDataList"
-                >
-                  <el-select
-                    class="transfer-footer"
-                    slot="left-footer"
-                    size="small"
-                    filterable
-                    v-model="ingType"
-                    @change="handleOnTypeChange"
-                  >
-                    <el-option
-                      v-for="dict in ingTypeOptions"
-                      :key="dict.dictValue"
-                      :label="dict.dictLabel"
-                      :value="dict.dictValue"
-                    />
-                  </el-select>
-                  <div
-                    class="transfer-footer"
-                    slot="right-footer"
-                    size="small"
-                  />
-                </el-transfer>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="分量" prop="weight">
-                <el-table
-                  :data="selTableData"
-                  border
-                  show-summary
-                  size="mini"
-                  :summary-method="getSummaries"
-                  style="width: 100%"
-                >
-                  <el-table-column prop="name" label="食材" align="center" />
-                  <el-table-column label="通俗计量" align="center">
-                    <template slot-scope="scope">
-                      <span class="cus-unit">
-                        <el-select size="mini" v-model="scope.row.cusWeight">
-                          <el-option
-                            v-for="dict in cusWeightOptions"
-                            :key="dict.dictValue"
-                            :label="dict.dictLabel"
-                            :value="parseInt(dict.dictValue)"
-                          />
-                        </el-select>
-                        <el-select size="mini" v-model="scope.row.cusUnit">
-                          <el-option
-                            v-for="dict in cusUnitOptions"
-                            :key="dict.dictValue"
-                            :label="dict.dictLabel"
-                            :value="parseInt(dict.dictValue)"
-                          />
-                        </el-select>
-                      </span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column prop="weight" label="重量(g)" align="center">
-                    <template slot-scope="scope">
-                      <el-input-number
-                        class="weight"
-                        v-model="scope.row.weight"
-                        size="mini"
-                        controls-position="right"
-                        :min="0"
-                        :step="5"
-                      />
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    prop="proteinRatio"
-                    label="蛋白质/100g"
-                    align="center"
-                  />
-                  <el-table-column
-                    prop="fatRatio"
-                    label="脂肪/100g"
-                    align="center"
-                  />
-                  <el-table-column
-                    prop="carbonRatio"
-                    label="碳水/100g"
-                    align="center"
-                  />
-                  <el-table-column label="热量" align="center">
-                    <template slot-scope="scope">
-                      {{
-                        `${(
-                          ((scope.row.proteinRatio * scope.row.weight) / 100) *
-                            4 +
-                          ((scope.row.fatRatio * scope.row.weight) / 100) * 9 +
-                          ((scope.row.carbonRatio * scope.row.weight) / 100) * 4
-                        ).toFixed(1)} kcal`
-                      }}
-                    </template>
-                  </el-table-column>
-                </el-table>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="推荐人群">
-                <el-tag
-                  style="margin-right: 4px"
-                  v-for="rec in selRec"
-                  :key="rec"
-                  type="success"
-                >
-                  {{ rec }}
-                </el-tag>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="忌口人群">
-                <el-tag
-                  style="margin-right: 4px"
-                  v-for="notRec in selNotRec"
-                  :key="notRec"
-                  type="danger"
-                >
-                  {{ notRec }}
-                </el-tag>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="审核状态" prop="reviewStatus">
-                <el-select
-                  v-model="form.reviewStatus"
-                  placeholder="请选择审核状态"
-                  clearable
-                >
-                  <el-option
-                    v-for="dict in reviewStatusOptions"
-                    :key="dict.dictValue"
-                    :label="dict.dictLabel"
-                    :value="dict.dictValue"
-                  />
-                </el-select>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="做法" prop="methods">
-                <el-input
-                  v-model="form.methods"
-                  type="textarea"
-                  placeholder="请输入内容"
-                  rows="4"
-                />
-              </el-form-item>
-            </el-col>
-          </el-form>
-        </el-row>
-        <div slot="footer" class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </div>
-    </el-drawer>
+    <EditDishesDrawer
+      ref="dishesDrawerRef"
+      :typeOptions="typeOptions"
+      :reviewStatusOptions="reviewStatusOptions"
+      :dishClassBigOptions="dishClassBigOptions"
+      :dishClassSmallOptions="dishClassSmallOptions"
+      :dishClassOptions="dishClassOptions"
+      @onSuccess="getList"
+    />
   </div>
 </template>
 
 <script>
-import {
-  addDishes,
-  delDishes,
-  exportDishes,
-  getDishes,
-  listDishes,
-  updateDishes,
-} from "@/api/custom/dishes";
-import { listAllIngredient } from "@/api/custom/ingredient";
+import { delDishes, exportDishes, listDishes } from "@/api/custom/dishes";
 import AutoHideInfo from "@/components/AutoHideInfo";
+import EditDishesDrawer from "./EditDishesDrawer";
 
 export default {
   name: "Dishes",
   components: {
     autohideinfo: AutoHideInfo,
+    EditDishesDrawer,
   },
   data() {
     return {
@@ -425,10 +202,6 @@ export default {
       loading: true,
       // 选中数组
       ids: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
       // 显示搜索条件
       showSearch: true,
       // 总条数
@@ -437,13 +210,7 @@ export default {
       dishesList: [],
       // 审核状态
       reviewStatusOptions: [],
-      // 弹出层标题
-      title: "",
-      // 是否显示弹出层
-      open: false,
-      ingType: "1",
-      // 食材类别字典
-      ingTypeOptions: [],
+
       // 远程数据缓存,预防新增的食材找不到
       oriDataList: [],
       // 备选食材列表
@@ -456,14 +223,10 @@ export default {
       selNotRec: [],
       // 选中的食材id
       selIngIds: [],
-      // 选中的食材分量列表
-      selTableData: [],
+
       // 菜品类别字典
       typeOptions: [],
-      // 通俗单位
-      cusUnitOptions: [],
-      //
-      cusWeightOptions: [],
+
       dishClassOptions: [],
       dishClassBigOptions: [],
       dishClassSmallOptions: [],
@@ -476,10 +239,6 @@ export default {
         bigClass: null,
         smallClass: null,
       },
-      // 表单参数
-      form: {},
-      // 表单校验
-      rules: {},
       //菜品种类查询种类
       dishClassQueryParam: [],
     };
@@ -489,15 +248,7 @@ export default {
     this.getDicts("cus_dishes_type").then((response) => {
       this.typeOptions = response.data;
     });
-    this.getDicts("cus_ing_type").then((response) => {
-      this.ingTypeOptions = response.data;
-    });
-    this.getDicts("cus_cus_unit").then((response) => {
-      this.cusUnitOptions = response.data;
-    });
-    this.getDicts("cus_cus_weight").then((response) => {
-      this.cusWeightOptions = response.data;
-    });
+
     this.getDicts("cus_review_status").then((response) => {
       this.reviewStatusOptions = response.data;
     });
@@ -582,12 +333,7 @@ export default {
             .split(",")
             .map((type) => this.selectDictLabel(this.typeOptions, type));
     },
-    cusUnitFormat(row, column) {
-      return this.selectDictLabel(this.cusUnitOptions, row.type);
-    },
-    cusWeightFormat(row, column) {
-      return this.selectDictLabel(this.cusWeightOptions, row.cusWeight);
-    },
+
     // 地域字典翻译
     reviewStatusFormat(row, column) {
       return this.selectDictLabel(this.reviewStatusOptions, row.area);
@@ -607,35 +353,6 @@ export default {
       }
       return "";
     },
-    // 取消按钮
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    // 表单重置
-    reset() {
-      this.form = {
-        id: null,
-        name: null,
-        type: [],
-        dishClass: [],
-        methods: null,
-        createBy: null,
-        createTime: null,
-        updateBy: null,
-        updateTime: null,
-        igdList: [],
-        isMain: 1,
-      };
-      this.selIngIds = [];
-      this.selIngList = [];
-      this.selTableData = [];
-      this.oriDataList = [];
-      this.selRec = [];
-      this.selNotRec = [];
-      this.ingType = "1";
-      this.resetForm("form");
-    },
     /** 搜索按钮操作 */
     handleQuery() {
       this.queryParams.pageNum = 1;
@@ -647,101 +364,13 @@ export default {
       this.dishClassQueryParam = [];
       this.handleQuery();
     },
-    // 多选框选中数据
-    handleSelectionChange(selection) {
-      this.ids = selection.map((item) => item.id);
-      this.single = selection.length !== 1;
-      this.multiple = !selection.length;
-    },
     /** 新增按钮操作 */
     handleAdd() {
-      this.reset();
-      listAllIngredient({ type: this.ingType }).then((response) => {
-        this.open = true;
-        this.title = "添加菜品";
-        this.oriDataList = response.rows;
-        this.ingDataList = this.oriDataList.map((obj) => ({
-          key: obj.id,
-          label: obj.name,
-        }));
-      });
+      this.$refs.dishesDrawerRef.showDrawer();
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
-      this.reset();
-      const id = row.id || this.ids;
-      getDishes(id).then((response) => {
-        this.form = response.data;
-        this.form.dishClass = [this.form.bigClass, this.form.smallClass];
-        this.form.type = this.form.type ? this.form.type.split(",") : null;
-        this.form.igdList.forEach((obj) => {
-          this.selIngIds.push(obj.id);
-          this.selIngList.push({
-            key: obj.id,
-            label: obj.name,
-          });
-          this.selTableData.push(obj);
-          if (obj.rec) {
-            obj.rec.split(",").forEach((rec) => {
-              if (!this.selRec.includes(rec)) {
-                this.selRec.push(rec);
-              }
-            });
-          }
-          if (obj.notRec) {
-            obj.notRec.split(",").forEach((notRec) => {
-              if (!this.selNotRec.includes(notRec)) {
-                this.selNotRec.push(notRec);
-              }
-            });
-          }
-        });
-        listAllIngredient({ type: this.ingType }).then((res) => {
-          this.open = true;
-          this.title = "修改菜品";
-          this.oriDataList = res.rows.concat(this.form.igdList);
-          this.ingDataList = this.oriDataList.reduce((arr, cur) => {
-            if (!arr.some(({ key }) => key === cur.id)) {
-              arr.push({
-                key: cur.id,
-                label: cur.name,
-              });
-            }
-            return arr;
-          }, []);
-        });
-      });
-    },
-    /** 提交按钮 */
-    submitForm() {
-      this.$refs["form"].validate((valid) => {
-        if (valid) {
-          if (!this.selTableData.length) {
-            this.$message.error("食材不能为空");
-            return;
-          }
-          const data = JSON.parse(JSON.stringify(this.form));
-          data.igdList = this.selTableData;
-          data.type = data.type.join(",");
-          if (data.id != null) {
-            updateDishes(data).then((response) => {
-              if (response.code === 200) {
-                this.msgSuccess("修改成功");
-                this.open = false;
-                this.getList();
-              }
-            });
-          } else {
-            addDishes(data).then((response) => {
-              if (response.code === 200) {
-                this.msgSuccess("新增成功");
-                this.open = false;
-                this.getList();
-              }
-            });
-          }
-        }
-      });
+      this.$refs.dishesDrawerRef.showDrawer(row.id);
     },
     /** 删除按钮操作 */
     handleDelete(row) {
@@ -776,178 +405,8 @@ export default {
         })
         .catch(function () {});
     },
-    handleChange(value, direction, movedKeys) {
-      // console.log({
-      //   oriIgdList: this.oriDataList,
-      //   selIgdList: this.form.igdList,
-      //   ingDataList: this.ingDataList,
-      //   value,
-      //   ingType: this.ingType,
-      // });
-      const newTableData = [];
-      this.selRec = [];
-      this.selNotRec = [];
-      this.selIngList = value.map((id) => {
-        // 搜索table中的数据
-        let tmpTableObj = this.selTableData.find((obj) => obj.id === id);
-        if (tmpTableObj) {
-          newTableData.push(tmpTableObj);
-        } else {
-          // 搜索请求的缓存数据
-          tmpTableObj = this.oriDataList.find((obj) => obj.id === id);
-          if (tmpTableObj) {
-            newTableData.push({
-              ...tmpTableObj,
-              weight: 100,
-              cusWeight: 1,
-              cusUnit: 1,
-            });
-          }
-        }
-        if (tmpTableObj) {
-          if (tmpTableObj.rec) {
-            tmpTableObj.rec.split(",").forEach((rec) => {
-              if (!this.selRec.includes(rec)) {
-                this.selRec.push(rec);
-              }
-            });
-          }
-          if (tmpTableObj.notRec) {
-            tmpTableObj.notRec.split(",").forEach((notRec) => {
-              if (!this.selNotRec.includes(notRec)) {
-                this.selNotRec.push(notRec);
-              }
-            });
-          }
-        }
-        const tarObj = this.ingDataList.find(({ key }) => key === id);
-        return tarObj;
-      });
-      this.selTableData = newTableData;
-    },
-    handleOnTypeChange(value) {
-      listAllIngredient({ type: value }).then((res) => {
-        this.oriDataList = res.rows.concat(this.form.igdList);
-        this.ingDataList = this.oriDataList.reduce((arr, cur) => {
-          if (!arr.some(({ key }) => key === cur.id)) {
-            arr.push({
-              key: cur.id,
-              label: cur.name,
-            });
-          }
-          return arr;
-        }, []);
-      });
-    },
-    getSummaries(param) {
-      const { columns, data } = param;
-      // console.log(data);
-      return columns.reduce(
-        (arr, cur, idx) => {
-          if (idx > 1) {
-            if (idx === 6) {
-              arr[6] = arr[3] * 4 + arr[4] * 9 + arr[5] * 4 + " kcal";
-            } else {
-              arr[idx] = data.reduce((acc, dAcc) => {
-                if (idx === 2) {
-                  return acc + parseFloat(dAcc.weight);
-                }
-                return parseFloat(
-                  (
-                    acc +
-                    (dAcc[cur.property] * parseFloat(dAcc.weight)) / 100
-                  ).toFixed(1)
-                );
-              }, 0);
-            }
-          }
-          return arr;
-        },
-        ["合计"]
-      );
-    },
   },
 };
 </script>
 <style rel="stylesheet/scss" lang="scss">
-#el-drawer__title {
-  & > span:focus {
-    outline: 0;
-  }
-}
-
-.el-transfer-panel__filter {
-  margin: 2px;
-}
-
-.el-transfer-panel__list.is-filterable {
-  padding-bottom: 28px;
-}
-
-.cus-unit {
-  display: inline-flex;
-  .el-input-number--mini {
-    width: 38px;
-  }
-
-  .el-input-number {
-    .el-input-number__decrease {
-      display: none;
-    }
-    .el-input-number__increase {
-      display: none;
-    }
-
-    .el-input {
-      width: 38px;
-    }
-
-    .el-input .el-input__inner {
-      padding: 0;
-      border-radius: 0;
-      border: unset;
-      border-bottom: 1px solid #dcdfe6;
-    }
-  }
-
-  .el-select {
-    .el-input__suffix {
-      display: none;
-    }
-
-    .el-input__inner {
-      padding: 0 4px;
-      /* border: unset; */
-      text-align: center;
-    }
-  }
-}
-
-.weight {
-  width: 70px;
-
-  .el-input .el-input__inner {
-    padding: 0 32px 0 4px;
-  }
-}
-
-.drawer_content {
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-
-  .content_detail {
-    flex: 1 1 0;
-    padding: 12px;
-    overflow: auto;
-  }
-
-  .dialog-footer {
-    flex: 0 0 45px;
-    display: inline-flex;
-    align-items: center;
-    justify-content: flex-end;
-    padding: 0 12px;
-  }
-}
 </style>
diff --git a/stdiet-ui/src/views/custom/ingredient/index.vue b/stdiet-ui/src/views/custom/ingredient/index.vue
index 8bac238f2..038315fdb 100644
--- a/stdiet-ui/src/views/custom/ingredient/index.vue
+++ b/stdiet-ui/src/views/custom/ingredient/index.vue
@@ -146,6 +146,16 @@
           </el-tag>
         </template>
       </el-table-column>
+      <el-table-column label="图片" align="center" width="100">
+        <template slot-scope="scope">
+          <img
+            width="100"
+            height="auto"
+            :src="scope.row.imgList[0] ? scope.row.imgList[0].previewUrl : ''"
+            :alt="scope.row.imgList[0] ? scope.row.imgList[0].name : ''"
+          />
+        </template>
+      </el-table-column>
       <el-table-column
         label="食材名称"
         align="center"