1 Chinld Component
<template>
<div>
<a-button type="link" @click="showModal">选择模板</a-button>
<a-modal
width="400px"
v-model:open="visible"
title="选择模板"
@ok="handleOk"
>
<a-select
v-model:value="value"
:options="options"
mode="tags"
:size="size"
placeholder="Please select"
style="width: 200px"
></a-select>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { SelectProps } from 'ant-design-vue'
import request from '@/utils/request'
const emit = defineEmits(['selectionData'])
const queryByPageUrl = '/api/list'
const value = ref<string[]>([])
const size = ref<SelectProps['size']>()
const options = ref<{ label: string
[]
)
const reqParams: { [key: string]: any } = {
pageNum: 1,
pageSize: 999,
status: 1,
}
const selectionData = ref<any>([])
const selectionOption = () =>
request
.post(queryByPageUrl, reqParams)
.then((res: any) => {
if (res.code === 200) {
const { data } = res
options.value = data.list?.map((item: any) => ({
label: item.title,
value: item.id,
templateNumber: item.templateNumber,
}))
}
})
.catch((error: any) => {
console.error('Error fetching data:', error)
})
const visible = ref(false)
const showModal = () => {
console.log('open selection modal')
visible.value = true
selectionOption()
}
const handleOk = () => {
console.log('selection value', value.value)
console.log('options', options.value)
visible.value = false
selectionData.value = options.value.filter((item: any) =>
value.value.includes(item.value)
)
console.log('selectionData', selectionData.value)
// Paraments passing
emit('selectionData', selectionData.value)
}
</script>
```<script lang="ts">
import { defineComponent, reactive, ref, nextTick, onMounted } from 'vue'
import Sortable from 'sortablejs'
import { getDrawConfig, saveDrawConfig } from './service'
import { DrawConfigInter, TemplateInter } from './interface'
import TemplateList from './TemplateList.vue'
import { message } from 'ant-design-vue'
import dayjs, { Dayjs } from 'dayjs'
import LottorySelection from './components/LottorySelection.vue'
export default defineComponent({
components: {
TemplateList,
LottorySelection,
},
setup() {
const formState = reactive<Partial<DrawConfigInter>>({
ruleName: '',
longTerm: true,
startTime: '',
endTime: '',
templateConfig: [],
winnerLimit: 0,
rewardType: 1,
rewardProperties: {
starValidityTimeUnit: '',
starValidityDuration: 0,
starCount: 0,
},
})
const pageType = ref<string>('detail')
const templateListItems = ref<Array<TemplateInter>>([])
const dateRange = ref<Dayjs[]>([])
const questionnaireTemplateRef = ref(null)
let sortableInstance: any = null
const initSortable = () => {
const el = questionnaireTemplateRef.value
if (el) {
sortableInstance = Sortable.create(el, {
animation: 150,
onEnd: (evt: any) => {
const { oldIndex, newIndex } = evt
if (oldIndex !== null && newIndex !== null) {
const item = formState.templateConfig?.splice(oldIndex, 1)[0]
if (item) {
formState.templateConfig?.splice(newIndex, 0, item)
}
}
},
})
}
}
onMounted(async () => {
try {
const res: any = await getDrawConfig()
if (res.code === 200) {
const data = res.data as DrawConfigInter
formState.ruleName = data.ruleName
formState.longTerm = data.longTerm
if (!data.longTerm) {
dateRange.value = [dayjs(data.startTime), dayjs(data.endTime)]
}
formState.templateConfig = data.templateConfig || []
templateListItems.value = data.templateConfig || []
formState.winnerLimit = data.winnerLimit
formState.rewardType = data.rewardType
// 确保 rewardProperties 存在且字段完整
formState.rewardProperties = {
...(data.rewardProperties || {}),
starValidityTimeUnit:
data.rewardProperties?.starValidityTimeUnit || '',
starValidityDuration:
data.rewardProperties?.starValidityDuration || 0,
starCount: data.rewardProperties?.starCount || 0,
}
}
} catch (error) {
console.error('Failed to fetch draw config:', error)
}
// 在接口数据加载完成后初始化可拖动功能
nextTick(() => {
initSortable()
})
})
const handleSubmit = async () => {
try {
const payload: Partial<DrawConfigInter> = {
ruleName: formState.ruleName,
longTerm: formState.longTerm,
startTime: dayjs(dateRange.value?.[0]).format(),
endTime: dayjs(dateRange.value?.[1]).format(),
templateConfig: templateListItems.value,
winnerLimit: formState.winnerLimit,
rewardType: formState.rewardType,
rewardProperties: formState.rewardProperties,
}
console.log('payload', payload)
const res: any = await saveDrawConfig(payload)
if (res.code === 200) {
message.success('保存成功')
} else {
message.error('保存失败')
}
} catch (error) {
console.error('Failed to save draw config:', error)
message.error('保存失败')
}
}
return {
pageType,
dateRange,
formState,
templateListItems,
questionnaireTemplateRef,
handleSubmit,
}
},
})
</script>
<template>
<div class="draw-config">
<a-form :model="formState" layout="vertical">
<a-form-item label="活动名称:" required>
<a-input v-model:value="formState.ruleName" />
</a-form-item>
<a-form-item label="活动有效期:" required>
<a-radio-group v-model:value="formState.longTerm">
<a-radio :value="true">长期有效</a-radio>
<a-radio :value="false">固定有效期</a-radio>
</a-radio-group>
<a-range-picker
v-if="formState.longTerm === false"
v-model:value="dateRange"
:placeholder="['开始日期', '结束日期']"
:rangeSeparator="'-'"
style="margin-top: 8px"
/>
</a-form-item>
<a-row>
<LottorySelection
ref="templateSelection"
// accept paramter from the chile component
@selectionData="(data) => {
console.log('processFormData', data);
data.map((item: any) => {
templateListItems.push({
title: item.label,
templateNumber: item.templateNumber,
});
});
}"
/>
</a-row>
<a-form-item label="参与抽奖问卷模版:" required>
<TemplateList
ref="compInfoRef"
:pageType="pageType"
:tableData="templateListItems"
/>
</a-form-item>
<a-form-item label="中奖数量配置:" required>
<a-input-number v-model:value="formState.winnerLimit" />
</a-form-item>
<a-form-item label="奖励类型:" required>
<a-radio-group v-model:value="formState.rewardType">
<a-radio :value="1">好礼星星</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
label="好礼星星有效期:"
required
v-if="formState.rewardType === 1"
>
<a-select
v-model:value="formState.rewardProperties!.starValidityTimeUnit"
>
<a-select-option value="day">天</a-select-option>
<a-select-option value="month">月</a-select-option>
<a-select-option value="year">年</a-select-option>
</a-select>
<a-input-number
v-model:value="formState.rewardProperties!.starValidityDuration"
style="margin-left: 8px"
/>
</a-form-item>
<a-form-item
label="好礼星星数量:"
required
v-if="formState.rewardType === 1"
>
<a-input-number v-model:value="formState.rewardProperties!.starCount" />
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSubmit">保存</a-button>
</a-form-item>
</a-form>
</div>
</template>
<style scoped>
.questionnaire-template-list {
list-style: none
padding: 0
}
.questionnaire-template-item {
display: flex
align-items: center
margin-bottom: 8px
background-color:
padding: 4px 8px
border-radius: 4px
}
.drag-btn {
cursor: move
margin-right: 10px
}
</style>