feat[litemall-wx, litemall-wx-api]: 支持售后申请、售后详情和售后列表页面
This commit is contained in:
@@ -36,5 +36,8 @@ public class WxResponseCode {
|
||||
public static final int COUPON_RECEIVE_FAIL= 741;
|
||||
public static final int COUPON_CODE_INVALID= 742;
|
||||
|
||||
public static final int AFTERSALE_UNALLOWED = 750;
|
||||
public static final int AFTERSALE_INVALID_AMOUNT = 751;
|
||||
public static final int AFTERSALE_IS_REQUESTED = 752;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
package org.linlinjava.litemall.wx.web;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.core.validator.Order;
|
||||
import org.linlinjava.litemall.core.validator.Sort;
|
||||
import org.linlinjava.litemall.db.domain.*;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.util.AftersaleConstant;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.linlinjava.litemall.wx.annotation.LoginUser;
|
||||
import org.linlinjava.litemall.wx.util.WxResponseCode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 售后服务
|
||||
*
|
||||
* 目前只支持订单整体售后,不支持订单商品单个售后
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/wx/aftersale")
|
||||
@Validated
|
||||
public class WxAftersaleController {
|
||||
private final Log logger = LogFactory.getLog(WxAftersaleController.class);
|
||||
|
||||
@Autowired
|
||||
private LitemallAftersaleService aftersaleService;
|
||||
@Autowired
|
||||
private LitemallOrderService orderService;
|
||||
@Autowired
|
||||
private LitemallOrderGoodsService orderGoodsService;
|
||||
|
||||
/**
|
||||
* 售后列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param status 状态类型,如果是空则是全部
|
||||
* @param page 分页页数
|
||||
* @param limit 分页大小
|
||||
* @param sort 排序字段
|
||||
* @param order 排序方式
|
||||
* @return 售后列表
|
||||
*/
|
||||
@GetMapping("list")
|
||||
public Object list(@LoginUser Integer userId,
|
||||
@RequestParam Short status,
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer limit,
|
||||
@Sort @RequestParam(defaultValue = "add_time") String sort,
|
||||
@Order @RequestParam(defaultValue = "desc") String order) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
List<LitemallAftersale> aftersaleList = aftersaleService.queryList(userId, status, page, limit, sort, order);
|
||||
|
||||
List<Map<String, Object>> aftersaleVoList = new ArrayList<>(aftersaleList.size());
|
||||
for (LitemallAftersale aftersale : aftersaleList) {
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(aftersale.getOrderId());
|
||||
|
||||
Map<String, Object> aftersaleVo = new HashMap<>();
|
||||
aftersaleVo.put("aftersale", aftersale);
|
||||
aftersaleVo.put("goodsList", orderGoodsList);
|
||||
|
||||
aftersaleVoList.add(aftersaleVo);
|
||||
}
|
||||
|
||||
return ResponseUtil.okList(aftersaleVoList, aftersaleList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 售后详情
|
||||
*
|
||||
* @param id 售后ID
|
||||
* @return 售后详情
|
||||
*/
|
||||
@GetMapping("detail")
|
||||
public Object detail(@LoginUser Integer userId, @NotNull Integer id) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
LitemallAftersale aftersale = aftersaleService.findById(id);
|
||||
if(id == null){
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
if(!userId.equals(aftersale.getUserId())){
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(aftersale.getOrderId());
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
|
||||
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("aftersale", aftersale);
|
||||
data.put("order", order);
|
||||
data.put("orderGoods", orderGoodsList);
|
||||
return ResponseUtil.ok(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请售后
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param aftersale 用户售后信息
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("submit")
|
||||
public Object submit(@LoginUser Integer userId, @RequestBody LitemallAftersale aftersale) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Object error = validate(aftersale);
|
||||
if (error != null) {
|
||||
return error;
|
||||
}
|
||||
// 进一步验证
|
||||
Integer orderId = aftersale.getOrderId();
|
||||
if(orderId == null){
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if(order == null){
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
if(!order.getUserId().equals(userId)){
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
if(!OrderUtil.isConfirmStatus(order) && !OrderUtil.isAutoConfirmStatus(order)){
|
||||
return ResponseUtil.fail(WxResponseCode.AFTERSALE_UNALLOWED, "不支持售后");
|
||||
}
|
||||
BigDecimal amount = order.getActualPrice().subtract(order.getFreightPrice());
|
||||
if(aftersale.getAmount().compareTo(amount) > 0){
|
||||
return ResponseUtil.fail(WxResponseCode.AFTERSALE_INVALID_AMOUNT, "退款金额不正确");
|
||||
}
|
||||
|
||||
if(aftersaleService.countByOrderIdWithoutReject(userId, orderId) > 0){
|
||||
return ResponseUtil.fail(WxResponseCode.AFTERSALE_UNALLOWED, "已申请售后");
|
||||
}
|
||||
|
||||
aftersale.setStatus(AftersaleConstant.STATUS_REQUEST);
|
||||
aftersale.setAftersaleSn(aftersaleService.generateAftersaleSn(userId));
|
||||
aftersale.setUserId(userId);
|
||||
aftersaleService.add(aftersale);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
private Object validate(LitemallAftersale aftersale) {
|
||||
Short type = aftersale.getType();
|
||||
if (type == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
BigDecimal amount = aftersale.getAmount();
|
||||
if (amount == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
String reason = aftersale.getReason();
|
||||
if (StringUtils.isEmpty(reason)) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,11 @@ public class WxOrderController {
|
||||
* 订单列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param showType 订单信息
|
||||
* @param showType 显示类型,如果是0则是全部订单
|
||||
* @param page 分页页数
|
||||
* @param limit 分页大小
|
||||
* @param sort 排序字段
|
||||
* @param order 排序方式
|
||||
* @return 订单列表
|
||||
*/
|
||||
@GetMapping("list")
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
"pages/groupon/grouponDetail/grouponDetail",
|
||||
"pages/groupon/grouponList/grouponList",
|
||||
"pages/coupon/coupon",
|
||||
"pages/help/help"
|
||||
"pages/help/help",
|
||||
"pages/ucenter/aftersale/aftersale",
|
||||
"pages/ucenter/aftersaleList/aftersaleList",
|
||||
"pages/ucenter/aftersaleDetail/aftersaleDetail"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarBackgroundColor": "#FFFFFF",
|
||||
@@ -87,6 +90,13 @@
|
||||
},
|
||||
"debug": true,
|
||||
"usingComponents": {
|
||||
"van-cell": "./lib/vant-weapp/cell/index",
|
||||
"van-cell-group": "./lib/vant-weapp/cell-group/index",
|
||||
"van-picker": "./lib/vant-weapp/picker/index",
|
||||
"van-popup": "./lib/vant-weapp/popup/index",
|
||||
"van-field": "./lib/vant-weapp/field/index",
|
||||
"van-uploader": "./lib/vant-weapp/uploader/index",
|
||||
"van-button": "./lib/vant-weapp/button/index",
|
||||
"van-tag": "./lib/vant-weapp/tag/index",
|
||||
"van-icon": "./lib/vant-weapp/icon/index",
|
||||
"van-checkbox": "./lib/vant-weapp/checkbox/index",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 以下是业务服务器API地址
|
||||
// 本机开发时使用
|
||||
var WxApiRoot = 'http://localhost:8080/wx/';
|
||||
// var WxApiRoot = 'http://localhost:8080/wx/';
|
||||
// 局域网测试使用
|
||||
// var WxApiRoot = 'http://192.168.0.101:8080/wx/';
|
||||
var WxApiRoot = 'http://192.168.1.3:8080/wx/';
|
||||
// 云平台部署时使用
|
||||
// var WxApiRoot = 'http://122.51.199.160:8080/wx/';
|
||||
// 云平台上线时使用
|
||||
@@ -77,6 +77,10 @@ module.exports = {
|
||||
OrderGoods: WxApiRoot + 'order/goods', // 代评价商品信息
|
||||
OrderComment: WxApiRoot + 'order/comment', // 评价订单商品信息
|
||||
|
||||
AftersaleSubmit: WxApiRoot + 'aftersale/submit', // 提交售后申请
|
||||
AftersaleList: WxApiRoot + 'aftersale/list', // 售后列表
|
||||
AftersaleDetail: WxApiRoot + 'aftersale/detail', // 售后详情
|
||||
|
||||
FeedbackAdd: WxApiRoot + 'feedback/submit', //添加反馈
|
||||
FootprintList: WxApiRoot + 'footprint/list', //足迹列表
|
||||
FootprintDelete: WxApiRoot + 'footprint/delete', //删除足迹
|
||||
|
||||
171
litemall-wx/pages/ucenter/aftersale/aftersale.js
Normal file
171
litemall-wx/pages/ucenter/aftersale/aftersale.js
Normal file
@@ -0,0 +1,171 @@
|
||||
var util = require('../../../utils/util.js');
|
||||
var api = require('../../../config/api.js');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
orderId: 0,
|
||||
orderInfo: {},
|
||||
orderGoods: [],
|
||||
aftersale: {
|
||||
pictures: []
|
||||
},
|
||||
columns: ['未收货退款', '不退货退款', '退货退款'],
|
||||
contentLength: 0,
|
||||
fileList: []
|
||||
},
|
||||
onLoad: function (options) {
|
||||
// 页面初始化 options为页面跳转所带来的参数
|
||||
this.setData({
|
||||
orderId: options.id
|
||||
});
|
||||
this.getOrderDetail();
|
||||
},
|
||||
getOrderDetail: function () {
|
||||
wx.showLoading({
|
||||
title: '加载中',
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
wx.hideLoading()
|
||||
}, 2000);
|
||||
|
||||
let that = this;
|
||||
util.request(api.OrderDetail, {
|
||||
orderId: that.data.orderId
|
||||
}).then(function (res) {
|
||||
if (res.errno === 0) {
|
||||
console.log(res.data);
|
||||
that.setData({
|
||||
orderInfo: res.data.orderInfo,
|
||||
orderGoods: res.data.orderGoods,
|
||||
'aftersale.orderId': that.data.orderId,
|
||||
'aftersale.amount': res.data.orderInfo.actualPrice - res.data.orderInfo.freightPrice
|
||||
});
|
||||
}
|
||||
|
||||
wx.hideLoading();
|
||||
});
|
||||
},
|
||||
deleteImage (event) {
|
||||
const { fileList = [] } = this.data;
|
||||
fileList.splice(event.detail.index, 1)
|
||||
this.setData({
|
||||
fileList: fileList
|
||||
})
|
||||
},
|
||||
afterRead(event) {
|
||||
const { file } = event.detail
|
||||
let that = this
|
||||
const uploadTask = wx.uploadFile({
|
||||
url: api.StorageUpload,
|
||||
filePath: file.path,
|
||||
name: 'file',
|
||||
success: function (res) {
|
||||
var _res = JSON.parse(res.data);
|
||||
if (_res.errno === 0) {
|
||||
var url = _res.data.url
|
||||
that.data.aftersale.pictures.push(url)
|
||||
const { fileList = [] } = that.data;
|
||||
fileList.push({ ...file, url: url });
|
||||
that.setData({
|
||||
fileList: fileList
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: function (e) {
|
||||
wx.showModal({
|
||||
title: '错误',
|
||||
content: '上传失败',
|
||||
showCancel: false
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
previewImage: function (e) {
|
||||
wx.previewImage({
|
||||
current: e.currentTarget.id, // 当前显示图片的http链接
|
||||
urls: this.data.files // 需要预览的图片http链接列表
|
||||
})
|
||||
},
|
||||
contentInput: function (e) {
|
||||
this.setData({
|
||||
contentLength: e.detail.cursor,
|
||||
'aftersale.comment': e.detail.value,
|
||||
});
|
||||
},
|
||||
onReasonChange: function (e) {
|
||||
this.setData({
|
||||
'aftersale.reason': e.detail,
|
||||
});
|
||||
},
|
||||
showTypePicker: function () {
|
||||
this.setData({
|
||||
showPicker: true,
|
||||
});
|
||||
},
|
||||
|
||||
onCancel: function () {
|
||||
this.setData({
|
||||
showPicker: false,
|
||||
});
|
||||
},
|
||||
onConfirm: function (event) {
|
||||
this.setData({
|
||||
'aftersale.type': event.detail.index,
|
||||
'aftersale.typeDesc': event.detail.value,
|
||||
showPicker: false,
|
||||
});
|
||||
},
|
||||
submit: function () {
|
||||
let that = this;
|
||||
if (that.data.aftersale.type == undefined) {
|
||||
util.showErrorToast('请选择退款类型');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (that.data.reason == '') {
|
||||
util.showErrorToast('请输入退款原因');
|
||||
return false;
|
||||
}
|
||||
|
||||
wx.showLoading({
|
||||
title: '提交中...',
|
||||
mask: true,
|
||||
success: function () {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
util.request(api.AftersaleSubmit, that.data.aftersale, 'POST').then(function (res) {
|
||||
wx.hideLoading();
|
||||
|
||||
if (res.errno === 0) {
|
||||
wx.showToast({
|
||||
title: '申请售后成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
complete: function () {
|
||||
wx.switchTab({
|
||||
url: '/pages/ucenter/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
util.showErrorToast(res.errmsg);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
onReady: function () {
|
||||
// 页面渲染完成
|
||||
},
|
||||
onShow: function () {
|
||||
// 页面显示
|
||||
},
|
||||
onHide: function () {
|
||||
// 页面隐藏
|
||||
},
|
||||
onUnload: function () {
|
||||
// 页面关闭
|
||||
}
|
||||
})
|
||||
3
litemall-wx/pages/ucenter/aftersale/aftersale.json
Normal file
3
litemall-wx/pages/ucenter/aftersale/aftersale.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "售后"
|
||||
}
|
||||
45
litemall-wx/pages/ucenter/aftersale/aftersale.wxml
Normal file
45
litemall-wx/pages/ucenter/aftersale/aftersale.wxml
Normal file
@@ -0,0 +1,45 @@
|
||||
<view class="container">
|
||||
<view class="order-goods">
|
||||
<view class="h">
|
||||
退款商品
|
||||
</view>
|
||||
<view class="goods">
|
||||
<view class="item" wx:for="{{orderGoods}}" wx:key="id">
|
||||
<view class="img">
|
||||
<image src="{{item.picUrl}}"></image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="t">
|
||||
<text class="name">{{item.goodsName}}</text>
|
||||
<text class="number">x{{item.number}}</text>
|
||||
</view>
|
||||
<view class="attr">{{item.specifications}}</view>
|
||||
<view class="price">¥{{item.price}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<van-cell-group title="订单明细">
|
||||
<van-cell title="商品总价" value=" ¥{{orderInfo.goodsPrice}}元" />
|
||||
<van-cell title=" 运费" value=" ¥{{orderInfo.freightPrice}}元" />
|
||||
<van-cell title=" 优惠" value="-¥{{orderInfo.couponPrice}}元" />
|
||||
<van-cell title="订单实付" value=" ¥{{orderInfo.actualPrice}}元" />
|
||||
</van-cell-group>
|
||||
|
||||
<van-cell-group title="操作">
|
||||
<van-field value="{{ aftersale.typeDesc }}" label="退款类型" placeholder="请选择" input-align="right" required clickable bind:tap="showTypePicker" />
|
||||
<van-field value="{{ aftersale.reason }}" label="退款原因" placeholder="请输入" bind:change="onReasonChange" input-align="right" required clearable />
|
||||
<van-cell title="退款金额" value="¥{{ aftersale.amount }}元" label="不可修改,即订单实付- 运费" required/>
|
||||
<van-field label="退款说明" value="{{ aftersale.comment }}" placeholder="请输入" type="textarea" input-align="right" autosize/>
|
||||
<van-cell title="上传凭证" label="最多上传三张">
|
||||
<van-uploader file-list="{{ fileList }}" bind:after-read="afterRead" bind:delete="deleteImage" max-count="3" preview-size="50px"/>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
|
||||
<van-button type="danger" bind:click="submit" block>申请售后</van-button>
|
||||
|
||||
<van-popup show="{{showPicker}}" position="bottom">
|
||||
<van-picker show-toolbar columns="{{columns}}" bind:cancel="onCancel" bind:confirm="onConfirm" />
|
||||
</van-popup>
|
||||
</view>
|
||||
103
litemall-wx/pages/ucenter/aftersale/aftersale.wxss
Normal file
103
litemall-wx/pages/ucenter/aftersale/aftersale.wxss
Normal file
@@ -0,0 +1,103 @@
|
||||
page {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.order-goods {
|
||||
margin-top: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.order-goods .h {
|
||||
height: 93.75rpx;
|
||||
line-height: 93.75rpx;
|
||||
margin-left: 31.25rpx;
|
||||
border-bottom: 1px solid #f4f4f4;
|
||||
padding-right: 31.25rpx;
|
||||
}
|
||||
|
||||
.order-goods .h .label {
|
||||
float: left;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-goods .h .status {
|
||||
float: right;
|
||||
font-size: 30rpx;
|
||||
color: #b4282d;
|
||||
}
|
||||
|
||||
.order-goods .item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 192rpx;
|
||||
margin-left: 31.25rpx;
|
||||
padding-right: 31.25rpx;
|
||||
border-bottom: 1px solid #f4f4f4;
|
||||
}
|
||||
|
||||
.order-goods .item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.order-goods .item .img {
|
||||
height: 145.83rpx;
|
||||
width: 145.83rpx;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.order-goods .item .img image {
|
||||
height: 145.83rpx;
|
||||
width: 145.83rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .info {
|
||||
flex: 1;
|
||||
height: 145.83rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .t {
|
||||
margin-top: 8rpx;
|
||||
height: 33rpx;
|
||||
line-height: 33rpx;
|
||||
margin-bottom: 10.5rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .t .name {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 33rpx;
|
||||
line-height: 33rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .t .number {
|
||||
display: block;
|
||||
float: right;
|
||||
height: 33rpx;
|
||||
text-align: right;
|
||||
line-height: 33rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .attr {
|
||||
height: 29rpx;
|
||||
line-height: 29rpx;
|
||||
color: #666;
|
||||
margin-bottom: 25rpx;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .price {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 30rpx;
|
||||
line-height: 30rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
65
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.js
Normal file
65
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.js
Normal file
@@ -0,0 +1,65 @@
|
||||
var util = require('../../../utils/util.js');
|
||||
var api = require('../../../config/api.js');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
aftersaleId: 0,
|
||||
order: {},
|
||||
orderGoods: [],
|
||||
aftersale: {},
|
||||
statusColumns: ['已申请', '处理中', '退款成功', '已拒绝'],
|
||||
typeColumns: ['未收货退款', '不退货退款', '退货退款'],
|
||||
fileList: []
|
||||
},
|
||||
onLoad: function (options) {
|
||||
// 页面初始化 options为页面跳转所带来的参数
|
||||
this.setData({
|
||||
aftersaleId: options.id
|
||||
});
|
||||
this.getAftersaleDetail();
|
||||
},
|
||||
getAftersaleDetail: function () {
|
||||
wx.showLoading({
|
||||
title: '加载中',
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
wx.hideLoading()
|
||||
}, 2000);
|
||||
|
||||
let that = this;
|
||||
util.request(api.AftersaleDetail, {
|
||||
id: that.data.aftersaleId
|
||||
}).then(function (res) {
|
||||
if (res.errno === 0) {
|
||||
let _fileList = []
|
||||
res.data.aftersale.pictures.forEach(function (v) {
|
||||
_fileList.push({
|
||||
url: v
|
||||
})
|
||||
});
|
||||
|
||||
that.setData({
|
||||
order: res.data.order,
|
||||
orderGoods: res.data.orderGoods,
|
||||
aftersale: res.data.aftersale,
|
||||
fileList: _fileList
|
||||
});
|
||||
}
|
||||
|
||||
wx.hideLoading();
|
||||
});
|
||||
},
|
||||
onReady: function () {
|
||||
// 页面渲染完成
|
||||
},
|
||||
onShow: function () {
|
||||
// 页面显示
|
||||
},
|
||||
onHide: function () {
|
||||
// 页面隐藏
|
||||
},
|
||||
onUnload: function () {
|
||||
// 页面关闭
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "售后详情"
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<view class="container">
|
||||
<van-cell-group title="退款明细">
|
||||
<van-cell value="{{ statusColumns[aftersale.status] }}" title="售后状态" required/>
|
||||
<van-cell value="{{ aftersale.addTime }}" title="申请时间" required/>
|
||||
<van-cell value="{{ aftersale.aftersaleSn }}" title="服务编号" required/>
|
||||
<van-cell value="{{ typeColumns[aftersale.type] }}" title="退款类型" required/>
|
||||
<van-cell value="{{ aftersale.reason }}" title="退款原因" required/>
|
||||
<van-cell title="退款金额" value="¥{{ aftersale.amount }}元" label="即订单实付- 运费" required/>
|
||||
<van-field label="退款说明" value="{{ aftersale.comment }}" type="textarea" autosize disabled/>
|
||||
<van-cell title="上传凭证" >
|
||||
<van-uploader file-list="{{ fileList }}" disabled deletable="{{false}}" max-count="0" preview-size="50px"/>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
|
||||
<view class="order-goods">
|
||||
<view class="h">
|
||||
退款商品
|
||||
</view>
|
||||
<view class="goods">
|
||||
<view class="item" wx:for="{{orderGoods}}" wx:key="id">
|
||||
<view class="img">
|
||||
<image src="{{item.picUrl}}"></image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="t">
|
||||
<text class="name">{{item.goodsName}}</text>
|
||||
<text class="number">x{{item.number}}</text>
|
||||
</view>
|
||||
<view class="attr">{{item.specifications}}</view>
|
||||
<view class="price">¥{{item.price}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<van-cell-group title="订单明细">
|
||||
<van-cell title="商品总价" value=" ¥{{order.goodsPrice}}元" />
|
||||
<van-cell title=" 运费" value=" ¥{{order.freightPrice}}元" />
|
||||
<van-cell title=" 优惠" value="-¥{{order.couponPrice}}元" />
|
||||
<van-cell title="订单实付" value=" ¥{{order.actualPrice}}元" />
|
||||
</van-cell-group>
|
||||
</view>
|
||||
187
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.wxss
Normal file
187
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.wxss
Normal file
@@ -0,0 +1,187 @@
|
||||
page {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.order-goods {
|
||||
margin-top: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.order-goods .h {
|
||||
height: 93.75rpx;
|
||||
line-height: 93.75rpx;
|
||||
margin-left: 31.25rpx;
|
||||
border-bottom: 1px solid #f4f4f4;
|
||||
padding-right: 31.25rpx;
|
||||
}
|
||||
|
||||
.order-goods .h .label {
|
||||
float: left;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-goods .h .status {
|
||||
float: right;
|
||||
font-size: 30rpx;
|
||||
color: #b4282d;
|
||||
}
|
||||
|
||||
.order-goods .item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 192rpx;
|
||||
margin-left: 31.25rpx;
|
||||
padding-right: 31.25rpx;
|
||||
border-bottom: 1px solid #f4f4f4;
|
||||
}
|
||||
|
||||
.order-goods .item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.order-goods .item .img {
|
||||
height: 145.83rpx;
|
||||
width: 145.83rpx;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.order-goods .item .img image {
|
||||
height: 145.83rpx;
|
||||
width: 145.83rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .info {
|
||||
flex: 1;
|
||||
height: 145.83rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .t {
|
||||
margin-top: 8rpx;
|
||||
height: 33rpx;
|
||||
line-height: 33rpx;
|
||||
margin-bottom: 10.5rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .t .name {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 33rpx;
|
||||
line-height: 33rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .t .number {
|
||||
display: block;
|
||||
float: right;
|
||||
height: 33rpx;
|
||||
text-align: right;
|
||||
line-height: 33rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .attr {
|
||||
height: 29rpx;
|
||||
line-height: 29rpx;
|
||||
color: #666;
|
||||
margin-bottom: 25rpx;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
.order-goods .item .price {
|
||||
display: block;
|
||||
float: left;
|
||||
height: 30rpx;
|
||||
line-height: 30rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
|
||||
.fb-body {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
height: 300rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.fb-body .content {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.weui-uploader__files {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.weui-uploader__file {
|
||||
float: left;
|
||||
margin-right: 9px;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
.weui-uploader__img {
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.weui-uploader__input-box {
|
||||
float: left;
|
||||
position: relative;
|
||||
margin-right: 9px;
|
||||
margin-bottom: 9px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.weui-uploader__input-box:after, .weui-uploader__input-box:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: #d9d9d9;
|
||||
}
|
||||
|
||||
.weui-uploader__input-box:before {
|
||||
width: 2px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.weui-uploader__input-box:after {
|
||||
width: 30px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.weui-uploader__input-box:active {
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.weui-uploader__input-box:active:after, .weui-uploader__input-box:active:before {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
.weui-uploader__input {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
.fb-body .text-count {
|
||||
float: right;
|
||||
color: #666;
|
||||
font-size: 24rpx;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
69
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.js
Normal file
69
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.js
Normal file
@@ -0,0 +1,69 @@
|
||||
var util = require('../../../utils/util.js');
|
||||
var api = require('../../../config/api.js');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
aftersaleList: [],
|
||||
showType: 0,
|
||||
page: 1,
|
||||
limit: 10,
|
||||
totalPages: 1
|
||||
},
|
||||
onLoad: function (options) {
|
||||
},
|
||||
getAftersaleList() {
|
||||
let that = this;
|
||||
util.request(api.AftersaleList, {
|
||||
status: that.data.showType,
|
||||
page: that.data.page,
|
||||
limit: that.data.limit
|
||||
}).then(function (res) {
|
||||
if (res.errno === 0) {
|
||||
console.log(res.data);
|
||||
that.setData({
|
||||
aftersaleList: that.data.aftersaleList.concat(res.data.list),
|
||||
totalPages: res.data.pages
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.data.totalPages > this.data.page) {
|
||||
this.setData({
|
||||
page: this.data.page + 1
|
||||
});
|
||||
this.getAftersaleList();
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: '没有更多售后了',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
switchTab: function (event) {
|
||||
let showType = event.currentTarget.dataset.index;
|
||||
this.setData({
|
||||
aftersaleList: [],
|
||||
showType: showType,
|
||||
page: 1,
|
||||
limit: 10,
|
||||
totalPages: 1
|
||||
});
|
||||
this.getAftersaleList();
|
||||
},
|
||||
onReady: function () {
|
||||
// 页面渲染完成
|
||||
},
|
||||
onShow: function () {
|
||||
// 页面显示
|
||||
this.getAftersaleList();
|
||||
},
|
||||
onHide: function () {
|
||||
// 页面隐藏
|
||||
},
|
||||
onUnload: function () {
|
||||
// 页面关闭
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "我的售后"
|
||||
}
|
||||
42
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.wxml
Normal file
42
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.wxml
Normal file
@@ -0,0 +1,42 @@
|
||||
<view class="container">
|
||||
<view class="aftersales-switch">
|
||||
<view class="item {{ showType == 0 ? 'active' : ''}}" bindtap="switchTab" data-index='0'>
|
||||
<view class="txt">申请中</view>
|
||||
</view>
|
||||
<view class="item {{ showType == 1 ? 'active' : ''}}" bindtap="switchTab" data-index='1'>
|
||||
<view class="txt">处理中</view>
|
||||
</view>
|
||||
<view class="item {{ showType == 2 ? 'active' : ''}}" bindtap="switchTab" data-index='2'>
|
||||
<view class="txt">已完成</view>
|
||||
</view>
|
||||
<view class="item {{ showType == 3 ? 'active' : ''}}" bindtap="switchTab" data-index='3'>
|
||||
<view class="txt">已拒绝</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="no-aftersale" wx:if="{{aftersaleList.length <= 0}}">
|
||||
<view class="c">
|
||||
<text>还没有呢</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="aftersales">
|
||||
<navigator url="../aftersaleDetail/aftersaleDetail?id={{item.aftersale.id}}" class="aftersale" open-type="redirect" wx:for="{{aftersaleList}}" wx:key="id">
|
||||
<view class="h">
|
||||
<view class="l">服务编号:{{item.aftersale.aftersaleSn}}</view>
|
||||
</view>
|
||||
<view class="goods" wx:for="{{item.goodsList}}" wx:key="id" wx:for-item="gitem">
|
||||
<view class="img">
|
||||
<image src="{{gitem.picUrl}}"></image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="name">{{gitem.goodsName}}</text>
|
||||
<text class="number">{{gitem.number}}件商品</text>
|
||||
</view>
|
||||
<view class="status"></view>
|
||||
</view>
|
||||
<view class="b">
|
||||
<view class="l">申请退款金额:¥{{item.aftersale.amount}}元</view>
|
||||
</view>
|
||||
</navigator>
|
||||
</view>
|
||||
</view>
|
||||
165
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.wxss
Normal file
165
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.wxss
Normal file
@@ -0,0 +1,165 @@
|
||||
page {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.aftersales-switch {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
height: 84rpx;
|
||||
}
|
||||
|
||||
.aftersales-switch .item {
|
||||
display: inline-block;
|
||||
height: 82rpx;
|
||||
width: 18%;
|
||||
padding: 0 15rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.aftersales-switch .item .txt {
|
||||
display: inline-block;
|
||||
height: 82rpx;
|
||||
padding: 0 20rpx;
|
||||
line-height: 82rpx;
|
||||
color: #9a9ba1;
|
||||
font-size: 30rpx;
|
||||
width: 170rpx;
|
||||
}
|
||||
|
||||
.aftersales-switch .item.active .txt {
|
||||
color: #ab956d;
|
||||
border-bottom: 4rpx solid #ab956d;
|
||||
}
|
||||
|
||||
.no-aftersale {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.no-aftersale .c {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-top: 400rpx;
|
||||
}
|
||||
|
||||
.no-aftersale .c text {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
width: 258rpx;
|
||||
height: 29rpx;
|
||||
line-height: 29rpx;
|
||||
text-align: center;
|
||||
font-size: 29rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.aftersales {
|
||||
height: auto;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aftersale {
|
||||
margin-top: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.aftersale .h {
|
||||
height: 83.3rpx;
|
||||
line-height: 83.3rpx;
|
||||
margin-left: 31.25rpx;
|
||||
padding-right: 31.25rpx;
|
||||
border-bottom: 1px solid #f4f4f4;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.aftersale .h .l {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.aftersale .h .r {
|
||||
float: right;
|
||||
color: #b4282d;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.aftersale .goods {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 199rpx;
|
||||
margin-left: 31.25rpx;
|
||||
}
|
||||
|
||||
.aftersale .goods .img {
|
||||
height: 145.83rpx;
|
||||
width: 145.83rpx;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
.aftersale .goods .img image {
|
||||
height: 145.83rpx;
|
||||
width: 145.83rpx;
|
||||
}
|
||||
|
||||
.aftersale .goods .info {
|
||||
height: 145.83rpx;
|
||||
flex: 1;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.aftersale .goods .name {
|
||||
margin-top: 30rpx;
|
||||
display: block;
|
||||
height: 44rpx;
|
||||
line-height: 44rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.aftersale .goods .number {
|
||||
display: block;
|
||||
height: 37rpx;
|
||||
line-height: 37rpx;
|
||||
color: #666;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
.aftersale .goods .status {
|
||||
width: 105rpx;
|
||||
color: #b4282d;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
.aftersale .b {
|
||||
height: 103rpx;
|
||||
line-height: 103rpx;
|
||||
margin-left: 31.25rpx;
|
||||
padding-right: 31.25rpx;
|
||||
border-top: 1px solid #f4f4f4;
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.aftersale .b .l {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.aftersale .b .r {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.aftersale .b .btn {
|
||||
margin-top: 19rpx;
|
||||
height: 64.5rpx;
|
||||
line-height: 64.5rpx;
|
||||
text-align: center;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 5rpx;
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
background: #b4282d;
|
||||
}
|
||||
@@ -190,11 +190,15 @@ Page({
|
||||
});
|
||||
},
|
||||
goAfterSale: function() {
|
||||
wx.showToast({
|
||||
title: '目前不支持',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
if (this.data.hasLogin) {
|
||||
wx.navigateTo({
|
||||
url: "/pages/ucenter/aftersaleList/aftersaleList"
|
||||
});
|
||||
} else {
|
||||
wx.navigateTo({
|
||||
url: "/pages/auth/login/login"
|
||||
});
|
||||
};
|
||||
},
|
||||
aboutUs: function() {
|
||||
wx.navigateTo({
|
||||
|
||||
@@ -190,6 +190,10 @@ Page({
|
||||
}
|
||||
});
|
||||
},
|
||||
// “申请售后”点击效果
|
||||
aftersaleOrder: function () {
|
||||
util.redirect('/pages/ucenter/aftersale/aftersale?id=' + this.data.orderId );
|
||||
},
|
||||
onReady: function() {
|
||||
// 页面渲染完成
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<view class="btn active" bindtap="confirmOrder" wx:if="{{handleOption.confirm}}">确认收货</view>
|
||||
<view class="btn active" bindtap="deleteOrder" wx:if="{{handleOption.delete}}">删除订单</view>
|
||||
<view class="btn active" bindtap="refundOrder" wx:if="{{handleOption.refund}}">申请退款</view>
|
||||
<view class="btn active" bindtap="aftersaleOrder" wx:if="{{handleOption.aftersale}}">申请售后</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -186,6 +186,7 @@ page {
|
||||
.order-bottom .address {
|
||||
height: 128rpx;
|
||||
padding-top: 25rpx;
|
||||
border-top: 1px solid #f4f4f4;
|
||||
border-bottom: 1px solid #f4f4f4;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,18 @@
|
||||
"postcss": true,
|
||||
"minified": true,
|
||||
"newFeature": true,
|
||||
"uglifyFileName": true
|
||||
"coverView": true,
|
||||
"autoAudits": false,
|
||||
"uglifyFileName": true,
|
||||
"checkInvalidKey": true,
|
||||
"checkSiteMap": true,
|
||||
"uploadWithSourceMap": true,
|
||||
"babelSetting": {
|
||||
"ignore": [],
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
},
|
||||
"nodeModules": true
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"libVersion": "2.4.0",
|
||||
@@ -30,6 +41,10 @@
|
||||
"game": {
|
||||
"list": []
|
||||
},
|
||||
"gamePlugin": {
|
||||
"current": -1,
|
||||
"list": []
|
||||
},
|
||||
"miniprogram": {
|
||||
"current": 22,
|
||||
"list": [
|
||||
@@ -274,6 +289,27 @@
|
||||
"pathName": "pages/groupon/myGroupon/myGroupon",
|
||||
"query": "",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"id": -1,
|
||||
"name": "申请售后",
|
||||
"pathName": "pages/ucenter/aftersale/aftersale",
|
||||
"query": "id=2",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"id": -1,
|
||||
"name": "售后列表",
|
||||
"pathName": "pages/ucenter/aftersaleList/aftersaleList",
|
||||
"query": "",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"id": -1,
|
||||
"name": "售后详情",
|
||||
"pathName": "pages/ucenter/aftersaleDetail/aftersaleDetail",
|
||||
"query": "id=1",
|
||||
"scene": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user