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

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