爱简收旧衣按件回收前端代码仓库
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
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
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
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
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.name }}</text>
  110. <text class="goods-desc">{{ item.details }}</text>
  111. <view class="goods-meta">
  112. <text class="goods-price">¥ {{ item.onePrice }}<text class="goods-unit"> /</text></text>
  113. <text class="goods-count">x{{ item.num }}</text>
  114. </view>
  115. </view>
  116. <text class="goods-total">¥{{ item.price }}</text>
  117. </view>
  118. </view>
  119. </view>
  120. <!-- 质检结果卡片仅结款状态显示 -->
  121. <view class="order-detail-card" v-if="currentStep === 4">
  122. <text class="order-title">质检结果</text>
  123. <view class="order-row"><text class="order-label">质检数量</text><text class="order-value">9 </text></view>
  124. <view class="order-row"><text class="order-label">质检合格</text><text class="order-value">7 </text></view>
  125. <view class="order-row"><text class="order-label">质量问题</text><text class="order-value">2 </text></view>
  126. <view class="order-row"><text class="order-label">不可回收</text><text class="order-value">0 </text></view>
  127. <view class="order-row"><text class="order-label">订单重量</text><text class="order-value">2.85 kg</text></view>
  128. <view class="order-divider"></view>
  129. <view class="report-btn" @tap="viewReport">点此查看质检报告详情</view>
  130. </view>
  131. <!-- 详细信息卡片仅结款状态显示 -->
  132. <view class="order-detail-card detail-info-card" v-if="currentStep === 4">
  133. <text class="order-title">详细信息</text>
  134. <view class="order-row">
  135. <text class="order-label">预约时间</text>
  136. <text class="order-value">2025-03-20 11:00~12:00</text>
  137. </view>
  138. <view class="order-row">
  139. <text class="order-label">取件地址</text>
  140. <text class="order-value">{{ address }}</text>
  141. </view>
  142. </view>
  143. </view>
  144. <!-- 底部按钮仅待取件时显示 -->
  145. <view class="bottom-btns" v-if="currentStatus.text === '【待取件】快递员正在赶来'">
  146. <button class="btn cancel-btn" @tap="showCancelModal = true">取消订单</button>
  147. <button class="btn contact-btn" @tap="contactCourier">联系快递员</button>
  148. </view>
  149. <!-- 取消订单弹窗 -->
  150. <view v-if="showCancelModal" class="modal-mask">
  151. <view class="modal-box">
  152. <view class="modal-title">取消订单</view>
  153. <view class="modal-content">确认要取消订单吗</view>
  154. <view class="modal-actions">
  155. <button class="modal-btn modal-cancel" @tap="showCancelModal = false">取消</button>
  156. <button class="modal-btn modal-confirm" @tap="confirmCancelOrder">确认</button>
  157. </view>
  158. </view>
  159. </view>
  160. </view>
  161. </template>
  162. <script>
  163. import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
  164. export default {
  165. mixins: [pullRefreshMixin],
  166. data() {
  167. return {
  168. orderId: '',
  169. currentStep: 1, // 当前进行到第几步
  170. processSteps: [
  171. ],
  172. address: '',
  173. appointmentTime: '',
  174. estimatePrice: '',
  175. finalPrice: '',
  176. clothesList: [],
  177. currentStatus: {
  178. text: '',
  179. time: '',
  180. icon: ''
  181. },
  182. phone: '',
  183. hasReport: false,
  184. reportTime: '',
  185. showEditButton: true,
  186. expressCompany: '',
  187. expressNo: '',
  188. showCancelModal: false,
  189. statusBarHeight: 0,
  190. orderDetail: null
  191. }
  192. },
  193. computed: {
  194. timeLabel() {
  195. // 根据状态返回不同的时间标签
  196. if (this.currentStep === 4) {
  197. return '回收到账时间'
  198. } else if (this.currentStep === 3) {
  199. return '质检完成时间'
  200. } else {
  201. return '上门时间'
  202. }
  203. },
  204. showEstimate() {
  205. return this.currentStep < 3
  206. }
  207. },
  208. methods: {
  209. async onRefresh() {
  210. // 模拟刷新数据
  211. await new Promise(resolve => setTimeout(resolve, 1000))
  212. uni.stopPullRefresh()
  213. },
  214. goBack() {
  215. getApp().globalData.shouldClearRecycle = true
  216. uni.navigateBack()
  217. },
  218. showMore() {
  219. // 显示更多选项
  220. },
  221. onShare() {
  222. // 分享功能
  223. },
  224. viewAddress() {
  225. // 查看完整地址
  226. },
  227. viewReport() {
  228. if(this.currentStatus.text.includes("已结款") ){
  229. // 查看质检报告
  230. uni.navigateTo({
  231. url: '/pages/component/inspection?status=qualified'
  232. })
  233. }else {
  234. // 查看质检报告
  235. uni.navigateTo({
  236. url: '/pages/component/inspection?status=unqualified'
  237. })
  238. }
  239. },
  240. editOrder() {
  241. // 修改订单
  242. },
  243. // 更新订单状态
  244. updateOrderStatus(status) {
  245. switch(status) {
  246. case 'cancelled':
  247. this.currentStep = 0
  248. this.currentStatus = {
  249. text: '已取消',
  250. time: '',
  251. icon: '/static/my/【待取件】快递员正在赶来.png'
  252. }
  253. this.showEditButton = false
  254. break
  255. case 'processing':
  256. this.currentStep = 2
  257. this.currentStatus = {
  258. text: '【待取件】快递员正在赶来',
  259. time: '2025-04-20 11:00~13:00',
  260. icon: '/static/my/【待取件】快递员正在赶来.png'
  261. }
  262. break
  263. case 'collected':
  264. this.currentStep = 2
  265. this.currentStatus = {
  266. text: '【已取件】快递员正在送至质检',
  267. time: '2025-04-30 11:42',
  268. icon: '/static/my/【上门中】快递员正在赶来.png'
  269. }
  270. this.showEditButton = false
  271. break
  272. case 'inspecting':
  273. this.currentStep = 3
  274. this.currentStatus = {
  275. text: '【质检中】质检员正在质检',
  276. time: '2025-04-20 11:00',
  277. icon: '/static/my/逐件验-配图.png'
  278. }
  279. this.showEditButton = false
  280. break
  281. case 'pending_payment':
  282. this.currentStep = 4
  283. this.currentStatus = {
  284. text: '【待结款】待平台确认结款项',
  285. time: '2025-04-20 12:00',
  286. icon: '/static/my/【已结款】平台已结款至账户.png'
  287. }
  288. this.hasReport = true
  289. this.reportTime = '2025-03-20 11:40'
  290. this.showEditButton = false
  291. break
  292. case 'completed':
  293. this.currentStep = 4
  294. this.currentStatus = {
  295. text: '【已结款】平台已结款至账户',
  296. time: '2025-04-20 12:01',
  297. icon: '/static/my/【已结款】平台已结款至账户.png'
  298. }
  299. this.hasReport = true
  300. this.reportTime = '2025-03-20 11:40'
  301. this.showEditButton = false
  302. break
  303. }
  304. },
  305. copyExpressNo() {
  306. uni.setClipboardData({
  307. data: this.expressCompany + this.expressNo,
  308. success: () => {
  309. uni.showToast({ title: '已复制', icon: 'none' });
  310. }
  311. });
  312. },
  313. confirmCancelOrder() {
  314. this.showCancelModal = false;
  315. // 模拟取消动作
  316. this.currentStep = 0;
  317. this.currentStatus = {
  318. text: '已取消',
  319. time: this.getNowTime(),
  320. icon: '/static/【待取件】快递员正在赶来.png'
  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.price || ''
  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.phone || ''
  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. .goods-desc {
  737. font-size: 24rpx;
  738. color: #bcbcbc;
  739. margin-bottom: 10rpx;
  740. }
  741. .goods-meta {
  742. display: flex;
  743. align-items: center;
  744. gap: 10rpx;
  745. }
  746. .goods-price {
  747. color: #ff9c00;
  748. font-size: 26rpx;
  749. font-weight: bold;
  750. }
  751. .goods-unit {
  752. color: #bcbcbc;
  753. font-size: 22rpx;
  754. font-weight: normal;
  755. }
  756. .goods-count {
  757. color: #bcbcbc;
  758. font-size: 24rpx;
  759. margin-left: 8rpx;
  760. }
  761. .goods-total {
  762. color: #222;
  763. font-size: 30rpx;
  764. font-weight: bold;
  765. margin-left: 18rpx;
  766. flex-shrink: 0;
  767. }
  768. .bottom-btns {
  769. position: fixed;
  770. left: 0;
  771. right: 0;
  772. bottom: 30rpx;
  773. z-index: 10;
  774. background: #fff;
  775. display: flex;
  776. justify-content: space-between;
  777. align-items: center;
  778. padding: 24rpx 24rpx calc(env(safe-area-inset-bottom) + 12rpx) 24rpx;
  779. box-shadow: 0 -2rpx 8rpx rgba(255, 156, 0, 0.04);
  780. border-radius: 24rpx 24rpx 0 0;
  781. gap: 24rpx;
  782. }
  783. .btn {
  784. flex: 1;
  785. height: 78rpx;
  786. font-size: 32rpx;
  787. font-weight: bold;
  788. border-radius: 44rpx;
  789. margin: 0;
  790. padding: 0;
  791. }
  792. .cancel-btn {
  793. color: #ff9c00;
  794. background: #fff0d2;
  795. border: 2rpx solid #ffd01e;
  796. }
  797. .contact-btn {
  798. color: #fff;
  799. background: linear-gradient(90deg, #ffd01e 0%, #ff8917 100%);
  800. border: none;
  801. }
  802. .express-info {
  803. // border: 1rpx solid #ffdca8;
  804. border-radius: 12rpx;
  805. // padding: 18rpx 20rpx 10rpx 20rpx;
  806. margin-bottom: 12rpx;
  807. margin-top: 8rpx;
  808. background: #fff;
  809. position: relative;
  810. }
  811. .express-label {
  812. color: #bcbcbc;
  813. font-size: 24rpx;
  814. margin-bottom: 8rpx;
  815. display: block;
  816. }
  817. .express-row {
  818. display: flex;
  819. justify-content: space-between;
  820. align-items: center;
  821. }
  822. .express-value {
  823. color: #222;
  824. font-size: 28rpx;
  825. font-weight: 500;
  826. word-break: break-all;
  827. }
  828. .express-copy {
  829. color: #ff9c00;
  830. font-size: 26rpx;
  831. font-weight: 500;
  832. margin-left: 16rpx;
  833. }
  834. .modal-mask {
  835. position: fixed;
  836. left: 0; right: 0; top: 0; bottom: 0;
  837. background: rgba(0,0,0,0.35);
  838. z-index: 999;
  839. display: flex;
  840. align-items: center;
  841. justify-content: center;
  842. }
  843. .modal-box {
  844. width: 560rpx;
  845. background: #fff;
  846. border-radius: 32rpx;
  847. box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.08);
  848. padding: 56rpx 0 0 0;
  849. display: flex;
  850. flex-direction: column;
  851. align-items: center;
  852. }
  853. .modal-title {
  854. font-size: 36rpx;
  855. font-weight: bold;
  856. color: #222;
  857. text-align: center;
  858. margin-bottom: 18rpx;
  859. }
  860. .modal-content {
  861. font-size: 28rpx;
  862. color: #222;
  863. text-align: center;
  864. margin-bottom: 48rpx;
  865. }
  866. .modal-actions {
  867. width: 100%;
  868. display: flex;
  869. border-top: 1rpx solid #f0f0f0;
  870. height: 100rpx;
  871. }
  872. .modal-btn {
  873. flex: 1;
  874. border: none;
  875. outline: none;
  876. background: none;
  877. font-size: 32rpx;
  878. font-weight: 500;
  879. border-radius: 0 0 0 32rpx;
  880. height: 100rpx;
  881. line-height: 100rpx;
  882. }
  883. .modal-cancel {
  884. color: #999;
  885. background: #fff;
  886. border-bottom-left-radius: 32rpx;
  887. }
  888. .modal-confirm {
  889. color: #ff9c00;
  890. background: #fff;
  891. border-bottom-right-radius: 32rpx;
  892. }
  893. .cancel-tip {
  894. color: #bcbcbc;
  895. font-size: 26rpx;
  896. text-align: center;
  897. margin: 24rpx 0 0 0;
  898. }
  899. .info-divider {
  900. width: 100%;
  901. height: 1rpx;
  902. background: #f0f0f0;
  903. margin: 0;
  904. }
  905. .report-btn {
  906. width: 100%;
  907. margin: 24rpx 0 0 0;
  908. padding: 0;
  909. height: 80rpx;
  910. line-height: 80rpx;
  911. text-align: center;
  912. color: #ff9c00;
  913. background: #fff;
  914. border: 2rpx solid #ffd01e;
  915. border-radius: 44rpx;
  916. font-size: 28rpx;
  917. font-weight: bold;
  918. }
  919. .detail-info-card {
  920. margin-bottom: 48rpx;
  921. }
  922. .content {
  923. margin-top: calc(150rpx + var(--status-bar-height));
  924. }
  925. </style>