prizeDraw.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <template>
  2. <div class="prizeDrawBox">
  3. <div class="d-flex flex-column align-center">
  4. <div class="numberBox mb-5">房券抽奖</div>
  5. <gridPage v-if="props.type === '1'" :lotteryId="props.lotteryId" :disabled="disabled" @end="endCallback"></gridPage>
  6. <slotMachinePage v-if="props.type === '2'" :lotteryId="props.lotteryId" height="120" :disabled="disabled" @end="endCallback"></slotMachinePage>
  7. <v-card min-height="300" width="600" class="mt-5 pa-5">
  8. <div v-if="showDialog">
  9. <p v-for="(k, i) in prizeData" :key="i">{{ k.prize.prompt }}</p>
  10. <p>凭此房券在规定有效期内可享受免费住宿一晚。</p>
  11. <p class="mb-5">请提供收货地址,以便安排房券派送。</p>
  12. <!-- 收货地址 -->
  13. <div>
  14. <v-radio-group v-model="addressSelect" color="primary">
  15. <v-radio v-for="val in address" :key="val.id" :label="val.id === 9999 ? val.label : (val.name + ',' + val.mobile + ',' + val.areaName + val.detailAddress)" :value="val.id"></v-radio>
  16. </v-radio-group>
  17. <v-form v-if="addressSelect === 9999" ref="addressFormRef">
  18. <v-row>
  19. <v-col :cols="6">
  20. <v-text-field v-model="newAddress.name" label="收货人名称 *" color="primary" density="compact" variant="outlined"></v-text-field>
  21. </v-col>
  22. <v-col :cols="6">
  23. <v-text-field v-model="newAddress.mobile" :rules="phoneRules" label="收货人手机号码 *" color="primary" density="compact" variant="outlined"></v-text-field>
  24. </v-col>
  25. </v-row>
  26. <div class="d-flex" style="width: 100%;">
  27. <div class="mt-2" style="color: #777; width: 100px;">省市区 *</div>
  28. <el-cascader
  29. ref="cascaderAddr"
  30. v-model="newAddress.areaId"
  31. size="large"
  32. clearable
  33. class="mb-5"
  34. placeholder="省市区 *"
  35. style="flex: 1;"
  36. :props="{ value: 'id', label: 'name', emitPath: false }"
  37. :options="areaTreeData"
  38. @change="handleChangeArea(item)"
  39. ></el-cascader>
  40. </div>
  41. <v-text-field v-model="newAddress.detailAddress" label="详情地址 *" color="primary" density="compact" variant="outlined"></v-text-field>
  42. </v-form>
  43. <div class="text-center mt-3">
  44. <v-btn color="primary" class="elevation-5" width="180" @click.stop="handleSubmit">确 认</v-btn>
  45. </div>
  46. </div>
  47. </div>
  48. </v-card>
  49. </div>
  50. </div>
  51. </template>
  52. <script setup>
  53. defineOptions({ name: 'prizeDraw'})
  54. import gridPage from './prizeDraw/grid.vue'
  55. import slotMachinePage from './prizeDraw/slotMachine.vue'
  56. import { ref } from 'vue'
  57. import { getLuckLotteryRecordByOrderId } from '@/api/mall/prize'
  58. import { getMallUserAddressList } from '@/api/mall/address'
  59. import Snackbar from '@/plugins/snackbar'
  60. import { luckyLotteryRecordReceive } from '@/api/mall/prize'
  61. import { useRouter } from 'vue-router'
  62. import { getDict } from '@/hooks/web/useDictionaries'
  63. const emit = defineEmits(['success'])
  64. const props = defineProps({
  65. lotteryId: [Number, String],
  66. orderId: [Number, String],
  67. type: {
  68. type: String,
  69. default: '1'
  70. }
  71. })
  72. const router = useRouter()
  73. const newAddress = ref({
  74. name: '',
  75. areaId: '',
  76. areaName: '',
  77. mobile: '',
  78. detailAddress: ''
  79. })
  80. const addressSelect = ref()
  81. const disabled = ref(false)
  82. const addressFormRef = ref()
  83. const cascaderAddr = ref()
  84. const areaTreeData = ref([])
  85. getDict('areaTreeData', null, 'areaTreeData').then(({ data }) => {
  86. data = data?.length && data || []
  87. areaTreeData.value = data
  88. })
  89. const phoneRules = ref([
  90. value => {
  91. if (value) return true
  92. return t('login.mobileNumberPlaceholder')
  93. },
  94. value => {
  95. if (value?.length <= 11 && /^1[3456789]\d{9}$/.test(value)) return true
  96. return t('login.correctPhoneNumber')
  97. }
  98. ])
  99. // 地区选择
  100. const handleChangeArea = () => {
  101. const node = cascaderAddr.value.getCheckedNodes() ? cascaderAddr.value.getCheckedNodes()[0] : null
  102. if (!node) return
  103. newAddress.value.areaName = node.pathLabels.join(' ')
  104. }
  105. // 获取中奖记录、收货地址
  106. const address = ref([])
  107. const prizeData = ref({})
  108. const getRecord = async () => {
  109. const data = await getLuckLotteryRecordByOrderId(props.orderId)
  110. prizeData.value = data || []
  111. if (!data || !data.length) disabled.value = true
  112. const addressData = await getMallUserAddressList()
  113. address.value = [...addressData, { id: 9999, label: '使用新地址' }] || []
  114. if (addressData && addressData.length) addressSelect.value = addressData[0].id
  115. }
  116. if (props.orderId) getRecord()
  117. const showDialog = ref(false)
  118. const endCallback = () => {
  119. if (!prizeData.value.length) return Snackbar.warning('您已经抽过奖了哦')
  120. showDialog.value = true
  121. disabled.value = true
  122. }
  123. function checkValue(obj) {
  124. for (let key in obj) {
  125. if (obj.hasOwnProperty(key) && !obj[key]) {
  126. return false
  127. }
  128. }
  129. return true
  130. }
  131. // 领取
  132. const handleSubmit = async () => {
  133. let query = {}
  134. if (addressSelect.value === 9999) {
  135. if (!checkValue(newAddress.value)) return Snackbar.warning('请完善收货信息')
  136. query = newAddress.value
  137. } else query = address.value.find(item => item.id === addressSelect.value)
  138. await luckyLotteryRecordReceive({ id: prizeData.value[0].record.id, receiveInfo: JSON.stringify(query) })
  139. Snackbar.success('领取成功,待商家发货')
  140. router.push('/recruit/personal/personalCenter/tradeOrder?key=1')
  141. }
  142. </script>
  143. <style scoped lang="scss">
  144. .prizeDrawBox {
  145. padding: 20px 40px;
  146. background-color: var(--default-bgc);
  147. }
  148. .prizeDraw {
  149. margin: 0 auto;
  150. }
  151. .numberBox {
  152. font-size: 20px;
  153. font-weight: bold;
  154. padding: 2px 38px;
  155. border-bottom: 3px solid var(--v-primary-base);
  156. }
  157. .colorBase {
  158. color: var(--v-primary-base);
  159. margin: 0 6px;
  160. font-size: 22px;
  161. }
  162. </style>