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

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