增加商品功能完成。

This commit is contained in:
aaron 2025-01-12 00:16:33 +08:00
parent 364c4c069b
commit a3a6fb1d05

View File

@ -3,6 +3,7 @@
<div class="product-list">
<div class="table-header">
<h1>商品列表</h1>
<a-button type="primary" @click="showAddModal">添加商品</a-button>
</div>
<!-- 过滤区域 -->
@ -67,20 +68,131 @@
</template>
</template>
</a-table>
<!-- 添加商品模态框 -->
<a-modal
v-model:visible="addModalVisible"
title="添加商品"
:confirmLoading="confirmLoading"
width="600px"
@cancel="handleCancel"
>
<template #footer>
<a-space>
<a-button @click="handleCancel">取消</a-button>
<a-button type="primary" :loading="confirmLoading" @click="handleAdd">
保存
</a-button>
</a-space>
</template>
<a-form
ref="formRef"
:model="formState"
:rules="rules"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 16 }"
>
<a-form-item label="所属商家" name="merchant_id" required>
<a-select
v-model:value="formState.merchant_id"
placeholder="请选择商家"
:options="merchantOptions"
:field-names="{ label: 'name', value: 'id' }"
/>
</a-form-item>
<a-form-item label="商品名称" name="name" required>
<a-input v-model:value="formState.name" placeholder="请输入商品名称" />
</a-form-item>
<a-form-item label="商品图片" name="image_url" required>
<div class="upload-wrapper">
<div v-if="formState.image_url" class="image-preview">
<img :src="formState.image_url" alt="商品图片" />
<div class="image-actions">
<a-button type="link" danger @click="handleRemoveImage">删除</a-button>
</div>
</div>
<a-upload
v-else
name="files"
:customRequest="handleUpload"
:show-upload-list="false"
accept="image/*"
>
<a-button>
<upload-outlined />
上传图片
</a-button>
</a-upload>
</div>
</a-form-item>
<a-form-item label="商品原价" name="product_price" required>
<a-input-number
v-model:value="formState.product_price"
:min="0"
:precision="2"
style="width: 100%"
placeholder="请输入商品原价"
/>
</a-form-item>
<a-form-item label="销售价格" name="sale_price" required>
<a-input-number
v-model:value="formState.sale_price"
:min="0"
:precision="2"
style="width: 100%"
placeholder="请输入销售价格"
/>
</a-form-item>
<a-form-item label="结算价格" name="settlement_amount" required>
<a-input-number
v-model:value="formState.settlement_amount"
:min="0"
:precision="2"
style="width: 100%"
placeholder="请输入结算价格"
/>
</a-form-item>
<a-form-item label="标签" name="tags">
<a-input v-model:value="formState.tags" placeholder="多个标签用逗号分隔" />
</a-form-item>
<a-form-item label="最高抵扣消费金" name="max_deduct_points" required>
<a-input-number
v-model:value="formState.max_deduct_points"
:min="0"
:precision="0"
style="width: 100%"
placeholder="请输入最高抵扣消费金"
/>
</a-form-item>
</a-form>
</a-modal>
</div>
</page-container>
</template>
<script>
import { defineComponent, ref, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import { message, Upload, InputNumber, Tag } from 'ant-design-vue'
import { UploadOutlined } from '@ant-design/icons-vue'
import PageContainer from '@/components/PageContainer.vue'
import { getMerchantProducts } from '@/api/merchant'
import request from '@/utils/request'
export default defineComponent({
components: {
PageContainer
PageContainer,
UploadOutlined,
AUpload: Upload,
AInputNumber: InputNumber,
ATag: Tag
},
setup() {
const loading = ref(false)
@ -221,6 +333,106 @@ export default defineComponent({
console.log('修改商品:', record)
}
//
const addModalVisible = ref(false)
const confirmLoading = ref(false)
const formRef = ref(null)
const formState = ref({
merchant_id: undefined,
name: '',
image_url: '',
product_price: null,
sale_price: null,
settlement_amount: null,
tags: '',
max_deduct_points: null
})
const rules = {
merchant_id: [{ required: true, message: '请选择所属商家' }],
name: [{ required: true, message: '请输入商品名称' }],
image_url: [{ required: true, message: '请上传商品图片' }],
product_price: [{ required: true, message: '请输入商品原价' }],
sale_price: [{ required: true, message: '请输入销售价格' }],
settlement_amount: [{ required: true, message: '请输入结算价格' }],
max_deduct_points: [{ required: true, message: '请输入最高抵扣消费金' }]
}
//
const showAddModal = () => {
addModalVisible.value = true
}
//
const handleUpload = async ({ file, onSuccess, onError }) => {
const formData = new FormData()
formData.append('files', file)
try {
const res = await request.post('/api/upload/images', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
if (res.code === 200 && res.data && res.data.urls && res.data.urls.length > 0) {
formState.value.image_url = res.data.urls[0]
onSuccess()
message.success('上传成功')
} else {
throw new Error('上传失败')
}
} catch (error) {
console.error('上传图片失败:', error)
message.error('上传失败')
onError()
}
}
//
const handleRemoveImage = () => {
formState.value.image_url = ''
}
//
const handleAdd = () => {
formRef.value.validate().then(async () => {
try {
confirmLoading.value = true
const res = await request.post('/api/merchant/product', formState.value)
if (res.code === 200) {
message.success('添加成功')
addModalVisible.value = false
fetchData()
} else {
throw new Error(res.message || '添加失败')
}
} catch (error) {
console.error('添加商品失败:', error)
message.error(error.message || '添加失败')
} finally {
confirmLoading.value = false
}
})
}
//
const handleCancel = () => {
formRef.value?.resetFields()
formState.value = {
merchant_id: undefined,
name: '',
image_url: '',
product_price: null,
sale_price: null,
settlement_amount: null,
tags: '',
max_deduct_points: null
}
addModalVisible.value = false
}
onMounted(() => {
fetchMerchantOptions()
})
@ -234,7 +446,17 @@ export default defineComponent({
filterForm,
handleTableChange,
handleMerchantChange,
handleEdit
handleEdit,
addModalVisible,
confirmLoading,
formRef,
formState,
rules,
showAddModal,
handleUpload,
handleRemoveImage,
handleAdd,
handleCancel
}
}
})
@ -281,4 +503,37 @@ export default defineComponent({
:deep(.ant-tag) {
margin: 2px;
}
.upload-wrapper {
display: flex;
align-items: center;
}
.image-preview {
position: relative;
width: 104px;
height: 104px;
border-radius: 4px;
overflow: hidden;
}
.image-preview img {
width: 100%;
height: 100%;
object-fit: cover;
}
.image-actions {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.45);
padding: 4px 0;
text-align: center;
}
.image-actions .ant-btn {
color: #fff;
}
</style>