campus-errand/admin/src/views/ShopDishes.vue
2026-03-17 15:42:18 +08:00

132 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
<div style="display: flex; align-items: center; gap: 12px;">
<el-button @click="$router.push('/shops')">返回门店列表</el-button>
<h3 style="margin: 0;">菜品管理门店 #{{ shopId }}</h3>
</div>
<el-button type="primary" @click="openDialog()">新增菜品</el-button>
</div>
<el-table :data="list" v-loading="loading" border>
<el-table-column label="照片" width="100">
<template #default="{ row }">
<el-image :src="row.photo" style="width: 60px; height: 60px;" fit="cover" />
</template>
</el-table-column>
<el-table-column prop="name" label="菜品名称" />
<el-table-column prop="price" label="价格(元)" width="120" />
<el-table-column label="状态" width="80">
<template #default="{ row }">
<el-tag :type="row.isEnabled ? 'success' : 'info'" size="small">{{ row.isEnabled ? '启用' : '禁用' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="160" fixed="right">
<template #default="{ row }">
<el-button size="small" @click="openDialog(row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增/编辑菜品弹窗 -->
<el-dialog v-model="dialogVisible" :title="isEdit ? '编辑菜品' : '新增菜品'" width="500px">
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px">
<el-form-item label="菜品名称" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="菜品照片" prop="photo">
<el-upload action="/api/upload/image" :headers="uploadHeaders" :show-file-list="false"
:on-success="(res) => form.photo = res.url" accept="image/*">
<el-image v-if="form.photo" :src="form.photo" style="width: 120px; height: 120px; cursor: pointer; border-radius: 8px;" fit="cover" />
<el-button v-else size="small">上传照片</el-button>
</el-upload>
<el-button v-if="form.photo" size="small" text type="danger" style="margin-top: 4px;" @click="form.photo = ''">移除</el-button>
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input-number v-model="form.price" :min="0" :precision="2" :step="1" />
</el-form-item>
<el-form-item label="启用状态">
<el-switch v-model="form.isEnabled" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '../utils/request'
const route = useRoute()
const shopId = route.params.id
const loading = ref(false)
const submitting = ref(false)
const list = ref([])
const dialogVisible = ref(false)
const isEdit = ref(false)
const editId = ref(null)
const formRef = ref(null)
const uploadHeaders = { Authorization: `Bearer ${localStorage.getItem('admin_token')}` }
const defaultForm = () => ({ name: '', photo: '', price: 0, isEnabled: true })
const form = reactive(defaultForm())
const rules = {
name: [{ required: true, message: '菜品名称不能为空', trigger: 'blur' }],
photo: [{ required: true, message: '菜品照片不能为空', trigger: 'blur' }]
}
async function fetchList() {
loading.value = true
try {
list.value = await request.get(`/admin/shops/${shopId}/dishes`)
} finally {
loading.value = false
}
}
function openDialog(row) {
isEdit.value = !!row
editId.value = row?.id || null
Object.assign(form, row ? { name: row.name, photo: row.photo, price: row.price, isEnabled: row.isEnabled } : defaultForm())
dialogVisible.value = true
}
async function handleSubmit() {
const valid = await formRef.value.validate().catch(() => false)
if (!valid) return
submitting.value = true
try {
if (isEdit.value) {
await request.put(`/admin/shops/${shopId}/dishes/${editId.value}`, form)
ElMessage.success('更新成功')
} else {
await request.post(`/admin/shops/${shopId}/dishes`, form)
ElMessage.success('创建成功')
}
dialogVisible.value = false
fetchList()
} finally {
submitting.value = false
}
}
async function handleDelete(row) {
await ElMessageBox.confirm(`确定删除菜品「${row.name}」?`, '提示', { type: 'warning' })
await request.delete(`/admin/shops/${shopId}/dishes/${row.id}`)
ElMessage.success('删除成功')
fetchList()
}
onMounted(fetchList)
</script>