| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- <template>
- <div class="food-category">
- <el-card shadow="hover">
- <template #header>
- <div class="card-header">
- <span>食品数据管理</span>
- </div>
- </template>
-
- <!-- 搜索和筛选区域 -->
- <div class="search-filter">
- <el-form :model="searchForm" label-width="80px" inline>
- <el-form-item label="食品名称">
- <el-input
- v-model="searchForm.productName"
- placeholder="请输入食品名称"
- clearable
- @keyup.enter="getProductList"
- />
- </el-form-item>
- <el-form-item label="食品类型">
- <el-select
- v-model="searchForm.foodType"
- placeholder="请选择食品类型"
- clearable
- >
- <el-option label="蔬菜" value="vegetable" />
- <el-option label="水果" value="fruit" />
- <el-option label="肉类" value="meat" />
- <el-option label="海鲜" value="seafood" />
- <el-option label="加工食品" value="processed" />
- </el-select>
- </el-form-item>
- <el-form-item label="生成状态">
- <el-select
- v-model="searchForm.status"
- placeholder="请选择状态"
- clearable
- >
- <el-option label="已生成" value="success" />
- <el-option label="生成中" value="generating" />
- <el-option label="生成失败" value="failed" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getProductList">搜索</el-button>
- <el-button @click="resetSearch">重置</el-button>
- </el-form-item>
- </el-form>
- </div>
-
- <!-- 产品列表 -->
- <div class="food-list">
- <el-table
- :data="productList"
- style="width: 100%"
- stripe
- @row-click="handleRowClick"
- >
- <el-table-column prop="id" label="食品ID" width="80" />
- <el-table-column prop="productName" label="食品名称" width="200" />
- <el-table-column prop="foodType" label="食品类型" width="120">
- <template #default="scope">
- <el-tag
- :type="scope.row.foodType === 'vegetable' ? 'success' :
- scope.row.foodType === 'fruit' ? 'warning' :
- scope.row.foodType === 'meat' ? 'danger' :
- scope.row.foodType === 'seafood' ? 'primary' : 'info'"
- >
- {{ scope.row.foodType === 'vegetable' ? '蔬菜' :
- scope.row.foodType === 'fruit' ? '水果' :
- scope.row.foodType === 'meat' ? '肉类' :
- scope.row.foodType === 'seafood' ? '海鲜' : '加工食品' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="size" label="图片尺寸" width="120" />
- <el-table-column prop="style" label="设计风格" width="120" />
- <el-table-column prop="status" label="生成状态" width="120">
- <template #default="scope">
- <el-tag
- :type="scope.row.status === 'success' ? 'success' :
- scope.row.status === 'generating' ? 'warning' : 'danger'"
- >
- {{ scope.row.status === 'success' ? '已生成' :
- scope.row.status === 'generating' ? '生成中' : '生成失败' }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="createTime" label="创建时间" width="180" />
- <el-table-column label="操作" width="200">
- <template #default="scope">
- <el-button type="primary" size="small" @click="viewProduct(scope.row)">查看详情</el-button>
- <el-button type="danger" size="small" @click="deleteProduct(scope.row.id)">删除</el-button>
- </template>
- </el-table-column>
- </el-table>
-
- <!-- 分页 -->
- <div class="pagination">
- <el-pagination
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- :current-page="pagination.currentPage"
- :page-sizes="[10, 20, 50, 100]"
- :page-size="pagination.pageSize"
- layout="total, sizes, prev, pager, next, jumper"
- :total="pagination.total"
- />
- </div>
- </div>
- </el-card>
-
- <!-- 产品详情对话框 -->
- <el-dialog
- v-model="detailDialogVisible"
- title="食品详情"
- width="800px"
- :before-close="handleDetailClose"
- >
- <div class="food-detail" v-if="selectedProduct">
- <div class="detail-section">
- <h3>基本信息</h3>
- <el-descriptions :column="2" border>
- <el-descriptions-item label="食品ID">{{ selectedProduct.id }}</el-descriptions-item>
- <el-descriptions-item label="食品名称">{{ selectedProduct.productName }}</el-descriptions-item>
- <el-descriptions-item label="食品类型">
- <el-tag
- :type="selectedProduct.foodType === 'vegetable' ? 'success' :
- selectedProduct.foodType === 'fruit' ? 'warning' :
- selectedProduct.foodType === 'meat' ? 'danger' :
- selectedProduct.foodType === 'seafood' ? 'primary' : 'info'"
- >
- {{ selectedProduct.foodType === 'vegetable' ? '蔬菜' :
- selectedProduct.foodType === 'fruit' ? '水果' :
- selectedProduct.foodType === 'meat' ? '肉类' :
- selectedProduct.foodType === 'seafood' ? '海鲜' : '加工食品' }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="产地">{{ selectedProduct.origin }}</el-descriptions-item>
- <el-descriptions-item label="营养价值">{{ selectedProduct.nutrition }}</el-descriptions-item>
- <el-descriptions-item label="图片尺寸">{{ selectedProduct.size }}</el-descriptions-item>
- <el-descriptions-item label="设计风格">{{ selectedProduct.style }}</el-descriptions-item>
- <el-descriptions-item label="生成状态">
- <el-tag
- :type="selectedProduct.status === 'success' ? 'success' :
- selectedProduct.status === 'generating' ? 'warning' : 'danger'"
- >
- {{ selectedProduct.status === 'success' ? '已生成' :
- selectedProduct.status === 'generating' ? '生成中' : '生成失败' }}
- </el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="创建时间" :span="2">{{ selectedProduct.createTime }}</el-descriptions-item>
- </el-descriptions>
- </div>
-
- <div class="detail-section">
- <h3>提示词信息</h3>
- <el-input
- v-model="selectedProduct.prompt"
- type="textarea"
- :rows="4"
- readonly
- style="background-color: #f5f7fa"
- />
- </div>
-
- <div class="detail-section">
- <h3>生成结果</h3>
- <div class="generated-image">
- <el-image
- v-if="selectedProduct.generatedImage"
- :src="selectedProduct.generatedImage"
- fit="contain"
- style="max-width: 100%; max-height: 400px"
- >
- <template #error>
- <div class="image-error">图片加载失败</div>
- </template>
- </el-image>
- <el-empty v-else description="暂无生成图片" />
- </div>
- </div>
- </div>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import {ref,reactive,onMounted} from 'vue'
- import {ElMessage,ElMessageBox,ElEmpty,ElImage} from 'element-plus'
- import {Loading} from '@element-plus/icons-vue'
- import {useUserStore} from '@/pinia/modules/user'
- // 假设存在获取产品列表的API,需要根据实际情况修改
- // import {getProductListApi, deleteProductApi} from '@/api/mes/product'
- // 定义组件名称
- defineOptions({name: 'Category'})
- // 搜索表单
- const searchForm = reactive({
- productName: '',
- foodType: '',
- status: ''
- })
- // 食品列表数据
- const productList = ref([])
- // 分页信息
- const pagination = reactive({
- currentPage: 1,
- pageSize: 10,
- total: 0
- })
- // 加载状态
- const loading = ref(false)
- // 详情对话框
- const detailDialogVisible = ref(false)
- const selectedProduct = ref(null)
- // 模拟食品数据
- const mockProducts = [
- {
- id: 1,
- productName: '有机胡萝卜',
- foodType: 'vegetable',
- origin: '山东寿光',
- nutrition: '富含胡萝卜素、维生素A',
- size: '1024x1024',
- style: 'realistic',
- status: 'success',
- createTime: '2023-10-20 10:30:00',
- prompt: '创建一张有机胡萝卜的宣传图片,展示新鲜的有机胡萝卜,背景使用自然土壤色调,突出健康、有机的主题。',
- generatedImage: 'https://picsum.photos/seed/carrot1/1024/1024'
- },
- {
- id: 2,
- productName: '挪威三文鱼',
- foodType: 'seafood',
- origin: '挪威',
- nutrition: '富含Omega-3脂肪酸、蛋白质',
- size: '1024x1024',
- style: 'realistic',
- status: 'success',
- createTime: '2023-10-21 11:45:00',
- prompt: '设计一张挪威三文鱼的宣传海报,展示新鲜的三文鱼片,背景使用海洋元素,突出其新鲜和营养价值。',
- generatedImage: 'https://picsum.photos/seed/salmon1/1024/1024'
- },
- {
- id: 3,
- productName: '原味鱼干',
- foodType: 'processed',
- origin: '福建厦门',
- nutrition: '富含蛋白质、钙、磷',
- size: '1024x1024',
- style: 'realistic',
- status: 'success',
- createTime: '2023-10-23 09:00:00',
- prompt: '创建一张原味鱼干的宣传图片,展示自然晾晒的鱼干,背景使用海边场景,突出其新鲜和传统工艺。',
- generatedImage: 'https://images.unsplash.com/photo-1610486295123-078299c50e79?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1024&q=80'
- }
- ]
- // 获取食品列表
- const getProductList = async () => {
- loading.value = true
- try {
- // 实际项目中这里应该调用API获取数据
- // const res = await getProductListApi({
- // page: pagination.currentPage,
- // pageSize: pagination.pageSize,
- // productName: searchForm.productName,
- // foodType: searchForm.foodType,
- // status: searchForm.status
- // })
-
- // 模拟API调用
- await new Promise(resolve => setTimeout(resolve, 500))
-
- // 模拟筛选数据
- let filteredProducts = [...mockProducts]
- if (searchForm.productName) {
- filteredProducts = filteredProducts.filter(p => p.productName.includes(searchForm.productName))
- }
- if (searchForm.foodType) {
- filteredProducts = filteredProducts.filter(p => p.foodType === searchForm.foodType)
- }
- if (searchForm.status) {
- filteredProducts = filteredProducts.filter(p => p.status === searchForm.status)
- }
-
- productList.value = filteredProducts
- pagination.total = filteredProducts.length
-
- ElMessage({ message: '获取食品列表成功', type: 'success' })
- } catch (error) {
- console.error('获取食品列表失败:', error)
- ElMessage({ message: '获取食品列表失败', type: 'error' })
- } finally {
- loading.value = false
- }
- }
- // 重置搜索
- const resetSearch = () => {
- searchForm.productName = ''
- searchForm.foodType = ''
- searchForm.status = ''
- pagination.currentPage = 1
- getProductList()
- }
- // 分页处理
- const handleSizeChange = (size) => {
- pagination.pageSize = size
- pagination.currentPage = 1
- getProductList()
- }
- const handleCurrentChange = (current) => {
- pagination.currentPage = current
- getProductList()
- }
- // 查看产品详情
- const viewProduct = (product) => {
- selectedProduct.value = {...product}
- detailDialogVisible.value = true
- }
- // 处理行点击
- const handleRowClick = (row) => {
- viewProduct(row)
- }
- // 删除产品
- const deleteProduct = (id) => {
- ElMessageBox.confirm('确定要删除该产品吗?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(async () => {
- try {
- // 实际项目中这里应该调用API删除数据
- // await deleteProductApi(id)
-
- // 模拟API调用
- await new Promise(resolve => setTimeout(resolve, 300))
-
- // 从列表中移除
- const index = productList.value.findIndex(p => p.id === id)
- if (index > -1) {
- productList.value.splice(index, 1)
- pagination.total--
- }
-
- ElMessage({ message: '删除成功', type: 'success' })
- } catch (error) {
- console.error('删除失败:', error)
- ElMessage({ message: '删除失败', type: 'error' })
- }
- }).catch(() => {
- // 取消删除
- })
- }
- // 处理详情对话框关闭
- const handleDetailClose = () => {
- detailDialogVisible.value = false
- selectedProduct.value = null
- }
- // 页面挂载时获取产品列表
- onMounted(() => {
- getProductList()
- })
- </script>
- <style scoped>
- .product-category {
- padding: 20px;
- }
- .card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .search-filter {
- margin-bottom: 20px;
- }
- .product-list {
- margin-top: 20px;
- }
- .pagination {
- margin-top: 20px;
- text-align: right;
- }
- .product-detail {
- padding: 10px 0;
- }
- .detail-section {
- margin-bottom: 25px;
- }
- .detail-section h3 {
- margin-bottom: 15px;
- font-size: 16px;
- font-weight: 600;
- color: #303133;
- border-bottom: 1px solid #ebeef5;
- padding-bottom: 5px;
- }
- .generated-image {
- margin-top: 10px;
- padding: 20px;
- background-color: #fafafa;
- border-radius: 8px;
- text-align: center;
- }
- .image-error {
- display: flex;
- justify-content: center;
- align-items: center;
- width: 100%;
- height: 200px;
- background-color: #f5f7fa;
- color: #909399;
- }
- </style>
|