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

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