售后申请,售后列表

msb_beta
ch 3 years ago
parent 68c11b79a9
commit cd457a63b0

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2019-04-01 01:47:12
* @LastEditors: ch
* @LastEditTime: 2022-04-09 14:59:18
* @LastEditTime: 2022-04-13 14:07:10
* @Description: file content
-->
<script>
@ -24,7 +24,7 @@
<style lang="scss">
/* 注意要写在第一行同时给style标签加入lang="scss"属性 */
@import "uview-ui/index.scss";
view,text{
view,text,textarea{
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-size: $font-size-base;

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-29 17:38:17
* @LastEditors: ch
* @LastEditTime: 2022-04-11 18:00:46
* @LastEditTime: 2022-04-13 17:20:46
* @Description: file content
*/
import {ToAsyncAwait, MsbRequestTk} from '@/common/utils';
@ -55,4 +55,22 @@ export const ApiPutCancelOrder = (data) =>
export const ApiPostWxPay = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/pay/wxPay/app`, data));
/**
* 申请售后
* @param {*} data
*/
export const ApiPostApplySaleAfter = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/app/refundOrder/applyRefund`, data));
/**
* 售后订单列表
* @param {*} data
*/
export const ApiGetSaleAfterOrderList = (params) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/refundOrder/page`, params));
/**
* 售后订单详情
* @param {*} data
*/
export const ApiGetSaleAfterOrderDetail = (params) =>
ToAsyncAwait(MsbRequestTk.get(`${BASE_URL}/app/refundOrder/${params.refundId}`));

@ -0,0 +1,13 @@
/*
* @Author: ch
* @Date: 2022-04-13 14:30:33
* @LastEditors: ch
* @LastEditTime: 2022-04-13 14:31:55
* @Description: file content
*/
import {ToAsyncAwait, MsbRequestTk} from '@/common/utils';
const BASE_URL = '/oss/oss';
export const ApiPostGetOssConfig = (data) =>
ToAsyncAwait(MsbRequestTk.post(`${BASE_URL}/generateOssSignature`, data));

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-17 16:36:59
* @LastEditors: ch
* @LastEditTime: 2022-04-07 10:10:16
* @LastEditTime: 2022-04-13 13:36:15
* @Description: 针对uniapp request请求做了一次封装使用思维参考axios
*
*

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-17 17:42:32
* @LastEditors: ch
* @LastEditTime: 2022-04-12 09:28:17
* @LastEditTime: 2022-04-13 13:38:25
* @Description: 项目接口请求统一处理器返回一个需要token和不需要token的请求封装方法
*/

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-26 10:06:38
* @LastEditors: ch
* @LastEditTime: 2022-04-09 15:01:39
* @LastEditTime: 2022-04-13 17:44:38
* @Description: file content
-->
<template>
@ -17,7 +17,7 @@ export default {
},
size : {
type : String,
default : 'normal' //normal 60 max 80
default : 'normal' //normal 60 max 80 min 50
},
disabed:{
type : Boolean,
@ -41,6 +41,11 @@ export default {
line-height: 70rpx;
font-size: $font-size-base;
}
&__min{
height: 50rpx;
line-height: 50rpx;
font-size: $font-size-base;
}
&__max{
width: 690rpx;
height: 80rpx;

@ -76,10 +76,13 @@
"devServer" : {
"proxy" : {
"/uc/" : {
"target" : "http://192.168.10.52:8090/"
"target" : "http://192.168.10.109:8090/"
},
"/mall/" : {
"target" : "http://192.168.10.52:8090/"
"target" : "http://192.168.10.109:8090/"
},
"/oss/" : {
"target" : "http://192.168.10.109:8090/"
}
}
}

@ -139,11 +139,19 @@
"navigationBarTitleText": "提交订单"
}
},
{
"path": "pages/order/list",
"aliasPath" : "/orderList",
"style": {
"navigationBarTitleText": "我的订单"
}
},
{
"path": "pages/order/detail/index",
"aliasPath" : "/orderDetail",
"style": {
"navigationBarTitleText": "订单详情"
"navigationBarTitleText": "订单详情",
"navigationBarBackgroundColor" : "#F8F8F8"
}
},
{
@ -161,17 +169,25 @@
}
},
{
"path": "pages/order/saleAfter/saleAfterApplication",
"aliasPath" : "/saleAfterApplication",
"path": "pages/order/saleAfter/saleAfterList",
"aliasPath" : "/saleAfterList",
"style": {
"navigationBarTitleText": "申请退款"
"navigationBarTitleText": "售后订单"
}
},
{
"path": "pages/order/list",
"aliasPath" : "/orderList",
"path": "pages/order/saleAfter/saleAfterDetail/index",
"aliasPath" : "/saleAfterDetail",
"style": {
"navigationBarTitleText": "我的订单"
"navigationBarTitleText": "售后详情",
"navigationBarBackgroundColor" : "#F8F8F8"
}
},
{
"path": "pages/order/saleAfter/saleAfterApply",
"aliasPath" : "/saleAfterApply",
"style": {
"navigationBarTitleText": "申请退款"
}
},
{

@ -3,7 +3,7 @@
components: { UiCell },: ch
* @Date: 2019-08-22 19:41:20
* @LastEditors: ch
* @LastEditTime: 2022-04-11 10:44:18
* @LastEditTime: 2022-04-13 16:15:34
* @Description: file content
-->
<template>
@ -40,7 +40,7 @@
</view>
</view>
<view class="cell">
<UiCell title="退货/售后">
<UiCell title="退货/售后" @click="$Router.push('/saleAfterList')">
<image slot="icon" class="cell--icon" src="@/static/account/tk.png" />
</UiCell>
<UiCell title="收货地址" @click="$Router.push('/addressList')">

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-28 15:38:23
* @LastEditors: ch
* @LastEditTime: 2022-04-11 10:58:10
* @LastEditTime: 2022-04-13 14:45:56
* @Description: file content
-->
<template>
@ -25,7 +25,7 @@ import UiButton from '@/components/UiButton.vue'
import UiCell from '@/components/UiCell.vue';
import {Request} from '@/common/utils';
import {ApiPutUser} from '@/common/api/account';
const OSS = {"accessid":"LTAI4GHRNb5Xn2w5NeHVbR4c","policy":"eyJleHBpcmF0aW9uIjoiMjAyMi0wNC0xNVQyMDowODoyNi4zMTlaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJ0ZXN0LyJdXX0=","signature":"okaB3sNp3vzyfM0S3ypudaUAZ+0=","dir":"test/","host":"https://msb-edu-dev.oss-cn-beijing.aliyuncs.com","expire":"1650053306"}
const OSS = {"accessId":"LTAI4GHRNb5Xn2w5NeHVbR4c","policy":"eyJleHBpcmF0aW9uIjoiMjAyMi0wNC0xM1QwOTozMDoxNC45MjNaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJyZWZ1bmQtZXZpZGVuY2UiXV19","signature":"RDaMnKgLslcO8NX+WIwiJ5khYNc=","dir":"refund-evidence","host":"https://msb-edu-dev.oss-cn-beijing.aliyuncs.com","expire":1649842214,"callback":"eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwiY2FsbGJhY2tCb2R5IjoiZmlsZW5hbWU9JHtvYmplY3R9JnNpemU9JHtzaXplfSZtaW1lVHlwZT0ke21pbWVUeXBlfSZoZWlnaHQ9JHtpbWFnZUluZm8uaGVpZ2h0fSZ3aWR0aD0ke2ltYWdlSW5mby53aWR0aH0mc2VydmljZU5hbWU9bWFsbC10cmFkZSJ9","md5":null}
export default {
components: { UiCell, UiButton },
data(){

@ -2,22 +2,22 @@
* @Author: ch
* @Date: 2022-04-12 17:33:42
* @LastEditors: ch
* @LastEditTime: 2022-04-12 18:12:45
* @LastEditTime: 2022-04-13 13:47:07
* @Description: file content
-->
<template>
<view class="seckill">
<view class="seckill--price-box">
<text class="seckill--price-icon"></text>
<text class="seckill--price">9.9</text>
<text class="seckill--price-org">29</text>
<text class="seckill--price">{{data.activityPrice}}</text>
<text class="seckill--price-org">{{data.originalPrice}}</text>
</view>
<view class="seckill--timer">
<view>00</view>
<view>{{hours}}</view>
<text>:</text>
<view>00</view>
<view>{{minute}}</view>
<text>:</text>
<view>00</view>
<view>{{second}}</view>
</view>
</view>
</template>
@ -31,22 +31,74 @@ export default {
},
data(){
return {
secondNum : 0
secondNum : 0,
timerStop : null
}
},
watch:{
data(){
this.calcStartSecond();
}
},
mounted(){
this.calcStartSecond();
},
computed:{
hours(){
let hours = parseInt(this.secondNum / 3600);
return hours > 9 ? hours : `0${hours}`;
},
minute(){
let minute = parseInt((this.secondNum - hours * 3600) / 60);
return minute > 9 ? hours : `0${minute}`;
let minute = parseInt((this.secondNum - this.hours * 3600) / 60);
return minute > 9 ? minute : `0${minute}`;
},
second(){
let second = parseInt(this.secondNum % 60);
return second > 9 ? second : `0${second}`;
}
},
methods:{
/**
* 计算倒计时开始秒数
*/
calcStartSecond(){
const {isStartActivity, activityStartTime, activityEndTime , currentTime} = this.data;
let curTime = (new Date(currentTime)).getTime(),
expireTime = 0;
if(isStartActivity){
//
expireTime = (new Date(activityEndTime)).getTime();
}else{
//
expireTime = (new Date(activityStartTime)).getTime();
}
const second = Math.floor((expireTime - curTime) / 1000);
this.secondNum = second > 0 ? second : 0;
this.timer();
},
/**
* 倒计时
*/
timer(){
if(this.secondNum < 2){
clearTimeout(this.timerStop);
this.$emit('change');
// 0
// if(this.data.isStartActivity){
// this.$emit('change');
// // this.$emit('update:data',{...this.data, isActivity : false});
// }else{
// this.$emit('change');
// //
// // this.$emit('update:data',{...this.data, isStartActivity : true});
// // this.calcStartSecond();
// }
return false;
}
this.secondNum--;
this.timerStop = setTimeout(this.timer, 1000)
}
}
}
</script>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-23 17:27:21
* @LastEditors: ch
* @LastEditTime: 2022-04-12 17:35:22
* @LastEditTime: 2022-04-13 11:33:46
* @Description: file content
-->
<template>
@ -11,9 +11,9 @@
<image class="back--icon" src="@/static/goods/back.png"/>
</view>
<SlideImage :images="goods.pictureList"></SlideImage>
<SeckillPrice :data.sync="productActivityVO" v-if="productActivityVO.isActivity" @change="getGoodsDetail"></SeckillPrice>
<view class="goods-info">
<view class="pirce">
<view class="pirce" v-if="!productActivityVO.isActivity">
<text></text>
<text class="pirce--max">{{goods.startingPrice}}</text>
<text></text>
@ -37,7 +37,9 @@
</view>
<view class="footer--btns">
<UiButton class="btn" @click="onShowSkuPopup(2)"></UiButton>
<UiButton class="btn btn--buy" @click="onShowSkuPopup(3)"></UiButton>
<UiButton class="btn btn--buy" @click="onShowSkuPopup(3)">
{{(!productActivityVO.isStartActivity && productActivityVO.isActivity) ? '原价购买' : '立即购买'}}
</UiButton>
</view>
</view>
</view>
@ -50,8 +52,9 @@ import Service from './components/Service.vue';
import SkuPopup from './components/SkuPopup.vue';
import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html';
import UiButton from '../../../components/UiButton.vue';
import SeckillPrice from './components/SeckillPrice.vue';
export default {
components: { SlideImage, mpHtml, Service, SkuPopup, UiButton},
components: { SlideImage, mpHtml, Service, SkuPopup, UiButton, SeckillPrice},
data(){
return {
goods : {
@ -65,12 +68,12 @@ export default {
selectedSkuInfo : {
sku : '',
num : 1
}
},
productActivityVO : {}
}
},
onLoad(){
this.getGoodsDetail();
this.getGoodsSkus();
},
methods:{
async getGoodsDetail(){
@ -83,12 +86,21 @@ export default {
this.goods = {...result,
images : result.pictureList || [],
};
//
this.productActivityVO = {
...result.productActivityVO,
//
originalPrice:result.startingPrice
};
this.getGoodsSkus();
},
async getGoodsSkus(){
const {query} = this.$Route;
const {error, result} = await ApiGetGoodsSkus({productId : query.id});
if(error) {
uin.$u.totast(error.message);
uni.$u.totast(error.message);
return false;
}
this.skuInfoData = result;

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-23 10:07:48
* @LastEditors: ch
* @LastEditTime: 2022-04-12 18:55:54
* @LastEditTime: 2022-04-13 09:45:18
* @Description: file content
-->
<template>
@ -61,18 +61,16 @@ export default {
* 监听数据变化后做倒计时
*/
data(nVal){
const {isStartActivity, activityTimeVO:{startTime, endTime }} = nVal;
const {isStartActivity, activityTimeVO:{startTime, endTime }, currentTime} = nVal;
if(endTime){
let curTime = (new Date('2022-4-12 12:00:50')).getTime(),
let curTime = (new Date(`2022/01/01 ${currentTime}`)).getTime(),
expireTime = 0;
if(isStartActivity){
//
// expireTime = (new Date(endTime)).getTime()
expireTime = (new Date('2022-4-12 15:00:00')).getTime();
expireTime = (new Date(`2022/01/01 ${endTime}`)).getTime();
}else{
//
expireTime = (new Date('2022-4-12 17:00:00')).getTime()
expireTime = (new Date(startTime)).getTime()
expireTime = (new Date(`2022/01/01 ${startTime}`)).getTime();
}
const second = Math.floor((expireTime - curTime) / 1000);
this.secondNum = second > 0 ? second : 0;

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-31 14:26:09
* @LastEditors: ch
* @LastEditTime: 2022-04-11 16:53:15
* @LastEditTime: 2022-04-13 17:43:55
* @Description: file content
-->
<template>
@ -11,7 +11,7 @@
<UiWhiteBox>
<UiGoodsInfo v-for="(item, index) in orderInfo.products" :data="item" :key="index">
<template slot="operation">
<UiButton @click="$Router.push('/saleAfterApplication')"></UiButton>
<UiButton size="min" @click="$Router.push(`/saleAfterApply?type=1&id=${item.orderProductId}`)"></UiButton>
</template>
</UiGoodsInfo>
</UiWhiteBox>

@ -1,99 +0,0 @@
<!--
* @Author: ch
* @Date: 2022-04-11 13:51:10
* @LastEditors: ch
* @LastEditTime: 2022-04-12 13:52:58
* @Description: file content
-->
<template>
<view>
<view class="box">
<UiCell title="货物状态" @click="receiveShow = true">
<input class="input" slot="value" disabled placeholder="请选择" :value="receiveSelected.label"/>
</UiCell>
<UiCell title="退款原因" @click="refundShow=true">
<input class="input" slot="value" disabled placeholder="请选择" :value="refundSelected.label"/>
</UiCell>
<UiCell title="退款金额" :rightIcon="false">
<text class="price" slot="value">36.3</text>
</UiCell>
<UiCell title="问题描述"></UiCell>
</view>
<view class="box">
<u-upload
:fileList="fileList3"
@afterRead="afterRead"
@delete="deletePic"
name="3"
multiple
:maxCount="10"
:previewFullImage="true"
></u-upload>
</view>
<UiButton size="max" type="gradual">提交申请</UiButton>
<UiRadioPicker title="退款原因" :show.sync="refundShow"
:options="refundReasonData" v-model="refundSelected"></UiRadioPicker>
<UiRadioPicker title="货物状态" :show.sync="receiveShow"
:options="receiveStatusData" v-model="receiveSelected"></UiRadioPicker>
</view>
</template>
<script>
import UiButton from '../../../components/UiButton.vue';
import UiCell from "../../../components/UiCell.vue";
import UiRadioPicker from '../../../components/UiRadioPicker.vue';
export default {
components: { UiCell, UiButton, UiRadioPicker },
data() {
return {
fileList3: [
{
url: "https://cdn.uviewui.com/uview/swiper/1.jpg",
},
],
params : {
receiveStatus : '',
refundReason : '',
refundType : '',
orderProductId : '',
problemDescribe : '',
evidenceImages : ''
},
refundShow : false,
refundSelected : {},
refundReasonData : [
{label : '7天无理由退款', value: '1'},
{label : '不喜欢/效果不满意', value: '2'},
{label : '商品不符合描述', value: '3'},
{label : '其它原因', value: '4'},
],
receiveSelected : {},
receiveShow : false,
receiveStatusData : [
{label : '未收到货', value: '1'},
{label : '已收到货', value: '2'}
]
};
},
};
</script>
<style lang="scss">
page{
background: $color-grey1;
}
</style>
<style lang="scss" scoped>
.box{
padding: 0 40rpx;
margin: 20rpx 0;
background: $color-grey0;
}
.input{
font-size: $font-size-base;
text-align: right;
flex: 1;
}
.price{
color: $color-yellow4;
}
</style>

@ -0,0 +1,201 @@
<!--
* @Author: ch
* @Date: 2022-04-11 13:51:10
* @LastEditors: ch
* @LastEditTime: 2022-04-13 16:23:58
* @Description: file content
-->
<template>
<view>
<view class="box">
<UiCell title="货物状态" @click="receiveShow = true" v-if="!$Route.query.status">
<input class="input" slot="value" disabled placeholder="请选择" :value="receiveSelected.label"/>
</UiCell>
<UiCell title="退款原因" @click="refundShow=true">
<input class="input" slot="value" disabled placeholder="请选择" :value="refundSelected.label"/>
</UiCell>
<UiCell title="退款金额" :rightIcon="false">
<text class="price" slot="value">36.3</text>
</UiCell>
<view class="title">
<view>
<text>问题描述</text>
<text class="title--min">选填</text>
</view>
<text class="title--min">{{params.problemDescribe.length}}/45</text>
</view>
<textarea class="textarea" v-model="params.problemDescribe" maxlength="45" placeholder="请输入您申请退款的问题"></textarea>
</view>
<view class="box upload">
<view class="title">
<text>上传凭证</text>
<text class="title--min">{{fileList.length}}/9</text>
</view>
<u-upload
:fileList="fileList"
@afterRead="upload"
@delete="delImage"
multiple
:maxCount="9"
:previewFullImage="true"
></u-upload>
</view>
<UiButton class="btn" size="max" type="gradual" @click="apply"></UiButton>
<UiRadioPicker title="退款原因" :show.sync="refundShow"
:options="refundReasonData" v-model="refundSelected"></UiRadioPicker>
<UiRadioPicker title="货物状态" :show.sync="receiveShow"
:options="receiveStatusData" v-model="receiveSelected"></UiRadioPicker>
</view>
</template>
<script>
import UiButton from '../../../components/UiButton.vue';
import UiCell from "../../../components/UiCell.vue";
import UiRadioPicker from '../../../components/UiRadioPicker.vue';
import {ApiPostGetOssConfig} from '@/common/api/oss.js';
import {ApiPostApplySaleAfter} from '@/common/api/order.js';
export default {
components: { UiCell, UiButton, UiRadioPicker },
data() {
return {
fileList: [],
params : {
receiveStatus : '',
refundReason : '',
// 1退2退退
refundType : this.$Route.query.type,
orderProductId : this.$Route.query.id,
problemDescribe : '',
evidenceImages : ''
},
refundShow : false,
refundSelected : {},
refundReasonData : [
{label : '7天无理由退款', value: '1'},
{label : '不喜欢/效果不满意', value: '2'},
{label : '商品不符合描述', value: '3'},
{label : '其它原因', value: '4'},
],
receiveSelected : {},
receiveShow : false,
receiveStatusData : [
{label : '未收到货', value: '1'},
{label : '已收到货', value: '2'}
]
};
},
onShow(){
this.receiveSelected = this.receiveStatusData.find(i => i.value == this.$Route.query.status) || {};
},
methods: {
setDefaultParams(){
},
async getOssCon(){
const {error, result} = await ApiPostGetOssConfig({
configId : 'refund-evidence/',
serviceName : 'mall-trade'
});
if(error){
uni.$u.toast(error.message);
return false
}
return result;
},
async upload(val){
const file = val.file[0];
const oss = await this.getOssCon();
if(!oss) {
return false
}
uni.uploadFile({
name : 'file',
filePath : file.url,
url : oss.host,
formData : {
name : file.name,
key : `${oss.dir}${'${filename}'}`,
policy : oss.policy,
OSSAccessKeyId : oss.accessId,
success_action_status : 200,
signature : oss.signature
},
success:(res)=>{
this.fileList.push({
url : `${oss.host}/${oss.dir}${file.name}`
})
}
})
},
/**
* 删除凭证图片
*/
delImage(val){
this.fileList.splice(val.index , 1);
},
async apply(){
if(!this.receiveSelected.value){
uni.$u.toast('请选择货物状态');
return false;
}
if(!this.refundSelected.value){
uni.$u.toast('请选择退货原因');
return false;
}
this.params.receiveStatus = this.receiveSelected.value;
this.params.refundReason = this.refundSelected.value;
if(this.fileList.length){
this.params.evidenceImages = this.fileList.map(i => i.url);
}
const {error, result} = await ApiPostApplySaleAfter(this.params);
if(error){
uni.$u.toast(error.message);
return false;
}
}
}
};
</script>
<style lang="scss">
page{
background: $color-grey1;
}
</style>
<style lang="scss" scoped>
.box{
padding: 0 40rpx;
margin: 20rpx 0;
background: $color-grey0;
}
.input{
font-size: $font-size-base;
text-align: right;
flex: 1;
}
.price{
color: $color-yellow4;
}
.title{
padding : 30rpx 0;
display: flex;
justify-content: space-between;
&--min{
font-size: $font-size-sm;
color: $color-grey4;
}
}
textarea{
height: 100rpx;
}
.upload{
padding-bottom: 20rpx;
}
.btn{
position: fixed;
bottom: 40rpx;
left: 30rpx;
}
</style>

@ -0,0 +1,78 @@
<!--
* @Author: ch
* @Date: 2022-04-13 17:59:48
* @LastEditors: ch
* @LastEditTime: 2022-04-13 18:45:43
* @Description: file content
-->
<template>
<UiWhiteBox>
<text class="title">退款信息</text>
<UiGoodsInfo class="goods-info" :data="data.refundProduct"></UiGoodsInfo>
<view class="info">
<view class="info--cell">
<text class="info--cell-label">退款原因</text>
<view class="info--cell-value">{{data.refundReason}}</view>
</view>
<view class="info--cell">
<text class="info--cell-label">退款金额</text>
<view class="info--cell-value">{{data.refundAmount}}</view>
</view>
<view class="info--cell">
<text class="info--cell-label">申请件款</text>
<view class="info--cell-value">{{data.refundProduct.quantity}}</view>
</view>
<view class="info--cell">
<text class="info--cell-label">申请时间</text>
<view class="info--cell-value">{{data.applyTime}}</view>
</view>
<view class="info--cell">
<text class="info--cell-label">退款编号</text>
<view class="info--cell-value">{{data.refundNo}}</view>
</view>
</view>
</UiWhiteBox>
</template>
<script>
import UiWhiteBox from '@/components/UiWhiteBox.vue'
import UiGoodsInfo from '@/components/UiGoodsInfo.vue'
import UiCell from '@/components/UiCell.vue'
export default {
components: { UiWhiteBox, UiGoodsInfo, UiCell },
props : {
data : {
type : Object,
default : ()=>({})
}
}
}
</script>
<style lang="scss" scoped>
.title{
display: block;
height: 100rpx;
line-height: 100rpx;
padding-left: 30rpx;
border-bottom: 1px solid $color-grey2;
}
.goods-info{
border:0
}
.info{
padding: 0 30rpx 10rpx;
&--cell{
margin: 30rpx 0;
display: flex;
justify-content: space-between;
}
&--cell-label{
color: $color-grey4;
font-size: $font-size-sm;
}
&--cell-value{
font-size: $font-size-sm;
color: $color-grey5;
}
}
</style>

@ -0,0 +1,103 @@
<!--
* @Author: ch
* @Date: 2022-03-31 17:53:43
* @LastEditors: ch
* @LastEditTime: 2022-03-31 20:43:19
* @Description: file content
-->
<template>
<view class="status">
<image class="status--icon" :src="ctxCon.icon"></image>
<view class="status--name">{{ctxCon.name}}</view>
<view class="status--desc">{{ctxCon.tips}}</view>
</view>
</template>
<script>
import {DictOrderStatus } from '@/common/dicts/order'
import Enum from "@/common/plugins/enum"
export default {
props : {
orderInfo : {
type : Object,
default : {}
}
},
data(){
return {
ctxData : {
awaitPay : {name:'待付款', tips:'', icon: require('@/static/order/fk.png')},
close : {name:'交易关闭' , tips:'关闭原因', icon: require('@/static/order/qx.png')},
awaitSend : {name:'等待发货', tips:'您的包裹整装待发', icon: require('@/static/order/fh.png')},
finishSend : {name:'已发货', tips:'您的包裹正向您飞来', icon: require('@/static/order/fh.png')},
finishReceiving : {name:'已收货', icon: require('@/static/order/fh.png')},
end : {name:'交易成功', icon: require('@/static/order/cg.png')},
},
ctxCon : {},
secondNum : 0
}
},
mounted(){
},
watch : {
orderInfo(nVal){
this.ctxCon = this.ctxData[this.statusKey];
if(this.statusKey === 'awaitPay'){
let expireTime = (new Date(this.orderInfo.expireTime)).getTime(),
curTime = (new Date(this.orderInfo.serverTime)).getTime(),
second = Math.floor((expireTime - curTime) / 1000);
this.secondNum = second > 0 ? second : 0;
this.timer()
}else if(this.statusKey === 'close'){
this.ctxCon.tips = this.orderInfo.closeReason;
}
}
},
computed:{
// key
statusKey (){
return DictOrderStatus[this.orderInfo.orderStatus].value
}
},
methods:{
/**
* 待付款的计时器
*/
timer(){
if(this.secondNum == 0){
this.$emit('close');
return;
}
this.secondNum--;
let minute = parseInt(this.secondNum / 60);
let second = parseInt(this.secondNum % 60);
this.ctxCon.tips = `剩余${minute > 0 ? `${minute}` : ''} ${second}`;
// console.log(this.ctxCon.tips);
setTimeout(()=>this.timer(),1000)
}
}
}
</script>
<style lang="scss" scoped>
.status{
padding: 30rpx 60rpx 0;
position: relative;
&--icon{
width: 100rpx;
height: 100rpx;
position: absolute;
right: 60rpx;
top: 10rpx;
}
&--name{
font-size: 36rpx;
margin-bottom: 20rpx;
}
&--desc{
font-size: $font-size-base;
color: $color-grey4;
margin-bottom: 48rpx;
}
}
</style>

@ -0,0 +1,176 @@
<!--
* @Author: ch
* @Date: 2022-03-31 14:26:09
* @LastEditors: ch
* @LastEditTime: 2022-04-13 18:34:04
* @Description: file content
-->
<template>
<view>
<StatusTips :orderInfo="orderInfo" @close="timerCloseOrder"></StatusTips>
<UiWhiteBox>
<UiGoodsInfo v-for="(item, index) in orderInfo.products" :data="item" :key="index">
<template slot="operation">
<UiButton @click="$Router.push(`/saleAfterApply?type=1&id=${item.orderProductId}`)"></UiButton>
</template>
</UiGoodsInfo>
</UiWhiteBox>
<UiWhiteBox>
<u-cell class="address" title="是的发生的" label="陈先生 190****2342"
:border="false" isLink @click="$Router.push('/addressList')">
<image class="address--icon" slot="icon" src="@/static/order/dw.png" />
</u-cell>
</UiWhiteBox>
<UiWhiteBox class="cellBox">
<view class="cell">
<text class="cell--title">订单编号:</text>
<text class="cell--value">{{orderInfo.orderNo}}</text>
</view>
<view class="cell">
<text class="cell--title">订单时间:</text>
<text class="cell--value">{{orderInfo.submitTime}}</text>
</view>
<view class="cell">
<text class="cell--title">支付方式:</text>
<text class="cell--value">{{orderInfo.payTypeDesc}}</text>
</view>
<view class="cell">
<text class="cell--title">买家留言:</text>
<text class="cell--value">{{orderInfo.userMessage}}</text>
</view>
</UiWhiteBox>
<UiWhiteBox class="cellBox">
<view class="cell">
<text class="cell--title">商品总额:</text>
<text class="cell--value">{{orderInfo.totalAmount}}</text>
</view>
<view class="cell">
<text class="cell--title">运费:</text>
<text class="cell--value">{{orderInfo.shippingAmount}}</text>
</view>
</UiWhiteBox>
<GoodsInfo :data="orderInfo"></GoodsInfo>
</view>
</template>
<script>
import UiPageHeader from '@/components/UiPageHeader.vue'
import UiGoodsInfo from '@/components/UiGoodsInfo.vue'
import UiWhiteBox from '@/components/UiWhiteBox.vue'
import {ApiGetSaleAfterOrderDetail} from '@/common/api/order'
import UiButton from '@/components/UiButton.vue'
import StatusTips from './components/StatusTips.vue'
import UiCell from '@/components/UiCell.vue'
import GoodsInfo from './components/GoodsInfo.vue'
export default {
components: { UiPageHeader, UiGoodsInfo, UiWhiteBox, UiButton, StatusTips, UiCell, GoodsInfo },
data(){
return {
orderInfo : {
refundProduct:{}
}
}
},
onLoad(){
this.getOrderInfo();
},
methods : {
/**
* 获取订单最新信息
*/
async getOrderInfo(){
const {error, result} = await ApiGetSaleAfterOrderDetail({refundId:this.$Route.query.id});
if(error){
uni.$u.toast(error.message);
return false;
}
this.orderInfo = {...result, orderStatus : 7};
},
/**
* 超时自动关闭订单
*/
timerCloseOrder(){
this.orderInfo = {...this.orderInfo, orderStatus : 2, closeReason:'超时未支付'};
// this.getOrderInfo();
}
}
}
</script>
<style lang="scss" scoped>
page{
// background: linear-gradient(180deg, #FDF9F5 0%, rgba(254, 253, 252, 0) 50%) $color-grey1;
background: $color-grey1;
padding-bottom: 138rpx;
}
.header{
background: none;
}
.address{
// background: $color-grey0;
&--icon{
width: 28rpx;
height: 34rpx;
margin-right: 30rpx;
}
}
.status{
padding: 30rpx 60rpx 0;
position: relative;
&--icon{
width: 100rpx;
height: 100rpx;
position: absolute;
right: 60rpx;
top: 10rpx;
}
&--name{
font-size: 36rpx;
margin-bottom: 20rpx;
}
&--desc{
font-size: $font-size-base;
color: $color-grey4;
margin-bottom: 48rpx;
}
}
.cellBox{
padding: 30rpx;
}
.cell{
height: 56rpx;
line-height: 56rpx;
display: flex;
justify-content: space-between;
&--value{
font-size: $font-size-sm;
}
&--title{
color: $color-grey4;
font-size: $font-size-sm;
}
}
.footer{
height: 138rpx;
padding: 0 30rpx;
background: $color-grey0;
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: flex-end;
align-items: center;
&--btn{
display: block;
margin: 0 0 0 30rpx;
}
}
</style>

@ -1,7 +1,207 @@
<!--
* @Author: ch
* @Date: 2022-04-11 13:54:31
* @Date: 2022-03-22 10:58:24
* @LastEditors: ch
* @LastEditTime: 2022-04-11 13:54:32
* @LastEditTime: 2022-04-13 17:26:05
* @Description: file content
-->
<template>
<view>
<BsEmpty class="empty" v-if="!orderListData.length && loadingStatus === 'nomore'" tips="暂无售后订单呢~" :icon="require('@/static/order/empty.png')">
<ui-button slot="btn" type="line" @click="$Router('/')"></ui-button>
</BsEmpty>
<view class="orders" v-for="item in orderListData" :key="item.refundId"
@click="$Router.push(`/saleAfterDetail?id=${item.refundId}`)">
<view class="orders--title">
<text class="orders--name">官方自营</text>
<text class="orders--status">{{item.refundStatusDesc}}</text>
</view>
<view class="orders--item">
<image class="orders--item-image" mode="widthFix" :src="item.refundProduct.productImageUrl" />
<view >
<view class="orders--item-con">
<text class="orders--item-title">{{item.refundProduct.productName}}</text>
<text class="orders--item-pirce">{{item.refundProduct.realAmount}}</text>
</view>
<view class="orders--item-desc">
<text>{{item.refundProduct.skuDescribe}}</text>
<text class="orders--item-num">x{{item.refundProduct.quantity}}</text>
</view>
</view>
</view>
<view class="orders--footer">
<button class="orders--footer-btn">查看详情</button>
</view>
</view>
<u-loadmore :status="loadingStatus" v-if="orderListData.length" />
</view>
</template>
<script>
import BsEmpty from '@/components/BsEmpty.vue';
import UiButton from '@/components/UiButton.vue';
import { DictOrderStatus } from '@/common/dicts/order';
import { ApiGetSaleAfterOrderList } from '@/common/api/order';
export default {
components: { BsEmpty, UiButton },
data () {
return {
orderListData : [],
loadingStatus : 'loading',
pageIndex : 1,
pageSize : 10
}
},
onLoad(){
this.getOrderList()
},
onReachBottom(){
this.next()
},
methods: {
async getOrderList(){
this.loadingStatus = 'loading';
const {error, result} = await ApiGetSaleAfterOrderList({
length : this.pageSize,
pageIndex : this.pageIndex
});
if(error){
uni.$u.toast(error.message);
return false;
}
//
if(result.records.length < this.pageSize){
this.loadingStatus = 'nomore';
}
this.orderListData = this.orderListData.concat(result.records);
},
/**
* 到底拉取下一页数据并判断是否执行拉取
*/
next(){
if(this.loadingStatus === 'nomore'){
return false
}
this.pageIndex++;
this.getOrderList();
}
}
}
</script>
<style lang="scss" scoped>
page{
background: $color-grey1;
overflow: hidden;
}
.empty{
height: 100vh;
}
.orders{
background: $color-grey0;
padding: 30rpx;
margin: 20rpx 0;
&--title{
display: flex;
justify-content: space-between;
align-items: center;
}
&--name{
font-size: $font-size-lg;
color: $color-grey6;
}
&--status{
font-size: $font-size-sm;
color: $color-yellow3;
}
&--item{
display: flex;
justify-content: space-between;
padding: 30rpx 0 0;
}
&--item-image{
width: 180rpx;
height: 180rpx;
margin-right: 30rpx;
}
&--item-con{
width: 510rpx;
display: flex;
justify-content: space-between;
font-size: $font-size-base;
color: $color-grey6;
line-height: 39rpx;
}
&--item-title{
overflow:hidden;
text-overflow:ellipsis;
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
}
&--item-pirce{
font-size: 22rpx;
margin-left: 60rpx;
}
&--item-desc{
width: 510rpx;
font-size: $font-size-sm;
color: $color-grey4;
margin-top: 20rpx;
line-height: 39rpx;
display: flex;
justify-content: space-between;
}
&--item-num{
font-size: $font-size-base;
margin-left: 60rpx;
}
&--total{
font-size: $font-size-sm;
color: $color-grey4;
display: flex;
align-items: center;
justify-content: end;
margin-top: 30rpx;
&__amount{
font-size: $font-size-base;
margin-right: 20rpx;
}
&__pay{
color: $color-grey6;
}
}
&--footer{
display: flex;
justify-content: end;
align-items: center;
margin-top: 30rpx;
&-btn{
height: 58rpx;
line-height: 58rpx;
border-radius: 30rpx;
margin: 0 0 0 30rpx;
border: 1px solid $color-grey6;
color: $color-grey6;
background: none;
font-size: 26rpx;
&__red{
background: linear-gradient(270deg, $color-yellow2 0%, $color-yellow1 100%);
color: $color-grey0;
border: 0;
height: 60rpx;
line-height: 60rpx;
}
}
}
}
//
</style>

@ -2,7 +2,7 @@
* @Author: ch
* @Date: 2022-03-21 18:08:07
* @LastEditors: ch
* @LastEditTime: 2022-04-12 16:47:35
* @LastEditTime: 2022-04-13 09:47:45
* @Description: file content
-->
<template>
@ -190,8 +190,10 @@ page{
display: flex;
justify-content: start;
align-items: center;
font-size: 22rpx;
color: #F31F07;
text{
font-size: 22rpx;
color: #F31F07;
}
}
&--prog{
width: 167rpx;

Loading…
Cancel
Save