feat(product): 添加商品下架和多条件查询功能
- 实现了商品下架功能,下架后SKU库存变为0且链接失效 - 添加了支持多条件查询的商品列表功能 - 增加了包含商品名称、链接码、状态、发售地区等查询条件 - 在商品管理页面添加了查询表单界面 - 实现了下架按钮的禁用逻辑和状态显示 - 添加了移动端响应式查询表单适配 - 集成了API接口和错误处理机制
This commit is contained in:
@@ -65,3 +65,30 @@ export function uploadProductImage(file) {
|
|||||||
// 注意:不设置 Content-Type,让浏览器自动设置(包含 boundary)
|
// 注意:不设置 Content-Type,让浏览器自动设置(包含 boundary)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下架商品
|
||||||
|
* 下架后商品所有SKU库存改为0,链接失效无法再被访问
|
||||||
|
*/
|
||||||
|
export function offShelfProductById(id) {
|
||||||
|
return request({
|
||||||
|
url: `/product/${id}/off-shelf`,
|
||||||
|
method: 'put'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询商品列表(支持多条件查询)
|
||||||
|
* @param {Object} query - 查询条件
|
||||||
|
* @param {string} query.name - 商品名称(模糊查询)
|
||||||
|
* @param {string} query.linkCode - 商品链接码(精确查询)
|
||||||
|
* @param {string} query.status - 商品状态(ACTIVE-上架,INACTIVE-下架)
|
||||||
|
* @param {string} query.salesRegion - 发售地区(货币代码,如:MYR, PHP, THB, VND, SGD, CNY, USD等)
|
||||||
|
*/
|
||||||
|
export function queryProducts(query) {
|
||||||
|
return request({
|
||||||
|
url: '/product/query',
|
||||||
|
method: 'post',
|
||||||
|
data: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,69 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- 查询表单 -->
|
||||||
|
<el-card class="search-card" style="margin-bottom: 20px">
|
||||||
|
<el-form :model="queryForm" :inline="true" class="search-form">
|
||||||
|
<el-form-item label="商品名称">
|
||||||
|
<el-input
|
||||||
|
v-model="queryForm.name"
|
||||||
|
placeholder="请输入商品名称"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="链接码">
|
||||||
|
<el-input
|
||||||
|
v-model="queryForm.linkCode"
|
||||||
|
placeholder="请输入链接码"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品状态">
|
||||||
|
<el-select
|
||||||
|
v-model="queryForm.status"
|
||||||
|
placeholder="请选择状态"
|
||||||
|
clearable
|
||||||
|
style="width: 150px"
|
||||||
|
>
|
||||||
|
<el-option label="上架" value="ACTIVE" />
|
||||||
|
<el-option label="下架" value="INACTIVE" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="发售地区">
|
||||||
|
<el-select
|
||||||
|
v-model="queryForm.salesRegion"
|
||||||
|
placeholder="请选择地区"
|
||||||
|
clearable
|
||||||
|
style="width: 150px"
|
||||||
|
>
|
||||||
|
<el-option label="马来西亚" value="MYR" />
|
||||||
|
<el-option label="菲律宾" value="PHP" />
|
||||||
|
<el-option label="泰国" value="THB" />
|
||||||
|
<el-option label="越南" value="VND" />
|
||||||
|
<el-option label="新加坡" value="SGD" />
|
||||||
|
<el-option label="中国" value="CNY" />
|
||||||
|
<el-option label="美国" value="USD" />
|
||||||
|
<el-option label="欧洲" value="EUR" />
|
||||||
|
<el-option label="英国" value="GBP" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleQuery">
|
||||||
|
<el-icon><Search /></el-icon>
|
||||||
|
查询
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="handleReset">
|
||||||
|
<el-icon><Refresh /></el-icon>
|
||||||
|
重置
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
<!-- 商品列表 -->
|
<!-- 商品列表 -->
|
||||||
<el-table :data="productList" v-loading="loading" style="width: 100%">
|
<el-table :data="productList" v-loading="loading" style="width: 100%">
|
||||||
<!-- 商品封面图 -->
|
<!-- 商品封面图 -->
|
||||||
@@ -115,8 +178,14 @@
|
|||||||
<el-button type="success" link size="small" @click="copyProductUrl(row.id, row.productUrl)">
|
<el-button type="success" link size="small" @click="copyProductUrl(row.id, row.productUrl)">
|
||||||
复制
|
复制
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="danger" link size="small" @click="deleteProduct(row.id)">
|
<el-button
|
||||||
删除
|
type="danger"
|
||||||
|
link
|
||||||
|
size="small"
|
||||||
|
@click="offShelfProduct(row.id)"
|
||||||
|
:disabled="row.status === 'INACTIVE'"
|
||||||
|
>
|
||||||
|
{{ row.status === 'INACTIVE' ? '已下架' : '下架' }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -130,14 +199,22 @@
|
|||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus, User } from '@element-plus/icons-vue'
|
import { Plus, User, Search, Refresh } from '@element-plus/icons-vue'
|
||||||
import { getProductList, getProductUrl } from '../api/product'
|
import { getProductList, getProductUrl, offShelfProductById, queryProducts } from '../api/product'
|
||||||
import { formatAmount } from '../utils/helpers'
|
import { formatAmount } from '../utils/helpers'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const productList = ref([])
|
const productList = ref([])
|
||||||
|
|
||||||
|
// 查询表单
|
||||||
|
const queryForm = ref({
|
||||||
|
name: '',
|
||||||
|
linkCode: '',
|
||||||
|
status: '',
|
||||||
|
salesRegion: ''
|
||||||
|
})
|
||||||
|
|
||||||
// 跳转到新增商品页面
|
// 跳转到新增商品页面
|
||||||
const goToCreate = () => {
|
const goToCreate = () => {
|
||||||
router.push('/manage/product/create')
|
router.push('/manage/product/create')
|
||||||
@@ -191,7 +268,7 @@ const getSalesRegions = (row) => {
|
|||||||
return regions
|
return regions
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载商品列表
|
// 加载商品列表(无查询条件)
|
||||||
const loadProductList = async () => {
|
const loadProductList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
@@ -212,6 +289,57 @@ const loadProductList = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询商品列表
|
||||||
|
const handleQuery = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// 构建查询条件(只包含非空字段)
|
||||||
|
const query = {}
|
||||||
|
if (queryForm.value.name && queryForm.value.name.trim()) {
|
||||||
|
query.name = queryForm.value.name.trim()
|
||||||
|
}
|
||||||
|
if (queryForm.value.linkCode && queryForm.value.linkCode.trim()) {
|
||||||
|
query.linkCode = queryForm.value.linkCode.trim()
|
||||||
|
}
|
||||||
|
if (queryForm.value.status) {
|
||||||
|
query.status = queryForm.value.status
|
||||||
|
}
|
||||||
|
if (queryForm.value.salesRegion) {
|
||||||
|
query.salesRegion = queryForm.value.salesRegion
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await queryProducts(query)
|
||||||
|
if (response.code === '0000' && response.data) {
|
||||||
|
productList.value = response.data
|
||||||
|
if (productList.value.length === 0) {
|
||||||
|
ElMessage.info('未找到符合条件的商品')
|
||||||
|
} else {
|
||||||
|
ElMessage.success(`查询到 ${productList.value.length} 条商品`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.error(response.message || '查询商品列表失败')
|
||||||
|
productList.value = []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询商品列表失败:', error)
|
||||||
|
ElMessage.error('查询商品列表失败')
|
||||||
|
productList.value = []
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置查询条件
|
||||||
|
const handleReset = () => {
|
||||||
|
queryForm.value = {
|
||||||
|
name: '',
|
||||||
|
linkCode: '',
|
||||||
|
status: '',
|
||||||
|
salesRegion: ''
|
||||||
|
}
|
||||||
|
loadProductList()
|
||||||
|
}
|
||||||
|
|
||||||
// 编辑商品
|
// 编辑商品
|
||||||
const editProduct = (id) => {
|
const editProduct = (id) => {
|
||||||
// TODO: 实现编辑功能,跳转到编辑页面
|
// TODO: 实现编辑功能,跳转到编辑页面
|
||||||
@@ -259,24 +387,30 @@ const copyProductUrl = async (id, url) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除商品
|
// 下架商品
|
||||||
const deleteProduct = async (id) => {
|
const offShelfProduct = async (id) => {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm('确定要删除该商品吗?', '提示', {
|
await ElMessageBox.confirm(
|
||||||
|
'确定要下架该商品吗?下架后商品所有SKU库存将改为0,链接将失效无法再被访问。',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// TODO: 实现删除商品API
|
const response = await offShelfProductById(id)
|
||||||
ElMessage.info('删除功能待实现')
|
if (response.code === '0000') {
|
||||||
// await request.delete(`/api/product/${id}`)
|
ElMessage.success('商品下架成功')
|
||||||
// ElMessage.success('商品删除成功')
|
loadProductList()
|
||||||
// loadProductList()
|
} else {
|
||||||
|
ElMessage.error(response.message || '商品下架失败')
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error !== 'cancel') {
|
if (error !== 'cancel') {
|
||||||
console.error('删除商品失败:', error)
|
console.error('下架商品失败:', error)
|
||||||
ElMessage.error('删除商品失败')
|
ElMessage.error('下架商品失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,5 +501,35 @@ onMounted(() => {
|
|||||||
color: #c0c4cc;
|
color: #c0c4cc;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 查询表单 */
|
||||||
|
.search-card {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form .el-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.search-form {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form .el-form-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form .el-form-item .el-input,
|
||||||
|
.search-form .el-form-item .el-select {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user