|
|
@@ -0,0 +1,311 @@
|
|
|
+<!--
|
|
|
+ 商城「退款售后」列表
|
|
|
+ 从「我的」退款/售后进入;按全部/处理中/已退款/已关闭筛选 xhMallRefundApply
|
|
|
+-->
|
|
|
+<template>
|
|
|
+ <view class="refund-list-page">
|
|
|
+ <view class="tab-bar">
|
|
|
+ <view
|
|
|
+ v-for="(tab, index) in tabs"
|
|
|
+ :key="tab.key"
|
|
|
+ class="tab-item"
|
|
|
+ @click="changeTab(index)"
|
|
|
+ >
|
|
|
+ <view class="tab-inner" :class="{ 'is-active': tabIndex === index }">
|
|
|
+ <text class="tab-text">{{ tab.name }}</text>
|
|
|
+ <view v-if="tab.key === '0' && pendingCount > 0" class="tab-badge">
|
|
|
+ <text class="tab-badge__num">{{ pendingCount > 99 ? '99+' : pendingCount }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="tab-line" :class="{ 'is-active': tabIndex === index }"></view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="list-body">
|
|
|
+ <block v-if="!$util.isEmpty(list.data)">
|
|
|
+ <refund-card
|
|
|
+ v-for="item in list.data"
|
|
|
+ :key="item.id"
|
|
|
+ :info="item"
|
|
|
+ scene="list"
|
|
|
+ @detail="goDetail"
|
|
|
+ @contact="contactService"
|
|
|
+ @modify="modifyApply"
|
|
|
+ />
|
|
|
+ <view class="load-more">
|
|
|
+ <text v-if="list.loading">加载中...</text>
|
|
|
+ <text v-else-if="list.finished">没有更多了</text>
|
|
|
+ </view>
|
|
|
+ </block>
|
|
|
+ <block v-else>
|
|
|
+ <app-wrapper-empty title="暂无售后记录" :is-empty="$util.isEmpty(list.data)" />
|
|
|
+ </block>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+/**
|
|
|
+ * 退款售后列表:Tab 对应申请 status;处理中角标来自 pendingCount
|
|
|
+ */
|
|
|
+import RefundCard from '@/components/refund/refund-card.vue'
|
|
|
+import AppWrapperEmpty from '@/components/app-wrapper-empty'
|
|
|
+import { list } from '@/mixins'
|
|
|
+import { refundList, cancelRefund } from '@/api/refund'
|
|
|
+import { currentInfo } from '@/api/user'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'refundList',
|
|
|
+ components: {
|
|
|
+ RefundCard,
|
|
|
+ AppWrapperEmpty
|
|
|
+ },
|
|
|
+ mixins: [list],
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ tabIndex: 0,
|
|
|
+ pendingCount: 0,
|
|
|
+ /** 首次 onLoad 完成前不在 onShow 里重拉,避免进页连打两次 */
|
|
|
+ inited: false,
|
|
|
+ user: { name: '', smallAvatar: '', id: 0 },
|
|
|
+ tabs: [
|
|
|
+ { name: '全部', key: 'all' },
|
|
|
+ { name: '处理中', key: '0' },
|
|
|
+ { name: '已退款', key: '1' },
|
|
|
+ { name: '已关闭', key: 'closed' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad() {
|
|
|
+ this.loadUserInfo()
|
|
|
+ this.reload().then(() => {
|
|
|
+ this.inited = true
|
|
|
+ }).catch(() => {
|
|
|
+ this.inited = true
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onShow() {
|
|
|
+ // 从详情/申请页返回后刷新,角标与状态及时更新
|
|
|
+ if (!this.inited) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.reload()
|
|
|
+ },
|
|
|
+ onReachBottom() {
|
|
|
+ if (!this.list.finished) {
|
|
|
+ this.fetchList()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onPullDownRefresh() {
|
|
|
+ this.reload().then(() => {
|
|
|
+ uni.stopPullDownRefresh()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ /** 重置到第一页再拉列表 */
|
|
|
+ reload() {
|
|
|
+ this.resetList()
|
|
|
+ return this.fetchList()
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 按当前 Tab 拉取申请列表
|
|
|
+ * status=all 不筛选;closed 为驳回+取消
|
|
|
+ */
|
|
|
+ fetchList() {
|
|
|
+ const tab = this.tabs[this.tabIndex] || this.tabs[0]
|
|
|
+ return refundList({
|
|
|
+ status: tab.key,
|
|
|
+ page: this.list.page
|
|
|
+ }).then((res) => {
|
|
|
+ if (res.code == 1) {
|
|
|
+ if (!res.data) {
|
|
|
+ res.data = {}
|
|
|
+ }
|
|
|
+ if (!res.data.list) {
|
|
|
+ res.data.list = []
|
|
|
+ }
|
|
|
+ this.completes(res)
|
|
|
+ this.pendingCount = Number(res.data.pendingCount) || 0
|
|
|
+ } else {
|
|
|
+ this.list.loading = false
|
|
|
+ this.list.finished = true
|
|
|
+ this.$msg(res.msg || '获取售后列表失败')
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ this.list.loading = false
|
|
|
+ this.list.finished = true
|
|
|
+ })
|
|
|
+ },
|
|
|
+ changeTab(index) {
|
|
|
+ if (this.tabIndex === index) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.pageScrollTo({ scrollTop: 0, duration: 0 })
|
|
|
+ this.tabIndex = index
|
|
|
+ this.reload()
|
|
|
+ },
|
|
|
+ loadUserInfo() {
|
|
|
+ currentInfo().then((res) => {
|
|
|
+ if (res.code == 1 && res.data && res.data.info) {
|
|
|
+ this.user = res.data.info
|
|
|
+ } else {
|
|
|
+ this.user = { name: '', smallAvatar: '', id: 0 }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 进入售后详情 */
|
|
|
+ goDetail(item) {
|
|
|
+ if (!item || !item.id) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.pageTo({ url: '/pages/order/refund-detail?id=' + item.id })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 打开门店客服聊天,参数与订单列表联系客服一致
|
|
|
+ * customId 必须是该店 xhCustom.id;字符串 "0" 不能当有效值传给 chatPage
|
|
|
+ * @param {Object} item 售后申请行
|
|
|
+ */
|
|
|
+ contactService(item) {
|
|
|
+ if (!item) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const customId = Number(item.customId)
|
|
|
+ const shopId = Number(item.shopId)
|
|
|
+ if (!customId || customId <= 0) {
|
|
|
+ this.$msg('客户数据异常,请稍后再试')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/chat/chatPage',
|
|
|
+ success: (res) => {
|
|
|
+ res.eventChannel.emit('acceptDataFromOpenerPage', {
|
|
|
+ shopId: shopId,
|
|
|
+ customId: customId,
|
|
|
+ userId: (this.loginInfo && this.loginInfo.id) || this.user.id || '',
|
|
|
+ name: this.user.name || '',
|
|
|
+ avatar: this.user.smallAvatar || '',
|
|
|
+ chatPerson: item.hdName || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 修改申请:待审核记录只能先撤销再重新提交,没有单独的改单接口
|
|
|
+ */
|
|
|
+ modifyApply(item) {
|
|
|
+ if (!item || !item.id) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showModal({
|
|
|
+ title: '修改申请',
|
|
|
+ content: '修改需先撤销当前申请,再重新填写。是否继续?',
|
|
|
+ success: (res) => {
|
|
|
+ if (!res.confirm) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.showLoading({ mask: true, title: '处理中' })
|
|
|
+ cancelRefund({ id: item.id }).then((resp) => {
|
|
|
+ uni.hideLoading()
|
|
|
+ if (resp.code == 1) {
|
|
|
+ this.pageTo({ url: '/pages/order/refund?id=' + item.orderId })
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ uni.hideLoading()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.refund-list-page {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #f5f5f5;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-bar {
|
|
|
+ position: sticky;
|
|
|
+ top: 0;
|
|
|
+ z-index: 20;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: stretch;
|
|
|
+ height: 88upx;
|
|
|
+ background: #ffffff;
|
|
|
+ border-bottom: 1upx solid #eeeeee;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-item {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-inner {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-text {
|
|
|
+ font-size: 28upx;
|
|
|
+ color: #666666;
|
|
|
+ line-height: 40upx;
|
|
|
+
|
|
|
+ .is-active & {
|
|
|
+ color: #1f7a3d;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.tab-badge {
|
|
|
+ position: absolute;
|
|
|
+ top: -10upx;
|
|
|
+ right: -28upx;
|
|
|
+ min-width: 28upx;
|
|
|
+ height: 28upx;
|
|
|
+ padding: 0 6upx;
|
|
|
+ border-radius: 14upx;
|
|
|
+ background: #ff4d4f;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-badge__num {
|
|
|
+ font-size: 18upx;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-line {
|
|
|
+ width: 48upx;
|
|
|
+ height: 6upx;
|
|
|
+ margin-top: 8upx;
|
|
|
+ border-radius: 6upx;
|
|
|
+ background: transparent;
|
|
|
+
|
|
|
+ &.is-active {
|
|
|
+ background: #1f7a3d;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.list-body {
|
|
|
+ padding-top: 20upx;
|
|
|
+ padding-bottom: 40upx;
|
|
|
+}
|
|
|
+
|
|
|
+.load-more {
|
|
|
+ padding: 16upx 0 40upx;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 24upx;
|
|
|
+ color: #999999;
|
|
|
+}
|
|
|
+</style>
|