爱简收旧衣按件回收前端代码仓库
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.

957 lines
26 KiB

2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
1 month ago
2 months ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months ago
1 month ago
2 months 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">{{ orderDetail && orderDetail.ordeNo ? orderDetail.ordeNo : orderId }}</text>
  9. </view>
  10. <!-- 内容区域 -->
  11. <view class="content">
  12. <!-- 回收流程卡片 -->
  13. <view class="card process-card">
  14. <view class="card-title">回收流程</view>
  15. <view class="process-steps">
  16. <view
  17. v-for="(step, index) in processSteps"
  18. :key="index"
  19. class="step-item"
  20. :class="{ cancel: state === 3 && index === status }"
  21. >
  22. <image :src="step.icon" mode="aspectFit" class="step-icon"></image>
  23. <view
  24. class="step-label"
  25. :class="{
  26. active: status === index && state !== 3,
  27. cancel: state === 3 && index === status
  28. }"
  29. >
  30. <view class="step-label-inner">
  31. <!-- <text class="step-num">{{ ['①','②','③','④'][index] }}</text> -->
  32. <text class="step-text">{{ step.text }}</text>
  33. </view>
  34. </view>
  35. </view>
  36. </view>
  37. <view class="process-divider"></view>
  38. <!-- 状态信息 -->
  39. <view class="status-info" v-if="currentStatus">
  40. <image class="status-icon" :src="currentStatus.icon" mode="aspectFit"></image>
  41. <view class="status-detail">
  42. <text class="status-text" v-if="state === 3">已取消本次预约</text>
  43. <text class="status-text" v-else>{{ currentStatus.text }}</text>
  44. <text class="status-time">{{ currentStatus.time }}</text>
  45. </view>
  46. </view>
  47. <!-- 取消后提示语 -->
  48. <view v-if="state === 3" class="cancel-tip">期待您下次的支持共同为地球减少碳排放出一份力</view>
  49. <!-- 物流公司仅status为01时显示 -->
  50. <view class="express-info" v-if="state !== 3 && status <= 1">
  51. <text class="express-label">物流公司</text>
  52. <view class="express-row">
  53. <text class="express-value">{{ expressCompany }}{{ expressNo }}</text>
  54. <text class="express-copy" @tap="copyExpressNo">复制</text>
  55. </view>
  56. </view>
  57. <view class="info-divider" v-if="state !== 3 && status < 3"></view>
  58. <!-- 地址信息仅非取消和非结款时显示 -->
  59. <view class="pickup-info" v-if="state !== 3 && status < 3">
  60. <view class="info-item" @tap="viewAddress">
  61. <text class="label">取件地址</text>
  62. <view class="value">
  63. <text class="text">{{ address }}</text>
  64. <!-- <text class="arrow">></text> -->
  65. </view>
  66. </view>
  67. <view class="info-item">
  68. <text class="label">{{ timeLabel }}</text>
  69. <view class="value">
  70. <text class="text">{{ appointmentTime }}</text>
  71. <!-- <text class="arrow">></text> -->
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. <!-- 订单详情卡片 -->
  77. <view class="order-detail-card">
  78. <text class="order-title">订单详情</text>
  79. <view class="order-row">
  80. <text class="order-label">订单编号</text>
  81. <text class="order-value">{{ orderDetail && orderDetail.ordeNo ? orderDetail.ordeNo : orderId }}</text>
  82. </view>
  83. <view class="order-divider"></view>
  84. <template v-if="status < 2">
  85. <view class="order-row">
  86. <text class="order-label">预估回收</text>
  87. <text class="order-value order-highlight">¥ {{ estimatePrice }}</text>
  88. </view>
  89. </template>
  90. <template v-else-if="status === 3">
  91. <view class="order-row">
  92. <text class="order-label">合格结算</text>
  93. <text class="order-value order-highlight">¥ {{ finalPrice }}</text>
  94. </view>
  95. <view class="order-row">
  96. <text class="order-label">运费扣除</text>
  97. <text class="order-value">¥ 0</text>
  98. </view>
  99. <view class="order-row">
  100. <text class="order-label">结算金额</text>
  101. <text class="order-value order-highlight">¥ {{ finalPrice }}</text>
  102. </view>
  103. </template>
  104. <view class="order-divider"></view>
  105. <view class="goods-list">
  106. <view class="goods-item" v-for="(item, index) in clothesList" :key="index">
  107. <image class="goods-img" :src="item.image" mode="aspectFit"></image>
  108. <view class="goods-info">
  109. <text class="goods-name">{{ item.title }}</text>
  110. <text class="desc">{{ item.pinName }}</text>
  111. <text class="goods-desc">{{ item.details }}</text>
  112. <view class="goods-meta">
  113. <text class="goods-price">¥ {{ item.onePrice }}<text class="goods-unit"> /</text></text>
  114. <text class="goods-count">x{{ item.num }}</text>
  115. </view>
  116. </view>
  117. <text class="goods-total">¥{{ item.estimatedPrice }}</text>
  118. </view>
  119. </view>
  120. </view>
  121. <!-- 质检结果卡片仅结款状态显示 -->
  122. <view class="order-detail-card" v-if="status === 3">
  123. <text class="order-title">质检结果</text>
  124. <view class="order-row"><text class="order-label">质检数量</text><text class="order-value">9 </text></view>
  125. <view class="order-row"><text class="order-label">质检合格</text><text class="order-value">7 </text></view>
  126. <view class="order-row"><text class="order-label">质量问题</text><text class="order-value">2 </text></view>
  127. <view class="order-row"><text class="order-label">不可回收</text><text class="order-value">0 </text></view>
  128. <view class="order-row"><text class="order-label">订单重量</text><text class="order-value">2.85 kg</text></view>
  129. <view class="order-divider"></view>
  130. <view class="report-btn" @tap="viewReport">点此查看质检报告详情</view>
  131. </view>
  132. <!-- 详细信息卡片仅结款状态显示 -->
  133. <view class="order-detail-card detail-info-card" v-if="status === 3">
  134. <text class="order-title">详细信息</text>
  135. <view class="order-row">
  136. <text class="order-label">预约时间</text>
  137. <text class="order-value">2025-03-20 11:00~12:00</text>
  138. </view>
  139. <view class="order-row">
  140. <text class="order-label">取件地址</text>
  141. <text class="order-value">{{ address }}</text>
  142. </view>
  143. </view>
  144. </view>
  145. <!-- 底部按钮仅在线预约时显示 -->
  146. <view class="bottom-btns" v-if="status === 0 && state !== 3">
  147. <button class="btn cancel-btn" @tap="showCancelModal = true">取消订单</button>
  148. <button class="btn contact-btn" @tap="contactCourier">联系快递员</button>
  149. </view>
  150. <!-- 取消订单弹窗 -->
  151. <view v-if="showCancelModal" class="modal-mask">
  152. <view class="modal-box">
  153. <view class="modal-title">取消订单</view>
  154. <view class="modal-content">确认要取消订单吗</view>
  155. <view class="modal-actions">
  156. <button class="modal-btn modal-cancel" @tap="showCancelModal = false">取消</button>
  157. <button class="modal-btn modal-confirm" @tap="confirmCancelOrder">确认</button>
  158. </view>
  159. </view>
  160. </view>
  161. </view>
  162. </template>
  163. <script>
  164. import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
  165. export default {
  166. mixins: [pullRefreshMixin],
  167. data() {
  168. return {
  169. orderId: '',
  170. currentStep: 1, // 当前进行到第几步
  171. processSteps: [
  172. ],
  173. address: '',
  174. appointmentTime: '',
  175. estimatePrice: '',
  176. finalPrice: '',
  177. clothesList: [],
  178. currentStatus: {
  179. text: '',
  180. time: '',
  181. icon: ''
  182. },
  183. phone: '',
  184. hasReport: false,
  185. reportTime: '',
  186. showEditButton: true,
  187. expressCompany: '',
  188. expressNo: '',
  189. showCancelModal: false,
  190. statusBarHeight: 0,
  191. orderDetail: null,
  192. status: null, // 订单状态:0:在线预约 1:快递上门 2:透明质检 3:现金打款
  193. state: null // 订单状态:0待取件 1已取件 2已完成 3已取消
  194. }
  195. },
  196. computed: {
  197. timeLabel() {
  198. // 根据状态返回不同的时间标签
  199. if (this.status === 3) {
  200. return '回收到账时间'
  201. } else if (this.status === 2) {
  202. return '质检完成时间'
  203. } else {
  204. return '上门时间'
  205. }
  206. },
  207. showEstimate() {
  208. return this.status < 2
  209. }
  210. },
  211. methods: {
  212. async onRefresh() {
  213. // 模拟刷新数据
  214. await new Promise(resolve => setTimeout(resolve, 1000))
  215. uni.stopPullRefresh()
  216. },
  217. goBack() {
  218. getApp().globalData.shouldClearRecycle = true
  219. uni.navigateBack()
  220. },
  221. showMore() {
  222. // 显示更多选项
  223. },
  224. onShare() {
  225. // 分享功能
  226. },
  227. viewAddress() {
  228. // 查看完整地址
  229. },
  230. viewReport() {
  231. // 查看质检报告,传入orderId
  232. uni.navigateTo({
  233. url: `/pages/subcomponent/inspection-report?orderId=${this.orderId}`
  234. })
  235. },
  236. editOrder() {
  237. // 修改订单
  238. },
  239. // 更新订单状态
  240. updateOrderStatus(status) {
  241. switch(status) {
  242. case 'cancelled':
  243. this.currentStep = 0
  244. this.currentStatus = {
  245. text: '已取消',
  246. time: '',
  247. icon: '/static/my/【待取件】快递员正在赶来.png'
  248. }
  249. this.showEditButton = false
  250. break
  251. case 'processing':
  252. this.currentStep = 2
  253. this.currentStatus = {
  254. text: '【待取件】快递员正在赶来',
  255. time: '2025-04-20 11:00~13:00',
  256. icon: '/static/my/【待取件】快递员正在赶来.png'
  257. }
  258. break
  259. case 'collected':
  260. this.currentStep = 2
  261. this.currentStatus = {
  262. text: '【已取件】快递员正在送至质检',
  263. time: '2025-04-30 11:42',
  264. icon: '/static/my/【上门中】快递员正在赶来.png'
  265. }
  266. this.showEditButton = false
  267. break
  268. case 'inspecting':
  269. this.currentStep = 3
  270. this.currentStatus = {
  271. text: '【质检中】质检员正在质检',
  272. time: '2025-04-20 11:00',
  273. icon: '/static/my/逐件验-配图.png'
  274. }
  275. this.showEditButton = false
  276. break
  277. case 'pending_payment':
  278. this.currentStep = 4
  279. this.currentStatus = {
  280. text: '【待结款】待平台确认结款项',
  281. time: '2025-04-20 12:00',
  282. icon: '/static/my/【已结款】平台已结款至账户.png'
  283. }
  284. this.hasReport = true
  285. this.reportTime = '2025-03-20 11:40'
  286. this.showEditButton = false
  287. break
  288. case 'completed':
  289. this.currentStep = 4
  290. this.currentStatus = {
  291. text: '【已结款】平台已结款至账户',
  292. time: '2025-04-20 12:01',
  293. icon: '/static/my/【已结款】平台已结款至账户.png'
  294. }
  295. this.hasReport = true
  296. this.reportTime = '2025-03-20 11:40'
  297. this.showEditButton = false
  298. break
  299. }
  300. },
  301. copyExpressNo() {
  302. uni.setClipboardData({
  303. data: this.expressCompany + this.expressNo,
  304. success: () => {
  305. uni.showToast({ title: '已复制', icon: 'none' });
  306. }
  307. });
  308. },
  309. confirmCancelOrder() {
  310. this.showCancelModal = false;
  311. // 模拟取消动作
  312. this.currentStep = 0;
  313. // this.currentStatus = {
  314. // text: '已取消',
  315. // time: this.getNowTime(),
  316. // icon: '/static/【待取件】快递员正在赶来.png'
  317. // };
  318. this.$api('cancelOrder', { orderId: this.orderId }, res => {
  319. if (res && res.code === 200) {
  320. console.log('res', res)
  321. uni.showToast({ title: '订单已取消', icon: 'none' });
  322. // 刷新页面数据
  323. this.fetchOrderDetail(this.orderId);
  324. // 通知订单列表页面刷新数据
  325. uni.$emit('orderStatusChanged');
  326. }
  327. })
  328. // uni.showToast({ title: '订单已取消', icon: 'none' });
  329. },
  330. getNowTime() {
  331. const now = new Date();
  332. const y = now.getFullYear();
  333. const m = (now.getMonth() + 1).toString().padStart(2, '0');
  334. const d = now.getDate().toString().padStart(2, '0');
  335. const h = now.getHours().toString().padStart(2, '0');
  336. const min = now.getMinutes().toString().padStart(2, '0');
  337. return `${y}-${m}-${d} ${h}:${min}`;
  338. },
  339. contactCourier() {
  340. // 联系快递员逻辑
  341. if (this.phone) {
  342. uni.makePhoneCall({
  343. phoneNumber: this.phone //仅为示例
  344. });
  345. }else{
  346. uni.showToast({ title: '暂无快递员电话', icon: 'none' });
  347. }
  348. },
  349. fetchOrderDetail(orderId) {
  350. this.$api && this.$api('getOrderDetail', { orderId }, res => {
  351. if (res && res.code === 200 && res.result) {
  352. this.orderDetail = res.result
  353. // 保存状态值
  354. this.status = res.result.status
  355. this.state = res.result.state
  356. // 赋值页面字段
  357. this.address = res.result.address + (res.result.addressDetail || '')
  358. this.appointmentTime = res.result.goTime || ''
  359. this.estimatePrice = res.result.estimatedPrice || ''
  360. this.finalPrice = res.result.price || ''
  361. this.clothesList = res.result.commonOrderList || []
  362. this.expressCompany = res.result.wliu || ''
  363. this.expressNo = res.result.expressNo || ''
  364. this.phone = res.result.deliveryPhone || ''
  365. // 状态判断
  366. this.setOrderStatus(res.result.status, res.result.state, res.result)
  367. }
  368. })
  369. },
  370. setOrderStatus(status, state, data) {
  371. // 0:在线预约 1:快递上门 2:透明质检 3:现金打款
  372. // state:0待取件 1已取件 2已完成 3已取消
  373. if (state == 3) {
  374. this.currentStep = 0
  375. this.currentStatus = {
  376. text: '已取消',
  377. time: '',
  378. icon: '/static/【待取件】快递员正在赶来.png'
  379. }
  380. this.showEditButton = false
  381. return
  382. }
  383. if (status == 0) {
  384. this.currentStep = 1
  385. this.currentStatus = {
  386. text: '【在线预约】',
  387. time: data.goTime || '',
  388. icon: '/static/home/① 在线预约.png'
  389. }
  390. } else if (status == 1 && state == 0) {
  391. this.currentStep = 2
  392. this.currentStatus = {
  393. text: '【待取件】快递员正在赶来',
  394. time: data.goTime || '',
  395. icon: '/static/my/【待取件】快递员正在赶来.png'
  396. }
  397. } else if (status == 1 && state == 1) {
  398. this.currentStep = 2
  399. this.currentStatus = {
  400. text: '【已取件】快递员正在送至质检',
  401. time: data.goTime || '',
  402. icon: '/static/my/【上门中】快递员正在赶来.png'
  403. }
  404. } else if (status == 2 && state == 1) {
  405. this.currentStep = 3
  406. this.currentStatus = {
  407. text: '【质检中】质检员正在质检',
  408. time: data.goTime || '',
  409. icon: '/static/my/逐件验-配图.png'
  410. }
  411. } else if (status == 3 && state == 1) {
  412. this.currentStep = 4
  413. this.currentStatus = {
  414. text: '【待结款】待平台确认结款项',
  415. time: data.goTime || '',
  416. icon: '/static/my/【已结款】平台已结款至账户.png'
  417. }
  418. this.hasReport = true
  419. this.reportTime = data.updateTime || ''
  420. } else if (status == 3 && state == 2) {
  421. this.currentStep = 4
  422. this.currentStatus = {
  423. text: '【已结款】平台已结款至账户',
  424. time: data.goTime || '',
  425. icon: '/static/my/【已结款】平台已结款至账户.png'
  426. }
  427. this.hasReport = true
  428. this.reportTime = data.updateTime || ''
  429. }
  430. },getAreaList() {
  431. this.$api('getAreaList', {}, (res) => {
  432. console.log(res,'getAreaList');
  433. if (res.code == 200 && Array.isArray(res.result)) {
  434. // 按sort升序排序
  435. const sorted = res.result.slice().sort((a, b) => a.sort - b.sort)
  436. this.processSteps = sorted.map(item => ({
  437. // id: item.id,
  438. icon: item.image,
  439. text: item.title
  440. }))
  441. }
  442. })
  443. },
  444. },
  445. onLoad(options) {
  446. if (options.id) {
  447. this.orderId = options.id
  448. this.fetchOrderDetail(options.id)
  449. }
  450. this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
  451. this.getAreaList()
  452. },
  453. onShow() {
  454. this.getAreaList()
  455. }
  456. }
  457. </script>
  458. <style scoped lang="scss">
  459. .container {
  460. min-height: 100vh;
  461. background: #f4f4f4;
  462. padding-bottom: 120rpx;
  463. }
  464. .card {
  465. background: linear-gradient(180deg, #fffbe6 0%, #fff 90%);
  466. border-radius: 28rpx;
  467. margin: 24rpx 24rpx 0 24rpx;
  468. box-shadow: 0 8rpx 24rpx rgba(255, 156, 0, 0.03);
  469. padding: 40rpx 32rpx;
  470. }
  471. .nav-bar {
  472. display: flex;
  473. align-items: center;
  474. position: fixed;
  475. top: 0;
  476. left: 0;
  477. right: 0;
  478. z-index: 999;
  479. height: calc(150rpx + var(--status-bar-height));
  480. background: #fff;
  481. padding: 0 32rpx;
  482. padding-top: var(--status-bar-height);
  483. box-sizing: border-box;
  484. box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
  485. .back {
  486. padding: 20rpx;
  487. margin-left: -20rpx;
  488. }
  489. .title {
  490. flex: 1;
  491. text-align: center;
  492. font-size: 34rpx;
  493. font-weight: 500;
  494. }
  495. .right-btns {
  496. display: flex;
  497. align-items: center;
  498. gap: 30rpx;
  499. .more, .target {
  500. font-size: 40rpx;
  501. color: #333;
  502. }
  503. }
  504. }
  505. .card-title, .card-header .title {
  506. font-size: 32rpx;
  507. font-weight: bold;
  508. color: #222;
  509. margin-bottom: 24rpx;
  510. }
  511. .process-card {
  512. background: linear-gradient(180deg, #fffbe6 0%, #fff 35%);
  513. border-radius: 32rpx;
  514. box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.04);
  515. padding: 40rpx 32rpx 32rpx 32rpx;
  516. margin: 24rpx;
  517. }
  518. .card-title {
  519. font-size: 32rpx;
  520. font-weight: bold;
  521. color: #222;
  522. margin-bottom: 24rpx;
  523. text-align: left;
  524. }
  525. .process-steps {
  526. display: flex;
  527. justify-content: space-between;
  528. align-items: flex-start;
  529. margin-bottom: 12rpx;
  530. gap: 18rpx;
  531. }
  532. .step-item {
  533. width: 150%;
  534. height: 150rpx;
  535. background: #fff8ea;
  536. border-radius: 20rpx;
  537. display: flex;
  538. flex-direction: column;
  539. align-items: center;
  540. box-shadow: 0 2rpx 8rpx rgba(255, 156, 0, 0.04);
  541. overflow: hidden;
  542. position: relative;
  543. }
  544. .step-item.cancel {
  545. background: linear-gradient(180deg, #fff0f3 0%, #ffd6df 100%) !important;
  546. }
  547. .step-icon {
  548. width: 86rpx;
  549. height: 86rpx;
  550. margin: 16rpx 0 0 0;
  551. flex-shrink: 0;
  552. }
  553. .step-label {
  554. width: 100%;
  555. height: 44rpx;
  556. background: transparent;
  557. position: absolute;
  558. left: 0;
  559. bottom: 0;
  560. border-radius: 0 0 16rpx 16rpx;
  561. display: flex;
  562. align-items: center;
  563. justify-content: center;
  564. transition: background 0.2s;
  565. overflow: hidden;
  566. }
  567. .step-label.active {
  568. background: linear-gradient(90deg, #ffd01e 0%, #ff8917 100%);
  569. }
  570. .step-label.cancel {
  571. background: linear-gradient(to right, #ff8e8e 0%, #ff5e5e 100%) !important;
  572. }
  573. .step-label.cancel .step-num,
  574. .step-label.cancel .step-text {
  575. color: #fff !important;
  576. }
  577. .step-label-inner {
  578. width: 100%;
  579. height: 100%;
  580. display: flex;
  581. flex-direction: row;
  582. // align-items: center;
  583. justify-content: center;
  584. white-space: nowrap;
  585. }
  586. .step-num,
  587. .step-text {
  588. font-family: PingFang SC;
  589. font-weight: 400;
  590. font-size: 11px;
  591. letter-spacing: 0%;
  592. line-height: 48rpx;
  593. margin: 0;
  594. padding: 0;
  595. color: #9b9b9b;
  596. }
  597. .step-num {
  598. margin-right: 6rpx;
  599. display: flex;
  600. justify-content: center;
  601. align-items: center;
  602. }
  603. .step-label.active .step-num,
  604. .step-label.active .step-text {
  605. font-family: PingFang SC;
  606. font-weight: 500;
  607. font-size: 11px;
  608. letter-spacing: 0%;
  609. color: #fff;
  610. }
  611. .process-divider {
  612. width: 100%;
  613. height: 0;
  614. border-bottom: 1rpx dashed #e6e6e6;
  615. margin: 20rpx 0 0 0;
  616. }
  617. .status-info {
  618. display: flex;
  619. align-items: center;
  620. margin: 24rpx 0;
  621. background: #fafafa;
  622. border-radius: 16rpx;
  623. padding: 16rpx;
  624. }
  625. .status-icon {
  626. width: 60rpx;
  627. height: 60rpx;
  628. margin-right: 16rpx;
  629. }
  630. .status-detail {
  631. display: flex;
  632. flex-direction: column;
  633. flex: 1;
  634. }
  635. .status-text {
  636. font-size: 28rpx;
  637. color: #222;
  638. font-weight: bold;
  639. display: block;
  640. }
  641. .status-time {
  642. font-size: 24rpx;
  643. color: #999;
  644. margin-top: 4rpx;
  645. display: block;
  646. }
  647. .pickup-info .info-item {
  648. display: flex;
  649. // justify-content: space-between;
  650. flex-direction: column;
  651. // align-items: center;
  652. padding: 18rpx 0;
  653. border-bottom: 1px solid #f0f0f0;
  654. margin: 20rpx 0 20rpx 0;
  655. }
  656. .pickup-info .info-item:last-child {
  657. border-bottom: none;
  658. }
  659. .label {
  660. color: #999;
  661. font-size: 26rpx;
  662. }
  663. .value {
  664. color: #222;
  665. font-size: 26rpx;
  666. display: flex;
  667. align-items: center;
  668. }
  669. .value .arrow {
  670. color: #bbb;
  671. margin-left: 8rpx;
  672. }
  673. .order-detail-card {
  674. background: linear-gradient(to bottom, #fff6e3 0%, #fff 20%);
  675. border-radius: 36rpx;
  676. box-shadow: 0 8rpx 32rpx rgba(255, 156, 0, 0.08);
  677. padding: 40rpx 36rpx 32rpx 36rpx;
  678. margin: 24rpx;
  679. margin-bottom: 164rpx;
  680. }
  681. .order-title {
  682. font-size: 36rpx;
  683. font-weight: bold;
  684. color: #222;
  685. margin-bottom: 32rpx;
  686. text-align: left;
  687. display: block;
  688. }
  689. .order-row {
  690. display: flex;
  691. // justify-content: space-between;
  692. align-items: center;
  693. margin-bottom: 18rpx;
  694. }
  695. .order-label {
  696. color: #bcbcbc;
  697. font-size: 26rpx;
  698. margin: 20rpx 0 20rpx 0;
  699. }
  700. .order-value {
  701. color: #222;
  702. font-size: 28rpx;
  703. margin-left: 30rpx;
  704. font-weight: 500;
  705. }
  706. .order-highlight {
  707. color: #ff9c00;
  708. font-size: 30rpx;
  709. font-weight: bold;
  710. }
  711. .order-divider {
  712. width: 100%;
  713. height: 1rpx;
  714. background: #f0f0f0;
  715. margin: 18rpx 0;
  716. }
  717. .goods-list {
  718. margin-top: 10rpx;
  719. display: flex;
  720. flex-direction: column;
  721. gap: 18rpx;
  722. }
  723. .goods-item {
  724. background: #fff;
  725. border-radius: 24rpx;
  726. display: flex;
  727. align-items: center;
  728. padding: 24rpx 20rpx;
  729. box-shadow: 0 2rpx 8rpx rgba(255, 156, 0, 0.04);
  730. position: relative;
  731. }
  732. .goods-img {
  733. width: 90rpx;
  734. height: 90rpx;
  735. border-radius: 18rpx;
  736. margin-right: 20rpx;
  737. // background: #fffbe6;
  738. flex-shrink: 0;
  739. }
  740. .goods-info {
  741. flex: 1;
  742. display: flex;
  743. flex-direction: column;
  744. justify-content: center;
  745. }
  746. .goods-name {
  747. font-size: 30rpx;
  748. color: #222;
  749. font-weight: bold;
  750. margin-bottom: 6rpx;
  751. }
  752. .desc { font-size: 24rpx; color: #999; margin: 4rpx 0 8rpx 0; }
  753. .goods-desc {
  754. font-size: 24rpx;
  755. color: #bcbcbc;
  756. margin-bottom: 10rpx;
  757. }
  758. .goods-meta {
  759. display: flex;
  760. align-items: center;
  761. gap: 10rpx;
  762. }
  763. .goods-price {
  764. color: #ff9c00;
  765. font-size: 26rpx;
  766. font-weight: bold;
  767. }
  768. .goods-unit {
  769. color: #bcbcbc;
  770. font-size: 22rpx;
  771. font-weight: normal;
  772. }
  773. .goods-count {
  774. color: #bcbcbc;
  775. font-size: 24rpx;
  776. margin-left: 8rpx;
  777. }
  778. .goods-total {
  779. color: #222;
  780. font-size: 30rpx;
  781. font-weight: bold;
  782. margin-left: 18rpx;
  783. flex-shrink: 0;
  784. }
  785. .bottom-btns {
  786. position: fixed;
  787. left: 0;
  788. right: 0;
  789. bottom: 30rpx;
  790. z-index: 10;
  791. background: #fff;
  792. display: flex;
  793. justify-content: space-between;
  794. align-items: center;
  795. padding: 24rpx 24rpx calc(env(safe-area-inset-bottom) + 12rpx) 24rpx;
  796. box-shadow: 0 -2rpx 8rpx rgba(255, 156, 0, 0.04);
  797. border-radius: 24rpx 24rpx 0 0;
  798. gap: 24rpx;
  799. }
  800. .btn {
  801. flex: 1;
  802. height: 78rpx;
  803. font-size: 32rpx;
  804. font-weight: bold;
  805. border-radius: 44rpx;
  806. margin: 0;
  807. padding: 0;
  808. }
  809. .cancel-btn {
  810. color: #ff9c00;
  811. background: #fff0d2;
  812. border: 2rpx solid #ffd01e;
  813. }
  814. .contact-btn {
  815. color: #fff;
  816. background: linear-gradient(90deg, #ffd01e 0%, #ff8917 100%);
  817. border: none;
  818. }
  819. .express-info {
  820. // border: 1rpx solid #ffdca8;
  821. border-radius: 12rpx;
  822. // padding: 18rpx 20rpx 10rpx 20rpx;
  823. margin-bottom: 12rpx;
  824. margin-top: 8rpx;
  825. background: #fff;
  826. position: relative;
  827. }
  828. .express-label {
  829. color: #bcbcbc;
  830. font-size: 24rpx;
  831. margin-bottom: 8rpx;
  832. display: block;
  833. }
  834. .express-row {
  835. display: flex;
  836. justify-content: space-between;
  837. align-items: center;
  838. }
  839. .express-value {
  840. color: #222;
  841. font-size: 28rpx;
  842. font-weight: 500;
  843. word-break: break-all;
  844. }
  845. .express-copy {
  846. color: #ff9c00;
  847. font-size: 26rpx;
  848. font-weight: 500;
  849. margin-left: 16rpx;
  850. }
  851. .modal-mask {
  852. position: fixed;
  853. left: 0; right: 0; top: 0; bottom: 0;
  854. background: rgba(0,0,0,0.35);
  855. z-index: 999;
  856. display: flex;
  857. align-items: center;
  858. justify-content: center;
  859. }
  860. .modal-box {
  861. width: 560rpx;
  862. background: #fff;
  863. border-radius: 32rpx;
  864. box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.08);
  865. padding: 56rpx 0 0 0;
  866. display: flex;
  867. flex-direction: column;
  868. align-items: center;
  869. }
  870. .modal-title {
  871. font-size: 36rpx;
  872. font-weight: bold;
  873. color: #222;
  874. text-align: center;
  875. margin-bottom: 18rpx;
  876. }
  877. .modal-content {
  878. font-size: 28rpx;
  879. color: #222;
  880. text-align: center;
  881. margin-bottom: 48rpx;
  882. }
  883. .modal-actions {
  884. width: 100%;
  885. display: flex;
  886. border-top: 1rpx solid #f0f0f0;
  887. height: 100rpx;
  888. }
  889. .modal-btn {
  890. flex: 1;
  891. border: none;
  892. outline: none;
  893. background: none;
  894. font-size: 32rpx;
  895. font-weight: 500;
  896. border-radius: 0 0 0 32rpx;
  897. height: 100rpx;
  898. line-height: 100rpx;
  899. }
  900. .modal-cancel {
  901. color: #999;
  902. background: #fff;
  903. border-bottom-left-radius: 32rpx;
  904. }
  905. .modal-confirm {
  906. color: #ff9c00;
  907. background: #fff;
  908. border-bottom-right-radius: 32rpx;
  909. }
  910. .cancel-tip {
  911. color: #bcbcbc;
  912. font-size: 26rpx;
  913. text-align: center;
  914. margin: 24rpx 0 0 0;
  915. }
  916. .info-divider {
  917. width: 100%;
  918. height: 1rpx;
  919. background: #f0f0f0;
  920. margin: 0;
  921. }
  922. .report-btn {
  923. width: 100%;
  924. margin: 24rpx 0 0 0;
  925. padding: 0;
  926. height: 80rpx;
  927. line-height: 80rpx;
  928. text-align: center;
  929. color: #ff9c00;
  930. background: #fff;
  931. border: 2rpx solid #ffd01e;
  932. border-radius: 44rpx;
  933. font-size: 28rpx;
  934. font-weight: bold;
  935. }
  936. .detail-info-card {
  937. margin-bottom: 48rpx;
  938. }
  939. .content {
  940. margin-top: calc(150rpx + var(--status-bar-height));
  941. }
  942. </style>