433 lines
9.4 KiB
Vue
Raw Normal View History

2025-05-08 09:16:37 +08:00
<template>
<view class="contBox">
<view class="oneBox box">
<view class="item" v-for="item in goodsList" :key="item.id">
<image :src="item.pic_url" mode="aspectFill"></image>
<view class="right">
<view class="txtBox flex">
<text class="name">{{item.goods_name}}</text>
<view class="price">
<text class="icon"></text>
<text>{{item.price}}</text>
</view>
</view>
<view class="sku flex">
<text>{{item.sku_name}}</text>
<text>x{{item.number}}</text>
</view>
</view>
</view>
</view>
<view class="twoBox box">
<view class="item flex" style="border-bottom: 1px solid #f5f5f5;">
<view>退款方式</view>
<view class="text">仅退款</view>
</view>
<view class="item flex" @click="showReason = true">
<view>退款原因</view>
<view style="display: flex;align-items: center;">
<view class="text">{{columnsValue}}</view>
<up-icon name="arrow-right" size="15" style="color: #98989F;" />
</view>
</view>
</view>
<view class="threeBox flex">
<view>退款金额</view>
<view class="price">{{refund_price}}</view>
</view>
<view class="fourBox">最多可退{{refund_price}}含运费{{order.freight_price}}退款将返还实际支付金额</view>
<view class="spBox">
<view class="sp">退款说明</view>
<up-textarea v-model="message" count placeholder="选填最多200字" style="font-size: 28rpx;" :height="70" :maxlength="200"></up-textarea>
</view>
<view class="refundImg">
<view class="tit">上传凭证</view>
<view class="comment">
<view class="imgBox">
<view class="imgList" v-for="(item, i) in picList" :key="i">
<image :src="item.url" mode="aspectFill" class="img"></image>
<view @click="deleteImage(i)" class="close"><view class="heng"></view></view>
</view>
<view @click="uploadImage()" class="plus" v-if="picList.length == 3 ? false : true">
<up-icon name="camera-fill" color="#E0E0E0" size="22" />
<text>图片上传</text>
</view>
</view>
<text style="color:#98989F; font-size: 26rpx;">可上传3张图片</text>
</view>
</view>
<view class="comment-btn" @click="submitBtn()">提交</view>
<div class="top" v-if="success">申请退款成功</div>
<!-- 退款原因 -->
<up-popup :show="showReason" :round="10" mode="bottom" close-on-click-overlay closeable @close="showReason = false">
<view class="reasonbox">
<view class="title">退款原因</view>
<view class="list">
<view class="row flex" v-for="(item, i) in reasonList" :key="i" @click="onConfirm(item, i)">
<view class="tit">{{item}}</view>
<up-icon v-if="i + 1 === reasonIndex" name="checkbox-mark" :color="Color" size="20" />
</view>
</view>
</view>
</up-popup>
<!-- 隐私协议弹窗 -->
<privacy-popup :show-dialog="showPrivacy" @close="showPrivacy = false" @agree="showPrivacy = false" @refuse="showPrivacy = false" />
</view>
</template>
<script>
import { ref, reactive, toRefs } from 'vue'
import { get, post } from '@/api/request.js'
import api from '/api/index'
import { showToast, judgePrivacy } from '@/components/common.js'
import { Style } from '@/utils/list.js'
import privacyPopup from '@/components/privacyPopup/index.vue'
export default {
components: {
privacyPopup
},
setup() {
const data = reactive({
goodsList: [],
refund_price: '',
itemIds: [],
success: false,
reasonList: [
'多拍/错拍/不想要',
'未按约定时间发货',
'配送时间太长',
'协商一致退款',
'其他'
],
message: '',
picList: [],
order: {},
columnsValue: '请选择',
urls: api.url + '/api/v1/upload',
showReason: false,
reasonIndex: 0,
odeId: '',
Color: uni.getStorageSync('theme_color'),
priceColor: Style[uni.getStorageSync('theme_index') * 1].priceColor,
showPrivacy: false
})
const getValue = (val) => {
data.message = val.detail
}
const uploadImage = async () => {
if(await judgePrivacy()) {
data.showPrivacy = true
return false
}
uni.chooseImage({
success(res) {
uni.showLoading({
title: '正在上传...',
mask: true
})
const tempFilePaths = res.tempFilePaths
for (let i = 0; i < tempFilePaths.length; i++) {
uni.uploadFile({
url: data.urls,
filePath: tempFilePaths[i],
name: 'file',
header: {
Authorization: uni.getStorageSync('token') || '',
accept: 'application/json',
appid: api.appId
},
success(ress) {
var img = JSON.parse(ress.data).data
data.picList.push({
url: img.link
})
}
})
}
uni.hideLoading()
}
})
}
const deleteImage = (i) => {
data.picList.splice(i, 1)
}
const onConfirm = (event, index) => {
data.columnsValue = event
data.reasonIndex = index + 1
data.showReason = false
}
const submitBtn = () => {
if (!data.reasonIndex) {
showToast('请选择退款原因')
return
}
uni.showLoading({
title: '退款中...',
mask: true
})
post(`/api/v1/orderRefund/batch/refund`, {
order_item_ids: data.itemIds,
user_pic_urls: data.picList,
user_refund_reason: data.reasonIndex,
user_refund_des: data.message
}).then((res) => {
data.success = true
setTimeout(() => {
uni.redirectTo({
url: '/pages/order/info/index?id=' + data.odeId
})
data.success = false
}, 1000)
uni.hideLoading()
})
}
function getItemsInfo(id) {
get(`/api/v1/orderRefund/items/${id}`).then((res) => {
data.goodsList = res.data.order_items
data.refund_price = res.data.refund_price
data.itemIds = res.data.order_item_ids
data.order = res.data.order
})
}
return {
...toRefs(data),
uploadImage,
deleteImage,
onConfirm,
submitBtn,
getValue,
getItemsInfo
}
},
onLoad(options) {
this.odeId = options.id
this.getItemsInfo(options.order_id)
}
}
</script>
<style lang="scss" scoped>
.top{
position: fixed;
top: 40%;
left: 50%;
transform: translate(-50%);
background: rgba(0, 0, 0, 0.7);
color: #fff;
font-size: 26rpx;
padding: 24rpx;
border-radius: 10rpx;
}
.reasonbox{
padding: 0 30rpx;
min-height: 50vh;
.title{
font-size: 30rpx;
color: #303030;
font-weight: bold;
padding: 30rpx 0;
border-bottom: 1rpx solid #E5E5E5;
}
.list{
padding-bottom: 100rpx;
.row{
padding: 20rpx 0;
.tit{
font-size: 28rpx;
color: #707070;
}
}
}
}
.flex{
display: flex;
justify-content: space-between;
align-items: center;
}
.contBox{
padding: 24rpx;
.box{
background: #fff;
border-radius: 10rpx;
padding: 0 24rpx 10rpx 24rpx;
margin-bottom: 24rpx;
}
.oneBox{
padding: 0 24rpx;
.item{
display: flex;
height: 144rpx;
padding: 24rpx 0;
border-top: 1px solid #f5f5f5;
&:first-child{
border-top: none;
}
image {
width: 144rpx;
height: 100%;
background: #cbcacb;
border-radius: 10rpx;
margin-right: 20rpx;
}
.right{
font-size: 28rpx;
flex: 1;
.txtBox{
color: #333;
.name{
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
flex: 1;
}
.icon{
font-size: 24rpx;
}
}
.sku{
font-size: 24rpx;
color: #999999;
margin-top: 24rpx;
}
}
}
}
.twoBox{
.item{
padding: 20rpx 0;
font-size: 28rpx;
color: #333;
}
}
}
.threeBox{
height: 86rpx;
font-size: 28rpx;
background: #fff;
border-radius: 10rpx;
padding: 0 20rpx;
margin-bottom: 24rpx;
color: #333;
.price{
color: v-bind('priceColor');
}
}
.spBox{
padding: 20rpx;
background: #fff;
border-radius: 10rpx;
margin-bottom: 24rpx;
font-size: 28rpx;
color: #333;
.sp{
margin-bottom: 20rpx;
}
}
.fourBox{
font-size: 24rpx;
color: #98989f;
text-align: center;
margin-bottom: 24rpx;
}
.refundImg{
padding: 20rpx;
box-sizing: border-box;
display: flex;
background: #fff;
.tit{
color:#303030;
font-size: 28rpx;
width: 130rpx;
}
}
.imgBox{
display: flex;
align-items: center;
flex-wrap: wrap;
.imgList{
width: 160rpx;
height: 160rpx;
margin: 0 20rpx 20rpx 0;
position: relative;
.img{
width: 100%;
height: 100%;
border-radius: 8rpx;
}
.close{
position: absolute;
right: -15rpx;
top: -20rpx;
color: #fff;
width: 40rpx;
height: 40rpx;
background-color: rgba(0,0,0,0.6);
border-radius: 50%;
.heng{
display: block;
width: 24rpx;
height: 4rpx;
background-color: #fff;
margin: 18rpx auto;
}
}
}
.plus{
border: 1px solid #e1e1e1;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 160rpx;
height: 160rpx;
box-sizing: border-box;
margin: 0 20rpx 20rpx 0;
text{
font-size: 24rpx;
color: #DBDBDB;
}
}
}
.comment-btn{
margin-top: 60rpx;
width: 80%;
background-color: v-bind('Color');
color: #fff;
height: 86rpx;
line-height: 86rpx;
font-size: 30rpx;
text-align: center;
border-radius: 49rpx;
margin-left: 10%;
}
</style>