logistics-detail.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <template>
  2. <view class="logistics-page">
  3. <!-- 顶部包裹切换 -->
  4. <scroll-view scroll-x class="package-tabs" :scroll-into-view="'tab-' + currentPackageIndex">
  5. <view class="tab-list">
  6. <view class="tab-item" v-for="(item, index) in packages" :key="index" :id="'tab-' + index"
  7. :class="{ active: currentPackageIndex === index }" @click="switchPackage(index)">
  8. {{ item.name }}
  9. </view>
  10. </view>
  11. </scroll-view>
  12. <!-- 物流基本信息 -->
  13. <view class="card info-card">
  14. <view class="info-row">
  15. <text class="label">承运商:</text>
  16. <text class="value">{{ currentPackage.carrier }}</text>
  17. </view>
  18. <view class="info-row">
  19. <text class="label">物流单号:</text>
  20. <text class="value">{{ currentPackage.trackingNo }}</text>
  21. <view class="copy-btn" @click="copyTrackingNo">复制</view>
  22. </view>
  23. </view>
  24. <!-- 物流轨迹 -->
  25. <view class="card timeline-card">
  26. <!-- 收货地址 -->
  27. <view class="timeline-item address-item">
  28. <view class="left-col">
  29. <view class="icon-box address-icon">收</view>
  30. <view class="line"></view>
  31. </view>
  32. <view class="right-col">
  33. <view class="status-title">收货地址:{{ currentPackage.address }}</view>
  34. </view>
  35. </view>
  36. <!-- 轨迹列表 -->
  37. <view class="timeline-item" v-for="(trace, index) in currentPackage.traces" :key="index">
  38. <view class="left-col">
  39. <!-- 不同状态显示不同图标 -->
  40. <view v-if="index === 0 && trace.status === '已签收'" class="icon-box check-icon">
  41. <u-icon name="checkmark" color="#fff" size="20"></u-icon>
  42. </view>
  43. <view v-else-if="trace.status === '派送中'" class="icon-box delivery-icon">
  44. <u-icon name="man" color="#fff" size="24"></u-icon> <!-- 使用uView图标或自定义 -->
  45. </view>
  46. <view v-else-if="trace.status === '运输中'" class="icon-box transport-icon">
  47. <u-icon name="car" color="#fff" size="24"></u-icon>
  48. </view>
  49. <view v-else-if="trace.status === '已下单'" class="icon-box order-icon">
  50. <u-icon name="order" color="#fff" size="24"></u-icon>
  51. </view>
  52. <view v-else class="dot"></view>
  53. <view class="line" v-if="index !== currentPackage.traces.length - 1"></view>
  54. </view>
  55. <view class="right-col" :class="{ 'is-first': index === 0 }">
  56. <view class="status-title">{{ trace.status }}</view>
  57. <view class="status-desc">{{ trace.desc }}</view>
  58. <view class="status-time">{{ trace.time }}</view>
  59. </view>
  60. </view>
  61. </view>
  62. </view>
  63. </template>
  64. <script>
  65. export default {
  66. data() {
  67. return {
  68. currentPackageIndex: 0,
  69. packages: [
  70. {
  71. name: '包裹1',
  72. carrier: '顺丰快递',
  73. trackingNo: '1486662178863',
  74. address: '四川省成都市武侯区城区锦城大道武侯区城区锦城大道武侯区城区锦城大道',
  75. traces: [
  76. {
  77. status: '已签收',
  78. desc: '您的包裹正在配送途中(快递员:蔡波,电话:18282828281)',
  79. time: '2021.03.03 21:29'
  80. },
  81. {
  82. status: '派送中',
  83. desc: '您的包裹正在配送途中(快递员:蔡波,电话:18285878382)',
  84. time: '2021.03.03 21:29'
  85. },
  86. {
  87. status: '运输中',
  88. desc: '您提交了订单,请等待第三方卖家系统确认',
  89. time: '2021.03.03 21:29'
  90. },
  91. {
  92. status: '',
  93. desc: '您的订单由第三方卖家捡货完成,待出库交付圆通快递包裹,运单号为:9830165317459',
  94. time: '2021.03.03 21:29'
  95. },
  96. {
  97. status: '',
  98. desc: '第三方卖家已经开始捡货',
  99. time: '2021.03.03 21:29'
  100. },
  101. {
  102. status: '',
  103. desc: '您的订单已进入第三方卖家仓库,准备出库',
  104. time: '2021.03.03 21:29'
  105. },
  106. {
  107. status: '已下单',
  108. desc: '您提交了订单,请等待第三方卖家系统确认',
  109. time: '2021.03.03 21:29'
  110. }
  111. ]
  112. },
  113. {
  114. name: '包裹2',
  115. carrier: '圆通速递',
  116. trackingNo: 'YT1234567890',
  117. address: '北京市朝阳区...',
  118. traces: []
  119. },
  120. {
  121. name: '包裹3',
  122. carrier: '中通快递',
  123. trackingNo: 'ZT0987654321',
  124. address: '上海市浦东新区...',
  125. traces: []
  126. },
  127. {
  128. name: '包裹4',
  129. carrier: '韵达快递',
  130. trackingNo: 'YD1122334455',
  131. address: '广东省广州市...',
  132. traces: []
  133. }
  134. ]
  135. };
  136. },
  137. computed: {
  138. currentPackage() {
  139. return this.packages[this.currentPackageIndex] || {};
  140. }
  141. },
  142. methods: {
  143. switchPackage(index) {
  144. this.currentPackageIndex = index;
  145. },
  146. copyTrackingNo() {
  147. uni.setClipboardData({
  148. data: this.currentPackage.trackingNo,
  149. success: () => {
  150. uni.showToast({
  151. title: '复制成功',
  152. icon: 'none'
  153. });
  154. }
  155. });
  156. }
  157. }
  158. }
  159. </script>
  160. <style lang="scss" scoped>
  161. .logistics-page {
  162. min-height: 100vh;
  163. background-color: #f5f5f5;
  164. padding: 20rpx;
  165. padding-bottom: 40rpx;
  166. }
  167. .package-tabs {
  168. white-space: nowrap;
  169. margin-bottom: 20rpx;
  170. .tab-list {
  171. display: flex;
  172. padding: 10rpx 0;
  173. }
  174. .tab-item {
  175. display: inline-block;
  176. padding: 12rpx 36rpx;
  177. background-color: #ccc; // Default gray
  178. color: #fff;
  179. font-size: 28rpx;
  180. border-radius: 8rpx;
  181. margin-right: 20rpx;
  182. transition: all 0.3s;
  183. &.active {
  184. background-color: #38C148; // Theme green
  185. font-weight: bold;
  186. }
  187. &:last-child {
  188. margin-right: 0;
  189. }
  190. }
  191. }
  192. .card {
  193. background-color: #fff;
  194. border-radius: 16rpx;
  195. padding: 30rpx;
  196. margin-bottom: 20rpx;
  197. }
  198. .info-card {
  199. .info-row {
  200. display: flex;
  201. align-items: center;
  202. margin-bottom: 20rpx;
  203. font-size: 30rpx;
  204. &:last-child {
  205. margin-bottom: 0;
  206. }
  207. .label {
  208. color: #333;
  209. width: 160rpx;
  210. font-weight: 500;
  211. }
  212. .value {
  213. color: #333;
  214. font-weight: 500;
  215. }
  216. .copy-btn {
  217. font-size: 24rpx;
  218. color: $app-theme-color;
  219. background-color: #edf7e8;
  220. padding: 4rpx 12rpx;
  221. border-radius: 4rpx;
  222. margin-left: 20rpx;
  223. }
  224. }
  225. }
  226. .timeline-card {
  227. padding: 30rpx 20rpx;
  228. }
  229. .timeline-item {
  230. display: flex;
  231. position: relative;
  232. .left-col {
  233. width: 80rpx;
  234. display: flex;
  235. flex-direction: column;
  236. align-items: center;
  237. margin-right: 10rpx;
  238. position: relative;
  239. .line {
  240. width: 2rpx;
  241. background-color: #eee;
  242. flex: 1;
  243. min-height: 40rpx;
  244. margin-top: 10rpx;
  245. margin-bottom: -10rpx; // Connect to next
  246. }
  247. .icon-box {
  248. width: 40rpx;
  249. height: 40rpx;
  250. border-radius: 50%;
  251. display: flex;
  252. justify-content: center;
  253. align-items: center;
  254. font-size: 20rpx;
  255. z-index: 1;
  256. &.address-icon {
  257. background-color: #ff5b5b;
  258. color: #fff;
  259. }
  260. &.check-icon {
  261. background-color: #ff5b5b;
  262. }
  263. &.delivery-icon,
  264. &.transport-icon,
  265. &.order-icon {
  266. background-color: #ccc;
  267. }
  268. }
  269. .dot {
  270. width: 16rpx;
  271. height: 16rpx;
  272. background-color: #eee;
  273. border-radius: 50%;
  274. margin-top: 12rpx;
  275. z-index: 1;
  276. }
  277. }
  278. .right-col {
  279. flex: 1;
  280. padding-bottom: 40rpx;
  281. &.is-first {
  282. .status-title {
  283. font-size: 32rpx;
  284. font-weight: bold;
  285. color: #333;
  286. }
  287. .status-desc {
  288. color: #333;
  289. }
  290. }
  291. .status-title {
  292. font-size: 30rpx;
  293. font-weight: 500;
  294. color: #333;
  295. margin-bottom: 10rpx;
  296. line-height: 1.4;
  297. }
  298. .status-desc {
  299. font-size: 26rpx;
  300. color: #999;
  301. line-height: 1.5;
  302. margin-bottom: 10rpx;
  303. }
  304. .status-time {
  305. font-size: 24rpx;
  306. color: #999;
  307. }
  308. }
  309. &.address-item {
  310. .right-col {
  311. padding-bottom: 30rpx;
  312. .status-title {
  313. font-weight: bold;
  314. margin-bottom: 0;
  315. }
  316. }
  317. }
  318. }
  319. </style>