index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <script setup lang="ts">
  2. import router from '@/router'
  3. definePage({
  4. name: 'common-afterSales',
  5. islogin: true,
  6. style: {
  7. navigationBarTitleText: '申请售后',
  8. },
  9. })
  10. const afterSalesType = ref(1)
  11. const isSeletAllGoods = ref(false)
  12. const selectGoods = ref<number[]>([])
  13. const fileList = ref<{ url: string }[]>([])
  14. const showReson = ref(false)
  15. const resonId = ref()
  16. const resonName = ref('请选择退款原因')
  17. const resonList = [
  18. { id: 1, name: '暂不需要商品(买错/多买/漏买)' },
  19. { id: 2, name: '冰品融化' },
  20. { id: 3, name: '订单中有商品发错' },
  21. { id: 4, name: '商品斤两不足' },
  22. { id: 5, name: '商品临期到期' },
  23. { id: 6, name: '商品破损/包装破损' },
  24. { id: 7, name: '其他' },
  25. ]
  26. const orderList = ref<Api.xsbOmsOrderItem[]>([])
  27. const remark = ref('')
  28. onLoad((options: any) => {
  29. orderList.value = JSON.parse(options.order)
  30. orderList.value = orderList.value.map((item: Api.xsbOmsOrderItem) => {
  31. item.num = 1
  32. return item
  33. })
  34. })
  35. const refunMoney = ref(0)
  36. const isSubmit = ref(false)
  37. async function handleSubmit() {
  38. console.log(fileList.value, 'fileList')
  39. if (!selectGoods.value.length) {
  40. useGlobalToast().show({ msg: '请选择需要退款的商品' })
  41. return
  42. }
  43. if (!resonId.value) {
  44. useGlobalToast().show({ msg: '请选择退款原因' })
  45. return
  46. }
  47. if (!orderList.value[0].orderNumber) {
  48. useGlobalToast().show({ msg: '订单数据异常' })
  49. return
  50. }
  51. isSubmit.value = true
  52. try {
  53. const res = await cathcApplRefund()
  54. router.push({ name: 'common-afterSalesDetail', params: { refundNumber: res } })
  55. isSubmit.value = false
  56. }
  57. catch (e) {
  58. isSubmit.value = false
  59. console.log(e)
  60. }
  61. // router.push({ name: 'common-afterSalesDetail' })
  62. }
  63. function cathcApplRefund(): Promise<string> {
  64. uni.showLoading({ mask: true })
  65. return new Promise((resolve, reject) => {
  66. const filerData = orderList.value.filter(it => selectGoods.value.includes(Number(it.skuId)))
  67. Apis.xsb.applyRefund({
  68. data: {
  69. orderNumber: orderList.value[0].orderNumber,
  70. businessType: 1,
  71. applyType: afterSalesType.value,
  72. refundType: 2,
  73. buyerReason: resonName.value,
  74. buyerDesc: remark.value,
  75. photoFiles: fileList.value.map(it => it.url).join(','),
  76. orderRefundSkuList: filerData.map((it) => {
  77. return {
  78. orderItemId: it.orderItemId,
  79. productCount: it.num,
  80. }
  81. }),
  82. },
  83. }).then((res) => { resolve(res.data) }).catch((err) => {
  84. reject(err)
  85. }).finally(() => { uni.hideLoading() })
  86. })
  87. }
  88. function handleSelectReson() {
  89. if (!resonId.value)
  90. return uni.showToast({ title: '请选择退款原因', icon: 'none' })
  91. showReson.value = false
  92. resonName.value = resonList.find(item => item.id === resonId.value)?.name || '请选择退款原因'
  93. }
  94. function handleSelectGoods() {
  95. console.log(orderList.value, 'orderList', selectGoods.value)
  96. if (selectGoods.value.length === orderList.value.length) {
  97. isSeletAllGoods.value = true
  98. }
  99. else {
  100. isSeletAllGoods.value = false
  101. refunMoney.value = 0
  102. }
  103. }
  104. function handleChangeAll() {
  105. console.log(isSeletAllGoods.value, 'isSeletAllGoods')
  106. if (isSeletAllGoods.value) {
  107. selectGoods.value = orderList.value.map(it => it.skuId) as number[]
  108. }
  109. else {
  110. selectGoods.value = []
  111. refunMoney.value = 0
  112. }
  113. }
  114. watch(() => [selectGoods.value, orderList.value], () => {
  115. if (selectGoods.value.length) {
  116. getReufndMoney()
  117. }
  118. })
  119. async function getReufndMoney() {
  120. console.log(orderList.value[0].orderNumber, 'orderList.value')
  121. const filerData = orderList.value.filter(it => selectGoods.value.includes(Number(it.skuId)))
  122. const res = await Apis.xsb.calculateMoney({ data: {
  123. orderNumber: String(orderList.value[0].orderNumber),
  124. orderRefundSkuList: filerData.map((it) => {
  125. return {
  126. orderItemId: it.orderItemId,
  127. productCount: it.num,
  128. }
  129. }),
  130. } })
  131. refunMoney.value = res.data
  132. }
  133. function handleChangeMoney() {
  134. if (selectGoods.value.length) {
  135. getReufndMoney()
  136. }
  137. }
  138. </script>
  139. <template>
  140. <page-meta :page-style="showReson ? 'overflow: hidden;' : '' " />
  141. <view class="page-xsb">
  142. <view class="box-border w-full flex items-center bg-#f8e3ca px24rpx py12rpx">
  143. <wd-icon name="info-circle-filled" size="22px" color="#FF941A" />
  144. <view class="ml16rpx text-28rpx">
  145. 部分退款时,有积分消费的,优先返还积分。
  146. </view>
  147. </view>
  148. <view class="px24rpx py24rpx">
  149. <view class="rounded-16rpx bg-white px24rpx py28rpx">
  150. <view class="mb24rpx text-32rpx font-semibold">
  151. 售后类型
  152. </view>
  153. <wd-radio-group v-model="afterSalesType" shape="dot" inline>
  154. <wd-radio :value="1">
  155. <view>
  156. <view class="text-left text-28rpx font-semibold">
  157. 我要退款
  158. </view>
  159. <view class="mt16rpx text-24rpx text-#AAAAAA">
  160. 没收到货,货已收到货与商家协商后无需退货只退款
  161. </view>
  162. </view>
  163. </wd-radio>
  164. <view class="mt24rpx">
  165. <wd-radio :value="2">
  166. <view>
  167. <view class="text-left text-28rpx font-semibold">
  168. 我要退货退款
  169. </view>
  170. <view class="mt16rpx text-24rpx text-#AAAAAA">
  171. 已收到货,需要退还已收到的商品
  172. </view>
  173. </view>
  174. </wd-radio>
  175. </view>
  176. </wd-radio-group>
  177. </view>
  178. <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
  179. <view class="flex items-center justify-between">
  180. <view class="text-32rpx font-semibold">
  181. 退款商品
  182. </view>
  183. <view class="text-28rpx text-#FF4D3A font-semibold">
  184. 退款金额:¥{{ refunMoney }}
  185. </view>
  186. </view>
  187. <view class="mt24rpx">
  188. <wd-checkbox v-model="isSeletAllGoods" @change="handleChangeAll">
  189. 全选
  190. </wd-checkbox>
  191. </view>
  192. <view class="mt24rpx h2rpx w-full bg-#F0F0F0" />
  193. <view class="goods mt24rpx">
  194. <CollapsePanel :line-height="150">
  195. <wd-checkbox-group v-model="selectGoods" @change="handleSelectGoods">
  196. <template v-for="item in orderList" :key="item.skuId">
  197. <view class="flex items-center justify-between">
  198. <wd-checkbox :model-value="item.skuId" />
  199. <view class="box-border w-full flex items-center">
  200. <image :src="item.pic" class="h120rpx w120rpx flex-shrink-0" />
  201. <view class="ml20rpx box-border flex-1">
  202. <view class="w-full flex justify-between">
  203. <view class="max-w-320rpx whitespace-pre-wrap break-words break-all text-28rpx">
  204. {{ item.prodName }}
  205. </view>
  206. <view class="w30% flex-shrink-0 text-32rpx text-#FF4D3A font-semibold">
  207. ¥{{ item.productTotalAmount }}
  208. </view>
  209. </view>
  210. <view class="text-24rpx text-#AAAAAA">
  211. 规格:{{ item.spec }}
  212. </view>
  213. <view class="flex items-center justify-between">
  214. <view class="text-24rpx text-#AAAAAA">
  215. 单价:¥{{ item.price }}
  216. </view>
  217. <view>
  218. <wd-input-number v-model="item.num" :max="item.prodCount" :min="1" @change="handleChangeMoney" />
  219. </view>
  220. </view>
  221. </view>
  222. </view>
  223. </view>
  224. <view class="my20rpx h2rpx w-full bg-#F0F0F0" />
  225. </template>
  226. </wd-checkbox-group>
  227. </CollapsePanel>
  228. </view>
  229. </view>
  230. <view class="mt20rpx rounded-16rpx bg-white px24rpx py28rpx">
  231. <view class="flex items-center justify-between">
  232. <view class="text-32rpx font-semibold">
  233. 退款原因
  234. </view>
  235. <view class="flex items-center text-28rpx" @click="showReson = true">
  236. <view class="text-#AAAAAA">
  237. {{ resonName }}
  238. </view> <wd-icon name="arrow-right" size="18px" color="#aaa" />
  239. </view>
  240. </view>
  241. <view class="mt20rpx rounded-16rpx bg-#F6F6F6 p24rpx">
  242. <wd-textarea v-model="remark" placeholder="请填写退款原因" show-word-limit :maxlength="200" />
  243. <view class="upload mt18rpx">
  244. <Zupload v-model:value="fileList" />
  245. </view>
  246. </view>
  247. </view>
  248. </view>
  249. <Zpopup v-model="showReson">
  250. <view class="p24rpx">
  251. <view class="w-full text-center text-32rpx font-semibold">
  252. 选择退款原因
  253. </view>
  254. <view class="mt20rpx flex items-center rounded-16rpx bg-#f8e3ca px24rpx py12rpx">
  255. <wd-icon name="info-circle-filled" size="22px" color="#FF941A" />
  256. <view class="ml16rpx text-28rpx">
  257. 部分退款时,有积分消费的,优先返还积分。
  258. </view>
  259. </view>
  260. <view class="mt20rpx rounded-32rpx bg-white p24rpx">
  261. <view class="mb20rpx text-28rpx font-semibold">
  262. 请选择退款原因 <text class="text-#AAAAAA">
  263. (必选)
  264. </text>
  265. </view>
  266. <wd-radio-group v-model="resonId" shape="dot">
  267. <wd-radio v-for="item in resonList" :key="item.id" :value="item.id">
  268. <view class="w-full text-24rpx">
  269. {{ item.name }}
  270. </view>
  271. </wd-radio>
  272. </wd-radio-group>
  273. </view>
  274. </view>
  275. <template #footer>
  276. <wd-button block @click="handleSelectReson">
  277. 确定
  278. </wd-button>
  279. </template>
  280. </Zpopup>
  281. <view class="h200rpx" />
  282. <view
  283. class="ios fixed bottom-0 z-10 box-border w-full w-full rounded-t-32rpx bg-white px32rpx pt-16rpx"
  284. >
  285. <wd-button block :loading="isSubmit" @click="handleSubmit">
  286. 提交
  287. </wd-button>
  288. </view>
  289. </view>
  290. </template>
  291. <style scoped lang="scss">
  292. .page-xsb {
  293. :deep() {
  294. .goods .wd-checkbox{
  295. display: flex;
  296. align-items: center;
  297. .wd-checkbox__shape{
  298. flex-shrink: 0;
  299. }
  300. .wd-checkbox__label {
  301. width:100%;
  302. .wd-checkbox__txt{
  303. width: 100%;
  304. }
  305. }
  306. }
  307. .wd-textarea{
  308. background: #F6F6F6 !important;
  309. .wd-textarea__value{
  310. background: #F6F6F6 !important;
  311. }
  312. .wd-textarea__count{
  313. background: #F6F6F6 !important;
  314. }
  315. }
  316. }
  317. }
  318. </style>