apply.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <div class="w-full min-h-[100%]" v-loading="loading">
  3. <div class="main-container" v-if="Object.values(detail).length">
  4. <el-breadcrumb class="my-[20px]" :separator-icon="ArrowRight">
  5. <el-breadcrumb-item>
  6. <span class="cursor-pointer text-[#333]" @click="router.push('/')">{{ t('index') }}</span>
  7. </el-breadcrumb-item>
  8. <el-breadcrumb-item>
  9. <span class="text-[#666]">{{ t('apply') }}</span>
  10. </el-breadcrumb-item>
  11. </el-breadcrumb>
  12. <div ></div>
  13. <div class="px-[30px] pt-[30px] pb-[20px] bg-[#fff]">
  14. <div>
  15. <div class="mb-[30px] flex items-center cursor-pointer" v-if="detail.site" @click="router.push({ path: '/shop/detail', query: { site_id: detail.site.site_id } })">
  16. <span class="iconfont icon-Vector-25 text-[#999] mr-[6px]"></span>
  17. <span class="text-[14px] text-[#333]">{{ detail.site.site_name }}</span>
  18. </div>
  19. <div class="flex justify-between items-center mb-[30px]">
  20. <div class="flex">
  21. <div class="flex items-center flex-shrink-0">
  22. <el-image class="w-[100px] h-[100px]" :src="img(orderDetail.goods_image_thumb_small ? orderDetail.goods_image_thumb_small : '')" fit="cover">
  23. <template #error>
  24. <img src="@/assets/images/goods_default.png" class="w-[100px] h-[100px]">
  25. </template>
  26. </el-image>
  27. </div>
  28. <div class="ml-[20px] flex flex-col justify-center">
  29. <div class="text-[14px] text-[#333] font-500 w-[420px] truncate mb-[14px]">{{ orderDetail.goods_name }}</div>
  30. <div class="text-[14px] text-[#333] oppoSans-R" v-if="orderDetail.sku_name">规格:{{ orderDetail.sku_name }}</div>
  31. </div>
  32. </div>
  33. <div class="flex items-center justify-center">
  34. <div class="w-[160px] text-[14px] text-[#333] price-font">¥{{orderDetail.price}}</div>
  35. <div class="w-[100px] text-[14px] text-[#333] text-right">x{{orderDetail.num}}</div>
  36. <div class="w-[160px] text-right text-primary">
  37. <span class="text-[12px] price-font">¥</span>
  38. <span class="text-[18px] font-600 price-font">{{parseFloat(orderDetail.price * orderDetail.num).toFixed(2)}}</span>
  39. </div>
  40. </div>
  41. </div>
  42. </div>
  43. <el-divider border-style="dashed" />
  44. <div class="mt-[20px]">
  45. <el-form :model="formData" label-width="100px" ref="formRef" :rules="formRules" class="page-form">
  46. <el-form-item :label="t('refundType')" prop="refund_type">
  47. <el-radio-group v-model="formData.refund_type" class="ml-4">
  48. <el-radio :label="1" >{{ t('refundOnly') }}</el-radio>
  49. <el-radio :label="2" v-if="orderDetail.goods_type == 'real' && (!orderDetail.delivery_status || orderDetail.delivery_status != 'wait_delivery')">{{ t('returnRefund') }}</el-radio>
  50. </el-radio-group>
  51. </el-form-item>
  52. <el-form-item :label="t('refundMoney')" prop="apply_money">
  53. <div>
  54. <el-input v-model.trim="formData.apply_money" clearable :placeholder="t('applyMoneyPlaceholder')" class="input-width" />
  55. <div class="text-xs text-[#999] mt-[6px]">
  56. <span>{{ t('maxRefundMoney') }}¥{{ refundMoney.refund_money }}</span>
  57. <span v-if="refundMoney.is_refund_delivery === 1 && Number(refundMoney.refund_delivery_money) > 0" class="ml-[10rpx]">({{ t('includeDelivery') }} ¥{{ refundMoney.refund_delivery_money }})</span>
  58. </div>
  59. </div>
  60. </el-form-item>
  61. <el-form-item :label="t('refundReason')" prop="reason">
  62. <el-select v-model="formData.reason" clearable class="input-width" placeholder="请选择">
  63. <el-option v-for="(item, index) in reason" :key="index" :label="item" :value="item" />
  64. </el-select>
  65. </el-form-item>
  66. <el-form-item :label="t('refundRemark')" >
  67. <el-input v-model.trim="formData.remark" clearable type="textarea" :placeholder="t('remarkPlaceholder')" class="input-width" maxlength="100"/>
  68. </el-form-item>
  69. </el-form>
  70. </div>
  71. <div class="ml-[100px]">
  72. <el-button type="primary" class="!bg-[var(--el-color-primary)] !border-[var(--el-color-primary)]" @click="confirm(formRef)">{{ t('submit') }}</el-button>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </template>
  78. <script setup lang="ts">
  79. import { computed, ref } from 'vue'
  80. import { ArrowRight } from '@element-plus/icons-vue'
  81. import { moneyFormat } from '@/utils/common'
  82. import { getMallOrderDetail } from '@/addon/mall/api/order'
  83. import { getRefundReason, applyRefund,editRefund,getRefundDetail, getRefundMoney, getRefundMoneyAgain } from '@/addon/mall/api/refund'
  84. import { useRouter, useRoute } from 'vue-router'
  85. const route = useRoute()
  86. const router = useRouter()
  87. let orderGoodsId =route.query.order_goods_id
  88. let orderId = route.query.order_id
  89. let orderRefundNo = route.query.order_refund_no
  90. let loading = ref(false)
  91. const detail = ref({})
  92. const orderDetail = ref({})
  93. const formData = ref({
  94. order_id: orderId,
  95. order_goods_id: orderGoodsId,
  96. refund_type: 1,
  97. apply_money: '',
  98. reason: '',
  99. remark: ''
  100. })
  101. // 获取商品详情
  102. const getMallOrderDetailFn = (id) =>{
  103. loading.value = true
  104. getMallOrderDetail(id).then(({ data }) => {
  105. detail.value = data
  106. detail.value.order_goods.forEach((item,index)=>{
  107. if(orderGoodsId == item.order_goods_id){
  108. orderDetail.value = item;
  109. }
  110. })
  111. loading.value = false
  112. })
  113. }
  114. let refundMoney = ref({}) // 可退款金额
  115. const getRefundMoneyFn = (id) =>{
  116. getRefundMoney({order_goods_id: id}).then(res =>{
  117. refundMoney.value = res.data
  118. formData.value.apply_money = moneyFormat(refundMoney.value.refund_money)
  119. })
  120. }
  121. // 获取退款详情
  122. const getRefundDetailFn = (id) =>{
  123. loading.value = true
  124. getRefundDetail(id).then(({ data }) => {
  125. detail.value = data
  126. orderDetail.value = data.order_goods
  127. formData.value.order_goods_id = data.order_goods_id;
  128. formData.value.order_id = data.order_id;
  129. formData.value.order_refund_no = data.order_refund_no;
  130. formData.value.remark = data.remark;
  131. formData.value.reason = data.reason;
  132. loading.value = false
  133. })
  134. }
  135. const getRefundMoneyAgainFn = (id) =>{
  136. getRefundMoneyAgain({order_refund_no: id}).then(res =>{
  137. refundMoney.value = res.data
  138. formData.value.apply_money = moneyFormat(refundMoney.value.refund_money)
  139. })
  140. }
  141. if(orderRefundNo){
  142. getRefundDetailFn(orderRefundNo)
  143. getRefundMoneyAgainFn(orderRefundNo)
  144. }else{
  145. getMallOrderDetailFn(orderId)
  146. getRefundMoneyFn(orderGoodsId)
  147. }
  148. // 退款原因
  149. const reason = ref([])
  150. const getRefundReasonFn = ()=>{
  151. getRefundReason().then(({ data }) => {
  152. reason.value = data
  153. }).catch()
  154. }
  155. getRefundReasonFn()
  156. const formRef = ref(null)
  157. const formRules = computed(() => {
  158. return {
  159. refund_type: [
  160. { required: true, message: t('refundTypePlaceholder'), trigger: 'change' }
  161. ],
  162. apply_money: [
  163. { required: true, message: t('applyMoneyPlaceholder'), trigger: 'blur' },
  164. { required: true, validator: validateMoney, trigger: 'blur' }
  165. ],
  166. reason: [
  167. { required: true, message: t('reasonPlaceholder'), trigger: ['blur','change'] }
  168. ],
  169. }
  170. })
  171. // 验证退款金额
  172. const validateMoney = (rule, value, callback) => {
  173. if ( Number(value).toFixed(2) < 0) {
  174. return callback(new Error(t('退款金额不能为0,保留两位小数')))
  175. } else if (Number(value)>Number(refundMoney.value.refund_money)) {
  176. return callback(new Error(t('退款金额不能大于可退款总额')))
  177. } else {
  178. return callback()
  179. }
  180. }
  181. const confirm = async (formEl) => {
  182. if (loading.value || !formEl) return
  183. await formEl.validate(async (valid) => {
  184. if (valid) {
  185. loading.value = true
  186. const save = orderRefundNo ? editRefund : applyRefund
  187. save(formData.value).then(res => {
  188. loading.value = false
  189. setTimeout(()=> {
  190. router.push({path:'/order/detail',query: {order_id: formData.value.order_id}})
  191. }, 1000)
  192. }).catch(() => {
  193. loading.value = false
  194. })
  195. }
  196. })
  197. }
  198. </script>
  199. <style lang="scss" scoped>
  200. .input-width{
  201. width:540px;
  202. }
  203. </style>