list.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <!-- 售后列表 -->
  2. <template>
  3. <s-layout :title="t('order.after_sales_list')">
  4. <!-- tab -->
  5. <su-sticky bgColor="#fff">
  6. <su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" />
  7. </su-sticky>
  8. <s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" :text="t('common.no_data')" />
  9. <!-- 列表 -->
  10. <view v-if="state.pagination.total > 0">
  11. <view class="list-box ss-m-y-20" v-for="order in state.pagination.list" :key="order.id"
  12. @tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })">
  13. <view class="order-head ss-flex ss-col-center ss-row-between">
  14. <text class="no">{{t('order.service_order_number')}}:{{ order.no }}</text>
  15. <text class="state">{{ formatAfterSaleStatus(order) }}</text>
  16. </view>
  17. <s-goods-item
  18. :img="order.picUrl"
  19. :title="order.spuName"
  20. :skuText="order.properties.map((property) => property.valueName).join(' ')"
  21. :price="order.refundPrice"
  22. />
  23. <view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
  24. <view class="ss-flex ss-col-center">
  25. <view class="title ss-m-r-20">{{ order.way === 10 ? t('order.refund_only') : t('order.refund_and_return') }}</view>
  26. <view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
  27. </view>
  28. <text class="_icon-forward"></text>
  29. </view>
  30. <view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
  31. <!-- TODO 功能缺失:填写退货信息 -->
  32. <view>
  33. <button class="ss-reset-button tool-btn" @tap.stop="onApply(order.id)"
  34. v-if="order?.buttons.includes('cancel')">{{t('order.cancel_request')}}</button>
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. <uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
  40. contentdown: '上拉加载更多',
  41. }" @tap="loadMore" />
  42. </s-layout>
  43. </template>
  44. <script setup>
  45. import sheep from '@/sheep';
  46. import { onLoad, onReachBottom } from '@dcloudio/uni-app';
  47. import { reactive } from 'vue';
  48. import _ from 'lodash';
  49. import { formatAfterSaleStatus, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods';
  50. import AfterSaleApi from '@/sheep/api/trade/afterSale';
  51. import { t } from '@/locale'
  52. const paginationNull = {
  53. list: [],
  54. total: 0,
  55. pageNo: 1,
  56. pageSize: 10
  57. };
  58. const state = reactive({
  59. currentTab: 0,
  60. showApply: false,
  61. pagination: {
  62. list: [],
  63. total: 0,
  64. pageNo: 1,
  65. pageSize: 10
  66. },
  67. loadStatus: '',
  68. });
  69. // TODO 非繁人:优化点,增加筛选
  70. const tabMaps = [{
  71. name: t('common.all'),
  72. value: 'all',
  73. },
  74. // {
  75. // name: '申请中',
  76. // value: 'nooper',
  77. // },
  78. // {
  79. // name: '处理中',
  80. // value: 'ing',
  81. // },
  82. // {
  83. // name: '已完成',
  84. // value: 'completed',
  85. // },
  86. // {
  87. // name: '已拒绝',
  88. // value: 'refuse',
  89. // },
  90. ];
  91. // 切换选项卡
  92. function onTabsChange(e) {
  93. state.pagination = paginationNull
  94. state.currentTab = e.index;
  95. getOrderList();
  96. }
  97. // 获取售后列表
  98. async function getOrderList() {
  99. state.loadStatus = 'loading';
  100. let { data, code } = await AfterSaleApi.getAfterSalePage({
  101. // type: tabMaps[state.currentTab].value,
  102. pageNo: state.pagination.pageNo,
  103. pageSize: state.pagination.pageSize,
  104. });
  105. if (code !== 0) {
  106. return;
  107. }
  108. data.list.forEach(order => handleAfterSaleButtons(order));
  109. state.pagination.list = _.concat(state.pagination.list, data.list);
  110. state.pagination.total = data.total;
  111. state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
  112. }
  113. function onApply(orderId) {
  114. uni.showModal({
  115. title: t('setting.prompt'),
  116. content: t('order.confirm_cancel_request'),
  117. success: async function(res) {
  118. if (!res.confirm) {
  119. return;
  120. }
  121. const { code } = await AfterSaleApi.cancelAfterSale(orderId);
  122. if (code === 0) {
  123. state.pagination = paginationNull
  124. await getOrderList();
  125. }
  126. },
  127. });
  128. }
  129. onLoad(async (options) => {
  130. if (options.type) {
  131. state.currentTab = options.type;
  132. }
  133. await getOrderList();
  134. });
  135. // 加载更多
  136. function loadMore() {
  137. if (state.loadStatus === 'noMore') {
  138. return
  139. }
  140. state.pagination.pageNo++;
  141. getOrderList();
  142. }
  143. // 上拉加载更多
  144. onReachBottom(() => {
  145. loadMore();
  146. });
  147. </script>
  148. <style lang="scss" scoped>
  149. .list-box {
  150. background-color: #fff;
  151. .order-head {
  152. padding: 0 25rpx;
  153. height: 77rpx;
  154. }
  155. .apply-box {
  156. height: 82rpx;
  157. .title {
  158. font-size: 24rpx;
  159. }
  160. .value {
  161. font-size: 22rpx;
  162. color: $dark-6;
  163. }
  164. }
  165. .tool-btn-box {
  166. height: 100rpx;
  167. .tool-btn {
  168. // width: 160rpx;
  169. padding:0 10rpx;
  170. height: 60rpx;
  171. background: #f6f6f6;
  172. border-radius: 30rpx;
  173. font-size: 26rpx;
  174. font-weight: 400;
  175. }
  176. }
  177. }
  178. </style>