feat(admin): 权益等级管理功能完善 - 添加新增/删除权益等级功能 - 隐藏奖品配置中的中奖概率字段
This commit is contained in:
parent
14ebb2221e
commit
0c93aa7d62
|
|
@ -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 ====================
|
// ==================== 权益等级奖品 API ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="dialogVisible"
|
v-model="dialogVisible"
|
||||||
title="编辑权益等级"
|
:title="isEdit ? '编辑权益等级' : '新增权益等级'"
|
||||||
width="500px"
|
width="500px"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
|
|
@ -55,14 +55,17 @@
|
||||||
import { ref, reactive, computed, watch } from 'vue'
|
import { ref, reactive, computed, watch } from 'vue'
|
||||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||||
import {
|
import {
|
||||||
|
createQyLevel,
|
||||||
updateQyLevel,
|
updateQyLevel,
|
||||||
type QyLevelResponse,
|
type QyLevelResponse,
|
||||||
|
type QyLevelCreateRequest,
|
||||||
type QyLevelUpdateRequest
|
type QyLevelUpdateRequest
|
||||||
} from '@/api/business/qylevel'
|
} from '@/api/business/qylevel'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: boolean
|
modelValue: boolean
|
||||||
level: QyLevelResponse | null
|
level: QyLevelResponse | null
|
||||||
|
isEdit: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|
@ -131,13 +134,18 @@ const formRules: FormRules = {
|
||||||
|
|
||||||
// 监听弹窗打开,初始化数据
|
// 监听弹窗打开,初始化数据
|
||||||
watch(() => props.modelValue, (visible) => {
|
watch(() => props.modelValue, (visible) => {
|
||||||
if (visible && props.level) {
|
if (visible) {
|
||||||
// 编辑模式:回显数据
|
if (props.isEdit && props.level) {
|
||||||
Object.assign(formData, {
|
// 编辑模式:回显数据
|
||||||
level: props.level.level || 1,
|
Object.assign(formData, {
|
||||||
title: props.level.title || '',
|
level: props.level.level || 1,
|
||||||
requiredPoints: props.level.requiredPoints || 0
|
title: props.level.title || '',
|
||||||
})
|
requiredPoints: props.level.requiredPoints || 0
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 新增模式:重置数据
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -179,22 +187,32 @@ const handleSubmit = async () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.level) {
|
|
||||||
ElMessage.error('未选择要编辑的等级')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
submitLoading.value = true
|
submitLoading.value = true
|
||||||
try {
|
try {
|
||||||
const submitData: QyLevelUpdateRequest = {
|
if (props.isEdit) {
|
||||||
level: formData.level,
|
// 编辑模式
|
||||||
title: formData.title,
|
if (!props.level) {
|
||||||
requiredPoints: formData.requiredPoints
|
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')
|
emit('success')
|
||||||
handleClose()
|
handleClose()
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,6 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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">
|
<el-table-column label="操作" width="130" align="center" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link size="small" @click="handleEdit(row)">
|
<el-button type="primary" link size="small" @click="handleEdit(row)">
|
||||||
|
|
@ -201,11 +195,6 @@ const handleClose = () => {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.probability-value {
|
|
||||||
color: #409eff;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
|
||||||
|
|
@ -39,20 +39,6 @@
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</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>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -107,43 +93,19 @@ const couponLoading = ref(false)
|
||||||
interface FormDataType {
|
interface FormDataType {
|
||||||
couponId: number | undefined
|
couponId: number | undefined
|
||||||
quantity: number
|
quantity: number
|
||||||
probability: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = reactive<FormDataType>({
|
const formData = reactive<FormDataType>({
|
||||||
couponId: undefined,
|
couponId: undefined,
|
||||||
quantity: 1,
|
quantity: 1
|
||||||
probability: 0
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 概率验证器
|
|
||||||
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>(() => ({
|
const formRules = computed<FormRules>(() => ({
|
||||||
couponId: [{ required: true, message: '请选择优惠券', trigger: 'change' }],
|
couponId: [{ required: true, message: '请选择优惠券', trigger: 'change' }],
|
||||||
quantity: [
|
quantity: [
|
||||||
{ required: true, message: '请输入数量', trigger: 'blur' },
|
{ required: true, message: '请输入数量', trigger: 'blur' },
|
||||||
{ type: 'number', min: 1, message: '数量必须大于0', 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, {
|
Object.assign(formData, {
|
||||||
couponId: props.prize.couponId,
|
couponId: props.prize.couponId,
|
||||||
quantity: props.prize.quantity || 1,
|
quantity: props.prize.quantity || 1
|
||||||
probability: props.prize.probability || 0
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 新增模式:重置数据
|
// 新增模式:重置数据
|
||||||
|
|
@ -184,8 +145,7 @@ watch(() => props.modelValue, (visible) => {
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
Object.assign(formData, {
|
Object.assign(formData, {
|
||||||
couponId: undefined,
|
couponId: undefined,
|
||||||
quantity: 1,
|
quantity: 1
|
||||||
probability: 0
|
|
||||||
})
|
})
|
||||||
formRef.value?.resetFields()
|
formRef.value?.resetFields()
|
||||||
}
|
}
|
||||||
|
|
@ -206,19 +166,6 @@ const handleSubmit = async () => {
|
||||||
return
|
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) {
|
if (!formData.couponId) {
|
||||||
ElMessage.error('请选择优惠券')
|
ElMessage.error('请选择优惠券')
|
||||||
|
|
@ -234,8 +181,7 @@ const handleSubmit = async () => {
|
||||||
const submitData: QyLevelPrizeCreateRequest | QyLevelPrizeUpdateRequest = {
|
const submitData: QyLevelPrizeCreateRequest | QyLevelPrizeUpdateRequest = {
|
||||||
type: QyLevelPrizeType.Coupon,
|
type: QyLevelPrizeType.Coupon,
|
||||||
couponId: formData.couponId,
|
couponId: formData.couponId,
|
||||||
quantity: formData.quantity,
|
quantity: formData.quantity
|
||||||
probability: formData.probability
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.isEdit && props.prize) {
|
if (props.isEdit && props.prize) {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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 }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link size="small" @click="handleEdit(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 type="success" link size="small" @click="handlePrizes(row)">
|
||||||
奖品
|
奖品
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button type="danger" link size="small" @click="handleDelete(row)">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -78,6 +81,7 @@ const emit = defineEmits<{
|
||||||
(e: 'size-change', size: number): void
|
(e: 'size-change', size: number): void
|
||||||
(e: 'edit', row: QyLevelResponse): void
|
(e: 'edit', row: QyLevelResponse): void
|
||||||
(e: 'prizes', row: QyLevelResponse): void
|
(e: 'prizes', row: QyLevelResponse): void
|
||||||
|
(e: 'delete', row: QyLevelResponse): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const currentPage = ref(props.page)
|
const currentPage = ref(props.page)
|
||||||
|
|
@ -106,6 +110,10 @@ const handleEdit = (row: QyLevelResponse) => {
|
||||||
const handlePrizes = (row: QyLevelResponse) => {
|
const handlePrizes = (row: QyLevelResponse) => {
|
||||||
emit('prizes', row)
|
emit('prizes', row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDelete = (row: QyLevelResponse) => {
|
||||||
|
emit('delete', row)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>权益等级管理</span>
|
<span>权益等级管理</span>
|
||||||
|
<el-button type="primary" @click="handleAdd">
|
||||||
|
<el-icon><Plus /></el-icon>新增
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -38,6 +41,7 @@
|
||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
@edit="handleEdit"
|
@edit="handleEdit"
|
||||||
@prizes="handlePrizes"
|
@prizes="handlePrizes"
|
||||||
|
@delete="handleDelete"
|
||||||
/>
|
/>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
|
@ -45,6 +49,7 @@
|
||||||
<QyLevelFormDialog
|
<QyLevelFormDialog
|
||||||
v-model="formDialogVisible"
|
v-model="formDialogVisible"
|
||||||
:level="currentLevel"
|
:level="currentLevel"
|
||||||
|
:is-edit="isEdit"
|
||||||
@success="fetchData"
|
@success="fetchData"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -58,12 +63,14 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
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 QyLevelTable from './components/QyLevelTable.vue'
|
||||||
import QyLevelFormDialog from './components/QyLevelFormDialog.vue'
|
import QyLevelFormDialog from './components/QyLevelFormDialog.vue'
|
||||||
import QyLevelPrizeDialog from './components/QyLevelPrizeDialog.vue'
|
import QyLevelPrizeDialog from './components/QyLevelPrizeDialog.vue'
|
||||||
import {
|
import {
|
||||||
getQyLevels,
|
getQyLevels,
|
||||||
|
deleteQyLevel,
|
||||||
type QyLevelListRequest,
|
type QyLevelListRequest,
|
||||||
type QyLevelResponse
|
type QyLevelResponse
|
||||||
} from '@/api/business/qylevel'
|
} from '@/api/business/qylevel'
|
||||||
|
|
@ -84,6 +91,7 @@ const queryParams = reactive<QyLevelListRequest>({
|
||||||
const formDialogVisible = ref(false)
|
const formDialogVisible = ref(false)
|
||||||
const prizeDialogVisible = ref(false)
|
const prizeDialogVisible = ref(false)
|
||||||
const currentLevel = ref<QyLevelResponse | null>(null)
|
const currentLevel = ref<QyLevelResponse | null>(null)
|
||||||
|
const isEdit = ref(false)
|
||||||
|
|
||||||
// 获取权益等级列表
|
// 获取权益等级列表
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
|
@ -122,12 +130,36 @@ const handleSizeChange = (size: number) => {
|
||||||
fetchData()
|
fetchData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新增权益等级
|
||||||
|
const handleAdd = () => {
|
||||||
|
isEdit.value = false
|
||||||
|
currentLevel.value = null
|
||||||
|
formDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
// 编辑权益等级
|
// 编辑权益等级
|
||||||
const handleEdit = (row: QyLevelResponse) => {
|
const handleEdit = (row: QyLevelResponse) => {
|
||||||
|
isEdit.value = true
|
||||||
currentLevel.value = { ...row }
|
currentLevel.value = { ...row }
|
||||||
formDialogVisible.value = true
|
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) => {
|
const handlePrizes = (row: QyLevelResponse) => {
|
||||||
currentLevel.value = { ...row }
|
currentLevel.value = { ...row }
|
||||||
|
|
@ -150,6 +182,11 @@ onMounted(() => {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-header span {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.search-form {
|
.search-form {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user