爱简收旧衣按件回收前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
11 KiB

3 weeks ago
2 weeks ago
3 weeks ago
2 weeks ago
3 weeks ago
2 weeks ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
2 weeks ago
3 weeks ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
5 days ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
2 weeks ago
3 weeks ago
5 days ago
3 weeks ago
  1. <template>
  2. <view class="container">
  3. <!-- 顶部导航 -->
  4. <view class="nav-bar">
  5. <view class="back" @tap="goBack">
  6. <uni-icons type="left" size="20"></uni-icons>
  7. </view>
  8. <text class="title">我的订单</text>
  9. </view>
  10. <!-- 页面内容 -->
  11. <view class="content">
  12. <!-- <view class="page-header">
  13. <text class="page-title">我的订单</text>
  14. <text class="view-all" @tap="viewAll">查看全部 ></text>
  15. </view> -->
  16. <!-- 标签页 -->
  17. <view class="tabs">
  18. <view
  19. v-for="(tab, index) in tabs"
  20. :key="index"
  21. class="tab-item"
  22. :class="{ active: currentTab === index }"
  23. @tap="switchTab(index)"
  24. >
  25. <text>{{ tab.name }}</text>
  26. <text v-if="tab.count > 0" class="badge">{{ tab.count }}</text>
  27. </view>
  28. </view>
  29. <!-- 订单列表 -->
  30. <scroll-view
  31. scroll-y
  32. class="order-list"
  33. @scrolltolower="loadMore"
  34. >
  35. <view
  36. v-for="order in orderList"
  37. :key="order.id"
  38. class="order-card"
  39. @tap="goToDetail(order)"
  40. >
  41. <!-- 订单号 -->
  42. <view class="order-header">
  43. <text class="order-id">
  44. 订单编号
  45. <text class="order-ids">{{order.ordeNo || order.id}}</text>
  46. </text>
  47. </view>
  48. <!-- 订单内容 -->
  49. <view class="order-content">
  50. <image class="order-image" :src="order.image || '/static/回收/衣物.png'" mode="aspectFill"></image>
  51. <view class="order-arrow">
  52. <text class="iconfont"></text>
  53. </view>
  54. <view class="order-info">
  55. <text class="order-count">{{ order.num || order.count || 1 }} </text>
  56. <text class="order-price">¥ {{ order.onePrice || order.priceRange || 0 }} /</text>
  57. <view class="order-estimate">
  58. <text>预估 ¥{{ order.price || order.estimatePrice }}</text>
  59. </view>
  60. </view>
  61. </view>
  62. <!-- 订单状态 -->
  63. <view class="order-status">
  64. <image class="status-icon" :src="order.statusIcon || '/static/my/【待取件】快递员正在赶来.png'" mode="aspectFill"></image>
  65. <view class="status-info">
  66. <text class="status-text">{{ getOrderStatusText(order) }}</text>
  67. <text class="status-time">{{ order.goTime || order.statusTime }}</text>
  68. </view>
  69. </view>
  70. </view>
  71. <view class="order-loading" v-if="loading">
  72. <uni-loading color="#ffac07" :size="40" />
  73. <text class="loading-text">加载中...</text>
  74. </view>
  75. <view class="order-nomore" v-else-if="!hasMore && orderList.length">
  76. <text class="nomore-text">没有更多订单了</text>
  77. </view>
  78. </scroll-view>
  79. </view>
  80. </view>
  81. </template>
  82. <script>
  83. import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
  84. export default {
  85. mixins: [pullRefreshMixin],
  86. data() {
  87. return {
  88. tabs: [
  89. { name: '全部', count: 0 },
  90. { name: '进行中', count: 0 },
  91. { name: '已完成', count: 0 }
  92. ],
  93. currentTab: 0,
  94. orderList: [], // 当前显示的订单列表
  95. loading: false,
  96. page: 1,
  97. pageSize: 10,
  98. hasMore: true
  99. }
  100. },
  101. created() {
  102. this.fetchOrderList()
  103. },
  104. methods: {
  105. async fetchOrderList(isLoadMore = false) {
  106. this.loading = true
  107. let statusArr = []
  108. if (this.currentTab === 1) statusArr = [0, 1, 2] // 进行中
  109. else if (this.currentTab === 2) statusArr = [3] // 已完成
  110. else statusArr = [] // 全部
  111. let allOrders = []
  112. if (statusArr.length === 0) {
  113. // 全部
  114. await new Promise(resolve => {
  115. this.$api('getOrderListPage', { pageSize: this.pageSize, current: this.page }, res => {
  116. if (res && res.code === 200 && res.result && Array.isArray(res.result.records)) {
  117. allOrders = res.result.records
  118. if (isLoadMore) {
  119. this.orderList = this.orderList.concat(allOrders)
  120. } else {
  121. this.orderList = allOrders
  122. }
  123. this.hasMore = allOrders.length === this.pageSize
  124. }
  125. resolve()
  126. })
  127. })
  128. } else {
  129. // 多状态合并
  130. for (let status of statusArr) {
  131. await new Promise(resolve => {
  132. this.$api('getOrderListPage', { status, pageSize: this.pageSize, current: this.page }, res => {
  133. if (res && res.code === 200 && res.result && Array.isArray(res.result.records)) {
  134. allOrders = allOrders.concat(res.result.records)
  135. }
  136. resolve()
  137. })
  138. })
  139. }
  140. // 去重
  141. const map = {}
  142. allOrders = allOrders.filter(item => {
  143. if (map[item.id]) return false
  144. map[item.id] = 1
  145. return true
  146. })
  147. if (isLoadMore) {
  148. this.orderList = this.orderList.concat(allOrders)
  149. } else {
  150. this.orderList = allOrders
  151. }
  152. this.hasMore = allOrders.length === this.pageSize
  153. }
  154. this.loading = false
  155. },
  156. switchTab(index) {
  157. if (this.currentTab === index) return
  158. this.currentTab = index
  159. this.page = 1 // 重置页码
  160. this.hasMore = true
  161. this.orderList = []
  162. this.fetchOrderList()
  163. },
  164. getOrderStatusText(order) {
  165. const { status, state } = order
  166. if (state == 3) return '已取消'
  167. if (status == 0) return '【在线预约】'
  168. if (status == 1 && state == 0) return '【待取件】快递员正在赶来'
  169. if (status == 1 && state == 1) return '【已取件】快递员正在送至质检'
  170. if (status == 2 && state == 1) return '【质检中】质检员正在质检'
  171. if (status == 3 && state == 1) return '【待结款】待平台确认结款项'
  172. if (status == 3 && state == 2) return '【已结款】平台已结款至账户'
  173. return ''
  174. },
  175. async onRefresh() {
  176. // 模拟刷新数据
  177. await new Promise(resolve => setTimeout(resolve, 1000))
  178. uni.stopPullRefresh()
  179. },
  180. goBack() {
  181. uni.navigateBack()
  182. },
  183. showMore() {
  184. // 显示更多选项
  185. },
  186. onShare() {
  187. // 分享功能
  188. },
  189. viewAll() {
  190. this.switchTab(0) // 切换到全部标签
  191. },
  192. // 加载更多
  193. loadMore() {
  194. if (this.loading || !this.hasMore) return
  195. this.page++
  196. this.fetchOrderList(true)
  197. },
  198. goToDetail(order) {
  199. uni.navigateTo({
  200. url: `/pages/subcomponent/detail?id=${order.id}`
  201. })
  202. }
  203. }
  204. }
  205. </script>
  206. <style lang="scss" scoped>
  207. .container {
  208. background: #f8f8f8;
  209. padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
  210. overflow: hidden;
  211. height: 100vh;
  212. }
  213. .nav-bar {
  214. display: flex;
  215. align-items: center;
  216. height: calc(150rpx + var(--status-bar-height));
  217. padding: 0 32rpx;
  218. padding-top: var(--status-bar-height);
  219. background: #fff;
  220. position: fixed;
  221. top: 0;
  222. left: 0;
  223. right: 0;
  224. z-index: 999;
  225. box-sizing: border-box;
  226. .back {
  227. padding: 20rpx;
  228. margin-left: -20rpx;
  229. }
  230. .title {
  231. flex: 1;
  232. text-align: center;
  233. font-size: 34rpx;
  234. font-weight: 500;
  235. color: #222;
  236. }
  237. .right-btns {
  238. display: flex;
  239. align-items: center;
  240. gap: 32rpx;
  241. .more, .target {
  242. font-size: 40rpx;
  243. color: #333;
  244. }
  245. }
  246. }
  247. .content {
  248. padding: 30rpx 0 0 0;
  249. margin-top: calc(150rpx + var(--status-bar-height) + 80rpx);
  250. height: 100%;
  251. display: flex;
  252. flex-direction: column;
  253. overflow: hidden;
  254. box-sizing: border-box;
  255. .page-header {
  256. display: flex;
  257. justify-content: space-between;
  258. align-items: center;
  259. margin-bottom: 30rpx;
  260. .page-title {
  261. font-size: 34rpx;
  262. font-weight: bold;
  263. }
  264. .view-all {
  265. font-size: 28rpx;
  266. color: #999;
  267. }
  268. }
  269. }
  270. .tabs {
  271. display: flex;
  272. background: #f5f5f5;
  273. border-radius: 8rpx;
  274. margin-bottom: 30rpx;
  275. position: fixed;
  276. top: calc(150rpx + var(--status-bar-height));
  277. left: 0;
  278. width: 100%;
  279. z-index: 998;
  280. box-sizing: border-box;
  281. .tab-item {
  282. flex: 1;
  283. height: 80rpx;
  284. display: flex;
  285. align-items: center;
  286. justify-content: center;
  287. font-size: 28rpx;
  288. color: #666;
  289. position: relative;
  290. &.active {
  291. color: #333;
  292. background-color: #e7e7e7;
  293. font-weight: 500;
  294. border-radius: 8rpx;
  295. }
  296. .badge {
  297. position: absolute;
  298. top: 10rpx;
  299. right: 10rpx;
  300. min-width: 32rpx;
  301. height: 32rpx;
  302. line-height: 32rpx;
  303. text-align: center;
  304. background: #ff4d4f;
  305. color: #fff;
  306. border-radius: 16rpx;
  307. font-size: 24rpx;
  308. padding: 0 6rpx;
  309. }
  310. }
  311. }
  312. .order-list {
  313. flex: 1;
  314. min-height: 0;
  315. overflow-y: scroll;
  316. padding-bottom: env(safe-area-inset-bottom);
  317. box-sizing: border-box;
  318. }
  319. .order-card {
  320. background: #fff;
  321. border-radius: 16rpx;
  322. padding: 40rpx;
  323. margin-bottom: 20rpx;
  324. .order-header {
  325. margin-bottom: 20rpx;
  326. .order-id {
  327. font-size: 28rpx;
  328. color: #999;
  329. .order-ids{
  330. font-family: PingFang SC;
  331. font-weight: 600;
  332. font-size: 16px;
  333. line-height: 140%;
  334. letter-spacing: 0%;
  335. color: #333;
  336. }
  337. }
  338. }
  339. .order-content {
  340. display: flex;
  341. align-items: center;
  342. margin-bottom: 20rpx;
  343. flex-direction: row;
  344. justify-content: space-between;
  345. .order-image {
  346. width: 160rpx;
  347. height: 160rpx;
  348. border-radius: 8rpx;
  349. // background-color: #fff8ea;
  350. background: #fffbe6;
  351. padding: 20rpx;
  352. box-sizing: border-box;
  353. display: block;
  354. }
  355. .order-arrow {
  356. padding: 0 30rpx;
  357. color: #999;
  358. }
  359. .order-info {
  360. // flex: 1;
  361. display: flex;
  362. flex-direction: column;
  363. text-align: center;
  364. .order-count {
  365. font-size: 32rpx;
  366. font-weight: 500;
  367. margin-bottom: 10rpx;
  368. background-color: #fffaee;
  369. // display: block;
  370. }
  371. .order-price {
  372. font-size: 28rpx;
  373. color: #666;
  374. margin-bottom: 10rpx;
  375. background-color: #fffaee;
  376. // display: block;
  377. }
  378. .order-estimate {
  379. display: inline-block;
  380. background:#ffac07;
  381. color: #fff;
  382. font-size: 26rpx;
  383. padding: 8rpx 20rpx;
  384. border-radius: 20rpx;
  385. }
  386. }
  387. }
  388. .order-status {
  389. display: flex;
  390. align-items: center;
  391. padding: 20rpx;
  392. background: #f4f4f4;
  393. border-radius: 8rpx;
  394. .status-icon {
  395. width: 80rpx;
  396. height: 80rpx;
  397. margin-right: 20rpx;
  398. }
  399. .status-info {
  400. flex: 1;
  401. .status-text {
  402. font-size: 28rpx;
  403. color: #333;
  404. margin-bottom: 6rpx;
  405. display: block;
  406. }
  407. .status-time {
  408. font-size: 26rpx;
  409. color: #999;
  410. }
  411. }
  412. }
  413. }
  414. .order-loading {
  415. display: flex;
  416. flex-direction: column;
  417. align-items: center;
  418. justify-content: center;
  419. padding: 30rpx 0;
  420. color: #ffac07;
  421. font-size: 28rpx;
  422. }
  423. .loading-text {
  424. margin-top: 10rpx;
  425. color: #ffac07;
  426. font-size: 26rpx;
  427. }
  428. .order-nomore {
  429. text-align: center;
  430. color: #bbb;
  431. font-size: 24rpx;
  432. padding: 20rpx 0 40rpx 0;
  433. }
  434. .nomore-text {
  435. color: #bbb;
  436. font-size: 24rpx;
  437. }
  438. </style>