132 lines
4.9 KiB
Vue
132 lines
4.9 KiB
Vue
<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>
|