2025-04-01 09:03:51 +08:00

631 lines
20 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.

<template>
<view style="background: #F1F2F8;min-height: 100vh;">
<view style="padding: 30rpx 30rpx 250rpx 30rpx;">
<view style="background-color: #ffffff;border-radius: 20rpx;padding:30rpx">
<view style="display: flex;align-self: center;align-items: start;">
<view style="width: 45%;">
<image :src="infoRefund.detail.headimage" style="width: 280rpx; height: 200rpx;"
mode="aspectFill">
</image>
</view>
<view style="padding-left: 20rpx;">
<view style="font-size: 36rpx;font-weight: 600;">{{infoRefund.detail.title}}</view>
<view style="font-size: 26rpx;color: #7A7A7A;margin-top: 15rpx;">
<image src="/static/center/address.png"
style="width: 40rpx;height: 40rpx;vertical-align: middle;"></image>
<text style="vertical-align: middle;">{{infoRefund.detail.address}}</text>
</view>
</view>
</view>
<view style="height: 1px;width: 70%;background: #D9D9D9;margin: 45rpx auto;"></view>
<view v-if="infoRefund!=''" class="item-spacing"
style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">当前状态</view>
<view style="color: #FF6D6D;" v-if="infoRefund.service_stauts==1">机构处理中</view>
<view style="color: #FF6D6D;" v-if="infoRefund.service_stauts==4">待用户确认</view>
<view style="color: #FF6D6D;" v-if="infoRefund.service_stauts==7">结算中</view>
<view style="color: #FF6D6D;" v-if="infoRefund.service_stauts==10">已完成</view>
<view style="color: #FF6D6D;" v-if="infoRefund.service_stauts==-3">驳回</view>
</view>
<view class="item-spacing" style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">课程机构</view>
<view style="color: #343434;">{{infoRefund.shop.name}}</view>
</view>
<view class="item-spacing" style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">讲师/电话</view>
<view style="color: #343434;" @click="callPhone(infoRefund.shop.tel)">
<text
style="vertical-align: middle;">{{infoRefund.detail.teacher.name}}/{{infoRefund.shop.tel}}</text>
<image src="/static/tel.png" style="width: 40rpx;height: 40rpx;vertical-align: middle;"></image>
</view>
</view>
<view class="item-spacing" style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">订单号</view>
<view style="color: #343434;">{{infoRefund.order_no}}</view>
</view>
<view class="item-spacing" style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">购买时间</view>
<view style="color: #343434;">
{{ infoRefund.detail ? formatTimestamp(infoRefund.detail.createtime) : '加载中...' }}
</view>
</view>
<view class="item-spacing" style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">全部课时</view>
<view style="color: #343434;">{{infoRefund.detail.classes_num}}</view>
</view>
<view class="item-spacing" style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">已用课时</view>
<view style="color: #343434;">{{infoRefund.detail.use_num}}</view>
</view>
<view style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">购买价格</view>
<view style="color: #FF5F5F;">¥{{infoRefund.detail.price}}</view>
</view>
<!-- 待用户确认 -->
<template v-if="infoRefund!=''&&infoRefund.service_stauts == 4">
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">商家退款金额</view>
<view style="color: #FF2323;font-size: 40rpx;font-weight: 600;">
¥{{infoRefund.tbc_price}}</view>
</view>
</template>
<!-- 结算中 -->
<template v-if="infoRefund!=''&&infoRefund.service_stauts == 7">
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">商家退款金额</view>
<view style="color: #FF2323;font-size: 40rpx;font-weight: 600;">
¥{{infoRefund.c_price}}</view>
</view>
</template>
<!-- 已完成 -->
<template v-if="infoRefund!=''&&infoRefund.service_stauts == 10">
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view style="display: flex; justify-content: space-between; font-size: 26rpx;">
<view style="color: #7A7A7A;">商家退款金额</view>
<view style="color: #FF2323;font-size: 40rpx;font-weight: 600;">
¥{{infoRefund.real_refundprice}}</view>
</view>
</template>
</view>
<template v-if="infoRefund!=''">
<view style="background-color: #ffffff;border-radius: 20rpx;padding:30rpx;margin-top: 30rpx;">
<view class="flex space-between flex-column"
style="font-size: 26rpx;color: #7A7A7A;align-items: flex-start">
<view>
<text>退款原因</text>
</view>
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 500;font-size: 24rpx;color: #343434;">
{{infoRefund.reason}}
</view>
</view>
</view>
<view v-if="infoRefund.sales_type==1"
style="background-color: #ffffff;border-radius: 20rpx;padding:30rpx;margin-top: 30rpx;">
<view class="flex align-items space-between" style="font-size: 26rpx;color: #7A7A7A;">
<view>
<text>机构驳回退款原因</text>
</view>
</view>
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view style="font-size: 26rpx;">{{infoRefund.reject_reason}}</view>
<view style="margin-top: 20rpx;">
<u-grid :border="false" :col="3" align="center">
<u-grid-item v-for="(item,index) in infoRefund.reject_images" @click="clickImg(item,index)">
<image :src="item" style="width: 200rpx;height: 200rpx;border-radius: 20rpx;"
mode="aspectFill">
</image>
</u-grid-item>
</u-grid>
</view>
</view>
<view v-if="infoRefund.sales_type==4"
style="background-color: #ffffff;border-radius: 20rpx;padding:30rpx;margin-top: 30rpx;">
<view class="flex align-items space-between" style="font-size: 26rpx;color: #7A7A7A;">
<view>
<text>用户驳回退款原因</text>
</view>
</view>
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view style="font-size: 26rpx;">{{infoRefund.reject_reason}}</view>
<view style="margin-top: 20rpx;">
<u-grid :border="false" @click="click" :col="3" align="center">
<u-grid-item v-for="(item,index) in infoRefund.reject_images">
<image :src="item" style="width: 200rpx;height: 200rpx;border-radius: 20rpx;"
mode="aspectFill">
</image>
</u-grid-item>
</u-grid>
</view>
</view>
<view v-if="infoRefund.sales_type==7"
style="background-color: #ffffff;border-radius: 20rpx;padding:30rpx;margin-top: 30rpx;">
<view class="flex align-items space-between" style="font-size: 26rpx;color: #7A7A7A;">
<view>
<text>平台驳回退款原因</text>
</view>
</view>
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view style="font-size: 26rpx;">{{infoRefund.reject_reason}}</view>
</view>
</template>
</view>
<view class="buttonClack" v-if="infoRefund.service_stauts==1 || infoRefund.service_stauts==4 || infoRefund==''">
<view class="flex align-items" style="text-align: center;justify-content: space-around;">
<view style="width: 100%;" v-if="infoRefund.service_stauts==1">
<view @click="cancelOrder"
style="margin: 0 auto;color: #ffffff;;background-color: #008CFF;width: 80%;height: 80rpx;border-radius: 80rpx;line-height: 80rpx;">
取 消</view>
</view>
<view style="width: 100%;" v-if="infoRefund==''">
<view @click="submitAdd"
style="margin: 0 auto;background-color: #008CFF;color: #ffffff;width: 80%;height: 80rpx;border-radius: 80rpx;line-height: 80rpx;">
申 请 售 后</view>
</view>
<template v-if="infoRefund.service_stauts==4">
<view>
<view @click="refuseShowOpen('no')"
style="border:2rpx solid #008CFF;color: #008CFF;;background-color: #ffffff;width: 300rpx;height: 80rpx;border-radius: 80rpx;line-height: 80rpx;">
不同意</view>
</view>
<view>
<view @click="refuseShowOpen('yes')"
style="color: #ffffff;;background-color: #008CFF;width: 300rpx;height: 80rpx;border-radius: 80rpx;line-height: 80rpx;">
同意</view>
</view>
</template>
</view>
</view>
<u-popup :show="refundShow" :round="10" :closeOnClickOverlay="true" @close="delShow">
<view style="padding: 30rpx 30rpx 0rpx 30rpx;">
<view>
<text style="font-size: 32rpx;">退款原因</text>
<text style="color: #FF5F5F;font-size: 24rpx;">(必选)</text>
</view>
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view>
<u-radio-group v-model="radioValue" placement="column" activeColor="#008CFF">
<u-radio v-for="(item,index) in radioList" :name="index" :label="item"
:customStyle="{marginBottom: '20rpx'}"></u-radio>
</u-radio-group>
<view>
<u--textarea v-model="otherText" placeholder="请填写退款原因" :maxlength="150" count></u--textarea>
</view>
</view>
<view style="padding-top: 30rpx;">
<view @click="chickRadio"
style="text-align: center;margin: 0rpx auto;background-color: #008CFF;color: #ffffff;width: 90%;height: 90rpx;border-radius: 90rpx;line-height: 90rpx;">
确 认</view>
</view>
</view>
</u-popup>
<u-popup :show="refuseShow" :round="10" mode="center" :customStyle="{width:'90%'}" :closeOnClickOverlay="false">
<view style="padding: 30rpx 30rpx 0rpx 30rpx;">
<view class="flex space-between align-items">
<view>
<text style="font-size: 40rpx;color: #008CFF;font-weight: 600;">详情</text>
</view>
<view @click="delShow">
<u-icon name="close" color="#008CFF" size="32px"></u-icon>
</view>
</view>
<view style="height: 1px;width: 100%;background: #D9D9D9;margin: 20rpx auto;"></view>
<view>
<view>
<u--textarea v-model="otherText" placeholder="请填写拒绝理由" :maxlength="150" count></u--textarea>
</view>
</view>
<view>
<view style="color: #7A7A7A;font-size: 24rpx;padding: 20rpx 0rpx;">图片补充(最多上传三张)</view>
<u-upload :fileList="fileList" @afterRead="afterRead" @delete="deletePic" multiple :maxCount="3"
:previewFullImage="true" width="180rpx" :maxSize="3*1024*1024" height="180rpx" @oversize="oversize">
<image src="/static/index/upload.png" style="width: 180rpx;height: 180rpx;">
</u-upload>
</view>
<view class="flex align-items"
style="text-align: center;justify-content: space-around;padding-top: 30rpx; margin-bottom: 34rpx;">
<view>
<view @click="refuseShow = false"
style="border:2rpx solid #008CFF;color: #008CFF;;background-color: #ffffff;width: 300rpx;height: 80rpx;border-radius: 80rpx;line-height: 80rpx;">
</view>
</view>
<view>
<view @click="userConfirmation()"
style="color: #ffffff;;background-color: #008CFF;width: 300rpx;height: 80rpx;border-radius: 80rpx;line-height: 80rpx;">
</view>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data() {
return {
refundShow: false,
radioValue: '',
//拒绝理由
otherText: '',
refuseShow: false,
fileList: [],
list: '',
id: 0,
info: {},
infoRefund: '',
myReason: '',
radioList: ['没有时间上课', '课程内容不符合预期', '位置不便', '其他课程时间冲突', '课程延期', '其他'],
classes_service_order_id: 0,
user_status: '',
};
},
onLoad(op) {
this.classes_service_order_id = op.id;
this.getRefundInfo();
//this.getOrderInfo();
//classes_service_order_id
},
computed: {
},
methods: {
formatTimestamp(timestamp) {
const date = new Date(timestamp * 1000); // 乘以1000转换为毫秒
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
refuseShowOpen(status) {
var that = this;
this.user_status = status;
if (status == 'no') {
this.refuseShow = true;
} else {
uni.showModal({
title: '提示',
content: '确定要同意吗?',
success: function(res) {
if (res.confirm) {
that.userConfirmation();
}
}
});
}
},
oversize(e) {
this.$u.toast("请传6MB以内大小的图片");
return false;
},
//用户处理售后接口
userConfirmation() {
if (this.otherText == '' && this.user_status == 'no') {
uni.showToast({
title: '请填写原因!',
icon: 'none',
duration: 2000
});
return;
}
uni.$u.http.post('/api/school.service_order/user_confirmation', {
order_no: this.classes_service_order_id,
status: this.user_status,
reject_reason: this.otherText,
reject_images: this.list,
}).then(res => {
console.log(res);
if (res.code == 1) {
uni.showToast({
title: '提交成功!',
icon: 'none',
duration: 2000
});
this.refuseShow = false;
this.getRefundInfo();
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
});
},
//取消订单确认
cancelOrder() {
var that = this;
uni.showModal({
title: '提示',
content: '确定要撤销售后订单吗?',
success: function(res) {
if (res.confirm) {
that.cancelOrderDo();
}
}
});
},
//取消订单
cancelOrderDo() {
uni.$u.http.post('/api/school.service_order/cancel', {
order_no: this.classes_service_order_id,
}).then(res => {
console.log(res);
if (res.code == 1) {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
this.infoRefund = '';
this.getOrderInfo();
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
});
},
//选择退款原因
chickRadio() {
var reason = "";
if (this.radioValue === '') {
uni.showToast({
title: '请选择原因!',
icon: 'none',
duration: 2000
});
return;
} else {
if (this.radioValue != 5) {
reason = this.radioList[this.radioValue];
} else {
reason = this.otherText;
}
}
this.refundShow = false;
this.myReason = reason;
},
//提交售后订单
submitAdd() {
console.log(this.radioValue);
var reason = "";
if (this.radioValue === '') {
uni.showToast({
title: '请选择原因!',
icon: 'none',
duration: 2000
});
return;
} else {
if (this.radioValue != 5) {
reason = this.radioList[this.radioValue];
} else {
reason = this.otherText;
}
}
uni.$u.http.post('/api/school.service_order/create', {
classes_order_id: this.id,
reason: reason,
}).then(res => {
console.log(res);
if (res.code == 1) {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
this.getOrderInfo();
} else {
uni.showToast({
title: res.msg,
icon: 'none',
duration: 2000
});
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
});
},
//订单详情
getOrderInfo() {
uni.$u.http.get('/api/school/order/detail', {
params: {
id: this.id
}
}).then(res => {
this.info = res.data.detail;
if (res.data.detail.classes_service_order_id != 0 && res.data.detail
.classes_service_order_id != null && res.data.detail.classes_service_order_id != '') {
this.classes_service_order_id = res.data.detail.classes_service_order_id;
this.getRefundInfo(res.data.detail.classes_service_order_id);
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
});
},
//售后详情
getRefundInfo() {
uni.$u.http.get('/api/school.service_order/detail', {
params: {
id: this.classes_service_order_id
}
}).then(res => {
if (res.data.detail == null) {
this.infoRefund = '';
} else {
this.infoRefund = res.data.detail;
}
}).catch(error => {
uni.showToast({
title: '请求失败,请稍后再试',
icon: 'none',
duration: 2000
});
});
},
delShow() {
this.refundShow = false;
this.refuseShow = false;
},
clickImg(item, index) {
uni.previewImage({
current: index,
urls: [item],
});
},
// 删除图片
deletePic(event) {
console.log(event);
const {
index
} = event;
if (index >= 0 && index < this.fileList.length) {
this.fileList.splice(index, 1);
this.list = this.fileList.map(item => item.url).join(',');
// 确保对应的 list 字段是一个数组
let list = this.list;
if (!Array.isArray(list)) {
console.warn(`list is not an array, skipping splice operation`);
} else {
list.splice(index, 1);
console.log(`Updated list`, list);
}
} else {
console.error('Invalid index');
}
},
// 新增图片
async afterRead(event) {
let lists = [].concat(event.file);
let fileListLen = this.fileList.length;
lists.map((item) => {
this.fileList.push({
...item,
status: 'uploading',
message: '上传中'
});
});
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url);
let item = this.fileList[fileListLen];
this.fileList.splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result
}));
fileListLen++;
// 更新对应的list字段
this.list = this.fileList.map(item => item.url).join(',');
}
},
//图片上传
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: 'https://testy.hschool.com.cn//api/common/upload', // 仅为示例,非真实的接口地址
filePath: url,
name: 'file',
formData: {
user: 'test'
},
header: {
"token": uni.getStorageSync("token")
},
success: (res) => {
resolve(JSON.parse(res.data).data.fullurl);
},
fail: (err) => {
reject(err);
}
});
});
},
callPhone(phone) {
uni.makePhoneCall({
phoneNumber: phone
})
}
}
}
</script>
<style lang="scss" scoped>
page {
background-color: #F1F2F8;
}
.buttonClack {
padding-top: 20rpx;
position: fixed;
bottom: 0;
width: 100%;
height: 100rpx;
background-color: #ffffff;
padding-bottom: calc(env(safe-area-inset-bottom));
box-shadow: 0rpx -6rpx 12rpx 0rpx rgba(111, 190, 255, 0.1);
}
.item-spacing {
padding-bottom: 30rpx;
}
.w-100 {
width: 100%;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.space-between {
justify-content: space-between;
}
.align-items {
align-items: center;
}
.flex-column {
flex-flow: column;
}
.justify-start {
justify-content: start;
}
.mar-top-30 {
margin-top: 30rpx;
}
</style>