This commit is contained in:
1154079537 2024-06-08 13:42:16 +08:00
parent 1dcbd2046b
commit 6f4cd56087
11 changed files with 1367 additions and 168 deletions

View File

@ -2,12 +2,6 @@
export default { export default {
onLaunch: function() { onLaunch: function() {
console.log('App Launch'); console.log('App Launch');
uni.addInterceptor('navigateTo', {
invoke(e) {
console.log('路由监听');
console.log(e);
}
})
}, },
onShow: function() { onShow: function() {
console.log('App Show') console.log('App Show')

View File

@ -59,4 +59,19 @@ export const writeCountApi = (data) => {
// 根据核销码查询记录 // 根据核销码查询记录
export const writeCodeApi = (data) => { export const writeCodeApi = (data) => {
return request.post('/order/order/write_code', data); return request.post('/order/order/write_code', data);
}
// 取消售后
export const cancelSaleApi = (data) => {
return request.get('/order/order/cancel_sale', data);
}
// 订单退款原因
export const refundReasonListApi = (data) => {
return request.post('/order/order/refund_reason', data);
}
// 订单退款申请
export const applyRefundApi = (data) => {
return request.post('/order/order/apply_refund', data);
} }

View File

@ -1,149 +1,151 @@
<template> <template>
<up-popup :show="show" closeable round="10" @close="close"> <up-popup :show="show" closeable round="10" @close="close">
<view class="address-popup"> <view class="address-popup">
<view class="head-title">收货人与详细地址</view> <view class="head-title">收货人与详细地址</view>
<view class="list-admin"> <view class="list-admin">
<view>常用地址</view> <view>常用地址</view>
<view class="admin-btn"> <view class="admin-btn">
<view class="btn" @click="navTo('/pagesOrder/addressList/addressList')"><up-icon name="edit-pen" <view class="btn" @click="navTo('/pagesOrder/addressList/addressList')"><up-icon name="edit-pen"
color="#20B128"></up-icon></view> color="#20B128"></up-icon></view>
<view class="btn" @click="navTo('/pagesOrder/addressEdit/addressEdit')"><up-icon name="plus" <view class="btn" @click="navTo('/pagesOrder/addressEdit/addressEdit')"><up-icon name="plus"
color="#20B128"></up-icon></view> color="#20B128"></up-icon></view>
</view> </view>
</view> </view>
<scroll-view style="height: 600rpx;padding-bottom: 20rpx;" scroll-y> <scroll-view style="height: 600rpx;padding-bottom: 20rpx;" scroll-y>
<view class="row" v-for="(item,index) in list" :key="index" @click="addressType=item.address_id"> <view class="row" v-for="(item,index) in list" :key="index" @click="addressType=item.address_id">
<view class="content"> <view class="content">
<view class="top"> <view class="top">
<view class="name">{{item.real_name}}</view> <view class="name">{{item.real_name}}</view>
<view class="phone">{{item.phone}}</view> <view class="phone">{{item.phone}}</view>
<u-tag v-if="item.is_default" style="pointer-events: none;" text="默认" type="success" plain <u-tag v-if="item.is_default" style="pointer-events: none;" text="默认" type="success" plain
size="mini"></u-tag> size="mini"></u-tag>
</view> </view>
<view class="bottom u-line-2">{{item.detail}}</view> <view class="bottom u-line-2">{{item.detail}}</view>
</view> </view>
<image v-if="addressType==item.address_id" src="@/static/icon/check.png"></image> <image v-if="addressType==item.address_id" src="@/static/icon/check.png"></image>
<image v-else src="@/static/icon/n-check.png"></image> <image v-else src="@/static/icon/n-check.png"></image>
</view> </view>
</scroll-view> </scroll-view>
<up-button color="#20B128" shape="circle" @click="submitAddress">确认</up-button> <up-button color="#20B128" shape="circle" @click="submitAddress">确认</up-button>
</view> </view>
</up-popup> </up-popup>
</template> </template>
<script setup> <script setup>
import { ref } from "vue" import {
ref
} from "vue"
const addressType = ref(-1) const addressType = ref(-1)
const props = defineProps({ const props = defineProps({
show: { show: {
type: Boolean, type: Boolean,
default: false default: false
}, },
list: { list: {
type: Array, type: Array,
default: () => [] default: () => []
}, },
}) })
const emit = defineEmits(['close', 'change']); const emit = defineEmits(['close', 'change']);
const close = () => { const close = () => {
emit('close'); emit('close');
} }
const submitAddress = () => { const submitAddress = () => {
let e = props.list.find(item=>item.address_id==addressType.value); let e = props.list.find(item => item.address_id == addressType.value);
if(addressType.value<=0 || !e) return uni.$u.toast('请选择地址'); if (addressType.value <= 0 || !e) return uni.$u.toast('请选择地址');
emit('change', e); emit('change', e);
} }
const navTo = (url) => { const navTo = (url) => {
uni.navigateTo({ uni.navigateTo({
url: url url: url
}) })
} }
const setCheck = (e)=>{ const setCheck = (e) => {
addressType.value = e; addressType.value = e;
} }
defineExpose({ defineExpose({
setCheck setCheck
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.address-popup { .address-popup {
padding: 30rpx; padding: 30rpx;
.head-title { .head-title {
font-weight: bold; font-weight: bold;
text-align: center; text-align: center;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.list-admin { .list-admin {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: 20rpx; margin-bottom: 20rpx;
.admin-btn { .admin-btn {
display: flex; display: flex;
color: #20B128; color: #20B128;
.btn { .btn {
margin-left: 20rpx; margin-left: 20rpx;
display: flex; display: flex;
align-items: center; align-items: center;
&:active { &:active {
color: rgba(#20B128, 0.8); color: rgba(#20B128, 0.8);
transition: background-color 0.5s; transition: background-color 0.5s;
animation: disappear 0.5s 0.5s forwards; animation: disappear 0.5s 0.5s forwards;
} }
} }
} }
} }
.row { .row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding-bottom: 20rpx; padding-bottom: 20rpx;
border-bottom: 1rpx solid #f6f6f6; border-bottom: 1rpx solid #f6f6f6;
margin-bottom: 20rpx; margin-bottom: 20rpx;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
margin-bottom: 0; margin-bottom: 0;
} }
.content { .content {
.top { .top {
display: flex; display: flex;
view { view {
margin-right: 20rpx; margin-right: 20rpx;
} }
} }
.bottom {} .bottom {}
} }
image { image {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
flex-shrink: 0; flex-shrink: 0;
} }
} }
} }
@keyframes disappear { @keyframes disappear {
to { to {
opacity: 0; opacity: 0;
/* 渐隐 */ /* 渐隐 */
transform: scale(0); transform: scale(0);
/* 缩小 */ /* 缩小 */
} }
} }
</style> </style>

View File

@ -9,7 +9,6 @@
} }
}, },
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages "pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{ {
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
@ -49,20 +48,36 @@
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, }, {
{
"path": "pages/charge/charge_record", "path": "pages/charge/charge_record",
"style": { "style": {
"navigationBarTitleText": "充值记录", "navigationBarTitleText": "充值记录",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
}, }, {
{
"path": "pages/charge/charge", "path": "pages/charge/charge",
"style": { "style": {
"navigationBarTitleText": "会员充值", "navigationBarTitleText": "会员充值",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
}, {
"path": "pages/afterSales/afterSales",
"style": {
"navigationBarTitleText": "售后退款",
"enablePullDownRefresh": false
}
}, {
"path": "pages/afterSales/afterSalesOrder",
"style": {
"navigationBarTitleText": "退款订单 ",
"enablePullDownRefresh": false
}
}, {
"path": "pages/afterSales/afterSalesOrderDetail",
"style": {
"navigationBarTitleText": "售后退款详情",
"enablePullDownRefresh": false
}
} }
], ],
"subPackages": [{ "subPackages": [{

View File

@ -0,0 +1,483 @@
<template>
<view class="afterSales">
<!-- 退款原因 -->
<view class="afterSales-detail">
<up-cell-group :border="false" class="cellGroup">
<up-cell title="退款原因" :value="refundForm.refund_message?refundForm.refund_message:'请选择'"
titleStyle="color:#444;font-size:30rpx;" isLink :required="true" @click="show = true"></up-cell>
<up-cell title="退款件数" :border="false">
<template #value>
<up-number-box v-model="refundForm.refund_num"></up-number-box>
</template>
</up-cell>
</up-cell-group>
</view>
<!-- 商品信息 -->
<view class="afterSales-goods">
<view class="afterSales-goods-wrap">
<view class="afterSales-goods-left">
<up-image width="140rpx" height="140rpx" border="8rpx"></up-image>
</view>
<view class="afterSales-goods-right">
<view class="afterSales-goods-right-title">
<text class="goods_name">黄牛牛腩</text>
<text class="goods_price">
<text style='font-size: 24rpx;'></text>
<text style="font-size: 32rpx;">10</text>
</text>
</view>
<view class="afterSales-goods-right-info">
<text class="goods_desc">牛腩块</text>
<text class="goods_num">x5</text>
</view>
</view>
</view>
<!-- <view class="afterSales-return">
<view class="afterSales-return-input">
<text>申请退款金额</text>
<up-input border="none" placeholder="最多可输入金额" fontSize="24rpx"
:placeholderStyle="{color:'#ccc',fontSize:'24rpx'}"></up-input>
</view>
<view class="afterSales-return-edit">
<view>
<text style='font-size: 24rpx;'></text>
<text style="font-size: 32rpx;">0.00</text>
</view>
<up-icon name="edit-pen" size="26" color="#989898"></up-icon>
</view>
</view> -->
</view>
<!-- 备注 -->
<view class="afterSales-remark">
<view class="afterSales-remark-title">
<view class="afterSales-remark-title-txt">备注说明</view>
<view class="afterSales-remark-title-count">0/200</view>
</view>
<view class="afterSales-remark-textarea">
<up-textarea :count="true"></up-textarea>
</view>
<view class="afterSales-remark-title">
<view class="afterSales-remark-title-txt">上传凭证</view>
</view>
<view class="afterSales-remark-img">
<up-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple
:maxCount="10"></up-upload>
</view>
</view>
<!-- btn -->
<view class="afterSales-btn">
<view class="afterSales-btn-wrap">
<text>提交申请</text>
</view>
</view>
<!-- 退款原因 -->
<up-popup :show="show" closeable round="10" @close="close">
<view class="address-popup">
<view class="head-title">退款原因</view>
<scroll-view style="height: 600rpx;padding-bottom: 20rpx;" scroll-y>
<block v-for="(item,index) in refundReasonList" :key="index">
<view class="row" @click="refundType = item.value">
<view class="content">
<view class="top"></view>
<view class="bottom u-line-2">{{item.value}}</view>
</view>
<image v-if="refundType==item.value" src="@/static/icon/check.png"></image>
<image v-else src="@/static/icon/n-check.png"></image>
</view>
</block>
</scroll-view>
<up-button color="#20B128" shape="circle" @click="onSubmitReason">提交</up-button>
</view>
</up-popup>
</view>
</template>
<script setup>
import {
reactive,
ref,
getCurrentInstance
} from "vue";
import {
orderListApi,
refundReasonListApi
} from "@/api/order.js";
import {
config
} from "@/config/app.js"
import {
onLoad,
onShow,
onReachBottom
} from "@dcloudio/uni-app";
import useUserStore from '@/store/user';
const userStore = useUserStore();
const instance = getCurrentInstance().proxy;
//
const show = ref(false);
const refundType = ref('');
const refundForm = reactive({
refund_message: '', //退
refund_num: '', //退
id: '', //id
old_cart_id: '', //id
refund_type: '', //0 退 1 退退 2
});
const shopInfo = ref(null);
//
const fileList1 = ref([]);
//
const deletePic = (event) => {
fileList1.value.splice(event.index, 1);
};
//
const afterRead = async (event) => {
let lists = [].concat(event.file);
let fileListLen = fileList1.value.length;
lists.map((item) => {
fileList1.value.push({
...item,
status: 'uploading',
message: '上传中',
});
});
for (let i = 0; i < lists.length; i++) {
const result = await uploadFilePromise(lists[i].url);
let item = fileList1.value[fileListLen];
fileList1.value.splice(fileListLen, 1, {
...item,
status: 'success',
message: '',
url: result,
});
fileListLen++;
}
};
const uploadFilePromise = (url) => {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: config.HTTP_REQUEST_URL + '/api/upload/image',
filePath: url,
name: 'file',
header: {
token: userStore.token
},
success: (res) => {
setTimeout(() => {
resolve(res.data.data);
}, 1000);
},
});
});
};
onLoad(() => {
getRefundReasonData();
const eventChannel = instance.getOpenerEventChannel();
eventChannel.on('orderDetail', function(data) {
shopInfo.value = data;
refundForm.value.id = shopInfo.value.order_id;
refundForm.value.old_cart_id = shopInfo.value.cart_id;
})
});
// 退
const onSubmitReason = () => {
show.value = false;
refundForm.refund_message = refundType.value;
}
//
const refundReasonList = ref([]);
const getRefundReasonData = () => {
refundReasonListApi().then(res => {
refundReasonList.value = res.data;
})
}
</script>
<style lang="scss" scoped>
.afterSales {
margin: 0 20rpx;
padding: 20rpx 0 200rpx 0;
.afterSales-detail {
background-color: #fff;
border-radius: 20rpx;
margin-bottom: 28rpx;
::v-deep.u-cell__title-text {
position: relative;
&::after {
content: "*";
display: block;
position: absolute;
right: -14rpx;
top: 50%;
transform: translateY(-50%);
font-size: 28rpx;
color: red;
}
}
}
.afterSales-goods {
background: #FFFFFF;
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 30rpx;
.afterSales-goods-wrap {
display: flex;
margin-bottom: 30rpx;
.afterSales-goods-left {
margin-right: 20rpx;
}
.afterSales-goods-right {
flex: 1;
.afterSales-goods-right-title {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.goods_name {
font-size: 28rpx;
color: #333333;
}
.goods_price {
font-weight: 600;
font-size: 24rpx;
color: #060606;
}
}
.afterSales-goods-right-info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
font-size: 24rpx;
color: #777777;
}
}
}
.afterSales-return {
display: flex;
justify-content: space-between;
align-items: center;
.afterSales-return-input {
display: flex;
align-items: center;
line-height: 28rpx;
text {
font-size: 28rpx;
color: #333333;
margin-right: 8rpx;
}
}
.afterSales-return-edit {
display: flex;
align-items: center;
text {
font-weight: 600;
font-size: 24rpx;
color: #060606;
}
.symbol {
font-size: 24rpx;
}
.num {
font-size: 32rpx;
}
}
}
}
.afterSales-remark {
padding: 30rpx;
background: #FFFFFF;
border-radius: 12rpx;
.afterSales-remark-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.afterSales-remark-title-txt {
font-size: 28rpx;
color: #444444;
}
.afterSales-remark-title-count {
font-size: 28rpx;
color: #989898;
}
}
.afterSales-remark-textarea {
margin-bottom: 30rpx;
}
.afterSales-remark-title {
margin-bottom: 20rpx;
}
.afterSales-remark-img {
display: flex;
flex-wrap: wrap;
.img-wrap {
margin-bottom: 16rpx;
&:not(:nth-child(4n)) {
margin-right: 14rpx;
}
}
.import {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 152rpx;
height: 152rpx;
background: #F9F9F9;
border-radius: 16rpx;
text {
margin-top: 20rpx;
font-size: 24rpx;
color: #777777;
}
}
}
}
.afterSales-btn {
position: fixed;
bottom: 0;
left: 0;
display: flex;
align-items: center;
width: 100%;
background-color: #F6F6F6;
height: 100rpx;
line-height: 100rpx;
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom);
.afterSales-btn-wrap {
width: 670rpx;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(132deg, #38BE41 0%, #20B128 100%);
border-radius: 40rpx;
margin: 0 auto;
font-size: 32rpx;
color: #FFFFFF;
text-align: center;
}
}
.address-popup {
padding: 30rpx;
.head-title {
font-weight: bold;
text-align: center;
margin-bottom: 20rpx;
}
.list-admin {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
.admin-btn {
display: flex;
color: #20B128;
.btn {
margin-left: 20rpx;
display: flex;
align-items: center;
&:active {
color: rgba(#20B128, 0.8);
transition: background-color 0.5s;
animation: disappear 0.5s 0.5s forwards;
}
}
}
}
.row {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f6f6f6;
margin-bottom: 20rpx;
&:last-child {
border-bottom: none;
margin-bottom: 0;
}
.content {
.top {
display: flex;
view {
margin-right: 20rpx;
}
}
.bottom {}
}
image {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
}
}
@keyframes disappear {
to {
opacity: 0;
/* 渐隐 */
transform: scale(0);
/* 缩小 */
}
}
}
</style>

View File

@ -0,0 +1,264 @@
<template>
<view class="multiple">
<view class="multiple-search">
<up-search v-model="queryParams.order_id" :animation="false" :showAction="true" bgColor="#f6f6f6"
placeholder="搜索商品" :actionStyle="{color:'#20B128','font-size':'28rpx'}" @custom="handleSearch"
@search="handleSearch" @clear="handleSearch"></up-search>
</view>
<view class="multiple-card">
<view class="multiple-card-wrap" style="padding-top: 12rpx;">
<block v-for="(item,indx) in shopList" :key="indx">
<view class="multiple-card-item" @click="onChooseShop(item)">
<view class="card-item-title">
<view class="card-item-title-order_id">{{item.order_id}}</view>
<view class="card-item-title-time">{{item.create_time}}</view>
</view>
<view class="afterSales-goods-wrap" v-for="(goods,indx) in item.goods_list" :key="indx">
<view class="afterSales-goods-left">
<up-image :src="goods.image" width="140rpx" height="140rpx" radius="8rpx"></up-image>
</view>
<view class="afterSales-goods-right">
<view class="afterSales-goods-right-title">
<text class="goods_name">{{goods.store_name}}</text>
<text class="goods_price">
<text style='font-size: 24rpx;'></text>
<text style="font-size: 32rpx;">{{goods.price}}</text>
</text>
</view>
<view class="afterSales-goods-right-info">
<text class="goods_desc">牛腩块</text>
<text class="goods_num">x{{item.cart_num || 0}}</text>
</view>
<view class="refund">
<view class="refund-txt">退款</view>
<view class="refund-money">{{item.refund_price || 0}}</view>
</view>
</view>
</view>
<view class="refund-status">
<view class="refund-status-txt">
<text v-if="item.status == -1">退款申请中</text>
<text v-if="item.status == -2">退款完成</text>
<text v-if="item.status == 5">取消售后</text>
<view v-if="item.status == -1">等待商家处理</view>
<view v-if="item.status == -2">退款成功{{item.refund_status}}</view>
<view v-if="item.status == 5">退款已关闭</view>
</view>
<up-icon name="arrow-right"></up-icon>
</view>
</view>
</block>
</view>
<up-loadmore :status="status" iconColor="#b3b3b3" color="#b3b3b3" />
</view>
</view>
</template>
<script setup>
import {
reactive,
ref,
} from "vue";
import {
onLoad,
onShow,
onReachBottom
} from "@dcloudio/uni-app";
import {
orderListApi,
refundReasonListApi
} from "@/api/order.js"
const shopList = ref([]); //
const status = ref(''); //
//
const queryParams = reactive({
page_no: 1,
page_size: 10,
order_id: '',
paid: '1',
status: '-1'
})
onReachBottom(() => {
getShopList();
})
//
onLoad(() => {
getShopList();
});
//
const onChooseShop = (item) => {
uni.navigateTo({
url: '/pages/afterSales/afterSalesOrderDetail',
fail(err) {
console.log(err);
},
success(res) {
res.eventChannel.emit('afterSalesOrderDetail', item)
}
})
}
//
const handleSearch = () => {
shopList.value = [];
queryParams.page_no = 1;
status.value = '';
getShopList();
}
//
const getShopList = () => {
if (status.value == 'nomore') return;
if (status.value == 'loading') return;
status.value == 'loading';
orderListApi(queryParams).then(res => {
let len = res.data.lists;
status.value = queryParams.page_size > len.length ? 'nomore' : 'loadmore';
shopList.value = shopList.value.concat(res.data.lists);
if (status.value == 'loadmore') queryParams.page_no += 1;
})
}
</script>
<style lang="scss">
page {
background: #FAFAFA;
}
.multiple {
padding-bottom: 30rpx;
.multiple-search {
position: sticky;
top: 0;
z-index: 10;
height: 90rpx;
background-color: #fff;
padding: 0 24rpx;
box-sizing: border-box;
}
.multiple-card {
padding-bottom: 12rpx;
.u-loadmore {
padding-bottom: 40rpx;
}
.multiple-card-item {
background: #FFFFFF;
border-radius: 16rpx;
margin: 0 24rpx 20rpx;
padding: 0 24rpx 24rpx;
overflow: hidden;
.card-item-title {
display: flex;
justify-content: space-between;
align-items: center;
height: 84rpx;
font-size: 28rpx;
color: #333333;
border-bottom: 2rpx solid #F8F9FA;
margin-bottom: 24rpx;
}
.afterSales-goods-wrap {
display: flex;
margin-bottom: 20rpx;
.afterSales-goods-left {
margin-right: 20rpx;
}
.afterSales-goods-right {
flex: 1;
.afterSales-goods-right-title {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.goods_name {
max-width: 400rpx;
font-size: 28rpx;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods_price {
font-weight: 600;
font-size: 24rpx;
color: #060606;
}
}
.afterSales-goods-right-info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
font-size: 24rpx;
color: #777777;
margin-bottom: 20rpx;
}
.refund {
display: flex;
color: #333333;
.refund-txt {
font-size: 24rpx;
align-self: flex-end;
}
.refund-money {
font-size: 32rpx;
}
}
}
}
.refund-status {
display: flex;
align-items: center;
justify-content: space-between;
height: 70rpx;
background: #F6F6F6;
border-radius: 16rpx;
padding: 0 30rpx 0 20rpx;
.refund-status-txt {
display: flex;
align-items: center;
text {
font-weight: 600;
font-size: 28rpx;
color: #333333;
margin-right: 30rpx;
}
view {
font-size: 28rpx;
color: #333333;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,281 @@
<template>
<view class="detail" v-if="shopInfo">
<view class="money" v-if="shopInfo.status == -2">
<view style="display: flex;align-items: center;">
<up-icon name="rmb-circle" color="#FC6957"></up-icon>
<text style="margin-left: 8rpx;">退款总金额</text>
</view>
<view>{{shopInfo.refund_price}}</view>
</view>
<view class="close" v-if="shopInfo.status == 5">
<view class="close-status">
<text>退款关闭</text>
<view>{{shopInfo.refund_cancle_time}}</view>
</view>
<view class="close-desc">因您取消退款申请退款已关闭交易将正常进行</view>
</view>
<view class="detail-wrap">
<view class="detail-wrap-title">退款信息</view>
<view class="afterSales-goods-wrap" v-for="item in shopInfo.goods_list">
<view class="afterSales-goods-left">
<up-image width="140rpx" height="140rpx" radius="8rpx" :src="item.image"></up-image>
</view>
<view class="afterSales-goods-right">
<view class="afterSales-goods-right-title">
<text class="goods_name">{{item.store_name}}</text>
</view>
<view class="afterSales-goods-right-info">
<text class="goods_desc">牛腩块</text>
</view>
</view>
</view>
<view class="info">
<view class="info-item">
<view class="info-label">退款原因</view>
<view class="info-con">{{shopInfo.refund_reason}}</view>
</view>
<view class="info-item">
<view class="info-label">退款金额</view>
<view class="info-con">{{shopInfo.refund_price}}</view>
</view>
<view class="info-item">
<view class="info-label">申请件数</view>
<view class="info-con">{{shopInfo.refund_num}}</view>
</view>
<view class="info-item">
<view class="info-label">订单编号</view>
<view class="info-con">{{shopInfo.order_id}}</view>
</view>
<view class="info-item">
<view class="info-label">申请时间</view>
<view class="info-con">{{shopInfo.refund_reason_time}}</view>
</view>
<view class="sh" v-if="shopInfo.status == -1">
<view class="sh-item" @click="onCancelRefund">取消售后</view>
<up-line direction="col" color="#707070" length="20rpx"></up-line>
<view class="sh-item" @click="onContactShop(shopInfo.store_phone)">联系商家</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import {
onLoad
} from "@dcloudio/uni-app";
import {
ref,
getCurrentInstance
} from "vue";
import {
cancelSaleApi
} from "@/api/order.js";
const instance = getCurrentInstance().proxy;
const shopInfo = ref(null);
onLoad(() => {
const eventChannel = instance.getOpenerEventChannel();
eventChannel.on('afterSalesOrderDetail', function(data) {
shopInfo.value = data;
console.log(shopInfo.value);
})
})
//
const onCancelRefund = () => {
uni.showModal({
title: '您确认要取消申请售后吗?',
confirmText: '确认',
cancelText: '申请售后',
success: (e) => {
if (!e.confirm) {
cancelSaleApi({
order_id: shopInfo.value.order_id
}).then(res => {
if (res.code == 1) {
uni.$u.toast('取消成功');
}
})
}
},
fail(err) {
console.log(err);
}
})
}
//
const onContactShop = (e) => {
if (!e) return;
uni.makePhoneCall({
phoneNumber: e
})
}
</script>
<style lang="scss">
.detail {
padding-top: 20rpx;
.detail-wrap {
margin: 0 20rpx;
background: #FFFFFF;
border-radius: 12rpx;
margin-bottom: 20rpx;
padding: 20rpx 20rpx 1rpx 20rpx;
box-sizing: border-box;
.detail-wrap-title {
font-weight: 600;
font-size: 28rpx;
color: #060606;
margin-bottom: 30rpx;
}
.afterSales-goods-wrap {
display: flex;
margin-bottom: 30rpx;
.afterSales-goods-left {
margin-right: 20rpx;
}
.afterSales-goods-right {
flex: 1;
.afterSales-goods-right-title {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.goods_name {
max-width: 400rpx;
font-size: 28rpx;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods_price {
font-weight: 600;
font-size: 24rpx;
color: #060606;
}
}
.afterSales-goods-right-info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
font-size: 24rpx;
color: #777777;
margin-bottom: 20rpx;
}
.refund {
display: flex;
color: #333333;
.refund-txt {
font-size: 24rpx;
align-self: flex-end;
}
.refund-money {
font-size: 32rpx;
}
}
}
}
.info {
.info-item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
.info-label {
font-size: 28rpx;
color: #333333;
}
.info-con {
font-size: 28rpx;
color: #777777;
}
}
}
}
}
.money {
display: flex;
justify-content: space-between;
align-items: center;
height: 96rpx;
padding: 0 30rpx;
font-size: 28rpx;
color: #FC6957;
background-color: #fff;
border-radius: 12rpx;
box-sizing: border-box;
margin: 0 20rpx 20rpx;
}
.close {
background: #FFFFFF;
border-radius: 12rpx;
padding: 30rpx;
margin: 0 20rpx 20rpx;
.close-status {
display: flex;
align-items: center;
margin-bottom: 8rpx;
text {
margin-right: 10rpx;
font-size: 28rpx;
color: #FC6957;
}
view {
font-size: 24rpx;
color: #989898;
}
}
.close-desc {
font-size: 24rpx;
color: #989898;
}
}
.sh {
display: flex;
align-items: center;
border-top: 2rpx solid #F3F3F3;
.sh-item {
flex: 1;
height: 88rpx;
line-height: 88rpx;
text-align: center;
font-size: 28rpx;
color: #333333;
}
}
</style>

View File

@ -74,14 +74,14 @@
<view class="badge" v-if="orderCount.waiting">{{orderCount.waiting}}</view> <view class="badge" v-if="orderCount.waiting">{{orderCount.waiting}}</view>
</view> </view>
<view class="list-item" @click="navTo(2)"> <view class="list-item" @click="navTo(3)">
<image src="/static/icon/done.webp"> <image src="/static/icon/done.webp">
</image> </image>
<view class="">已核销</view> <view class="">已核销</view>
<view class="badge" v-if="orderCount.receiving">{{orderCount.receiving}}</view> <view class="badge" v-if="orderCount.receiving">{{orderCount.receiving}}</view>
</view> </view>
<view class="list-item" @click="navTo()"> <view class="list-item" @click="navTo(4)">
<image src="/static/icon/back.webp"> <image src="/static/icon/back.webp">
</image> </image>
<view class="">售后/退款</view> <view class="">售后/退款</view>

View File

@ -39,6 +39,8 @@
size="small" plain color="#20B128" shape="circle">再次购买</up-button></view> size="small" plain color="#20B128" shape="circle">再次购买</up-button></view>
<view @click="navTo" style="width: 80px;"><up-button size="small" plain color="#20B128" <view @click="navTo" style="width: 80px;"><up-button size="small" plain color="#20B128"
shape="circle">查看详情</up-button></view> shape="circle">查看详情</up-button></view>
<view @click="applySh" style="width: 80px;" v-if="datas.status == 1 || datas.status == 2"><up-button
size="small" plain color="#ccc" shape="circle">申请售后</up-button></view>
</view> </view>
<!-- <view v-if="type==3" class="item-close"> <!-- <view v-if="type==3" class="item-close">
<view class="title"> <view class="title">
@ -85,6 +87,10 @@
const rePay = () => { const rePay = () => {
emit('rePay', props.datas) emit('rePay', props.datas)
} }
const applySh = () => {
emit('applyAfterSales', props.datas)
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -21,7 +21,7 @@
<view v-if="list.length>0" class="list"> <view v-if="list.length>0" class="list">
<good v-for="(item, index) in list" :datas="item" :key="index" :type="k" <good v-for="(item, index) in list" :datas="item" :key="index" :type="k"
@cancleOrder="cancleOrder" @takeOrder="takeOrder" @rePay="rePay" @cancleOrder="cancleOrder" @takeOrder="takeOrder" @rePay="rePay"
@purchaseAgain="purchaseAgain"></good> @purchaseAgain="purchaseAgain" @applyAfterSales="applyAfterSales"></good>
</view> </view>
<view v-if="!where[k].loading&&list.length==0" style="padding-top: 100rpx;"> <view v-if="!where[k].loading&&list.length==0" style="padding-top: 100rpx;">
<up-empty text="订单空空如也" <up-empty text="订单空空如也"
@ -43,8 +43,41 @@
</swiper> </swiper>
</view> </view>
<orderCanclePopup :show="showCancel" @close="showCancel=false" @change="submitCancel" /> <orderCanclePopup :show="showCancel" @close="showCancel=false" @change="submitCancel" />
<modal :show="showTake" title="确认收货" content="请确认您已收到货" @close="showTake=false" @change="confirmReceipt"> <modal :show="showTake" title="确认收货" content="请确认您已收到货" @close="showTake=false" @change="confirmReceipt" />
</modal>
<!-- 退款原因 -->
<up-popup :show="refundShow" closeable round="10" @close="close">
<view class="address-popup">
<view class="head-title">选择商品</view>
<view class="afterSales-type">
<view class="afterSales-type-title">售后类型</view>
<view class="afterSales-type-con">
<view class="afterSales-type-item">仅退款</view>
<view class="afterSales-type-item">退款退货</view>
<view class="afterSales-type-item">换货</view>
</view>
</view>
<scroll-view style="max-height: 50vh;padding-bottom: 20rpx;" scroll-y>
<block v-for="(item,index) in refundReasonList" :key="index">
<view class="row" @click="refundType = item.value">
<view class="content">
<view class="top"></view>
<view class="bottom u-line-2">{{item.value}}</view>
</view>
<image v-if="refundType==item.value" src="@/static/icon/check.png"></image>
<image v-else src="@/static/icon/n-check.png"></image>
</view>
</block>
</scroll-view>
<up-button color="#20B128" shape="circle" @click="onSubmitReason">提交</up-button>
</view>
</up-popup>
</template> </template>
<script setup> <script setup>
@ -93,9 +126,12 @@
}) => { }) => {
swiperCurrent.value = current; swiperCurrent.value = current;
tabsActive.value = current; tabsActive.value = current;
if (swiperCurrent.value == 0 && orderList.value[0].length == 0) getOrderList(0);
if (swiperCurrent.value == 1 && orderList.value[1].length == 0) getOrderList(1, '', 0); if (swiperCurrent.value == 0 && orderList.value[0].length == 0) getOrderList(0, '', ''); //
if (swiperCurrent.value == 2 && orderList.value[2].length == 0) getOrderList(2, 1); if (swiperCurrent.value == 1 && orderList.value[1].length == 0) getOrderList(1, '', 0); //
if (swiperCurrent.value == 2 && orderList.value[2].length == 0) getOrderList(2, 1, 1); //
if (swiperCurrent.value == 3 && orderList.value[3].length == 0) getOrderList(3, 2, 1); //
if (swiperCurrent.value == 4 && orderList.value[4].length == 0) getOrderList(2, -1, 1); //退
} }
// //
@ -114,6 +150,8 @@
orderList.value[1] = orderList.value[1].filter(item => item.id !== cancelId) orderList.value[1] = orderList.value[1].filter(item => item.id !== cancelId)
}) })
} }
//
const cancleOrder = (e) => { const cancleOrder = (e) => {
cancelId = e.id; cancelId = e.id;
showCancel.value = true; showCancel.value = true;
@ -126,6 +164,8 @@
takeId = e.id; takeId = e.id;
showTake.value = true; showTake.value = true;
} }
//
const confirmReceipt = () => { const confirmReceipt = () => {
confirmReceiptApi({ confirmReceiptApi({
order_id: takeId order_id: takeId
@ -148,6 +188,18 @@
}) })
} }
const refundShow = ref(true);
//
const applyAfterSales = (item) => {
uni.navigateTo({
url: "/pages/afterSales/afterSales",
success(res) {
res.eventChannel.emit('orderDetail', item)
}
})
}
const rePay = (e) => { const rePay = (e) => {
rePaymentApi({ rePaymentApi({
order_id: e.id, order_id: e.id,
@ -193,6 +245,18 @@
loading: false, loading: false,
loadend: false loadend: false
}, },
{
page_no: 1,
page_size: 25,
loading: false,
loadend: false
},
{
page_no: 1,
page_size: 25,
loading: false,
loadend: false
},
{ {
page_no: 1, page_no: 1,
page_size: 25, page_size: 25,
@ -205,6 +269,8 @@
[], [],
[], [],
[], [],
[],
[]
]) ])
const getOrderList = (type = 0, status = '', paid = 1) => { const getOrderList = (type = 0, status = '', paid = 1) => {
if (where.value[type].loadend) return; if (where.value[type].loadend) return;
@ -227,9 +293,11 @@
} }
const loadMoreGood = () => { const loadMoreGood = () => {
if (swiperCurrent.value == 0) getOrderList(0); if (swiperCurrent.value == 0) getOrderList(0, '', ''); //
if (swiperCurrent.value == 1) getOrderList(1, '', 0); if (swiperCurrent.value == 1) getOrderList(1, '', 0); //
if (swiperCurrent.value == 2) getOrderList(2, 1); if (swiperCurrent.value == 2) getOrderList(2, 1, 1); //
if (swiperCurrent.value == 3) getOrderList(3, 2, 1); //
if (swiperCurrent.value == 4) getOrderList(2, -1, 1); //退
} }
// //
@ -237,9 +305,11 @@
orderList.value[+swiperCurrent.value] = []; orderList.value[+swiperCurrent.value] = [];
where.value[+swiperCurrent.value].page_no = 1; where.value[+swiperCurrent.value].page_no = 1;
where.value[+swiperCurrent.value].loadend = false; where.value[+swiperCurrent.value].loadend = false;
if (swiperCurrent.value == 0) getOrderList(0); if (swiperCurrent.value == 0) getOrderList(0, '', ''); //
if (swiperCurrent.value == 1) getOrderList(1, '', 0); if (swiperCurrent.value == 1) getOrderList(1, '', 0); //
if (swiperCurrent.value == 2) getOrderList(2, 1); if (swiperCurrent.value == 2) getOrderList(2, 1, 1); //
if (swiperCurrent.value == 3) getOrderList(3, 2, 1); //
if (swiperCurrent.value == 4) getOrderList(2, -1, 1); //退
} }
let back = 0; let back = 0;
@ -254,9 +324,12 @@
item.page_no = 1; item.page_no = 1;
item.loadend = false; item.loadend = false;
}); });
getOrderList(1, '', 0);
getOrderList(0); getOrderList(0, '', ''); //
getOrderList(2, 1); getOrderList(1, '', 0); //
getOrderList(2, 1, 1); //
getOrderList(3, 2, 1); //
getOrderList(2, -1, 1); //退
} }
onLoad((options) => { onLoad((options) => {
@ -266,9 +339,6 @@
searchOn(); searchOn();
} }
if (options.back) back = options.back; if (options.back) back = options.back;
// getOrderList(0);
// getOrderList(1, '', 0);
// getOrderList(2, 1);
uni.$on('reLoadOrderList', reloadAll); uni.$on('reLoadOrderList', reloadAll);
}) })
@ -296,7 +366,79 @@
.page-box { .page-box {
margin: 20rpx; margin: 20rpx;
}
// .list {} .address-popup {
padding: 30rpx;
.head-title {
font-weight: bold;
text-align: center;
margin-bottom: 20rpx;
}
.list-admin {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
.admin-btn {
display: flex;
color: #20B128;
.btn {
margin-left: 20rpx;
display: flex;
align-items: center;
&:active {
color: rgba(#20B128, 0.8);
transition: background-color 0.5s;
animation: disappear 0.5s 0.5s forwards;
}
}
}
}
.row {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f6f6f6;
margin-bottom: 20rpx;
&:last-child {
border-bottom: none;
margin-bottom: 0;
}
.content {
.top {
display: flex;
view {
margin-right: 20rpx;
}
}
.bottom {}
}
image {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
}
}
@keyframes disappear {
to {
opacity: 0;
/* 渐隐 */
transform: scale(0);
/* 缩小 */
}
} }
</style> </style>

View File

@ -96,8 +96,8 @@
<text style="margin-left: 20rpx;font-size: 26rpx;">微信支付</text> <text style="margin-left: 20rpx;font-size: 26rpx;">微信支付</text>
</view> </view>
<view class="icon" @click="onChoosePaytype(1)"> <view class="icon" @click="onChoosePaytype(1)">
<image v-if="payType == 1" src="@/static/icon/check.png" /> <image v-if="pay_type == 1" src="@/static/icon/check.png" />
<image v-if="payType != 1 || payType == 3 || !payType" src="@/static/icon/n-check.png" /> <image v-if="pay_type != 1 || pay_type == 3 || !pay_type" src="@/static/icon/n-check.png" />
</view> </view>
</view> </view>
@ -107,8 +107,8 @@
<text style="margin-left: 20rpx;font-size: 26rpx;">余额支付</text> <text style="margin-left: 20rpx;font-size: 26rpx;">余额支付</text>
</view> </view>
<view class="icon" @click="onChoosePaytype(3)"> <view class="icon" @click="onChoosePaytype(3)">
<image v-if="payType == 3" src="@/static/icon/check.png" /> <image v-if="pay_type == 3" src="@/static/icon/check.png" />
<image v-if="payType != 3 || payType == 1 || !payType" src="@/static/icon/n-check.png" /> <image v-if="pay_type != 3 || pay_type == 1 || !pay_type" src="@/static/icon/n-check.png" />
</view> </view>
</view> </view>
</view> </view>
@ -181,11 +181,9 @@
const isAddress = ref(false); const isAddress = ref(false);
const toastAddressShow = ref(false); const toastAddressShow = ref(false);
const payType = ref('');
const onChoosePaytype = (e) => { const onChoosePaytype = (e) => {
console.log(e); pay_type.value = e;
payType.value = e;
} }
// //
@ -227,7 +225,6 @@
}) })
} }
// //
const shopRef = ref(null); const shopRef = ref(null);
const shopListShow = ref(false); const shopListShow = ref(false);
@ -333,14 +330,16 @@
}) })
} }
const pay_type = ref(1); const pay_type = ref('');
const createOrder = () => { const createOrder = () => {
if (!pay_type.value) return uni.$u.toast('请选择支付方式');
createOrderApi({ createOrderApi({
cart_id: cartStore.cartList, cart_id: cartStore.cartList,
address_id: addressInfo.value.address_id, address_id: addressInfo.value.address_id,
mer_id: shopInfo.value.mer_id, mer_id: shopInfo.value.mer_id,
pay_type: 1, pay_type: pay_type.value,
store_id: 2 store_id: 2
}).then(res => { }).then(res => {
console.log(res); console.log(res);
@ -361,9 +360,7 @@
uni.$u.toast(res.msg); uni.$u.toast(res.msg);
} }
} else { } else {
console.log(1);
if (!res.data?.nonceStr) return uni.$u.toast('支付失败!'); if (!res.data?.nonceStr) return uni.$u.toast('支付失败!');
console.log(2);
uni.requestPayment({ uni.requestPayment({
provider: 'wxpay', provider: 'wxpay',
timeStamp: res.data.timeStamp, timeStamp: res.data.timeStamp,