This commit is contained in:
zpc 2026-02-06 07:48:27 +08:00
parent 8a36e8c2ac
commit af6d00316b
3 changed files with 104 additions and 20 deletions

View File

@ -257,8 +257,10 @@ export interface PrizeItem {
rewardId: string | null
doubling: number
isLingzhu: number
goodsListId: number // 父奖品ID0表示父奖品>0表示子奖品
createdAt: string | null
updatedAt: string
children?: PrizeItem[] // 子奖品列表(前端构建树形结构用)
}
/** 创建奖品请求 */
@ -283,6 +285,7 @@ export interface PrizeCreateRequest {
rewardId?: string
doubling: number
isLingzhu: number
goodsListId?: number // 父奖品ID添加宝箱子奖品时使用
}
/** 更新奖品请求 */

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
v-model="dialogVisible"
title="新增奖品"
:title="dialogTitle"
width="800px"
:close-on-click-modal="false"
@close="handleClose"
@ -260,9 +260,14 @@ interface Props {
modelValue: boolean
goodsId: number
goodsType: number
parentPrizeId?: number // ID使
parentPrizeTitle?: string //
}
const props = defineProps<Props>()
const props = withDefaults(defineProps<Props>(), {
parentPrizeId: 0,
parentPrizeTitle: ''
})
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void
@ -274,6 +279,16 @@ const dialogVisible = computed({
set: (val) => emit('update:modelValue', val)
})
//
const isChildPrizeMode = computed(() => props.parentPrizeId > 0)
//
const dialogTitle = computed(() => {
return isChildPrizeMode.value
? `新增子奖品 - ${props.parentPrizeTitle}`
: '新增奖品'
})
const formRef = ref<FormInstance>()
const submitting = ref(false)
const prizeLevelOptions = ref<PrizeLevelOptionResponse[]>([])
@ -425,6 +440,7 @@ const handleSubmit = async () => {
rewardId: formData.rewardId || undefined,
doubling: formData.doubling,
isLingzhu: formData.isLingzhu,
goodsListId: props.parentPrizeId, // ID
}
await addPrize(props.goodsId, requestData)

View File

@ -28,7 +28,7 @@
<el-button type="warning" @click="handleDesignatedPrize">
<el-icon><Star /></el-icon>
</el-button>
<el-button type="primary" @click="handleAdd">
<el-button type="primary" @click="handleAdd()">
<el-icon><Plus /></el-icon>
</el-button>
<!-- 概率统计无限赏等类型显示 -->
@ -49,6 +49,7 @@
row-key="id"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
max-height="500px"
default-expand-all
>
<!-- ID -->
<el-table-column prop="id" label="ID" width="70" align="center" />
@ -75,7 +76,10 @@
<!-- 奖品名称 -->
<el-table-column prop="title" label="奖品名称" min-width="150">
<template #default="{ row }">
<div class="prize-title">{{ row.title }}</div>
<div class="prize-title">
<el-tag v-if="row.goodsListId > 0" type="info" size="small" style="margin-right: 4px;"></el-tag>
{{ row.title }}
</div>
</template>
</el-table-column>
@ -164,8 +168,17 @@
</el-table-column>
<!-- 操作 -->
<el-table-column label="操作" width="150" fixed="right" align="center">
<el-table-column label="操作" width="200" fixed="right" align="center">
<template #default="{ row }">
<!-- 宝箱类型奖品显示"子奖品"按钮 -->
<el-button
v-if="row.goodsType === PrizeCategory.BaoXiang && row.goodsListId === 0"
type="success"
link
@click="handleAddChildPrize(row)"
>
<el-icon><FolderAdd /></el-icon>
</el-button>
<el-button type="primary" link @click="handleEdit(row)">
<el-icon><Edit /></el-icon>
</el-button>
@ -185,6 +198,8 @@
v-model="addDialogVisible"
:goods-id="goodsId"
:goods-type="goodsType"
:parent-prize-id="currentParentPrizeId"
:parent-prize-title="currentParentPrizeTitle"
@success="handleRefresh"
/>
@ -209,7 +224,7 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Plus, Picture, Edit, Delete, Star } from '@element-plus/icons-vue'
import { Search, Plus, Picture, Edit, Delete, Star, FolderAdd } from '@element-plus/icons-vue'
import {
getGoodsPrizes,
updatePrize,
@ -250,6 +265,8 @@ const editDialogVisible = ref(false)
const designatedPrizeDialogVisible = ref(false)
const currentPrizeId = ref(0)
const currentPrizeData = ref<PrizeItem | undefined>(undefined)
const currentParentPrizeId = ref(0) // ID使
const currentParentPrizeTitle = ref('') //
// 使
const prizeColumnConfig = computed(() => getPrizeColumnConfig(props.goodsType))
@ -259,18 +276,56 @@ const showProbability = computed(() => prizeColumnConfig.value.showProbability)
const showDoubling = computed(() => prizeColumnConfig.value.showGiftMultiple)
const showLingzhu = computed(() => prizeColumnConfig.value.showIsLingzhu)
//
//
const probabilityTotal = computed(() => {
return prizeList.value.reduce((sum, item) => sum + (item.realPro || 0), 0)
return prizeList.value
.filter(item => (item.goodsListId ?? 0) === 0)
.reduce((sum, item) => sum + (item.realPro || 0), 0)
})
//
//
const buildTreePrizeList = (prizes: PrizeItem[]): PrizeItem[] => {
//
const parentPrizes = prizes.filter(p => (p.goodsListId ?? 0) === 0)
const childPrizes = prizes.filter(p => (p.goodsListId ?? 0) > 0)
//
return parentPrizes.map(parent => {
const children = childPrizes.filter(child => child.goodsListId === parent.id)
return {
...parent,
children: children.length > 0 ? children : undefined
}
})
}
//
const filteredPrizeList = computed(() => {
if (!searchTitle.value) return prizeList.value
const treeList = buildTreePrizeList(prizeList.value)
if (!searchTitle.value) return treeList
const keyword = searchTitle.value.toLowerCase()
return prizeList.value.filter(item =>
item.title.toLowerCase().includes(keyword)
)
//
return treeList.filter(item => {
const parentMatch = item.title.toLowerCase().includes(keyword)
const childMatch = item.children?.some(child =>
child.title.toLowerCase().includes(keyword)
)
return parentMatch || childMatch
}).map(item => {
if (item.children) {
return {
...item,
children: item.children.filter(child =>
child.title.toLowerCase().includes(keyword) ||
item.title.toLowerCase().includes(keyword)
)
}
}
return item
})
})
//
@ -298,11 +353,18 @@ const handleReset = () => {
searchTitle.value = ''
}
//
const handleAdd = () => {
// ID
const handleAdd = (parentPrizeId: number = 0, parentPrizeTitle: string = '') => {
currentParentPrizeId.value = parentPrizeId
currentParentPrizeTitle.value = parentPrizeTitle
addDialogVisible.value = true
}
//
const handleAddChildPrize = (parentPrize: PrizeItem) => {
handleAdd(parentPrize.id, parentPrize.title)
}
//
const handleDesignatedPrize = () => {
designatedPrizeDialogVisible.value = true
@ -317,12 +379,13 @@ const handleEdit = (row: PrizeItem) => {
//
const handleDelete = async (row: PrizeItem) => {
const hasChildren = row.children && row.children.length > 0
const confirmMsg = hasChildren
? `确定要删除宝箱奖品 "${row.title}" 及其所有子奖品吗?删除后不可恢复!`
: `确定要删除奖品 "${row.title}" 吗?删除后不可恢复!`
try {
await ElMessageBox.confirm(
`确定要删除奖品 "${row.title}" 吗?删除后不可恢复!`,
'删除确认',
{ type: 'warning' }
)
await ElMessageBox.confirm(confirmMsg, '删除确认', { type: 'warning' })
await deletePrize(row.id)
ElMessage.success('删除成功')
fetchPrizes()
@ -423,6 +486,8 @@ const handleOpen = () => {
const handleClose = () => {
searchTitle.value = ''
prizeList.value = []
currentParentPrizeId.value = 0
currentParentPrizeTitle.value = ''
emit('update:modelValue', false)
}