Files
pj_h5_cloud/src/pages/refund/apply.vue
T
2025-03-18 20:07:53 +08:00

213 lines
6.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, reactive, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import { hooks, router } from "@@/index"
import { orderApi, refundApi, commonApi } from "@@/api"
import { filePath } from "@@/utils/file"
const data = {
payType: [
{ text: "仅退款", disabled: false, visible: true, type: "10", value: "10" },
{ text: "退款退货", disabled: true, visible: false, type: "20", value: "20" },
],
}
const state = reactive<any>({
detailId: null,
detail: {},
shopCarList: [],
setting: {},
selectList: [],
})
const uploadApplyPicUrls = ref<Array<Record<string, any> | string>>([]) // 补充凭证图片
const applyPicUrls = computed(() => uploadApplyPicUrls.value.map((item: any) => JSON.parse(item.response).data.url).join(","))
const applyForm = reactive<any>({
way: data.payType[0].type,
remark: "",
reason: "",
reasonStr: "",
})
onLoad((options: any) => {
if (!isEmpty(options.id)) {
state.detailId = options.id
}
state.header = hooks.useDefaultHeader()
})
onShow(() => {
getDetail()
getSetting()
getShopCarList()
})
const getSetting = async () => {
const _pa = {}
const { data } = await commonApi.setting(_pa)
state.setting = data
state.selectList = data.afterSaleRefundReasons?.split(",").map((v) => {
return {
id: v,
title: v,
}
})
}
const getDetail = async () => {
if (isEmpty(state.detailId)) return
const _pa = { id: state.detailId }
const { data } = await orderApi.detail(_pa)
state.detail = data
}
const getShopCarList = async () => {
if (isEmpty(state.detailId)) return
const _pa = { orderId: state.detailId }
const { data } = await orderApi.shopCarList(_pa)
state.shopCarList = data
}
const radioChange = (e: any) => {
switch (e) {
case "10":
state.selectList = state.setting.afterSaleRefundReasons.map((v) => {
return {
id: v,
title: v,
}
})
break
case "20":
state.selectList = state.setting.afterSaleReturnReasons.map((v) => {
return {
id: v,
title: v,
}
})
break
}
}
const doSubmit = async () => {
if (isEmpty(applyForm.reasonStr)) {
uni.showToast({ title: "请选择申请原因", icon: "none" })
return
}
const _pa = {
way: applyForm.way,
refundPrice: state.detail.practicalTotalPrice,
orderId: state.detailId,
images: [],
applyReason: applyForm.reasonStr,
applyDescription: applyForm.remark,
applyPicUrls: applyPicUrls.value,
}
try {
uni.showLoading({ title: "申请中...", mask: false })
const data = await refundApi.create(_pa)
uni.hideLoading()
uni.showToast({ title: "申请成功", icon: "none" })
router.jump("/pages/order/detail", { id: state.detailId }, 2)
} catch (error) {
console.error(error)
uni.hideLoading()
}
}
</script>
<template>
<crud-layout title="申请售后" mainIsScroll bg="/static/page/blue-bg.png">
<view class="h-30rpx" />
<view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx">
<view class="m-t-15rpx">
<view
class="flex-row items-start justify-between"
v-for="(v, i) in state.shopCarList"
:key="i"
@tap.stop="router.jump('/pages/merchant/product-detail', { id: v.productId })"
>
<view class="flex-row items-center">
<image class="w-160rpx h-160rpx rounded-8rpx" :src="filePath(v.productPic)" mode="aspectFill" />
<view class="flex-col m-l-15rpx second-text-26">
<view class="sub-text-28">{{ v.productName }}</view>
<view class="m-t-5rpx">¥ {{ hooks.useMoney(v.productPrice) }}</view>
<view class="m-t-5rpx">x {{ v.productCount }}</view>
</view>
</view>
<view class="flex-row-center">
<view class="sub-text-32">¥ {{ hooks.useMoney(v.totalPrice) }}</view>
</view>
</view>
<view class="m-y-15rpx h-1px bg-#999 bg-opacity-5" />
<view class="flex-row items-center justify-between">
<view class="sub-text-28">实付款</view>
<view class="flex-row items-end">
<view class="sub-text-28">¥</view>
<view class="m-l-5rpx sub-text-28">{{ hooks.useMoney(state.detail.payPrice) }}</view>
</view>
</view>
</view>
</view>
<view class="card p-x-20rpx p-y-30rpx m-b-20rpx">
<view class="sub-text-28">售后类型</view>
<view class="m-t-20rpx">
<tm-radio-group @change="radioChange" direction="column" gap="20" v-model="applyForm.way">
<tm-radio :disabled="v.disabled" v-for="(v, i) in data.payType" :key="i" v-show="v.visible" :value="v.type" :label="v.text" />
</tm-radio-group>
</view>
</view>
<view class="flex-row items-center justify-between card p-x-20rpx p-y-30rpx m-b-20rpx">
<view class="sub-text-28">退款金额</view>
<view class="sub-text-28 color-red!">¥{{ hooks.useMoney(state.detail.payPrice) }}</view>
</view>
<view class="card p-x-20rpx p-y-30rpx m-b-20rpx">
<tm-picker
rang-key="title"
rang-text="title"
v-model="applyForm.reason"
v-model:model-str="applyForm.reasonStr"
:list="state.selectList"
>
<view class="flex-row items-center justify-between">
<view class="sub-text-28">申请原因</view>
<view class="flex-row items-center second-text-24">
<text>{{ applyForm.reasonStr || "请选择申请原因" }} </text>
<text class="m-l-10rpx color-#b1b1b1 iconfont icon-xiangxiajiantouxiao" />
</view>
</view>
</tm-picker>
</view>
<view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx">
<view class="sub-text-28">补充凭证图片</view>
<view class="m-t-20rpx">
<tm-upload-photo
v-model="uploadApplyPicUrls"
:maxFileSize="1024 * 1024 * 5"
:url="'/api/admin/sys-file/upload'"
:header="state.header"
:maxCount="6"
/>
</view>
<view class="sub-text-20 c-red!">注:图片大小不超过5M,最多上传6张</view>
</view>
<view class="flex-col justify-center card p-x-20rpx p-y-30rpx m-b-20rpx">
<view class="sub-text-28">相关描述</view>
<view class="m-t-20rpx">
<tm-input v-model="applyForm.remark" type="textarea" :showClear="false" placeholder="客官~请描述您遇到的问题"></tm-input>
</view>
</view>
<view class="h-30rpx" />
<template #main-bottom>
<view
v-if="state.detailType != 'view'"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-y-30rpx sub-text-30 color-white!"
@tap="doSubmit"
>
提交申请
</view>
</template>
</crud-layout>
</template>
<style lang="scss" scoped></style>