feat(admin): 权益等级管理功能完善 - 添加新增/删除权益等级功能 - 隐藏奖品配置中的中奖概率字段

This commit is contained in:
zpc 2026-02-12 09:43:38 +08:00
parent 14ebb2221e
commit 0c93aa7d62
6 changed files with 124 additions and 91 deletions

View File

@ -203,6 +203,41 @@ export function updateQyLevel(id: number, data: QyLevelUpdateRequest): Promise<A
})
}
/** 权益等级创建请求 */
export interface QyLevelCreateRequest {
/** 等级 */
level: number
/** 等级名称 */
title: string
/** 所需欧气值 */
requiredPoints: number
}
/**
*
* @param data
* @returns ID
*/
export function createQyLevel(data: QyLevelCreateRequest): Promise<ApiResponse<{ id: number }>> {
return request({
url: QYLEVEL_BASE_URL,
method: 'post',
data
})
}
/**
*
* @param id ID
* @returns
*/
export function deleteQyLevel(id: number): Promise<ApiResponse<string>> {
return request({
url: `${QYLEVEL_BASE_URL}/${id}`,
method: 'delete'
})
}
// ==================== 权益等级奖品 API ====================
/**

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
v-model="dialogVisible"
title="编辑权益等级"
:title="isEdit ? '编辑权益等级' : '新增权益等级'"
width="500px"
:close-on-click-modal="false"
@close="handleClose"
@ -55,14 +55,17 @@
import { ref, reactive, computed, watch } from 'vue'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import {
createQyLevel,
updateQyLevel,
type QyLevelResponse,
type QyLevelCreateRequest,
type QyLevelUpdateRequest
} from '@/api/business/qylevel'
const props = defineProps<{
modelValue: boolean
level: QyLevelResponse | null
isEdit: boolean
}>()
const emit = defineEmits<{
@ -131,13 +134,18 @@ const formRules: FormRules = {
//
watch(() => props.modelValue, (visible) => {
if (visible && props.level) {
//
Object.assign(formData, {
level: props.level.level || 1,
title: props.level.title || '',
requiredPoints: props.level.requiredPoints || 0
})
if (visible) {
if (props.isEdit && props.level) {
//
Object.assign(formData, {
level: props.level.level || 1,
title: props.level.title || '',
requiredPoints: props.level.requiredPoints || 0
})
} else {
//
resetForm()
}
}
})
@ -179,22 +187,32 @@ const handleSubmit = async () => {
return
}
if (!props.level) {
ElMessage.error('未选择要编辑的等级')
return
}
submitLoading.value = true
try {
const submitData: QyLevelUpdateRequest = {
level: formData.level,
title: formData.title,
requiredPoints: formData.requiredPoints
if (props.isEdit) {
//
if (!props.level) {
ElMessage.error('未选择要编辑的等级')
return
}
const submitData: QyLevelUpdateRequest = {
level: formData.level,
title: formData.title,
requiredPoints: formData.requiredPoints
}
await updateQyLevel(props.level.id, submitData)
ElMessage.success('更新成功')
} else {
//
const submitData: QyLevelCreateRequest = {
level: formData.level,
title: formData.title,
requiredPoints: formData.requiredPoints
}
await createQyLevel(submitData)
ElMessage.success('创建成功')
}
await updateQyLevel(props.level.id, submitData)
ElMessage.success('更新成功')
emit('success')
handleClose()
} finally {

View File

@ -29,12 +29,6 @@
</template>
</el-table-column>
<el-table-column label="概率" width="80" align="center">
<template #default="{ row }">
<span class="probability-value">{{ row.probability ?? 0 }}%</span>
</template>
</el-table-column>
<el-table-column label="操作" width="130" align="center" fixed="right">
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">
@ -201,11 +195,6 @@ const handleClose = () => {
margin-bottom: 16px;
}
.probability-value {
color: #409eff;
font-weight: 500;
}
.pagination {
margin-top: 16px;
justify-content: flex-end;

View File

@ -39,20 +39,6 @@
style="width: 100%"
/>
</el-form-item>
<!-- 通用字段 -->
<el-form-item label="中奖概率" prop="probability">
<el-input-number
v-model="formData.probability"
:min="0"
:max="100"
:precision="2"
:step="0.1"
placeholder="请输入中奖概率"
style="width: 100%"
/>
<div class="form-tip">概率范围0-100最多2位小数</div>
</el-form-item>
</el-form>
<template #footer>
@ -107,43 +93,19 @@ const couponLoading = ref(false)
interface FormDataType {
couponId: number | undefined
quantity: number
probability: number
}
const formData = reactive<FormDataType>({
couponId: undefined,
quantity: 1,
probability: 0
quantity: 1
})
//
const probabilityValidator = (_rule: any, value: any, callback: any) => {
if (value === undefined || value === null || value === '') {
callback(new Error('请输入中奖概率'))
} else if (typeof value !== 'number') {
callback(new Error('概率必须为数字'))
} else if (value < 0 || value > 100) {
callback(new Error('概率必须在0-100之间'))
} else {
//
const decimalPart = value.toString().split('.')[1]
if (decimalPart && decimalPart.length > 2) {
callback(new Error('概率最多保留2位小数'))
} else {
callback()
}
}
}
//
const formRules = computed<FormRules>(() => ({
couponId: [{ required: true, message: '请选择优惠券', trigger: 'change' }],
quantity: [
{ required: true, message: '请输入数量', trigger: 'blur' },
{ type: 'number', min: 1, message: '数量必须大于0', trigger: 'blur' }
],
probability: [
{ required: true, validator: probabilityValidator, trigger: 'blur' }
]
}))
@ -170,8 +132,7 @@ watch(() => props.modelValue, (visible) => {
//
Object.assign(formData, {
couponId: props.prize.couponId,
quantity: props.prize.quantity || 1,
probability: props.prize.probability || 0
quantity: props.prize.quantity || 1
})
} else {
//
@ -184,8 +145,7 @@ watch(() => props.modelValue, (visible) => {
const resetForm = () => {
Object.assign(formData, {
couponId: undefined,
quantity: 1,
probability: 0
quantity: 1
})
formRef.value?.resetFields()
}
@ -206,19 +166,6 @@ const handleSubmit = async () => {
return
}
//
if (formData.probability < 0 || formData.probability > 100) {
ElMessage.error('概率必须在0-100之间')
return
}
//
const decimalPart = formData.probability.toString().split('.')[1]
if (decimalPart && decimalPart.length > 2) {
ElMessage.error('概率最多保留2位小数')
return
}
//
if (!formData.couponId) {
ElMessage.error('请选择优惠券')
@ -234,8 +181,7 @@ const handleSubmit = async () => {
const submitData: QyLevelPrizeCreateRequest | QyLevelPrizeUpdateRequest = {
type: QyLevelPrizeType.Coupon,
couponId: formData.couponId,
quantity: formData.quantity,
probability: formData.probability
quantity: formData.quantity
}
if (props.isEdit && props.prize) {

View File

@ -33,7 +33,7 @@
</template>
</el-table-column>
<el-table-column label="操作" width="150" align="center" fixed="right">
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">
编辑
@ -41,6 +41,9 @@
<el-button type="success" link size="small" @click="handlePrizes(row)">
奖品
</el-button>
<el-button type="danger" link size="small" @click="handleDelete(row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
@ -78,6 +81,7 @@ const emit = defineEmits<{
(e: 'size-change', size: number): void
(e: 'edit', row: QyLevelResponse): void
(e: 'prizes', row: QyLevelResponse): void
(e: 'delete', row: QyLevelResponse): void
}>()
const currentPage = ref(props.page)
@ -106,6 +110,10 @@ const handleEdit = (row: QyLevelResponse) => {
const handlePrizes = (row: QyLevelResponse) => {
emit('prizes', row)
}
const handleDelete = (row: QyLevelResponse) => {
emit('delete', row)
}
</script>
<style scoped>

View File

@ -4,6 +4,9 @@
<template #header>
<div class="card-header">
<span>权益等级管理</span>
<el-button type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
</el-button>
</div>
</template>
@ -38,6 +41,7 @@
@size-change="handleSizeChange"
@edit="handleEdit"
@prizes="handlePrizes"
@delete="handleDelete"
/>
</el-card>
@ -45,6 +49,7 @@
<QyLevelFormDialog
v-model="formDialogVisible"
:level="currentLevel"
:is-edit="isEdit"
@success="fetchData"
/>
@ -58,12 +63,14 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { Search, Refresh } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Refresh, Plus } from '@element-plus/icons-vue'
import QyLevelTable from './components/QyLevelTable.vue'
import QyLevelFormDialog from './components/QyLevelFormDialog.vue'
import QyLevelPrizeDialog from './components/QyLevelPrizeDialog.vue'
import {
getQyLevels,
deleteQyLevel,
type QyLevelListRequest,
type QyLevelResponse
} from '@/api/business/qylevel'
@ -84,6 +91,7 @@ const queryParams = reactive<QyLevelListRequest>({
const formDialogVisible = ref(false)
const prizeDialogVisible = ref(false)
const currentLevel = ref<QyLevelResponse | null>(null)
const isEdit = ref(false)
//
const fetchData = async () => {
@ -122,12 +130,36 @@ const handleSizeChange = (size: number) => {
fetchData()
}
//
const handleAdd = () => {
isEdit.value = false
currentLevel.value = null
formDialogVisible.value = true
}
//
const handleEdit = (row: QyLevelResponse) => {
isEdit.value = true
currentLevel.value = { ...row }
formDialogVisible.value = true
}
//
const handleDelete = async (row: QyLevelResponse) => {
try {
await ElMessageBox.confirm(
`确定要删除等级"${row.title}"吗?删除后不可恢复!`,
'删除确认',
{ type: 'warning' }
)
await deleteQyLevel(row.id)
ElMessage.success('删除成功')
fetchData()
} catch {
//
}
}
//
const handlePrizes = (row: QyLevelResponse) => {
currentLevel.value = { ...row }
@ -150,6 +182,11 @@ onMounted(() => {
align-items: center;
}
.card-header span {
font-size: 16px;
font-weight: 500;
}
.search-form {
margin-bottom: 16px;
}