Browse Source

feat[litemall-wx, litemall-wx-api]: 支持售后申请、售后详情和售后列表页面

Junling Bu 5 years ago
parent
commit
0a02b924f0

+ 3 - 0
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/util/WxResponseCode.java

@@ -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;
 
 }

+ 176 - 0
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxAftersaleController.java

@@ -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;
+    }
+}

+ 3 - 1
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxOrderController.java

@@ -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")

+ 11 - 1
litemall-wx/app.json

@@ -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",

+ 6 - 2
litemall-wx/config/api.js

@@ -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 - 0
litemall-wx/pages/ucenter/aftersale/aftersale.js

@@ -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 - 0
litemall-wx/pages/ucenter/aftersale/aftersale.json

@@ -0,0 +1,3 @@
+{
+  "navigationBarTitleText": "售后"
+}

+ 45 - 0
litemall-wx/pages/ucenter/aftersale/aftersale.wxml

@@ -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 - 0
litemall-wx/pages/ucenter/aftersale/aftersale.wxss

@@ -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 - 0
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.js

@@ -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 () {
+    // 页面关闭
+  }
+})

+ 3 - 0
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.json

@@ -0,0 +1,3 @@
+{
+  "navigationBarTitleText": "售后详情"
+}

+ 42 - 0
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.wxml

@@ -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 - 0
litemall-wx/pages/ucenter/aftersaleDetail/aftersaleDetail.wxss

@@ -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 - 0
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.js

@@ -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 () {
+    // 页面关闭
+  }
+})

+ 3 - 0
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.json

@@ -0,0 +1,3 @@
+{
+  "navigationBarTitleText": "我的售后"
+}

+ 42 - 0
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.wxml

@@ -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 - 0
litemall-wx/pages/ucenter/aftersaleList/aftersaleList.wxss

@@ -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;
+}

+ 9 - 5
litemall-wx/pages/ucenter/index/index.js

@@ -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({

+ 4 - 0
litemall-wx/pages/ucenter/orderDetail/orderDetail.js

@@ -190,6 +190,10 @@ Page({
       }
     });
   },
+  // “申请售后”点击效果
+  aftersaleOrder: function () {
+    util.redirect('/pages/ucenter/aftersale/aftersale?id=' + this.data.orderId );
+  },
   onReady: function() {
     // 页面渲染完成
   },

+ 1 - 0
litemall-wx/pages/ucenter/orderDetail/orderDetail.wxml

@@ -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>

+ 1 - 0
litemall-wx/pages/ucenter/orderDetail/orderDetail.wxss

@@ -186,6 +186,7 @@ page {
 .order-bottom .address {
   height: 128rpx;
   padding-top: 25rpx;
+  border-top: 1px solid #f4f4f4;
   border-bottom: 1px solid #f4f4f4;
 }
 

+ 37 - 1
litemall-wx/project.config.json

@@ -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
 				}
 			]
 		}