<script setup lang="ts"> import { ref, reactive, onMounted, watch } from "vue"; import { ElMessage, FormRules } from "element-plus"; import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { addGoodsApi, GoodsDTO } from "@/api/shop/goods"; import { CategoryDTO, getCategoryAllApi } from "@/api/shop/category"; import Confirm from "@iconify-icons/ep/check"; import Upload from "@iconify-icons/ep/upload"; const { VITE_APP_BASE_API } = import.meta.env; const props = defineProps({ visible: { type: Boolean, default: false } }); const emit = defineEmits(["update:visible", "refresh"]); const formRef = ref(); const formData = reactive<GoodsDTO>({ goodsName: "", price: 0, stock: 0, status: 1, autoApproval: 0, categoryId: 0, goodsDetail: "", coverImg: "", usageInstruction: "" }); const rules = reactive<FormRules>({ goodsName: [{ required: true, message: "商品名称必填", trigger: "blur" }], price: [ { required: true, message: "价格必填", trigger: "blur" }, { type: 'number', min: 0, message: '价格不能小于0' } ], stock: [ { required: true, message: "库存必填", trigger: "blur" }, { type: 'number', min: 0, message: '库存不能小于0' } ], coverImg: [ { required: true, message: "请上传商品封面图", trigger: "change" } ] }); const handleConfirm = async () => { try { await formRef.value.validate(); await addGoodsApi(formData); ElMessage.success("商品添加成功"); emit("refresh"); closeDialog(); } catch (error) { console.error("表单验证失败", error); } }; const closeDialog = () => { formRef.value.resetFields(); emit("update:visible", false); }; // 在原有响应式数据后添加分类数据 const categoryOptions = ref<Array<CategoryDTO>>([]); // 加载分类数据 const loadCategories = async () => { try { const { data } = await getCategoryAllApi(); categoryOptions.value = data; if (data.length > 0) { formData.categoryId = data[0].categoryId; } } catch (e) { console.error("分类加载失败", e); } }; const handleAvatarSuccess = (response, uploadFile) => { // 这里根据实际API响应结构调整 formData.coverImg = response.data.url; }; const beforeAvatarUpload = (rawFile) => { if (!['image/jpeg', 'image/png'].includes(rawFile.type)) { ElMessage.error('封面图必须是 JPG/PNG 格式!') return false } if (rawFile.size > 50 * 1024 * 1024) { ElMessage.error('封面图大小不能超过 50MB!') return false } return true }; </script> <template> <el-dialog title="新增商品" :model-value="visible" width="600px" @close="closeDialog" @open="loadCategories"> <el-form ref="formRef" :model="formData" :rules="rules" label-width="80px" label-position="right"> <el-form-item label="商品名称" prop="goodsName"> <el-input v-model="formData.goodsName" placeholder="请输入商品名称" clearable /> </el-form-item> <el-form-item label="封面图" prop="coverImg"> <el-upload class="avatar-uploader" :action="VITE_APP_BASE_API + '/file/upload'" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"> <img v-if="formData.coverImg" :src="formData.coverImg" class="avatar" /> <el-icon v-else class="avatar-uploader-icon"> <Icon :icon="Upload" /> </el-icon> </el-upload> </el-form-item> <el-form-item label="价格" prop="price"> <el-input-number v-model="formData.price" :min="0" :precision="2" controls-position="right" /> </el-form-item> <el-form-item label="库存" prop="stock"> <el-input-number v-model="formData.stock" :min="0" controls-position="right" /> </el-form-item> <!-- 在状态表单项前添加分类选择 --> <el-form-item label="商品分类" prop="categoryId"> <el-select v-model="formData.categoryId" placeholder="请选择商品分类" clearable class="w-full"> <el-option v-for="category in categoryOptions" :key="category.categoryId" :label="category.categoryName" :value="category.categoryId" /> </el-select> </el-form-item> <el-form-item label="自动审批" prop="autoApproval"> <el-switch v-model="formData.autoApproval" :active-value="1" :inactive-value="0" active-text="启用" inactive-text="关闭" /> </el-form-item> <el-form-item label="状态" prop="status"> <el-radio-group v-model="formData.status"> <el-radio :label="1">上架</el-radio> <el-radio :label="2">下架</el-radio> </el-radio-group> </el-form-item> <el-form-item label="使用说明" prop="usageInstruction"> <el-input v-model="formData.usageInstruction" type="textarea" :rows="3" placeholder="请输入商品使用说明" /> </el-form-item> </el-form> <template #footer> <el-button @click="closeDialog">取消</el-button> <el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm"> 确认 </el-button> </template> </el-dialog> </template> <style scoped> .avatar-uploader { :deep(.el-upload) { border: 1px dashed var(--el-border-color); border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; transition: var(--el-transition-duration-fast); &:hover { border-color: var(--el-color-primary); } } } .avatar { width: 178px; height: 178px; display: block; } </style>