list.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. <template>
  2. <view class="content">
  3. <view class="navbar">
  4. <view v-for="(item, index) in navList" :key="index" class="nav-item" :class="{current: tabCurrentIndex === index}"
  5. @click="tabClick(index)">
  6. {{item.text}}
  7. </view>
  8. </view>
  9. <swiper :current="tabCurrentIndex" class="swiper-box" duration="300" @change="changeTab">
  10. <swiper-item class="tab-content" v-for="(tabItem,tabIndex) in navList" :key="tabIndex">
  11. <scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData">
  12. <!-- 空白页 -->
  13. <empty v-if="tabItem.loaded === true && tabItem.orderList.length === 0"></empty>
  14. <!-- 订单列表 -->
  15. <view v-for="(item,index) in tabItem.orderList" :key="index" class="order-item">
  16. <navigator :url="'/pageB/order/detail?orderNo=' + item.orderNo">
  17. <view class="i-top b-b">
  18. <text class="time">{{item.title}}</text>
  19. <text class="state">{{statusMap[item.status]}}</text>
  20. </view>
  21. <view class="flex solid-bottom padding justify-between">
  22. <view class='cu-tag' :class="'line-green'">{{item.orderNo}}</view>
  23. <view class='cu-tag' :class="'line-green'">{{item.level+item.goodsName}}</view>
  24. <view class='cu-tag' :class="'line-green'">{{item.count}}*{{item.unitPrice}}元</view>
  25. </view>
  26. </navigator>
  27. <view class="action-box b-t" v-if="item.status == 10">
  28. </view>
  29. <view class="action-box b-t" v-if="item.status == 20">
  30. </view>
  31. <view class="action-box b-t" v-if="item.status == 30">
  32. </view>
  33. <view class="action-box b-t" v-if="item.status == 40">
  34. <button :disabled="submiting" class="action-btn" @click="showShipTrace(item)">查看物流</button>
  35. </view>
  36. <view class="action-box b-t" v-if="item.status == 50">
  37. <button :disabled="submiting" class="action-btn" @click="showShipTrace(item)">查看物流</button>
  38. </view>
  39. </view>
  40. <uni-load-more :status="tabItem.loadingType"></uni-load-more>
  41. </scroll-view>
  42. </swiper-item>
  43. </swiper>
  44. </view>
  45. </template>
  46. <script>
  47. import neilModal from '@/components/neil-modal/neil-modal.vue';
  48. import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
  49. import empty from "@/components/empty";
  50. export default {
  51. components: {
  52. uniLoadMore,
  53. empty,
  54. neilModal
  55. },
  56. data() {
  57. return {
  58. statusMap: {
  59. 20: '销售交易中',
  60. 30: '采购交易中',
  61. 40: '运输中',
  62. 50: '交易完成'
  63. },
  64. submiting: false,
  65. refundShow: false,
  66. inputRefundReason: '',
  67. refundOrderItem: '',
  68. tabCurrentIndex: 0,
  69. navList: [{
  70. state: 10,
  71. text: '所有交易',
  72. loadingType: 'more',
  73. pageNo: 1,
  74. orderList: []
  75. },
  76. {
  77. state: 20,
  78. text: '销售交易中',
  79. loadingType: 'more',
  80. pageNo: 1,
  81. orderList: []
  82. },
  83. {
  84. state: 30,
  85. text: '采购交易中',
  86. loadingType: 'more',
  87. pageNo: 1,
  88. orderList: []
  89. },
  90. {
  91. state: 40,
  92. text: '运输中',
  93. loadingType: 'more',
  94. pageNo: 1,
  95. orderList: []
  96. },
  97. {
  98. state: 50,
  99. text: '交易完成',
  100. loadingType: 'more',
  101. pageNo: 1,
  102. orderList: []
  103. }
  104. ],
  105. };
  106. },
  107. onLoad(options) {
  108. /**
  109. * 修复app端点击除全部订单外的按钮进入时不加载数据的问题
  110. * 替换onLoad下代码即可
  111. */
  112. this.tabCurrentIndex = 0
  113. for (let i = 0; i < this.navList.length; i++) {
  114. if (this.navList[i].state === parseInt(options.state)) {
  115. this.tabCurrentIndex = i
  116. }
  117. }
  118. // #ifndef MP
  119. this.loadData()
  120. // #endif
  121. // #ifdef MP
  122. if (options.state == 10) {
  123. this.loadData()
  124. }
  125. // #endif
  126. },
  127. methods: {
  128. //获取订单列表
  129. loadData(source) {
  130. const that = this
  131. //这里是将订单挂载到tab列表下
  132. let index = that.tabCurrentIndex;
  133. let navItem = that.navList[index];
  134. let state = navItem.state;
  135. if (source === 'tabChange' && navItem.loaded === true) {
  136. //tab切换只有第一次需要加载数据
  137. return;
  138. }
  139. if (navItem.loadingType === 'loading') {
  140. //防止重复加载
  141. return;
  142. }
  143. navItem.loadingType = 'loading';
  144. let orderList = that.$api.request('order', 'getOrderPage', {
  145. pageNo: navItem.pageNo,
  146. status: navItem.state
  147. }).then(res => {
  148. navItem.pageNo = res.data.pageNo + 1
  149. navItem.loadingType = res.data.pageNo < res.data.totalPageNo ? 'more' : 'noMore'
  150. navItem.orderList = navItem.orderList.concat(res.data.items)
  151. //loaded新字段用于表示数据加载完毕,如果为空可以显示空白页
  152. that.$set(navItem, 'loaded', true);
  153. })
  154. },
  155. //swiper 切换
  156. changeTab(e) {
  157. this.tabCurrentIndex = e.target.current;
  158. this.loadData('tabChange');
  159. },
  160. //顶部tab点击
  161. tabClick(index) {
  162. this.tabCurrentIndex = index;
  163. },
  164. payOrder(item) {
  165. uni.navigateTo({
  166. url: '/pages/pay/pay?orderno='+ item.orderNo + '&price=' + item.actualPrice
  167. })
  168. },
  169. //取消订单
  170. cancelOrder(item) {
  171. const that = this
  172. uni.showModal({
  173. title: '取消?',
  174. content: '您确定要取消此订单吗?',
  175. success : (e) => {
  176. if (e.confirm) {
  177. that.submiting = true
  178. that.$api.request('order', 'cancel', {
  179. orderNo: item.orderNo
  180. }, failres => {
  181. that.submiting = false
  182. that.$api.msg(failres.errmsg)
  183. }).then(res => {
  184. that.submiting = false
  185. item.status = 80
  186. })
  187. }
  188. }
  189. })
  190. },
  191. //订单退款
  192. refundConfirm() {
  193. const that = this
  194. if (that.submiting) {
  195. return
  196. }
  197. that.submiting = true
  198. that.$api.request('order', 'refund', {
  199. orderNo: that.refundOrderItem.orderNo,
  200. reason: that.inputRefundReason
  201. }, failres => {
  202. that.submiting = false
  203. that.$api.msg(failres.errmsg)
  204. }).then(res => {
  205. that.submiting = false
  206. that.refundOrderItem.status = 60
  207. that.$api.msg('申请退款成功!')
  208. })
  209. },
  210. refundOrder(item) {
  211. const that = this
  212. that.refundOrderItem = item
  213. that.refundShow = true
  214. that.inputRefundReason = ''
  215. },
  216. //确认订单
  217. confirmOrder(item) {
  218. const that = this
  219. uni.showModal({
  220. title: '收货?',
  221. content: '您确定要确认收货吗?',
  222. success : (e) => {
  223. if (e.confirm) {
  224. that.submiting = true
  225. that.$api.request('order', 'confirm', {
  226. orderNo: item.orderNo
  227. }, failres => {
  228. that.submiting = false
  229. that.$api.msg(failres.errmsg)
  230. }).then(res => {
  231. that.submiting = false
  232. item.status = 40
  233. })
  234. }
  235. }
  236. })
  237. },
  238. showShipTrace(item) {
  239. uni.navigateTo({
  240. url: "/pageB/order/trace?orderNo=" + item.orderNo
  241. })
  242. },
  243. showDetail(item) {
  244. uni.navigateTo({
  245. url: "/pageB/order/trace?orderNo=" + item.orderNo
  246. })
  247. },
  248. //评价订单
  249. appraiseOrder(item) {
  250. uni.navigateTo({
  251. url: '/pageB/order/appraise?orderid=' + item.id
  252. })
  253. }
  254. }
  255. }
  256. </script>
  257. <style lang="scss" scoped>
  258. page,
  259. .content {
  260. background: $page-color-base;
  261. height: 100%;
  262. }
  263. .swiper-box {
  264. height: calc(100% - 40px);
  265. }
  266. .list-scroll-content {
  267. height: 100%;
  268. }
  269. .navbar {
  270. display: flex;
  271. height: 40px;
  272. padding: 0 5px;
  273. background: #fff;
  274. box-shadow: 0 1px 5px rgba(0, 0, 0, .06);
  275. position: relative;
  276. z-index: 10;
  277. .nav-item {
  278. flex: 1;
  279. display: flex;
  280. justify-content: center;
  281. align-items: center;
  282. height: 100%;
  283. font-size: 15px;
  284. color: $font-color-dark;
  285. position: relative;
  286. &.current {
  287. color: #e03997;
  288. &:after {
  289. content: '';
  290. position: absolute;
  291. left: 50%;
  292. bottom: 0;
  293. transform: translateX(-50%);
  294. width: 44px;
  295. height: 0;
  296. border-bottom: 2px solid #e03997;
  297. }
  298. }
  299. }
  300. }
  301. .uni-swiper-item {
  302. height: auto;
  303. }
  304. .order-item {
  305. display: flex;
  306. flex-direction: column;
  307. padding-left: 30upx;
  308. background: #fff;
  309. margin-top: 16upx;
  310. .i-top {
  311. display: flex;
  312. align-items: center;
  313. height: 80upx;
  314. padding-right: 30upx;
  315. font-size: $font-base;
  316. color: $font-color-dark;
  317. position: relative;
  318. .time {
  319. flex: 1;
  320. }
  321. .state {
  322. color: #e03997;
  323. }
  324. .del-btn {
  325. padding: 10upx 0 10upx 36upx;
  326. font-size: $font-lg;
  327. color: $font-color-light;
  328. position: relative;
  329. &:after {
  330. content: '';
  331. width: 0;
  332. height: 30upx;
  333. border-left: 1px solid $border-color-dark;
  334. position: absolute;
  335. left: 20upx;
  336. top: 50%;
  337. transform: translateY(-50%);
  338. }
  339. }
  340. }
  341. /* 多条商品 */
  342. .goods-box {
  343. height: 160upx;
  344. padding: 20upx 0;
  345. white-space: nowrap;
  346. .goods-item {
  347. width: 120upx;
  348. height: 120upx;
  349. display: inline-block;
  350. margin-right: 24upx;
  351. }
  352. .goods-img {
  353. display: block;
  354. width: 100%;
  355. height: 100%;
  356. }
  357. }
  358. /* 单条商品 */
  359. .goods-box-single {
  360. display: flex;
  361. padding: 20upx 0;
  362. .goods-img {
  363. display: block;
  364. width: 120upx;
  365. height: 120upx;
  366. }
  367. .right {
  368. flex: 1;
  369. display: flex;
  370. flex-direction: column;
  371. padding: 0 30upx 0 24upx;
  372. overflow: hidden;
  373. .title {
  374. font-size: $font-base + 2upx;
  375. color: $font-color-dark;
  376. line-height: 1;
  377. }
  378. .attr-box {
  379. font-size: $font-sm + 2upx;
  380. color: $font-color-light;
  381. padding: 10upx 12upx;
  382. }
  383. .price {
  384. color: $font-color-dark;
  385. &:before {
  386. font-size: $font-sm;
  387. margin: 0 2upx 0 8upx;
  388. }
  389. }
  390. }
  391. }
  392. .price-box {
  393. display: flex;
  394. justify-content: flex-end;
  395. align-items: baseline;
  396. padding: 20upx 30upx;
  397. font-size: $font-sm + 2upx;
  398. color: $font-color-light;
  399. .num {
  400. margin: 0 8upx;
  401. color: $font-color-dark;
  402. &:before {
  403. margin: 0 2upx 0 8upx;
  404. }
  405. &:after {
  406. margin: 0 2upx 0 8upx;
  407. }
  408. }
  409. .price {
  410. color: $font-color-dark;
  411. &:before {
  412. margin: 0 2upx 0 8upx;
  413. }
  414. &:after {
  415. margin: 0 2upx 0 8upx;
  416. }
  417. }
  418. .tag{
  419. margin-left:10upx ;
  420. }
  421. }
  422. .action-box {
  423. display: flex;
  424. justify-content: flex-end;
  425. align-items: center;
  426. height: 100upx;
  427. position: relative;
  428. padding-right: 30upx;
  429. }
  430. .action-btn {
  431. width: 160upx;
  432. height: 60upx;
  433. margin: 0;
  434. margin-left: 24upx;
  435. padding: 0;
  436. text-align: center;
  437. line-height: 60upx;
  438. font-size: $font-sm + 2upx;
  439. color: $font-color-dark;
  440. background: #fff;
  441. border-radius: 100px;
  442. &:after {
  443. border-radius: 100px;
  444. }
  445. &.recom {
  446. background: #fff9f9;
  447. color: #e03997;
  448. &:after {
  449. border-color: #f7bcc8;
  450. }
  451. }
  452. }
  453. }
  454. /* load-more */
  455. .uni-load-more {
  456. display: flex;
  457. flex-direction: row;
  458. height: 80upx;
  459. align-items: center;
  460. justify-content: center
  461. }
  462. .uni-load-more__text {
  463. font-size: 28upx;
  464. color: #999
  465. }
  466. .uni-load-more__img {
  467. height: 24px;
  468. width: 24px;
  469. margin-right: 10px
  470. }
  471. .uni-load-more__img>view {
  472. position: absolute
  473. }
  474. .uni-load-more__img>view view {
  475. width: 6px;
  476. height: 2px;
  477. border-top-left-radius: 1px;
  478. border-bottom-left-radius: 1px;
  479. background: #999;
  480. position: absolute;
  481. opacity: .2;
  482. transform-origin: 50%;
  483. animation: load 1.56s ease infinite
  484. }
  485. .uni-load-more__img>view view:nth-child(1) {
  486. transform: rotate(90deg);
  487. top: 2px;
  488. left: 9px
  489. }
  490. .uni-load-more__img>view view:nth-child(2) {
  491. transform: rotate(180deg);
  492. top: 11px;
  493. right: 0
  494. }
  495. .uni-load-more__img>view view:nth-child(3) {
  496. transform: rotate(270deg);
  497. bottom: 2px;
  498. left: 9px
  499. }
  500. .uni-load-more__img>view view:nth-child(4) {
  501. top: 11px;
  502. left: 0
  503. }
  504. .load1,
  505. .load2,
  506. .load3 {
  507. height: 24px;
  508. width: 24px
  509. }
  510. .load2 {
  511. transform: rotate(30deg)
  512. }
  513. .load3 {
  514. transform: rotate(60deg)
  515. }
  516. .load1 view:nth-child(1) {
  517. animation-delay: 0s
  518. }
  519. .load2 view:nth-child(1) {
  520. animation-delay: .13s
  521. }
  522. .load3 view:nth-child(1) {
  523. animation-delay: .26s
  524. }
  525. .load1 view:nth-child(2) {
  526. animation-delay: .39s
  527. }
  528. .load2 view:nth-child(2) {
  529. animation-delay: .52s
  530. }
  531. .load3 view:nth-child(2) {
  532. animation-delay: .65s
  533. }
  534. .load1 view:nth-child(3) {
  535. animation-delay: .78s
  536. }
  537. .load2 view:nth-child(3) {
  538. animation-delay: .91s
  539. }
  540. .load3 view:nth-child(3) {
  541. animation-delay: 1.04s
  542. }
  543. .load1 view:nth-child(4) {
  544. animation-delay: 1.17s
  545. }
  546. .load2 view:nth-child(4) {
  547. animation-delay: 1.3s
  548. }
  549. .load3 view:nth-child(4) {
  550. animation-delay: 1.43s
  551. }
  552. @-webkit-keyframes load {
  553. 0% {
  554. opacity: 1
  555. }
  556. 100% {
  557. opacity: .2
  558. }
  559. }
  560. </style>