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

View File

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

View File

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