Commit 049bef0f by lijiabin

【需求 23684】feat: 优化竞拍管理和出价校验

parent dacd3221
...@@ -2,6 +2,7 @@ import service from '@/utils/request/index' ...@@ -2,6 +2,7 @@ import service from '@/utils/request/index'
import type { import type {
BackendAuctionListSearchParams, BackendAuctionListSearchParams,
BackendAuctionListItemDto, BackendAuctionListItemDto,
BackendDeleteAuctionDto,
BackendAddOrUpdateAuctionItemDto, BackendAddOrUpdateAuctionItemDto,
BackendAuctionRecordItemDto, BackendAuctionRecordItemDto,
BackendLotteryPrizeListSearchParams, BackendLotteryPrizeListSearchParams,
...@@ -44,11 +45,11 @@ export const addOrUpdateAuctionItem = (data: BackendAddOrUpdateAuctionItemDto) = ...@@ -44,11 +45,11 @@ export const addOrUpdateAuctionItem = (data: BackendAddOrUpdateAuctionItemDto) =
/** /**
* 删除竞拍物品数据 * 删除竞拍物品数据
*/ */
export const deleteAuction = (idList: number[]) => { export const deleteAuction = (data: BackendDeleteAuctionDto) => {
return service.request({ return service.request({
url: 'api/cultureAuctionItems/deleteAuction', url: 'api/cultureAuctionItems/deleteAuction',
method: 'POST', method: 'POST',
data: { idList }, data,
}) })
} }
......
...@@ -36,8 +36,14 @@ export interface BackendAuctionListItemDto extends PageSearchParams { ...@@ -36,8 +36,14 @@ export interface BackendAuctionListItemDto extends PageSearchParams {
remainingTime: string remainingTime: string
} }
export interface BackendDeleteAuctionDto {
idList: number[]
confirmDelete: boolean
}
export interface BackendAddOrUpdateAuctionItemDto { export interface BackendAddOrUpdateAuctionItemDto {
id?: number id?: number
status?: AuctionStatusEnum
name: string name: string
quantity: number quantity: number
specification: string specification: string
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<div class="w-750px flex items-center gap-3"> <div class="w-750px flex items-center gap-3">
<el-select v-model="searchParams.itemType" placeholder="选择商品类型" clearable> <el-select v-model="searchParams.itemType" placeholder="选择商品类型" clearable>
<el-option label="亚声实物" :value="ShopGoodsTypeEnum.REAL_GOODS" /> <el-option label="亚声实物" :value="ShopGoodsTypeEnum.REAL_GOODS" />
<el-option label="虚拟装饰" :value="ShopGoodsTypeEnum.VIRTUAL_GOODS" /> <el-option label="虚拟商品" :value="ShopGoodsTypeEnum.VIRTUAL_GOODS" />
</el-select> </el-select>
<el-date-picker <el-date-picker
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
<el-table-column prop="itemType" label="商品类型" width="100" align="center"> <el-table-column prop="itemType" label="商品类型" width="100" align="center">
<template #default="scope"> <template #default="scope">
{{ scope.row.itemType === ShopGoodsTypeEnum.REAL_GOODS ? '亚声实物' : '虚拟装饰' }} {{ scope.row.itemType === ShopGoodsTypeEnum.REAL_GOODS ? '亚声实物' : '虚拟商品' }}
</template> </template>
</el-table-column> </el-table-column>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<div class="w-750px flex items-center gap-3"> <div class="w-750px flex items-center gap-3">
<!-- <el-select v-model="searchParams.type" placeholder="选择商品类型" clearable> <!-- <el-select v-model="searchParams.type" placeholder="选择商品类型" clearable>
<el-option label="亚声实物" :value="ShopGoodsTypeEnum.REAL_GOODS" /> <el-option label="亚声实物" :value="ShopGoodsTypeEnum.REAL_GOODS" />
<el-option label="虚拟装饰" :value="ShopGoodsTypeEnum.VIRTUAL_GOODS" /> <el-option label="虚拟商品" :value="ShopGoodsTypeEnum.VIRTUAL_GOODS" />
</el-select> --> </el-select> -->
<el-date-picker <el-date-picker
......
...@@ -175,10 +175,17 @@ const onBid = async (item: AuctionItemDto) => { ...@@ -175,10 +175,17 @@ const onBid = async (item: AuctionItemDto) => {
} else { } else {
if (val.value > yabiData.value.currentValue) return push.error('您的YA币余额不足') if (val.value > yabiData.value.currentValue) return push.error('您的YA币余额不足')
// 如果还没有出价 只需要出价大于等于起拍价
if(data.currentPrice === 0) {
if(val.value<data.startingPrice) return push.error(
`出价必须大于等于起拍价: 至少【${data.startingPrice}】YA币`,
)
}else{
if (val.value < data.minIncrement + (data.currentPrice || data.startingPrice)) if (val.value < data.minIncrement + (data.currentPrice || data.startingPrice))
return push.error( return push.error(
`出价必须大于等于前最高出价+最低加价幅度: 至少【${data.minIncrement + (data.currentPrice || data.startingPrice)}】YA币`, `出价必须大于等于前最高出价+最低加价幅度: 至少【${data.minIncrement + (data.currentPrice || data.startingPrice)}】YA币`,
) )
}
instance.confirmButtonLoading = true instance.confirmButtonLoading = true
instance.confirmButtonText = 'Loading...' instance.confirmButtonText = 'Loading...'
......
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
{{ {{
// 未展示的时候不展示竞拍状态 // 未展示的时候不展示竞拍状态
row.isDisplay === 0 row.isDisplay === 0
? '' ? '未展示在前台时不展示竞拍状态'
: auctionStatusListOptions.find((item) => item.value === row.status)?.label : auctionStatusListOptions.find((item) => item.value === row.status)?.label
}} }}
</template> </template>
...@@ -195,6 +195,17 @@ ...@@ -195,6 +195,17 @@
inactive-text="否" inactive-text="否"
/> />
</el-form-item> </el-form-item>
<el-form-item v-if="form.id" label="竞拍状态" prop="status">
<el-select v-model="form.status" placeholder="请选择竞拍状态" class="w-60%!">
<el-option
v-for="item in editAuctionStatusOptions"
:key="item.value"
:label="item.label"
:value="item.value"
:disabled="item.disabled"
/>
</el-select>
</el-form-item>
</el-form> </el-form>
</el-scrollbar> </el-scrollbar>
<template #footer> <template #footer>
...@@ -221,7 +232,7 @@ import { ...@@ -221,7 +232,7 @@ import {
} from '@/api/backend' } from '@/api/backend'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import type { BackendAuctionListItemDto, BackendAddOrUpdateAuctionItemDto } from '@/api/backend' import type { BackendAuctionListItemDto, BackendAddOrUpdateAuctionItemDto } from '@/api/backend'
import { auctionStatusListOptions } from '@/constants' import { AuctionStatusEnum, auctionStatusListOptions } from '@/constants'
import UploadFile from '@/components/common/UploadFile/index.vue' import UploadFile from '@/components/common/UploadFile/index.vue'
import AuctionRecordDialog from './components/auctionRecordDialog.vue' import AuctionRecordDialog from './components/auctionRecordDialog.vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
...@@ -253,19 +264,45 @@ const [form, resetForm] = useResetData<BackendAddOrUpdateAuctionItemDto>({ ...@@ -253,19 +264,45 @@ const [form, resetForm] = useResetData<BackendAddOrUpdateAuctionItemDto>({
isDisplay: 0, isDisplay: 0,
startTime: '', startTime: '',
endTime: '', endTime: '',
status: undefined,
})
// 可编辑的 竞拍状态 只可以选择 「竞拍成功 / 已流拍」
const editAuctionStatusOptions = computed(() => {
const options = auctionStatusListOptions
.filter((item) =>
[AuctionStatusEnum.AUCTION_SUCCESS, AuctionStatusEnum.AUCTION_FAILED].includes(item.value),
)
.map((item) => ({
...item,
disabled: false,
}))
const hasCurrentStatus = options.some((item) => item.value === form.value.status)
if (form.value.status !== undefined && !hasCurrentStatus) {
const currentStatus = auctionStatusListOptions.find((item) => item.value === form.value.status)
options.unshift({
label: currentStatus?.label || `未知状态(${form.value.status})`,
value: form.value.status,
disabled: true,
})
}
return options
}) })
// 表单验证规则 // 表单验证规则
const formRules: FormRules = { const formRules: FormRules = {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }], name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
description: [{ required: true, message: '请输入介绍内容', trigger: 'blur' }], description: [{ required: true, message: '请输入介绍内容', trigger: 'blur' }],
quantity: [{ required: true, message: '请输入数量', trigger: 'blur' }], quantity: [{ required: true, message: '请输入数量', trigger: 'blur' }],
specification: [{ required: true, message: '请输入规格', trigger: 'blur' }], // specification: [{ required: true, message: '请输入规格', trigger: 'blur' }],
startingPrice: [{ required: true, message: '请输入起拍价', trigger: 'blur' }], startingPrice: [{ required: true, message: '请输入起拍价', trigger: 'blur' }],
minIncrement: [{ required: true, message: '请输入最低加价幅度', trigger: 'blur' }], minIncrement: [{ required: true, message: '请输入最低加价幅度', trigger: 'blur' }],
bidLimit: [{ required: true, message: '请输入竞拍次数上限', trigger: 'blur' }], bidLimit: [{ required: true, message: '请输入竞拍次数上限', trigger: 'blur' }],
startTime: [{ required: true, message: '请选择竞拍时间', trigger: 'change' }], startTime: [{ required: true, message: '请选择竞拍时间', trigger: 'change' }],
isDisplay: [{ required: true, message: '请选择是否展示在前台', trigger: 'blur' }], isDisplay: [{ required: true, message: '请选择是否展示在前台', trigger: 'blur' }],
imageUrl: [{ required: true, message: '请上传图片', trigger: 'change' }], imageUrl: [{ required: true, message: '请上传图片', trigger: 'change' }],
status: [{ required: true, message: '请选择竞拍状态', trigger: 'change' }],
} }
const dateRange = computed({ const dateRange = computed({
get() { get() {
...@@ -304,21 +341,18 @@ const handleEdit = (row: BackendAddOrUpdateAuctionItemDto) => { ...@@ -304,21 +341,18 @@ const handleEdit = (row: BackendAddOrUpdateAuctionItemDto) => {
// 删除 // 删除
const handleDelete = async (row: BackendAuctionListItemDto) => { const handleDelete = async (row: BackendAuctionListItemDto) => {
const confirmDelete = row.currentPrice > 0
await confirm({ await confirm({
title: '提示', title: '提示',
message: `确定要删除竞拍物品"${row.name}"吗?`, message: confirmDelete
? '该竞拍已有人出价,是否确定删除?删除后无法恢复,并会同步删除竞拍者的记录'
: `确定要删除竞拍物品"${row.name}"吗?`,
type: 'danger', type: 'danger',
}) })
try {
await deleteAuction([row.id]) await deleteAuction({ idList: [row.id], confirmDelete })
refresh() refresh()
push.success('删除成功') push.success('删除成功')
refresh()
} catch (error) {
if (error !== 'cancel') {
push.error('删除失败')
}
}
} }
// 提交表单 // 提交表单
...@@ -384,13 +418,42 @@ const handleBatchShow = async () => { ...@@ -384,13 +418,42 @@ const handleBatchShow = async () => {
} }
const handleBatchDelete = async () => { const handleBatchDelete = async () => {
const bidRows = selectedRows.value.filter((item) => item.currentPrice > 0)
const unbidRows = selectedRows.value.filter((item) => item.currentPrice === 0)
const formatNames = (rows: BackendAuctionListItemDto[]) =>
rows.map((item) => `【${item.name}】`).join('')
let message = `确定要删除竞拍物品${formatNames(unbidRows)}吗?`
if (bidRows.length && unbidRows.length) {
message = `其中${formatNames(bidRows)}这些竞拍已有人出价,是否确定删除?删除后无法恢复,并会同步删除竞拍者的记录,其余${formatNames(unbidRows)}未出价会正常删除,确定删除吗?`
} else if (bidRows.length) {
message = `${formatNames(bidRows)}这些竞拍已有人出价,是否确定删除?删除后无法恢复,并会同步删除竞拍者的记录,确定删除吗?`
}
await confirm({ await confirm({
title: '提示', title: '提示',
message: '确定要删除这些竞拍物品吗?', message,
type: 'danger', type: 'danger',
}) })
await deleteAuction(selectedRows.value.map((item) => item.id)) if (unbidRows.length && bidRows.length) {
await Promise.all([
deleteAuction({
idList: unbidRows.map((item) => item.id),
confirmDelete: false,
}),
deleteAuction({
idList: bidRows.map((item) => item.id),
confirmDelete: true,
}),
])
} else {
const rows = bidRows.length ? bidRows : unbidRows
await deleteAuction({
idList: rows.map((item) => item.id),
confirmDelete: bidRows.length > 0,
})
}
refresh() refresh()
push.success('删除成功') push.success('删除成功')
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment