orderDetails.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. <template>
  2. <view class="container">
  3. <u-navbar leftIconColor="#fff" titleStyle="color:#fff;fontSize:36rpx;" :autoBack="true" bgColor="#2C6FF3"
  4. :placeholder="true" title="订单详情"></u-navbar>
  5. <view class="content">
  6. <view v-if="detail.orderGoods&&detail.orderGoods.length>0" class="box">
  7. <view class="title">商品信息</view>
  8. <view class="goods-container martop">
  9. <view class="goods-item" v-for="(item,index) in detail.orderGoods" :key="item.id">
  10. <view class="flex align-center">
  11. <view class="spxx-image">
  12. <u--image radius="4" width="130rpx" height="130rpx" :src="item.goodsImgUrl"
  13. mode="aspectFit" :lazy-lord="true"></u--image>
  14. </view>
  15. <view class="flex flex-direction justify-between goods-msg" style="width:600rpx;">
  16. <view class="flex justify-between">
  17. <view style="width:360rpx;" class="goods-name">{{item.goodsName}}
  18. *{{item.totalNumber}}</view>
  19. <view class="text" style="color: red;" v-if="item.refundMoney&&item.refundMoney>0">
  20. 已退款:¥{{$xy.delMoney(item.refundMoney)}}
  21. </view>
  22. </view>
  23. <view class="flex align-center justify-between">
  24. <view class="goods-price">
  25. 单价:¥{{(Number(item.totalMoney)/Number(item.totalNumber))/100}}</view>
  26. <!--<view class="">应收:¥2.00</view>
  27. <view class="">实收:¥2.00</view> -->
  28. </view>
  29. <!-- <view class="">优惠活动:暂无</view> -->
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. <view class="box">
  36. <view class="title">订单信息</view>
  37. <view class="orderinformation-container martop">
  38. <view class="flex align-center">
  39. <view class="">
  40. <view class="oc-name">订单编号:</view>{{detail.id||'/'}}<text class="under-line-text"
  41. @tap="copy(detail.id)">复制</text>
  42. </view>
  43. </view>
  44. <view class="flex align-center">
  45. <view class="">
  46. <view class="oc-name">商户单号:</view>{{detail.payQueryOrderId||'/'}}<text
  47. class="under-line-text" @tap="copy(detail.payQueryOrderId)">复制</text>
  48. </view>
  49. </view>
  50. <view class="flex align-center">
  51. <view class="oc-name">设备:</view>{{detail.deviceId||'/'}}
  52. </view>
  53. <view class="flex align-center">
  54. <view class="oc-name">交易时间:</view>{{detail.payTime||'/'}}
  55. </view>
  56. <view class="flex align-center justify-between">
  57. <view class="phone">
  58. <view class="oc-name">手机号:</view>{{detail.memberTel||'/'}}<text class="under-line-text"
  59. @click="$tab.navigateTo(`/pages/order/userInfo?id=${detail.memberId}`)">会员信息</text><text
  60. v-if="detail.memberIsBlacklist&&detail.memberTel">已拉黑</text>
  61. </view>
  62. <view class="block" v-if="detail.memberTel&&!detail.memberIsBlacklist" @click="block">
  63. 拉黑
  64. </view>
  65. </view>
  66. <view class="flex align-center">
  67. <view class="oc-name">订单状态:</view>{{detail.statusName||'/'}}
  68. </view>
  69. <view class="flex align-center">
  70. <view class="oc-name">商品总价:</view>¥{{$xy.delMoney(detail.orderTotalMoney)}}
  71. </view>
  72. <view class="">
  73. <view class="oc-name">优惠金额:</view>¥{{$xy.delMoney(detail.discountMoney)}}
  74. </view>
  75. <view class="">
  76. <view class="oc-name">订单总金额:</view>¥{{$xy.delMoney(detail.orderTotalMoney)}}
  77. </view>
  78. <view class="flex align-center justify-end" style="margin-top: 26rpx;">
  79. <view class="marleft">
  80. <xbutton bgColor="#F4F8FF" color="#2C6FF3" @tap="showlogs">交易日志</xbutton>
  81. </view>
  82. <view class="marleft">
  83. <xbutton bgColor="#F4F8FF" color="#2C6FF3">通知付款</xbutton>
  84. </view>
  85. <view class="marleft" v-if="detail.status==4">
  86. <xbutton bgColor="#F4F8FF" color="#2C6FF3" @tap="open">发起退款</xbutton>
  87. </view>
  88. <view class="marleft">
  89. <xbutton bgColor="#F4F8FF" color="#2C6FF3" @tap="showVideoView">查看交易视频</xbutton>
  90. </view>
  91. </view>
  92. </view>
  93. </view>
  94. <view class="box">
  95. <view class="title">支付信息</view>
  96. <view class="payments-container martop">
  97. <view class="flex align-center">
  98. <view class="oc-name">支付时间:</view>{{detail.payTime||'/'}}
  99. </view>
  100. <view class="">
  101. <view class="oc-name">支付方式:</view>{{$xy.getPayType(detail.payType)}}
  102. </view>
  103. <view class="">
  104. <view class="oc-name">支付金额:</view>¥{{$xy.delMoney(detail.payMoney)}}
  105. </view>
  106. <view class="flex align-center">
  107. <view class="">
  108. <view class="oc-name">支付订单号:</view>{{detail.payOrderId||'/'}}<text class="under-line-text"
  109. @tap="copy(detail.payOrderId)">复制</text>
  110. </view>
  111. </view>
  112. <view class="">
  113. <view class="oc-name">支付状态:</view>{{detail.payStatusName||'/'}}
  114. </view>
  115. </view>
  116. </view>
  117. <view class="box" v-if="refundDetail.id">
  118. <view class="title">用户退款记录</view>
  119. <view class="userrefundrecord-container martop">
  120. <view class="title1 martop">客户申请</view>
  121. <view class="">
  122. <view class="oc-name">申请时间:</view>{{refundDetail.createTime||'/'}}
  123. </view>
  124. <!-- <view class="">退款金额:¥{{refundDetail.createTime}}</view> -->
  125. <view class="">
  126. <view class="oc-name">用户备注:</view>{{refundDetail.remark||'/'}}
  127. </view>
  128. <view class="">
  129. <view class="oc-name">退款原因:</view>{{refundDetail.reason||'/'}}
  130. </view>
  131. <view class="title1 martop">退款产品</view>
  132. <block v-for="(item,index) in refundDetail.goodsList" :key="item.id">
  133. <u--image radius="4" width="130rpx" height="110rpx" :src="item.goodsImgUrl" mode="widthFix"
  134. :lazy-lord="true"></u--image>
  135. <view class="">{{item.goodsName}} *{{item.totalNumber}}</view>
  136. <!-- <view class="flex align-center justify-between">
  137. <view class="">商品原价:¥{{item.totalNumber}}</view>
  138. <view class="">商品卖价:¥{{item.sellPrice}}</view>
  139. <view class="">商品总价:¥{{item.totalMoney}}</view>
  140. </view> -->
  141. </block>
  142. <view class="">
  143. <view class="oc-name">优惠活动:</view>无
  144. </view>
  145. <view class="title1 martop">商家处理</view>
  146. <view class="">
  147. <view class="oc-name">处理结果:</view>{{refundDetail.refundStatusDesc||'/'}}
  148. </view>
  149. </view>
  150. </view>
  151. </view>
  152. <view :hidden="hiddenOrderVideos" class="popup_content">
  153. <view class="flex">
  154. <video id="myVideo" :src="videoUrl" style="width:100%;height: 372rpx; margin: 10rpx 10rpx;"></video>
  155. </view>
  156. <view class="flex" style="margin-top: 10rpx;">
  157. <view class="marleft">
  158. <xbutton size='medium' round='25rpx' padding='0rpx 20rpx' bgColor='#2C6FF3' @tap="playVideo(0)">主视频
  159. </xbutton>
  160. </view>
  161. <view class="marleft">
  162. <xbutton size='medium' round='25rpx' padding='0rpx 20rpx' bgColor='#2C6FF3' @tap="playVideo(1)">副视频
  163. </xbutton>
  164. </view>
  165. </view>
  166. </view>
  167. <view class="popup_overlay" :hidden="hiddenOrderVideos" @click="closeVideoView()"></view>
  168. <xpopup :show="show" @close="close" @confirm="submit" :showBtn="true" title="拉黑">
  169. <!-- 拉黑 -->
  170. <view class="pop-content">
  171. 是否确定拉黑该用户?
  172. </view>
  173. </xpopup>
  174. <u-popup :show="refundShow" mode="center" :safeAreaInsetBottom="false" @close="refundShow=false">
  175. <view class="refund-container">
  176. <u-radio-group placement="row" v-model="radioType" @change="radioChange">
  177. <u-radio :customStyle="{marginRight: '24rpx'}" activeColor="#2C6FF3" label="商品退款" name="2">
  178. </u-radio>
  179. <u-radio activeColor="#2C6FF3" label="金额退款" name="1"></u-radio>
  180. </u-radio-group>
  181. <view v-if="radioType=='2'">
  182. <view class="martop" v-for="(item,index) in orderGoods" :key="item.id">
  183. <view class="flex align-center" @tap="checked(item)">
  184. <view class="checked">
  185. <image v-if="item.checked"
  186. src="https://cdn.ossfile.mxrvending.com/assets/xy_merc_mini/images/commodity/selected.png"
  187. mode="widthFix">
  188. </image>
  189. <image v-else
  190. src="https://cdn.ossfile.mxrvending.com/assets/xy_merc_mini/images/commodity/select.png"
  191. mode="widthFix"></image>
  192. </view>
  193. <view class="">{{item.goodsName}}</view>
  194. </view>
  195. <view class="flex align-center" style="margin-top: 24rpx;">
  196. <u-number-box button-size="30" v-model="item.totalNumber" class='martop'></u-number-box>
  197. <view style="margin-left: 30rpx;">
  198. ¥{{item.totalNumber*item.price}}
  199. <!-- <u--input placeholder="退款金额" @blur="refundGoodsChange" type="digit" disabled
  200. v-model="item.totalMoney" border="surround">
  201. </u--input> -->
  202. </view>
  203. </view>
  204. </view>
  205. </view>
  206. <view class="flex align-center" style="margin-top: 24rpx;" v-else>
  207. <view style="width:200rpx">
  208. 退款金额
  209. </view>
  210. <view class='marleft' style="width: 100%;">
  211. <u--input placeholder="退款金额" @blur="refundGoodsChange" type="digit" v-model="refundMoney"
  212. border="surround">
  213. </u--input>
  214. </view>
  215. </view>
  216. <view class='' style="margin-top: 24rpx;" @click="actionsheetChange">
  217. <u--input clearable readonly suffixIcon="arrow-down" v-model="refundReasonName" border="surround"
  218. suffixIconStyle="color: #909399" placeholder="退款理由">
  219. </u--input>
  220. </view>
  221. <view class='' style="margin-top: 24rpx;">
  222. <u--textarea v-model="description" placeholder="备注"></u--textarea>
  223. </view>
  224. <view class="" style="margin-top: 24rpx;" v-if="radioType=='2'">总退款金额:¥{{refundTotalMoney}}</view>
  225. <view class="flex align-center justify-end" style="margin-top: 24rpx;">
  226. <view class="">
  227. <xbutton width='200rpx' @click='refundShow=false'>取消</xbutton>
  228. </view>
  229. <view class='marleft'>
  230. <xbutton width='200rpx' @click="refundSure">确定</xbutton>
  231. </view>
  232. </view>
  233. </view>
  234. </u-popup>
  235. <u-action-sheet :show="actionSheetShow" :actions="actions" :title="title" @close="actionSheetShow = false"
  236. @select="actionsheetSelect($event)"></u-action-sheet>
  237. </view>
  238. </template>
  239. <script>
  240. import {
  241. byId,
  242. refundDetail,
  243. setBlacklist,
  244. refundByMerc
  245. } from "@/api/order/order.js"
  246. import getDict from "@/utils/getDict.js"
  247. export default {
  248. data() {
  249. return {
  250. id: null,
  251. hiddenOrderVideos: true,
  252. selOrder: undefined,
  253. videoUrl: '',
  254. detail: {},
  255. refundDetail: {},
  256. show: false,
  257. refundShow: false,
  258. radioType: '2',
  259. remark: '',
  260. orderGoods: null,
  261. createTime: null,
  262. description: null,
  263. refundReason: null,
  264. refundReasonName: null,
  265. actions: [],
  266. actionSheetShow: false,
  267. refundMoney: ''
  268. }
  269. },
  270. computed: {
  271. refundTotalMoney() {
  272. let num = 0;
  273. if (this.orderGoods) {
  274. this.orderGoods.forEach(i => {
  275. if (i.checked) {
  276. num += Number(i.totalNumber) * i.price
  277. }
  278. })
  279. }
  280. return num
  281. }
  282. },
  283. onLoad(o) {
  284. this.id = o.id;
  285. this.createTime = o.createTime
  286. },
  287. onShow() {
  288. this.getbyId()
  289. this.getRefundDetail()
  290. },
  291. methods: {
  292. copy(text) {
  293. uni.setClipboardData({
  294. data: text,
  295. success: (data) => {
  296. uni.showToast({
  297. title: '复制成功'
  298. })
  299. },
  300. fail: function(err) {
  301. },
  302. complete: function(res) {
  303. }
  304. })
  305. },
  306. getbyId() {
  307. byId({
  308. id: this.id
  309. }).then(res => {
  310. if (res.code == 200) {
  311. this.detail = res.data
  312. }
  313. })
  314. },
  315. getRefundDetail() {
  316. refundDetail({
  317. orderId: this.id
  318. }).then(res => {
  319. if (res.code == 200) {
  320. this.refundDetail = res.data
  321. }
  322. })
  323. },
  324. showVideoView() {
  325. this.hiddenOrderVideos = false;
  326. var urls = this.detail.video.split(',');
  327. this.detail.url0 = urls[0];
  328. this.detail.url1 = urls[1];
  329. this.playVideo(0);
  330. },
  331. playVideo(o) {
  332. if (0 == o) {
  333. this.videoUrl = this.detail.url0;
  334. } else {
  335. this.videoUrl = this.detail.url1;
  336. }
  337. },
  338. closeVideoView() {
  339. this.videoUrl = '';
  340. this.hiddenOrderVideos = true;
  341. },
  342. block() {
  343. this.show = true
  344. },
  345. // 关闭弹框
  346. close(e) {
  347. this.show = false
  348. },
  349. // 弹框确定
  350. submit() {
  351. setBlacklist({
  352. memberId: this.detail.memberId
  353. }).then(res => {
  354. this.$modal.msg('拉黑成功~')
  355. this.getbyId()
  356. }).catch(err => {
  357. })
  358. this.close()
  359. },
  360. showlogs() {
  361. this.$tab.navigateTo('/pages/order/orderLogs?id=' + this.detail.activityId);
  362. },
  363. manualPayment() {
  364. this.$tab.navigateTo('/pages/order/orderDel?id=' + this.detail.id + '&deviceId=' + this.detail
  365. .deviceId)
  366. },
  367. open() {
  368. this.refundShow = true
  369. getDict('order_refund_refund_reason').then(res => {
  370. let actions = res.map(i => {
  371. return {
  372. type: i.value,
  373. name: i.msg
  374. }
  375. })
  376. this.actions = actions
  377. }).catch(err => {
  378. })
  379. this.orderGoods = JSON.parse(JSON.stringify(this.detail.orderGoods))
  380. this.orderGoods.forEach(i => {
  381. i.price = this.$xy.delMoney(i.totalMoney) / i.totalNumber
  382. i.totalMoney = this.$xy.delMoney(i.totalMoney)
  383. })
  384. },
  385. //退款选项
  386. radioChange(e) {},
  387. //选中商品
  388. checked(item) {
  389. this.orderGoods.forEach(i => {
  390. if (i.id == item.id) {
  391. i.checked = !i.checked
  392. }
  393. })
  394. this.orderGoods = JSON.parse(JSON.stringify(this.orderGoods))
  395. },
  396. refundGoodsChange(e) {
  397. if (!this.$xy.testPrice(e)) {
  398. this.$modal.msg('输入价格最低为分!')
  399. }
  400. },
  401. // 退款处理确认按钮
  402. refundSure() {
  403. let params = {}
  404. if (this.radioType == 2) { //订单商品退款
  405. let ordersGoods = [];
  406. for (var i = 0; i < this.orderGoods.length; i++) {
  407. let item = this.orderGoods[i]
  408. if (item.checked) {
  409. if (!this.$xy.testPrice(item.totalMoney)) {
  410. this.$modal.msg('输入价格最低为分!')
  411. return
  412. }
  413. ordersGoods.push({
  414. orderGoodsId: item.id,
  415. goodsNum: item.totalNumber,
  416. price: (item.totalMoney / Number(item.totalNumber)) * 100
  417. })
  418. }
  419. }
  420. if (ordersGoods && ordersGoods.length == 0) {
  421. this.$modal.msg('请选择退款商品!')
  422. return
  423. }
  424. params = {
  425. refundWay: this.radioType,
  426. orderId: this.id,
  427. createTime: this.createTime,
  428. refundGoods: ordersGoods,
  429. description: this.description,
  430. reason: this.refundReason
  431. }
  432. console.log('params', params)
  433. } else { //金额退款
  434. if (!this.refundMoney) {
  435. this.$modal.msg('请选择输入退款金额!')
  436. return
  437. }
  438. params = {
  439. refundWay: this.radioType,
  440. orderId: this.id,
  441. createTime: this.createTime,
  442. description: this.description,
  443. reason: this.refundReason,
  444. refundMoney: this.refundMoney * 100
  445. }
  446. }
  447. refundByMerc(params).then(res => {
  448. if (res.code == 200) {
  449. this.getbyId()
  450. this.getRefundDetail()
  451. setTimeout(() => {
  452. this.$modal.showToast('订单处理成功~')
  453. }, 1000)
  454. } else {
  455. this.$modal.showToast('订单处理失败~')
  456. }
  457. this.orderGoods = null;
  458. this.refundShow = false;
  459. })
  460. },
  461. actionsheetChange() {
  462. console.log(123)
  463. this.actionSheetShow = true;
  464. },
  465. actionsheetSelect(e) {
  466. this.refundReason = e.type
  467. this.refundReasonName = e.name
  468. }
  469. }
  470. }
  471. </script>
  472. <style scoped lang="scss">
  473. .container {
  474. padding: 24rpx;
  475. line-height: 50rpx;
  476. .content {
  477. overflow: hidden;
  478. }
  479. .text {
  480. color: #2C6FF3;
  481. }
  482. .martop {
  483. margin-top: 12rpx;
  484. }
  485. .marleft {
  486. margin-left: 10rpx;
  487. }
  488. .xian {
  489. border-bottom: 1px solid #5b5b5b;
  490. margin: 20rpx 0;
  491. }
  492. .title {
  493. font-size: 32rpx;
  494. line-height: 32rpx;
  495. font-weight: 800;
  496. color: #333;
  497. }
  498. .title1 {
  499. font-size: 28rpx;
  500. font-weight: 700;
  501. color: #333;
  502. line-height: 50rpx;
  503. position: relative;
  504. padding-left: 16rpx;
  505. &::before {
  506. content: '';
  507. width: 5rpx;
  508. height: 24rpx;
  509. background: #2C6FF3;
  510. position: absolute;
  511. left: 4rpx;
  512. top: 50%;
  513. transform: translateY(-60%);
  514. }
  515. }
  516. .under-line-text {
  517. font-size: 26rpx !important;
  518. font-weight: 500;
  519. font-style: italic;
  520. text-decoration: underline;
  521. color: #2C6FF3 !important;
  522. margin-left: 24rpx;
  523. background-color: #fff !important;
  524. }
  525. .oc-name {
  526. display: inline-block;
  527. width: 170rpx;
  528. }
  529. .payments-container,
  530. .userrefundrecord-container,
  531. .orderinformation-container {
  532. background-color: #fff;
  533. color: #777777;
  534. padding: 20rpx 0;
  535. border-radius: 15rpx;
  536. }
  537. .orderinformation-container {
  538. .phone {
  539. >text {
  540. display: inline-block;
  541. background-color: #5b5b5b;
  542. color: #fff;
  543. font-size: 22rpx;
  544. padding: 0 12rpx;
  545. border-radius: 6rpx;
  546. margin-left: 12rpx;
  547. line-height: 36rpx;
  548. }
  549. }
  550. .block {
  551. width: 92rpx;
  552. height: 38rpx;
  553. background: #F4F8FF;
  554. border-radius: 8rpx;
  555. font-size: 26rpx;
  556. line-height: 38rpx;
  557. font-weight: 500;
  558. color: #2C6FF3;
  559. text-align: center;
  560. }
  561. }
  562. .box {
  563. background-color: #fff;
  564. padding: 28rpx 25rpx;
  565. border-radius: 14rpx;
  566. margin-top: 20rpx;
  567. .goods-container {
  568. background-color: #fff;
  569. border-radius: 15rpx;
  570. margin-top: 35rpx;
  571. .goods-item {
  572. background: #F6F7FA;
  573. border-radius: 14rpx;
  574. padding: 8rpx;
  575. margin-top: 20rpx;
  576. .goods-msg {
  577. margin-left: 27rpx;
  578. .goods-name {
  579. font-size: 26rpx;
  580. font-weight: 800;
  581. color: #333333;
  582. }
  583. .goods-price {
  584. font-size: 24rpx;
  585. font-weight: 500;
  586. color: #555555;
  587. }
  588. }
  589. }
  590. .spxx-image {
  591. height: 130rpx;
  592. }
  593. }
  594. }
  595. }
  596. .popup_overlay {
  597. position: fixed;
  598. top: 0%;
  599. left: 0%;
  600. width: 100%;
  601. height: 100%;
  602. background-color: black;
  603. z-index: 1001;
  604. -moz-opacity: 0.8;
  605. opacity: .80;
  606. filter: alpha(opacity=88);
  607. }
  608. .popup_content {
  609. position: fixed;
  610. top: 50%;
  611. left: 50%;
  612. width: 700rpx;
  613. height: 500rpx;
  614. margin-left: -350rpx;
  615. margin-top: -250rpx;
  616. border: 10px solid white;
  617. background-color: white;
  618. z-index: 1002;
  619. overflow: auto;
  620. }
  621. .pop-content {
  622. padding: 24rpx;
  623. }
  624. .refund-container {
  625. background-color: #fff;
  626. width: 600rpx;
  627. padding: 20rpx 30rpx;
  628. .checked {
  629. width: 36rpx;
  630. height: 36rpx;
  631. margin-right: 12rpx;
  632. image {
  633. width: 36rpx;
  634. height: 36rpx;
  635. }
  636. }
  637. }
  638. </style>