|
@@ -1,11 +1,14 @@
|
|
|
<template>
|
|
|
<Dialog title="活动奖品配置" v-model="dialogVisible" style="width: 70%;">
|
|
|
- <div class="text-right mb-20px">
|
|
|
+ <div class="text-right">
|
|
|
<el-button type="primary" plain @click="handleAddPrize">
|
|
|
<Icon icon="ep:plus" class="mr-5px" /> 新增奖品
|
|
|
</el-button>
|
|
|
</div>
|
|
|
<div style="display: inline-block; width: 100%;">
|
|
|
+ <div class="mb-20px" style="color: var(--el-color-warning)">
|
|
|
+ 提示:抽奖概率 =(奖品权重 × 奖品数量)÷ 总权重,计算结果四舍五入保留两位小数
|
|
|
+ </div>
|
|
|
<el-table v-loading="loading" :data="list" :stripe="true">
|
|
|
<el-table-column label="奖品名称" align="center" prop="name" />
|
|
|
<el-table-column label="奖品图片" align="center" min-width="80" prop="image">
|
|
@@ -13,16 +16,19 @@
|
|
|
<img :src="scope.row.image" alt="" class="h-70px" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="奖品数量" align="center" prop="total" />
|
|
|
- <el-table-column label="权重" align="center" prop="chance" />
|
|
|
<el-table-column label="类型" align="center" prop="type">
|
|
|
<template #default="scope">
|
|
|
<dict-tag :type="DICT_TYPE.PROMOTION_LUCK_PRIZE_TYPE" :value="scope.row.type" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="提示语" align="center" prop="prompt" />
|
|
|
+ <el-table-column label="奖品数量" align="center" prop="total" />
|
|
|
+ <el-table-column label="权重" align="center" prop="chance" />
|
|
|
+ <el-table-column label="抽奖概率" align="center" prop="probability">
|
|
|
+ <template #default="scope">{{ scope.row.probability }}%</template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column label="排序" align="center" prop="sort" />
|
|
|
- <el-table-column label="操作" align="center">
|
|
|
+ <el-table-column label="操作" align="center" fixed="right" min-width="110">
|
|
|
<template #default="scope">
|
|
|
<el-button link type="primary" @click="handleEdit(scope.row.id)">编辑</el-button>
|
|
|
<el-button link type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
|
|
@@ -38,45 +44,61 @@
|
|
|
</Dialog>
|
|
|
|
|
|
<Dialog title="添加奖品" v-model="showAddPrize">
|
|
|
- <el-form
|
|
|
- ref="formRef"
|
|
|
- :model="addPrizeData"
|
|
|
- :rules="addPrizeFormRules"
|
|
|
- label-width="80px"
|
|
|
- >
|
|
|
- <el-form-item label="奖品" prop="type">
|
|
|
+ <el-form ref="formRef" :model="addPrizeData" label-width="80px">
|
|
|
+ <el-form-item label="奖品" prop="type" :rules="[{ required: true, message: '奖品类型不能为空', trigger: 'change' }]">
|
|
|
<el-radio-group v-model="addPrizeData.type">
|
|
|
- <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_LUCK_PRIZE_TYPE)" :key="dict.value" :value="dict.value.toString()" @change="handleChangeType">{{ dict.label }}</el-radio>
|
|
|
+ <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_LUCK_PRIZE_TYPE)" :key="dict.value" :value="dict.value.toString()" @change="handleChangePrizeType">{{ dict.label }}</el-radio>
|
|
|
</el-radio-group>
|
|
|
</el-form-item>
|
|
|
- <el-form-item v-if="isShowSpu" label="商品" prop="productId">
|
|
|
- <div style="width: 100%;">
|
|
|
- <el-image v-if="Object.keys(spu).length && spu?.id" class="w-100px h-100px" :src="spu?.picUrl" />
|
|
|
+ <el-form-item v-if="prizeType === '6'" label="商品" prop="productId">
|
|
|
+ <div class="w-full">
|
|
|
+ <el-image v-if="spu && Object.keys(spu).length && spu?.id" class="w-100px h-100px" :src="spu?.picUrl" />
|
|
|
</div>
|
|
|
<el-button :icon="Plus" type="primary" @click.stop="spuQueryParams.pageNo = 1,showSpu = true">选择商品</el-button>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="奖品名称" prop="name">
|
|
|
+ <el-form-item label="奖品名称" prop="name" :rules="[{ required: true, message: '奖品名称不能为空', trigger: 'blur' }]">
|
|
|
<el-input v-model="addPrizeData.name" placeholder="请输入奖品名称" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="奖品图片" prop="image">
|
|
|
- <UploadImg v-model="addPrizeData.image" :validSpecifications="true" height="150px" width="150px" :fileSize="10" :maxWidth="150" :maxHeight="150" />
|
|
|
+ <el-form-item label="奖品图片" prop="image" :rules="[{ required: true, message: '奖品图片不能为空', trigger: 'change' }]">
|
|
|
+ <UploadImg v-model="addPrizeData.image" :validSpecifications="true" height="150px" width="150px" :fileSize="10" :maxWidth="800" :maxHeight="800" />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="排序" prop="sort">
|
|
|
- <el-input-number v-model="addPrizeData.sort" :min="1" />
|
|
|
+ <el-input-number v-model="addPrizeData.sort" :min="0" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="奖品数量" prop="total">
|
|
|
- <el-input-number v-model="addPrizeData.total" :min="1" />
|
|
|
+ <el-form-item label="奖品数量" prop="total" :rules="[{ required: true, message: '商品数量不能为空', trigger: 'blur' }]">
|
|
|
+ <el-input-number v-model="addPrizeData.total" :min="0" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="奖品权重" prop="chance">
|
|
|
- <el-input-number v-model="addPrizeData.chance" :min="1" />
|
|
|
+ <el-form-item label="奖品权重" prop="chance" :rules="[{ required: true, message: '奖品权重不能为空', trigger: 'blur' }]">
|
|
|
+ <el-input-number v-model="addPrizeData.chance" :min="0" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="提示语" prop="prompt">
|
|
|
+ <el-form-item label="提示语" prop="prompt" :rules="[{ required: true, message: '提示语不能为空', trigger: 'blur' }]">
|
|
|
<el-input v-model="addPrizeData.prompt" placeholder="请输入提示语" />
|
|
|
</el-form-item>
|
|
|
+ <div v-if="prizeType === '99'">
|
|
|
+ <el-form-item label="省市区" required>
|
|
|
+ <el-cascader
|
|
|
+ ref="areaRef"
|
|
|
+ v-model="area"
|
|
|
+ class="w-full"
|
|
|
+ clearable
|
|
|
+ placeholder="省市区 *"
|
|
|
+ :props="{ value: 'id', label: 'name', emitPath: false }"
|
|
|
+ :options="areaTreeData"
|
|
|
+ @change="handleChangeArea"
|
|
|
+ @clear="handleClearArea"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="集团名称" prop="extend.bloc" :rules="[{ required: true, message: '集团名称不能为空', trigger: 'blur' }]">
|
|
|
+ <el-input v-model="addPrizeData.extend.bloc" placeholder="请输入集团名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="品牌名称" prop="extend.brand" :rules="[{ required: true, message: '品牌名称不能为空', trigger: 'blur' }]">
|
|
|
+ <el-input v-model="addPrizeData.extend.brand" placeholder="请输入品牌名称" />
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
</el-form>
|
|
|
<template #footer>
|
|
|
<el-button @click="submitPrize" type="primary">确 定</el-button>
|
|
|
- <el-button @click="showAddPrize = false, spu = {}">取 消</el-button>
|
|
|
+ <el-button @click="showAddPrize = false; spu = {}">取 消</el-button>
|
|
|
</template>
|
|
|
</Dialog>
|
|
|
|
|
@@ -96,6 +118,7 @@
|
|
|
import { LuckLotteryApi } from '@/api/mall/promotion/lottery/config'
|
|
|
import * as ProductSpuApi from '@/api/mall/product/spu'
|
|
|
import SpuList from './components/spuList.vue'
|
|
|
+ import { getDict } from '@/hooks/web/useDictionaries'
|
|
|
|
|
|
/** 幸运抽奖-活动 表单 */
|
|
|
defineOptions({ name: 'LuckLotteryForm' })
|
|
@@ -111,6 +134,22 @@
|
|
|
pageSize: 10,
|
|
|
lotteryId: undefined as any
|
|
|
})
|
|
|
+ const area = ref()
|
|
|
+ const areaRef = ref()
|
|
|
+ const areaTreeData = ref([])
|
|
|
+
|
|
|
+ const getDictData = async () => {
|
|
|
+ const { data } = await getDict('areaTreeData', {}, 'areaTreeData')
|
|
|
+ const obj = data.find(e => e.name === '中国')
|
|
|
+ const list = obj?.children ? obj.children.map(e =>{
|
|
|
+ // 市辖区直接显示区
|
|
|
+ const municipality = e.children && e.children.length && e.children[0].name === '市辖区'
|
|
|
+ if (municipality && e.children[0].children?.length) e.children = e.children[0].children
|
|
|
+ return e
|
|
|
+ }) : []
|
|
|
+ areaTreeData.value = list || []
|
|
|
+ }
|
|
|
+ getDictData()
|
|
|
|
|
|
// 获取奖品分页
|
|
|
const getList = async () => {
|
|
@@ -118,7 +157,7 @@
|
|
|
try {
|
|
|
const res = await LuckLotteryApi.getLuckLotteryPrizePage(queryParams)
|
|
|
list.value = res.list
|
|
|
- total.value = res.total
|
|
|
+ // total.value = res.total
|
|
|
} finally {
|
|
|
loading.value = false
|
|
|
}
|
|
@@ -143,6 +182,35 @@
|
|
|
spuLoading.value = false
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 地区选择
|
|
|
+ const handleChangeArea = () => {
|
|
|
+ const key = {
|
|
|
+ value: ['provinceId', 'cityId', 'districtId'],
|
|
|
+ label: ['provinceName', 'cityName', 'districtName']
|
|
|
+ }
|
|
|
+ const node = areaRef.value.getCheckedNodes() ? areaRef.value.getCheckedNodes()[0] : null
|
|
|
+ if (!node) return
|
|
|
+ for (let i in addPrizeData.value.extend) {
|
|
|
+ const index = key.value.indexOf(i)
|
|
|
+ if (index > -1) {
|
|
|
+ addPrizeData.value.extend[i] = node.pathValues[index]
|
|
|
+ addPrizeData.value.extend[key.label[index]] = node.pathLabels[index]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const handleClearArea = () => {
|
|
|
+ addPrizeData.value.extend = {
|
|
|
+ bloc: undefined,
|
|
|
+ brand: undefined,
|
|
|
+ provinceId: undefined,
|
|
|
+ provinceName: undefined,
|
|
|
+ cityId: undefined,
|
|
|
+ cityName: undefined,
|
|
|
+ districtId: undefined,
|
|
|
+ districtName: undefined
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/** 打开弹窗 */
|
|
|
const open = async (id: number) => {
|
|
@@ -172,7 +240,20 @@
|
|
|
const data = await LuckLotteryApi.getLuckLotteryPrize(id)
|
|
|
addPrizeData.value = data
|
|
|
spu.value = data.spu
|
|
|
- isShowSpu.value = data.type === '6'
|
|
|
+ prizeType.value = data.type
|
|
|
+ // 没有自定义参数,则初始化
|
|
|
+ if (!data.extend || !Object.keys(data.extend).length) {
|
|
|
+ addPrizeData.value.extend = {
|
|
|
+ bloc: undefined,
|
|
|
+ brand: undefined,
|
|
|
+ provinceId: undefined,
|
|
|
+ provinceName: undefined,
|
|
|
+ cityId: undefined,
|
|
|
+ cityName: undefined,
|
|
|
+ districtId: undefined,
|
|
|
+ districtName: undefined
|
|
|
+ }
|
|
|
+ }
|
|
|
showAddPrize.value = true
|
|
|
} catch {}
|
|
|
}
|
|
@@ -182,45 +263,57 @@
|
|
|
type: '1',
|
|
|
productId: undefined,
|
|
|
name: undefined,
|
|
|
- total: 10,
|
|
|
- chance: 10,
|
|
|
+ total: 0,
|
|
|
+ chance: 0,
|
|
|
prompt: undefined,
|
|
|
image: undefined,
|
|
|
status: 0,
|
|
|
sort: 0,
|
|
|
- lotteryId: undefined as any
|
|
|
+ lotteryId: undefined as any,
|
|
|
+ extend: {
|
|
|
+ bloc: undefined,
|
|
|
+ brand: undefined,
|
|
|
+ provinceId: undefined,
|
|
|
+ provinceName: undefined,
|
|
|
+ cityId: undefined,
|
|
|
+ cityName: undefined,
|
|
|
+ districtId: undefined,
|
|
|
+ districtName: undefined
|
|
|
+ }
|
|
|
})
|
|
|
const showAddPrize = ref(false)
|
|
|
const formRef = ref()
|
|
|
- const addPrizeFormRules = reactive({
|
|
|
- type: [{ required: true, message: '奖品类型不能为空', trigger: 'change' }],
|
|
|
- name: [{ required: true, message: '奖品名称不能为空', trigger: 'blur' }],
|
|
|
- chance: [{ required: true, message: '奖品权重不能为空', trigger: 'blur' }],
|
|
|
- image: [{ required: true, message: '奖品图片不能为空', trigger: 'blur' }],
|
|
|
- total: [{ required: true, message: '商品数量不能为空', trigger: 'blur' }],
|
|
|
- prompt: [{ required: true, message: '提示语不能为空', trigger: 'blur' }]
|
|
|
- })
|
|
|
const handleAddPrize = async () => {
|
|
|
formType.value = 'add'
|
|
|
- isShowSpu.value = false
|
|
|
+ prizeType.value = '1'
|
|
|
resetForm()
|
|
|
showAddPrize.value = true
|
|
|
await getSpuList()
|
|
|
}
|
|
|
|
|
|
// 只有站内商品才展示商品信息
|
|
|
- const isShowSpu = ref(false)
|
|
|
- const handleChangeType = (val: string) => {
|
|
|
- isShowSpu.value = val === '6'
|
|
|
+ const prizeType = ref('1')
|
|
|
+ const handleChangePrizeType = (val: string) => {
|
|
|
+ prizeType.value = val
|
|
|
}
|
|
|
+
|
|
|
const submitPrize = async () => {
|
|
|
+ console.log(addPrizeData.value, 'submit');
|
|
|
+
|
|
|
// 校验表单
|
|
|
await formRef.value.validate()
|
|
|
- if (isShowSpu.value && !Object.keys(spu.value).length && !spu.value?.id) return message.warning('请选择商品')
|
|
|
+
|
|
|
+ if (prizeType.value === '6' && !Object.keys(spu.value).length && !spu.value?.id) return message.warning('请选择商品')
|
|
|
+ if (prizeType.value !== '99') handleClearArea() // 奖品类型不是自定义时清空extend数据
|
|
|
+
|
|
|
+ // 奖品类型为自定义时,效验是否有选省市区
|
|
|
+ if (prizeType.value === '99' && !addPrizeData.value.extend.provinceId) return message.warning('请选择省市区')
|
|
|
+
|
|
|
addPrizeData.value.lotteryId = queryParams.lotteryId
|
|
|
- addPrizeData.value.productId = spu.value.id
|
|
|
- addPrizeData.value.image = spu.value?.picUrl
|
|
|
+ if (prizeType.value === '6') addPrizeData.value.productId = spu.value.id
|
|
|
+ if (addPrizeData.value.type === '6' && !addPrizeData.value.image) addPrizeData.value.image = spu.value?.picUrl
|
|
|
delete addPrizeData.value.spu
|
|
|
+
|
|
|
try {
|
|
|
formType.value === 'add' ? await LuckLotteryApi.createLuckLotteryPrize(addPrizeData.value) : await LuckLotteryApi.updateLuckLotteryPrize(addPrizeData.value)
|
|
|
message.success(formType.value === 'add' ? '添加成功' : '修改成功')
|
|
@@ -236,13 +329,23 @@
|
|
|
type: '1',
|
|
|
productId: undefined,
|
|
|
name: undefined,
|
|
|
- total: 10,
|
|
|
- chance: 10,
|
|
|
+ total: 0,
|
|
|
+ chance: 0,
|
|
|
prompt: undefined,
|
|
|
image: undefined,
|
|
|
status: 0,
|
|
|
sort: 0,
|
|
|
- lotteryId: undefined as any
|
|
|
+ lotteryId: undefined as any,
|
|
|
+ extend: {
|
|
|
+ bloc: undefined,
|
|
|
+ brand: undefined,
|
|
|
+ provinceId: undefined,
|
|
|
+ provinceName: undefined,
|
|
|
+ cityId: undefined,
|
|
|
+ cityName: undefined,
|
|
|
+ districtId: undefined,
|
|
|
+ districtName: undefined
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|