|
@@ -15,26 +15,26 @@
|
|
|
<div class="dish-grid">
|
|
<div class="dish-grid">
|
|
|
<div v-for="(dish, index) in paginatedDishList" :key="dish.id" class="dish-card">
|
|
<div v-for="(dish, index) in paginatedDishList" :key="dish.id" class="dish-card">
|
|
|
<div class="dish-image-wrapper">
|
|
<div class="dish-image-wrapper">
|
|
|
- <img v-if="dish.image" :src="dish.image" alt="菜品图片" />
|
|
|
|
|
|
|
+ <img v-if="dish.imgUrl" :src="dish.imgUrl" alt="菜品图片" />
|
|
|
<div v-else class="image-placeholder">
|
|
<div v-else class="image-placeholder">
|
|
|
<el-icon><Picture /></el-icon>
|
|
<el-icon><Picture /></el-icon>
|
|
|
</div>
|
|
</div>
|
|
|
- <el-tag v-if="dish.isRecommended" type="primary" class="recommend-tag"> 推荐 </el-tag>
|
|
|
|
|
|
|
+ <el-tag v-if="dish.dishType === 1" type="primary" class="recommend-tag"> 推荐 </el-tag>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="dish-info">
|
|
<div class="dish-info">
|
|
|
<div class="dish-name">
|
|
<div class="dish-name">
|
|
|
- {{ dish.name }}
|
|
|
|
|
|
|
+ {{ dish.dishName }}
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="dish-price">¥{{ dish.price }}/{{ dish.unit }}</div>
|
|
|
|
|
- <div v-if="activeTab === 'recommended'" class="dish-recommend-count">{{ dish.recommendCount || 0 }}人推荐</div>
|
|
|
|
|
|
|
+ <div class="dish-price">¥{{ dish.dishPrice }}/{{ dish.dishesUnit }}</div>
|
|
|
|
|
+ <div v-if="activeTab === 'recommended'" class="dish-recommend-count">{{ dish.likeCount || 0 }}人推荐</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="dish-actions">
|
|
<div class="dish-actions">
|
|
|
<el-button type="primary" link @click="editDish(dish, index)"> 编辑 </el-button>
|
|
<el-button type="primary" link @click="editDish(dish, index)"> 编辑 </el-button>
|
|
|
- <el-button type="primary" link @click="deleteDish(dish.id, index)"> 删除 </el-button>
|
|
|
|
|
- <el-button v-if="dish.isRecommended" type="primary" link @click="cancelRecommend(dish.id, index)">
|
|
|
|
|
|
|
+ <el-button type="primary" link @click="deleteDish(dish.id!, index)"> 删除 </el-button>
|
|
|
|
|
+ <el-button v-if="dish.dishType === 1" type="primary" link @click="cancelRecommend(dish.id!, index)">
|
|
|
取消推荐
|
|
取消推荐
|
|
|
</el-button>
|
|
</el-button>
|
|
|
- <el-button v-else type="primary" link @click="setRecommend(dish.id, index)"> 设为推荐 </el-button>
|
|
|
|
|
|
|
+ <el-button v-else type="primary" link @click="setRecommend(dish.id!, index)"> 设为推荐 </el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -44,7 +44,7 @@
|
|
|
<el-pagination
|
|
<el-pagination
|
|
|
v-model:current-page="pageable.pageNum"
|
|
v-model:current-page="pageable.pageNum"
|
|
|
v-model:page-size="pageable.pageSize"
|
|
v-model:page-size="pageable.pageSize"
|
|
|
- :page-sizes="[10, 20, 50, 100]"
|
|
|
|
|
|
|
+ :page-sizes="[2, 20, 50, 100]"
|
|
|
:total="pageable.total"
|
|
:total="pageable.total"
|
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
|
@size-change="handleSizeChange"
|
|
@size-change="handleSizeChange"
|
|
@@ -62,12 +62,12 @@
|
|
|
<!-- 新建/编辑菜品弹窗 -->
|
|
<!-- 新建/编辑菜品弹窗 -->
|
|
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px" @close="resetForm">
|
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px" @close="resetForm">
|
|
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
|
|
- <el-form-item label="菜品名称" prop="name">
|
|
|
|
|
- <el-input v-model="formData.name" placeholder="请输入" maxlength="10" show-word-limit clearable />
|
|
|
|
|
|
|
+ <el-form-item label="菜品名称" prop="dishName">
|
|
|
|
|
+ <el-input v-model="formData.dishName" placeholder="请输入" maxlength="10" show-word-limit clearable />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- <el-form-item label="价格 (¥)" prop="price">
|
|
|
|
|
|
|
+ <el-form-item label="价格 (¥)" prop="dishPrice">
|
|
|
<el-input-number
|
|
<el-input-number
|
|
|
- v-model="formData.price"
|
|
|
|
|
|
|
+ v-model="formData.dishPrice"
|
|
|
:min="0"
|
|
:min="0"
|
|
|
:max="99999.99"
|
|
:max="99999.99"
|
|
|
:precision="2"
|
|
:precision="2"
|
|
@@ -87,17 +87,18 @@
|
|
|
style="width: 100%"
|
|
style="width: 100%"
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- <el-form-item label="单位" prop="unit">
|
|
|
|
|
- <el-select v-model="formData.unit" placeholder="请选择" style="width: 100%">
|
|
|
|
|
|
|
+ <el-form-item label="单位" prop="dishesUnit">
|
|
|
|
|
+ <el-select v-model="formData.dishesUnit" placeholder="请选择" style="width: 100%">
|
|
|
<el-option v-for="unit in unitOptions" :key="unit.value" :label="unit.label" :value="unit.value" />
|
|
<el-option v-for="unit in unitOptions" :key="unit.value" :label="unit.label" :value="unit.value" />
|
|
|
</el-select>
|
|
</el-select>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- <el-form-item label="图片" prop="image">
|
|
|
|
|
|
|
+ <el-form-item label="图片" prop="imgUrl">
|
|
|
<UploadImg
|
|
<UploadImg
|
|
|
- v-model:image-url="formData.image"
|
|
|
|
|
|
|
+ v-model:image-url="formData.imgUrl"
|
|
|
:width="'200px'"
|
|
:width="'200px'"
|
|
|
:height="'200px'"
|
|
:height="'200px'"
|
|
|
:file-size="10"
|
|
:file-size="10"
|
|
|
|
|
+ :api="uploadImg"
|
|
|
:file-type="['image/jpeg', 'image/png', 'image/gif', 'image/webp']"
|
|
:file-type="['image/jpeg', 'image/png', 'image/gif', 'image/webp']"
|
|
|
:border-radius="'8px'"
|
|
:border-radius="'8px'"
|
|
|
/>
|
|
/>
|
|
@@ -113,14 +114,16 @@
|
|
|
clearable
|
|
clearable
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
- <el-form-item label="" prop="isRecommended">
|
|
|
|
|
|
|
+ <el-form-item label="" prop="dishType">
|
|
|
<el-checkbox v-model="formData.isRecommended"> 设为推荐 </el-checkbox>
|
|
<el-checkbox v-model="formData.isRecommended"> 设为推荐 </el-checkbox>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-form>
|
|
</el-form>
|
|
|
<template #footer>
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
<div class="dialog-footer">
|
|
|
<el-button @click="dialogVisible = false"> 取消 </el-button>
|
|
<el-button @click="dialogVisible = false"> 取消 </el-button>
|
|
|
- <el-button type="primary" :loading="submitLoading" @click="handleSubmit"> 新建菜品 </el-button>
|
|
|
|
|
|
|
+ <el-button type="primary" :loading="submitLoading" @click="handleSubmit">
|
|
|
|
|
+ {{ editId ? "确定" : "新建菜品" }}
|
|
|
|
|
+ </el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-dialog>
|
|
</el-dialog>
|
|
@@ -129,24 +132,25 @@
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref, reactive, computed, onMounted } from "vue";
|
|
import { ref, reactive, computed, onMounted } from "vue";
|
|
|
-import { ElMessage } from "element-plus";
|
|
|
|
|
|
|
+import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
import type { FormInstance, FormRules } from "element-plus";
|
|
import type { FormInstance, FormRules } from "element-plus";
|
|
|
import { Picture } from "@element-plus/icons-vue";
|
|
import { Picture } from "@element-plus/icons-vue";
|
|
|
import UploadImg from "@/components/Upload/Img.vue";
|
|
import UploadImg from "@/components/Upload/Img.vue";
|
|
|
-// TODO: 导入菜单相关的 API 接口
|
|
|
|
|
-// import { getDishList, createDish, updateDish, deleteDish, setRecommendDish, cancelRecommendDish } from "@/api/modules/storeDecoration";
|
|
|
|
|
|
|
+import { uploadImg } from "@/api/modules/newLoginApi";
|
|
|
|
|
+import { localGet } from "@/utils";
|
|
|
|
|
+import { createOrUpdateDish, getDishList, getDishDetail } from "@/api/modules/storeDecoration";
|
|
|
|
|
|
|
|
// 菜品接口
|
|
// 菜品接口
|
|
|
interface Dish {
|
|
interface Dish {
|
|
|
- id: string;
|
|
|
|
|
- name: string;
|
|
|
|
|
- price: number;
|
|
|
|
|
|
|
+ id?: string | number;
|
|
|
|
|
+ dishName: string;
|
|
|
|
|
+ dishPrice: number;
|
|
|
costPrice: number;
|
|
costPrice: number;
|
|
|
- unit: string;
|
|
|
|
|
- image: string;
|
|
|
|
|
|
|
+ dishesUnit: string;
|
|
|
|
|
+ imgUrl: string;
|
|
|
description?: string;
|
|
description?: string;
|
|
|
- isRecommended: boolean;
|
|
|
|
|
- recommendCount?: number;
|
|
|
|
|
|
|
+ dishType: number; // 0:未推荐, 1:推荐
|
|
|
|
|
+ likeCount?: number;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const dialogVisible = ref(false);
|
|
const dialogVisible = ref(false);
|
|
@@ -154,6 +158,7 @@ const formRef = ref<FormInstance>();
|
|
|
const submitLoading = ref(false);
|
|
const submitLoading = ref(false);
|
|
|
const activeTab = ref<"menu" | "recommended">("menu");
|
|
const activeTab = ref<"menu" | "recommended">("menu");
|
|
|
const editIndex = ref<number | null>(null);
|
|
const editIndex = ref<number | null>(null);
|
|
|
|
|
+const editId = ref<string | number | null>(null);
|
|
|
|
|
|
|
|
// 单位选项
|
|
// 单位选项
|
|
|
const unitOptions = [
|
|
const unitOptions = [
|
|
@@ -169,11 +174,8 @@ const unitOptions = [
|
|
|
// 菜品列表
|
|
// 菜品列表
|
|
|
const dishList = ref<Dish[]>([]);
|
|
const dishList = ref<Dish[]>([]);
|
|
|
|
|
|
|
|
-// 显示菜品列表(根据tab过滤)
|
|
|
|
|
|
|
+// 显示菜品列表(直接使用从接口获取的数据,不需要过滤)
|
|
|
const displayDishList = computed(() => {
|
|
const displayDishList = computed(() => {
|
|
|
- if (activeTab.value === "recommended") {
|
|
|
|
|
- return dishList.value.filter(dish => dish.isRecommended);
|
|
|
|
|
- }
|
|
|
|
|
return dishList.value;
|
|
return dishList.value;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -195,24 +197,24 @@ const paginatedDishList = computed(() => {
|
|
|
// 弹窗标题
|
|
// 弹窗标题
|
|
|
const dialogTitle = computed(() => (editIndex.value !== null ? "编辑菜品" : "新建菜品"));
|
|
const dialogTitle = computed(() => (editIndex.value !== null ? "编辑菜品" : "新建菜品"));
|
|
|
|
|
|
|
|
-// 表单数据
|
|
|
|
|
|
|
+// 表单数据(内部使用,方便表单绑定)
|
|
|
const formData = reactive({
|
|
const formData = reactive({
|
|
|
- name: "",
|
|
|
|
|
- price: undefined as number | undefined,
|
|
|
|
|
|
|
+ dishName: "",
|
|
|
|
|
+ dishPrice: undefined as number | undefined,
|
|
|
costPrice: undefined as number | undefined,
|
|
costPrice: undefined as number | undefined,
|
|
|
- unit: "份",
|
|
|
|
|
- image: "",
|
|
|
|
|
|
|
+ dishesUnit: "份",
|
|
|
|
|
+ imgUrl: "",
|
|
|
description: "",
|
|
description: "",
|
|
|
- isRecommended: true
|
|
|
|
|
|
|
+ isRecommended: true // 内部使用布尔值,提交时转换为 dishType
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 表单校验规则
|
|
// 表单校验规则
|
|
|
const rules = reactive<FormRules>({
|
|
const rules = reactive<FormRules>({
|
|
|
- name: [
|
|
|
|
|
|
|
+ dishName: [
|
|
|
{ required: true, message: "请输入菜品名称", trigger: "blur" },
|
|
{ required: true, message: "请输入菜品名称", trigger: "blur" },
|
|
|
{ max: 10, message: "菜品名称不能超过10个字", trigger: "blur" }
|
|
{ max: 10, message: "菜品名称不能超过10个字", trigger: "blur" }
|
|
|
],
|
|
],
|
|
|
- price: [
|
|
|
|
|
|
|
+ dishPrice: [
|
|
|
{ required: true, message: "请输入价格", trigger: "blur" },
|
|
{ required: true, message: "请输入价格", trigger: "blur" },
|
|
|
{
|
|
{
|
|
|
validator: (rule, value, callback) => {
|
|
validator: (rule, value, callback) => {
|
|
@@ -246,14 +248,15 @@ const rules = reactive<FormRules>({
|
|
|
trigger: "blur"
|
|
trigger: "blur"
|
|
|
}
|
|
}
|
|
|
],
|
|
],
|
|
|
- unit: [{ required: true, message: "请选择单位", trigger: "change" }],
|
|
|
|
|
- image: [{ required: true, message: "请上传图片", trigger: "change" }],
|
|
|
|
|
|
|
+ dishesUnit: [{ required: true, message: "请选择单位", trigger: "change" }],
|
|
|
|
|
+ imgUrl: [{ required: true, message: "请上传图片", trigger: "change" }],
|
|
|
description: [{ max: 300, message: "描述不能超过300个字", trigger: "blur" }]
|
|
description: [{ max: 300, message: "描述不能超过300个字", trigger: "blur" }]
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// Tab切换
|
|
// Tab切换
|
|
|
-const handleTabClick = () => {
|
|
|
|
|
|
|
+const handleTabClick = async () => {
|
|
|
pageable.pageNum = 1;
|
|
pageable.pageNum = 1;
|
|
|
|
|
+ await loadDishList();
|
|
|
updatePagination();
|
|
updatePagination();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -276,76 +279,195 @@ const handleCurrentChange = (page: number) => {
|
|
|
// 打开新建弹窗
|
|
// 打开新建弹窗
|
|
|
const openCreateDialog = () => {
|
|
const openCreateDialog = () => {
|
|
|
editIndex.value = null;
|
|
editIndex.value = null;
|
|
|
|
|
+ editId.value = null;
|
|
|
resetForm();
|
|
resetForm();
|
|
|
dialogVisible.value = true;
|
|
dialogVisible.value = true;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 编辑菜品
|
|
// 编辑菜品
|
|
|
-const editDish = (dish: Dish, index: number) => {
|
|
|
|
|
- // 在完整列表中查找索引
|
|
|
|
|
- const actualIndex = dishList.value.findIndex(d => d.id === dish.id);
|
|
|
|
|
- editIndex.value = actualIndex > -1 ? actualIndex : null;
|
|
|
|
|
- formData.name = dish.name;
|
|
|
|
|
- formData.price = dish.price;
|
|
|
|
|
- formData.costPrice = dish.costPrice;
|
|
|
|
|
- formData.unit = dish.unit;
|
|
|
|
|
- formData.image = dish.image;
|
|
|
|
|
- formData.description = dish.description || "";
|
|
|
|
|
- formData.isRecommended = dish.isRecommended;
|
|
|
|
|
- dialogVisible.value = true;
|
|
|
|
|
|
|
+const editDish = async (dish: Dish, index: number) => {
|
|
|
|
|
+ if (!dish.id) {
|
|
|
|
|
+ ElMessage.warning("菜品ID不存在");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 调用获取菜品详情接口
|
|
|
|
|
+ const res: any = await getDishDetail({ id: dish.id });
|
|
|
|
|
+ if (res && (res.code === 200 || res.code === "200") && res.data) {
|
|
|
|
|
+ const dishDetail = res.data;
|
|
|
|
|
+ editId.value = dishDetail.id;
|
|
|
|
|
+ formData.dishName = dishDetail.dishName || "";
|
|
|
|
|
+ formData.dishPrice = dishDetail.dishPrice;
|
|
|
|
|
+ formData.costPrice = dishDetail.costPrice;
|
|
|
|
|
+ formData.dishesUnit = dishDetail.dishesUnit || "份";
|
|
|
|
|
+ formData.imgUrl = dishDetail.imgUrl || "";
|
|
|
|
|
+ formData.description = dishDetail.description || "";
|
|
|
|
|
+ formData.isRecommended = dishDetail.dishType === 1; // 将数字转换为布尔值
|
|
|
|
|
+ dialogVisible.value = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res?.msg || "获取菜品详情失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ console.error("获取菜品详情失败:", error);
|
|
|
|
|
+ ElMessage.error(error?.msg || "获取菜品详情失败,请重试");
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 删除菜品
|
|
// 删除菜品
|
|
|
-const deleteDish = async (id: string, index: number) => {
|
|
|
|
|
- // TODO: 调用删除菜品接口 deleteDish API
|
|
|
|
|
- // await deleteDish({ id });
|
|
|
|
|
-
|
|
|
|
|
- const actualIndex = dishList.value.findIndex(d => d.id === id);
|
|
|
|
|
- if (actualIndex > -1) {
|
|
|
|
|
- dishList.value.splice(actualIndex, 1);
|
|
|
|
|
- updatePagination();
|
|
|
|
|
- // 如果当前页没有数据了,回到上一页
|
|
|
|
|
- if (paginatedDishList.value.length === 0 && pageable.pageNum > 1) {
|
|
|
|
|
- pageable.pageNum--;
|
|
|
|
|
|
|
+const deleteDish = async (id: string | number, index: number) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await ElMessageBox.confirm("确认删除该菜品吗?", "提示", {
|
|
|
|
|
+ confirmButtonText: "确定",
|
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
|
+ type: "warning"
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const dish = dishList.value.find(d => d.id === id);
|
|
|
|
|
+ if (!dish) {
|
|
|
|
|
+ ElMessage.error("未找到要删除的菜品");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
|
|
+ if (!storeId) {
|
|
|
|
|
+ ElMessage.error("未找到店铺ID");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 通过更新接口删除(设置deleteFlag,如果有的话,或者直接调用删除接口)
|
|
|
|
|
+ // 如果没有删除接口,可以通过更新dishType为-1或其他标记来删除
|
|
|
|
|
+ // 这里假设可以通过更新接口删除,实际需要根据后端接口调整
|
|
|
|
|
+ const params: any = {
|
|
|
|
|
+ id: dish.id,
|
|
|
|
|
+ storeId: Number(storeId),
|
|
|
|
|
+ dishName: dish.dishName,
|
|
|
|
|
+ dishPrice: dish.dishPrice,
|
|
|
|
|
+ costPrice: dish.costPrice,
|
|
|
|
|
+ dishesUnit: dish.dishesUnit,
|
|
|
|
|
+ imgUrl: dish.imgUrl,
|
|
|
|
|
+ description: dish.description || "",
|
|
|
|
|
+ dishType: dish.dishType,
|
|
|
|
|
+ deleteFlag: 1 // 假设有删除标记字段
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const res: any = await createOrUpdateDish(params);
|
|
|
|
|
+ if (res && (res.code === 200 || res.code === "200")) {
|
|
|
|
|
+ ElMessage.success("删除成功");
|
|
|
|
|
+ await loadDishList();
|
|
|
|
|
+ updatePagination();
|
|
|
|
|
+ // 如果当前页没有数据了,回到上一页
|
|
|
|
|
+ if (paginatedDishList.value.length === 0 && pageable.pageNum > 1) {
|
|
|
|
|
+ pageable.pageNum--;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res?.msg || "删除失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ if (error !== "cancel") {
|
|
|
|
|
+ console.error("删除菜品失败:", error);
|
|
|
|
|
+ ElMessage.error(error?.msg || "删除失败,请重试");
|
|
|
}
|
|
}
|
|
|
- ElMessage.success("删除成功");
|
|
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 设为推荐
|
|
// 设为推荐
|
|
|
-const setRecommend = async (id: string, index: number) => {
|
|
|
|
|
- // TODO: 调用设为推荐接口 setRecommendDish API
|
|
|
|
|
- // await setRecommendDish({ id });
|
|
|
|
|
-
|
|
|
|
|
- const dish = dishList.value.find(d => d.id === id);
|
|
|
|
|
- if (dish) {
|
|
|
|
|
- dish.isRecommended = true;
|
|
|
|
|
- dish.recommendCount = (dish.recommendCount || 0) + 1;
|
|
|
|
|
- ElMessage.success("设置推荐成功");
|
|
|
|
|
|
|
+const setRecommend = async (id: string | number, index: number) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const dish = dishList.value.find(d => d.id === id);
|
|
|
|
|
+ if (!dish) {
|
|
|
|
|
+ ElMessage.error("未找到菜品");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
|
|
+ if (!storeId) {
|
|
|
|
|
+ ElMessage.error("未找到店铺ID");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 通过更新接口设置推荐
|
|
|
|
|
+ const params: any = {
|
|
|
|
|
+ id: dish.id,
|
|
|
|
|
+ storeId: Number(storeId),
|
|
|
|
|
+ dishName: dish.dishName,
|
|
|
|
|
+ dishPrice: dish.dishPrice,
|
|
|
|
|
+ costPrice: dish.costPrice,
|
|
|
|
|
+ dishesUnit: dish.dishesUnit,
|
|
|
|
|
+ imgUrl: dish.imgUrl,
|
|
|
|
|
+ description: dish.description || "",
|
|
|
|
|
+ dishType: 1 // 设置为推荐
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const res: any = await createOrUpdateDish(params);
|
|
|
|
|
+ if (res && (res.code === 200 || res.code === "200")) {
|
|
|
|
|
+ ElMessage.success("设置推荐成功");
|
|
|
|
|
+ await loadDishList();
|
|
|
|
|
+ updatePagination();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res?.msg || "设置推荐失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ console.error("设置推荐失败:", error);
|
|
|
|
|
+ ElMessage.error(error?.msg || "设置推荐失败,请重试");
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 取消推荐
|
|
// 取消推荐
|
|
|
-const cancelRecommend = async (id: string, index: number) => {
|
|
|
|
|
- // TODO: 调用取消推荐接口 cancelRecommendDish API
|
|
|
|
|
- // await cancelRecommendDish({ id });
|
|
|
|
|
-
|
|
|
|
|
- const dish = dishList.value.find(d => d.id === id);
|
|
|
|
|
- if (dish) {
|
|
|
|
|
- dish.isRecommended = false;
|
|
|
|
|
- ElMessage.success("取消推荐成功");
|
|
|
|
|
|
|
+const cancelRecommend = async (id: string | number, index: number) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const dish = dishList.value.find(d => d.id === id);
|
|
|
|
|
+ if (!dish) {
|
|
|
|
|
+ ElMessage.error("未找到菜品");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
|
|
+ if (!storeId) {
|
|
|
|
|
+ ElMessage.error("未找到店铺ID");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 通过更新接口取消推荐
|
|
|
|
|
+ const params: any = {
|
|
|
|
|
+ id: dish.id,
|
|
|
|
|
+ storeId: Number(storeId),
|
|
|
|
|
+ dishName: dish.dishName,
|
|
|
|
|
+ dishPrice: dish.dishPrice,
|
|
|
|
|
+ costPrice: dish.costPrice,
|
|
|
|
|
+ dishesUnit: dish.dishesUnit,
|
|
|
|
|
+ imgUrl: dish.imgUrl,
|
|
|
|
|
+ description: dish.description || "",
|
|
|
|
|
+ dishType: 0 // 设置为未推荐
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const res: any = await createOrUpdateDish(params);
|
|
|
|
|
+ if (res && (res.code === 200 || res.code === "200")) {
|
|
|
|
|
+ ElMessage.success("取消推荐成功");
|
|
|
|
|
+ await loadDishList();
|
|
|
|
|
+ updatePagination();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res?.msg || "取消推荐失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error: any) {
|
|
|
|
|
+ console.error("取消推荐失败:", error);
|
|
|
|
|
+ ElMessage.error(error?.msg || "取消推荐失败,请重试");
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 重置表单
|
|
// 重置表单
|
|
|
const resetForm = () => {
|
|
const resetForm = () => {
|
|
|
- formData.name = "";
|
|
|
|
|
- formData.price = undefined;
|
|
|
|
|
|
|
+ formData.dishName = "";
|
|
|
|
|
+ formData.dishPrice = undefined;
|
|
|
formData.costPrice = undefined;
|
|
formData.costPrice = undefined;
|
|
|
- formData.unit = "份";
|
|
|
|
|
- formData.image = "";
|
|
|
|
|
|
|
+ formData.dishesUnit = "份";
|
|
|
|
|
+ formData.imgUrl = "";
|
|
|
formData.description = "";
|
|
formData.description = "";
|
|
|
formData.isRecommended = true;
|
|
formData.isRecommended = true;
|
|
|
|
|
+ editId.value = null;
|
|
|
formRef.value?.clearValidate();
|
|
formRef.value?.clearValidate();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -362,91 +484,87 @@ const handleSubmit = async () => {
|
|
|
|
|
|
|
|
submitLoading.value = true;
|
|
submitLoading.value = true;
|
|
|
try {
|
|
try {
|
|
|
- if (editIndex.value !== null && editIndex.value < dishList.value.length) {
|
|
|
|
|
- // 编辑菜品
|
|
|
|
|
- // TODO: 调用更新菜品接口 updateDish API
|
|
|
|
|
- // const params = {
|
|
|
|
|
- // id: dishList.value[editIndex.value].id,
|
|
|
|
|
- // ...formData
|
|
|
|
|
- // };
|
|
|
|
|
- // await updateDish(params);
|
|
|
|
|
-
|
|
|
|
|
- const dish = dishList.value[editIndex.value];
|
|
|
|
|
- const wasRecommended = dish.isRecommended;
|
|
|
|
|
- dish.name = formData.name;
|
|
|
|
|
- dish.price = formData.price!;
|
|
|
|
|
- dish.costPrice = formData.costPrice!;
|
|
|
|
|
- dish.unit = formData.unit;
|
|
|
|
|
- dish.image = formData.image;
|
|
|
|
|
- dish.description = formData.description;
|
|
|
|
|
- dish.isRecommended = formData.isRecommended;
|
|
|
|
|
-
|
|
|
|
|
- // 如果从非推荐变为推荐,增加推荐人数
|
|
|
|
|
- if (formData.isRecommended && !wasRecommended) {
|
|
|
|
|
- dish.recommendCount = (dish.recommendCount || 0) + 1;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
|
|
+ if (!storeId) {
|
|
|
|
|
+ ElMessage.error("未找到店铺ID");
|
|
|
|
|
+ submitLoading.value = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- ElMessage.success("编辑成功");
|
|
|
|
|
- } else {
|
|
|
|
|
- // 新建菜品
|
|
|
|
|
- // TODO: 调用创建菜品接口 createDish API
|
|
|
|
|
- // const params = {
|
|
|
|
|
- // ...formData,
|
|
|
|
|
- // recommendCount: formData.isRecommended ? 1 : 0
|
|
|
|
|
- // };
|
|
|
|
|
- // const res = await createDish(params);
|
|
|
|
|
- // dishList.value.push(res.data);
|
|
|
|
|
-
|
|
|
|
|
- const newDish: Dish = {
|
|
|
|
|
- id: `dish_${Date.now()}`,
|
|
|
|
|
- name: formData.name,
|
|
|
|
|
- price: formData.price!,
|
|
|
|
|
- costPrice: formData.costPrice!,
|
|
|
|
|
- unit: formData.unit,
|
|
|
|
|
- image: formData.image,
|
|
|
|
|
- description: formData.description,
|
|
|
|
|
- isRecommended: formData.isRecommended,
|
|
|
|
|
- recommendCount: formData.isRecommended ? 1 : 0
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- dishList.value.push(newDish);
|
|
|
|
|
- ElMessage.success("新建成功");
|
|
|
|
|
|
|
+ // 构建请求参数
|
|
|
|
|
+ const params: any = {
|
|
|
|
|
+ storeId: Number(storeId),
|
|
|
|
|
+ dishName: formData.dishName,
|
|
|
|
|
+ dishPrice: formData.dishPrice!,
|
|
|
|
|
+ costPrice: formData.costPrice!,
|
|
|
|
|
+ dishesUnit: formData.dishesUnit,
|
|
|
|
|
+ imgUrl: formData.imgUrl,
|
|
|
|
|
+ description: formData.description || "",
|
|
|
|
|
+ dishType: formData.isRecommended ? 1 : 0
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 如果是编辑,添加id
|
|
|
|
|
+ if (editId.value) {
|
|
|
|
|
+ params.id = editId.value;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- dialogVisible.value = false;
|
|
|
|
|
- updatePagination();
|
|
|
|
|
- resetForm();
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- ElMessage.error("操作失败,请重试");
|
|
|
|
|
|
|
+ const res: any = await createOrUpdateDish(params);
|
|
|
|
|
+ if (res && (res.code === 200 || res.code === "200")) {
|
|
|
|
|
+ ElMessage.success(editId.value ? "编辑成功" : "新建成功");
|
|
|
|
|
+ dialogVisible.value = false;
|
|
|
|
|
+ resetForm();
|
|
|
|
|
+ // 重新加载菜品列表
|
|
|
|
|
+ await loadDishList();
|
|
|
|
|
+ updatePagination();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res?.msg || (editId.value ? "编辑失败" : "新建失败"));
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error: any) {
|
|
|
console.error("操作失败:", error);
|
|
console.error("操作失败:", error);
|
|
|
|
|
+ ElMessage.error(error?.msg || "操作失败,请重试");
|
|
|
} finally {
|
|
} finally {
|
|
|
submitLoading.value = false;
|
|
submitLoading.value = false;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+// 加载菜品列表
|
|
|
|
|
+const loadDishList = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const userInfo: any = localGet("geeker-user")?.userInfo || {};
|
|
|
|
|
+ const storeId = userInfo.storeId;
|
|
|
|
|
+ if (!storeId) {
|
|
|
|
|
+ console.warn("未找到店铺ID");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 根据tab切换调用不同的dishType参数
|
|
|
|
|
+ // dishType: 0表示菜单, 1表示推荐
|
|
|
|
|
+ const dishType = activeTab.value === "recommended" ? 1 : 0;
|
|
|
|
|
+ const res: any = await getDishList({ storeId: Number(storeId), dishType });
|
|
|
|
|
+
|
|
|
|
|
+ if (res && (res.code === 200 || res.code === "200") && res.data) {
|
|
|
|
|
+ const dataList = Array.isArray(res.data) ? res.data : [];
|
|
|
|
|
+ dishList.value = dataList.map((dish: any) => ({
|
|
|
|
|
+ id: dish.id,
|
|
|
|
|
+ dishName: dish.dishName || "",
|
|
|
|
|
+ dishPrice: dish.dishPrice || 0,
|
|
|
|
|
+ costPrice: dish.costPrice || 0,
|
|
|
|
|
+ dishesUnit: dish.dishesUnit || "份",
|
|
|
|
|
+ imgUrl: dish.imgUrl || "",
|
|
|
|
|
+ description: dish.description || "",
|
|
|
|
|
+ dishType: dish.dishType !== undefined ? dish.dishType : 0,
|
|
|
|
|
+ likeCount: dish.likeCount || 0
|
|
|
|
|
+ }));
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error("获取菜品列表失败:", error);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// 页面初始化
|
|
// 页面初始化
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
- // TODO: 调用获取菜品列表接口 getDishList API
|
|
|
|
|
- // const res = await getDishList();
|
|
|
|
|
- // if (res.data) {
|
|
|
|
|
- // dishList.value = res.data;
|
|
|
|
|
- // updatePagination();
|
|
|
|
|
- // }
|
|
|
|
|
-
|
|
|
|
|
- // 示例数据
|
|
|
|
|
- // dishList.value = [
|
|
|
|
|
- // {
|
|
|
|
|
- // id: "1",
|
|
|
|
|
- // name: "火锅锅底",
|
|
|
|
|
- // price: 38,
|
|
|
|
|
- // costPrice: 20,
|
|
|
|
|
- // unit: "份",
|
|
|
|
|
- // image: "",
|
|
|
|
|
- // description: "",
|
|
|
|
|
- // isRecommended: true,
|
|
|
|
|
- // recommendCount: 1
|
|
|
|
|
- // }
|
|
|
|
|
- // ];
|
|
|
|
|
|
|
+ await loadDishList();
|
|
|
updatePagination();
|
|
updatePagination();
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|