|
|
- <template>
- <view class="container">
- <!-- 顶部导航 -->
- <view class="nav-bar" :style="{height: (statusBarHeight + 88) + 'rpx', paddingTop: statusBarHeight + 'px'}">
- <view class="back" @tap="goBack">
- <uni-icons type="left" size="20"></uni-icons>
- </view>
- <text class="title">{{ orderId }}</text>
- </view>
-
- <!-- 内容区域 -->
- <view class="content">
- <!-- 回收流程卡片 -->
- <view class="card process-card">
- <view class="card-title">回收流程</view>
- <view class="process-steps">
- <view
- v-for="(step, index) in processSteps"
- :key="index"
- class="step-item"
- :class="{ cancel: currentStep === 0 && index === 1 }"
- >
- <image :src="step.icon" mode="aspectFit" class="step-icon"></image>
- <view
- class="step-label"
- :class="{
- active: currentStep === index + 1,
- cancel: currentStep === 0 && index === 1
- }"
- >
- <view class="step-label-inner">
- <text class="step-num">{{ ['①','②','③','④'][index] }}</text>
- <text class="step-text">{{ step.text }}</text>
- </view>
- </view>
- </view>
- </view>
- <view class="process-divider"></view>
-
- <!-- 状态信息 -->
- <view class="status-info" v-if="currentStatus">
- <image class="status-icon" :src="currentStatus.icon" mode="aspectFit"></image>
- <view class="status-detail">
- <text class="status-text" v-if="currentStep === 0">已取消本次预约</text>
- <text class="status-text" v-else>{{ currentStatus.text }}</text>
- <text class="status-time">{{ currentStatus.time }}</text>
- </view>
- </view>
-
- <!-- 取消后提示语 -->
- <view v-if="currentStep === 0" class="cancel-tip">期待您下次的支持,共同为地球减少碳排放出一份力!</view>
- <!-- 物流公司,仅currentStep为1、2时显示 -->
- <view class="express-info" v-if="currentStep !== 0 && currentStep < 3">
- <text class="express-label">物流公司</text>
- <view class="express-row">
- <text class="express-value">{{ expressCompany }}{{ expressNo }}</text>
- <text class="express-copy" @tap="copyExpressNo">复制</text>
- </view>
- </view>
- <view class="info-divider" v-if="currentStep !== 0 && currentStep < 4"></view>
- <!-- 地址信息,仅非取消和非结款时显示 -->
- <view class="pickup-info" v-if="currentStep !== 0 && currentStep < 4">
- <view class="info-item" @tap="viewAddress">
- <text class="label">取件地址</text>
- <view class="value">
- <text class="text">{{ address }}</text>
- <!-- <text class="arrow">></text> -->
- </view>
- </view>
- <view class="info-item">
- <text class="label">{{ timeLabel }}</text>
- <view class="value">
- <text class="text">{{ appointmentTime }}</text>
- <!-- <text class="arrow">></text> -->
- </view>
- </view>
- </view>
-
- </view>
-
- <!-- 订单详情卡片 -->
- <view class="order-detail-card">
- <text class="order-title">订单详情</text>
- <view class="order-row">
- <text class="order-label">订单编号</text>
- <text class="order-value">{{ orderId }}</text>
- </view>
- <view class="order-divider"></view>
- <template v-if="currentStep < 3">
- <view class="order-row">
- <text class="order-label">预估回收</text>
- <text class="order-value order-highlight">¥ {{ estimatePrice }}</text>
- </view>
- </template>
- <template v-else-if="currentStep === 4">
- <view class="order-row">
- <text class="order-label">合格结算</text>
- <text class="order-value order-highlight">¥ {{ finalPrice }}</text>
- </view>
- <view class="order-row">
- <text class="order-label">运费扣除</text>
- <text class="order-value">¥ 0</text>
- </view>
- <view class="order-row">
- <text class="order-label">结算金额</text>
- <text class="order-value order-highlight">¥ {{ finalPrice }}</text>
- </view>
- </template>
- <view class="order-divider"></view>
- <view class="goods-list">
- <view class="goods-item" v-for="(item, index) in clothesList" :key="index">
- <image class="goods-img" :src="item.image" mode="aspectFit"></image>
- <view class="goods-info">
- <text class="goods-name">{{ item.name }}</text>
- <text class="goods-desc">{{ item.description }}</text>
- <view class="goods-meta">
- <text class="goods-price">¥ {{ item.price }}<text class="goods-unit"> /件</text></text>
- <text class="goods-count">x{{ item.count }}</text>
- </view>
- </view>
- <text class="goods-total">¥{{ item.total }}</text>
- </view>
- </view>
- </view>
-
- <!-- 质检结果卡片,仅结款状态显示 -->
- <view class="order-detail-card" v-if="currentStep === 4">
- <text class="order-title">质检结果</text>
- <view class="order-row"><text class="order-label">质检数量</text><text class="order-value">9 件</text></view>
- <view class="order-row"><text class="order-label">质检合格</text><text class="order-value">7 件</text></view>
- <view class="order-row"><text class="order-label">质量问题</text><text class="order-value">2 件</text></view>
- <view class="order-row"><text class="order-label">不可回收</text><text class="order-value">0 件</text></view>
- <view class="order-row"><text class="order-label">订单重量</text><text class="order-value">2.85 kg</text></view>
- <view class="order-divider"></view>
- <view class="report-btn" @tap="viewReport">点此查看质检报告详情</view>
- </view>
-
- <!-- 详细信息卡片,仅结款状态显示 -->
- <view class="order-detail-card detail-info-card" v-if="currentStep === 4">
- <text class="order-title">详细信息</text>
- <view class="order-row">
- <text class="order-label">预约时间</text>
- <text class="order-value">2025-03-20 11:00~12:00</text>
- </view>
- <view class="order-row">
- <text class="order-label">取件地址</text>
- <text class="order-value">{{ address }}</text>
- </view>
- </view>
- </view>
-
- <!-- 底部按钮,仅待取件时显示 -->
- <view class="bottom-btns" v-if="currentStatus.text === '【待取件】快递员正在赶来'">
- <button class="btn cancel-btn" @tap="showCancelModal = true">取消订单</button>
- <button class="btn contact-btn" @tap="contactCourier">联系快递员</button>
- </view>
-
- <!-- 取消订单弹窗 -->
- <view v-if="showCancelModal" class="modal-mask">
- <view class="modal-box">
- <view class="modal-title">取消订单</view>
- <view class="modal-content">确认要取消订单吗</view>
- <view class="modal-actions">
- <button class="modal-btn modal-cancel" @tap="showCancelModal = false">取消</button>
- <button class="modal-btn modal-confirm" @tap="confirmCancelOrder">确认</button>
- </view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- import pullRefreshMixin from '@/pages/mixins/pullRefreshMixin.js'
-
- export default {
- mixins: [pullRefreshMixin],
- data() {
- return {
- orderId: 'RE82738127861525',
- currentStep: 2, // 当前进行到第几步
- processSteps: [
- { text: '在线预约', icon: '/static/home/① 在线预约.png' },
- { text: '快递上门', icon: '/static/home/② 快递上门.png' },
- { text: '透明质检', icon: '/static/home/③ 透明质检.png' },
- { text: '现金打款', icon: '/static/home/④ 现金打款.png' }
- ],
- address: '海南省海口市秀英区秀英街道5单元',
- appointmentTime: '周四 11:00~13:00',
- estimatePrice: '73.6-75.8',
- finalPrice: '73.6',
- clothesList: [
- {
- name: '羽绒服',
- description: '允许脏破烂,160码以上',
- price: 8,
- count: 8,
- total: 64,
- image: '/static/home/羽绒服.png'
- },
- {
- name: '品牌羽绒服',
- description: '允许脏破烂,160码以上',
- price: 10,
- count: 1,
- total: 10,
- image: '/static/home/品牌羽绒服.png'
- }
- ],
- currentStatus: {
- text: '【待取件】快递员正在赶来',
- time: '2025-04-20 11:00~13:00',
- icon: '/static/delivery-person.png'
- },
- hasReport: false,
- reportTime: '',
- showEditButton: true,
- expressCompany: '德邦物流',
- expressNo: 'DPK202534653715',
- showCancelModal: false,
- statusBarHeight: 0,
- }
- },
- computed: {
- timeLabel() {
- // 根据状态返回不同的时间标签
- if (this.currentStep === 4) {
- return '回收到账时间'
- } else if (this.currentStep === 3) {
- return '质检完成时间'
- } else {
- return '上门时间'
- }
- },
- showEstimate() {
- return this.currentStep < 3
- }
- },
- methods: {
- async onRefresh() {
- // 模拟刷新数据
- await new Promise(resolve => setTimeout(resolve, 1000))
- this.stopPullRefresh()
- },
- goBack() {
- uni.navigateBack()
- },
- showMore() {
- // 显示更多选项
- },
- onShare() {
- // 分享功能
- },
- viewAddress() {
- // 查看完整地址
- },
- viewReport() {
- if(this.currentStatus.text.includes("已结款") ){
- // 查看质检报告
- uni.navigateTo({
- url: '/pages/component/inspection?status=qualified'
- })
- }else {
- // 查看质检报告
- uni.navigateTo({
- url: '/pages/component/inspection?status=unqualified'
- })
- }
-
- },
- editOrder() {
- // 修改订单
- },
- // 更新订单状态
- updateOrderStatus(status) {
- switch(status) {
- case 'cancelled':
- this.currentStep = 0
- this.currentStatus = {
- text: '已取消',
- time: '',
- icon: '/static/cancelled.png'
- }
- this.showEditButton = false
- break
- case 'processing':
- this.currentStep = 2
- this.currentStatus = {
- text: '【待取件】快递员正在赶来',
- time: '2025-04-20 11:00~13:00',
- icon: '/static/delivery-person.png'
- }
- break
- case 'collected':
- this.currentStep = 2
- this.currentStatus = {
- text: '【已取件】快递员正在送至质检',
- time: '2025-04-30 11:42',
- icon: '/static/collected-truck.png'
- }
- this.showEditButton = false
- break
- case 'inspecting':
- this.currentStep = 3
- this.currentStatus = {
- text: '【质检中】质检员正在质检',
- time: '2025-04-20 11:00',
- icon: '/static/inspector.png'
- }
- this.showEditButton = false
- break
- case 'pending_payment':
- this.currentStep = 4
- this.currentStatus = {
- text: '【待结款】待平台确认结款项',
- time: '2025-04-20 12:00',
- icon: '/static/payment.png'
- }
- this.hasReport = true
- this.reportTime = '2025-03-20 11:40'
- this.showEditButton = false
- break
- case 'completed':
- this.currentStep = 4
- this.currentStatus = {
- text: '【已结款】平台已结款至账户',
- time: '2025-04-20 12:01',
- icon: '/static/completed.png'
- }
- this.hasReport = true
- this.reportTime = '2025-03-20 11:40'
- this.showEditButton = false
- break
- }
- },
- copyExpressNo() {
- uni.setClipboardData({
- data: this.expressCompany + this.expressNo,
- success: () => {
- uni.showToast({ title: '已复制', icon: 'none' });
- }
- });
- },
- confirmCancelOrder() {
- this.showCancelModal = false;
- // 模拟取消动作
- this.currentStep = 0;
- this.currentStatus = {
- text: '已取消',
- time: this.getNowTime(),
- icon: '/static/cancelled.png'
- };
- // uni.showToast({ title: '订单已取消', icon: 'none' });
- },
- getNowTime() {
- const now = new Date();
- const y = now.getFullYear();
- const m = (now.getMonth() + 1).toString().padStart(2, '0');
- const d = now.getDate().toString().padStart(2, '0');
- const h = now.getHours().toString().padStart(2, '0');
- const min = now.getMinutes().toString().padStart(2, '0');
- return `${y}-${m}-${d} ${h}:${min}`;
- },
- contactCourier() {
- // 联系快递员逻辑
- uni.showToast({ title: '已联系快递员', icon: 'none' });
- }
- },
- onLoad(options) {
- // 接收上一页传来的订单状态
- if (options.status) {
- this.updateOrderStatus(options.status)
- }
- this.orderId = options.id
- this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
- }
- }
- </script>
-
- <style scoped lang="scss">
- .container {
- min-height: 100vh;
- background: #f4f4f4;
- padding-bottom: 120rpx;
- }
- .card {
- background: linear-gradient(180deg, #fffbe6 0%, #fff 90%);
- border-radius: 28rpx;
- margin: 24rpx 24rpx 0 24rpx;
- box-shadow: 0 8rpx 24rpx rgba(255, 156, 0, 0.03);
- padding: 40rpx 32rpx;
- }
- .nav-bar {
- display: flex;
- align-items: center;
- height: 88rpx;
- background: #fff;
- padding: 0 30rpx;
-
- .back {
- padding: 20rpx;
- margin-left: -20rpx;
- }
-
- .title {
- flex: 1;
- text-align: center;
- font-size: 34rpx;
- font-weight: 500;
- }
-
- .right-btns {
- display: flex;
- align-items: center;
- gap: 30rpx;
-
- .more, .target {
- font-size: 40rpx;
- color: #333;
- }
- }
- }
- .card-title, .card-header .title {
- font-size: 32rpx;
- font-weight: bold;
- color: #222;
- margin-bottom: 24rpx;
- }
- .process-card {
- background: linear-gradient(180deg, #fffbe6 0%, #fff 35%);
- border-radius: 32rpx;
- box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.04);
- padding: 40rpx 32rpx 32rpx 32rpx;
- margin: 24rpx;
- }
- .card-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #222;
- margin-bottom: 24rpx;
- text-align: left;
- }
- .process-steps {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- margin-bottom: 12rpx;
- gap: 18rpx;
- }
- .step-item {
- width: 150%;
- height: 150rpx;
- background: #fff8ea;
- border-radius: 20rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- box-shadow: 0 2rpx 8rpx rgba(255, 156, 0, 0.04);
- overflow: hidden;
- position: relative;
- }
- .step-item.cancel {
- background: linear-gradient(180deg, #fff0f3 0%, #ffd6df 100%) !important;
- }
- .step-icon {
- width: 86rpx;
- height: 86rpx;
- margin: 16rpx 0 0 0;
- flex-shrink: 0;
- }
- .step-label {
- width: 100%;
- height: 44rpx;
- background: transparent;
- position: absolute;
- left: 0;
- bottom: 0;
- border-radius: 0 0 16rpx 16rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: background 0.2s;
- overflow: hidden;
- }
- .step-label.active {
- background: linear-gradient(90deg, #ffd01e 0%, #ff8917 100%);
- }
- .step-label.cancel {
- background: linear-gradient(to right, #ff8e8e 0%, #ff5e5e 100%) !important;
- }
- .step-label.cancel .step-num,
- .step-label.cancel .step-text {
- color: #fff !important;
- }
- .step-label-inner {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: row;
- // align-items: center;
- justify-content: center;
- white-space: nowrap;
- }
- .step-num,
- .step-text {
- font-family: PingFang SC;
- font-weight: 400;
- font-size: 11px;
- letter-spacing: 0%;
- line-height: 48rpx;
- margin: 0;
- padding: 0;
- color: #9b9b9b;
- }
- .step-num {
- margin-right: 6rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .step-label.active .step-num,
- .step-label.active .step-text {
- font-family: PingFang SC;
- font-weight: 500;
- font-size: 11px;
- letter-spacing: 0%;
- color: #fff;
- }
- .process-divider {
- width: 100%;
- height: 0;
- border-bottom: 1rpx dashed #e6e6e6;
- margin: 20rpx 0 0 0;
- }
- .status-info {
- display: flex;
- align-items: center;
- margin: 24rpx 0;
- background: #fafafa;
- border-radius: 16rpx;
- padding: 16rpx;
- }
- .status-icon {
- width: 60rpx;
- height: 60rpx;
- margin-right: 16rpx;
- }
- .status-text {
- font-size: 28rpx;
- color: #222;
- font-weight: bold;
- }
- .status-time {
- font-size: 24rpx;
- color: #999;
- margin-top: 4rpx;
- }
- .pickup-info .info-item {
- display: flex;
- // justify-content: space-between;
- flex-direction: column;
- // align-items: center;
- padding: 18rpx 0;
- border-bottom: 1px solid #f0f0f0;
- margin: 20rpx 0 20rpx 0;
- }
- .pickup-info .info-item:last-child {
- border-bottom: none;
- }
- .label {
- color: #999;
- font-size: 26rpx;
- }
- .value {
- color: #222;
- font-size: 26rpx;
- display: flex;
- align-items: center;
- }
- .value .arrow {
- color: #bbb;
- margin-left: 8rpx;
- }
- .order-detail-card {
- background: linear-gradient(to bottom, #fff6e3 0%, #fff 20%);
- border-radius: 36rpx;
- box-shadow: 0 8rpx 32rpx rgba(255, 156, 0, 0.08);
- padding: 40rpx 36rpx 32rpx 36rpx;
- margin: 24rpx;
- margin-bottom: 164rpx;
- }
- .order-title {
- font-size: 36rpx;
- font-weight: bold;
- color: #222;
- margin-bottom: 32rpx;
- text-align: left;
- display: block;
- }
- .order-row {
- display: flex;
- // justify-content: space-between;
- align-items: center;
- margin-bottom: 18rpx;
- }
- .order-label {
- color: #bcbcbc;
- font-size: 26rpx;
- margin: 20rpx 0 20rpx 0;
- }
- .order-value {
- color: #222;
- font-size: 28rpx;
- margin-left: 30rpx;
- font-weight: 500;
- }
- .order-highlight {
- color: #ff9c00;
- font-size: 30rpx;
- font-weight: bold;
- }
- .order-divider {
- width: 100%;
- height: 1rpx;
- background: #f0f0f0;
- margin: 18rpx 0;
- }
- .goods-list {
- margin-top: 10rpx;
- display: flex;
- flex-direction: column;
- gap: 18rpx;
- }
- .goods-item {
- background: #fff;
- border-radius: 24rpx;
- display: flex;
- align-items: center;
- padding: 24rpx 20rpx;
- box-shadow: 0 2rpx 8rpx rgba(255, 156, 0, 0.04);
- position: relative;
- }
- .goods-img {
- width: 90rpx;
- height: 90rpx;
- border-radius: 18rpx;
- margin-right: 20rpx;
- // background: #fffbe6;
- flex-shrink: 0;
- }
- .goods-info {
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
- .goods-name {
- font-size: 30rpx;
- color: #222;
- font-weight: bold;
- margin-bottom: 6rpx;
- }
- .goods-desc {
- font-size: 24rpx;
- color: #bcbcbc;
- margin-bottom: 10rpx;
- }
- .goods-meta {
- display: flex;
- align-items: center;
- gap: 10rpx;
- }
- .goods-price {
- color: #ff9c00;
- font-size: 26rpx;
- font-weight: bold;
- }
- .goods-unit {
- color: #bcbcbc;
- font-size: 22rpx;
- font-weight: normal;
- }
- .goods-count {
- color: #bcbcbc;
- font-size: 24rpx;
- margin-left: 8rpx;
- }
- .goods-total {
- color: #222;
- font-size: 30rpx;
- font-weight: bold;
- margin-left: 18rpx;
- flex-shrink: 0;
- }
- .bottom-btns {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 30rpx;
- z-index: 10;
- background: #fff;
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 24rpx 24rpx calc(env(safe-area-inset-bottom) + 12rpx) 24rpx;
- box-shadow: 0 -2rpx 8rpx rgba(255, 156, 0, 0.04);
- border-radius: 24rpx 24rpx 0 0;
- gap: 24rpx;
- }
- .btn {
- flex: 1;
- height: 78rpx;
- font-size: 32rpx;
- font-weight: bold;
- border-radius: 44rpx;
- margin: 0;
- padding: 0;
- }
- .cancel-btn {
- color: #ff9c00;
- background: #fff0d2;
- border: 2rpx solid #ffd01e;
- }
- .contact-btn {
- color: #fff;
- background: linear-gradient(90deg, #ffd01e 0%, #ff8917 100%);
- border: none;
- }
- .express-info {
- // border: 1rpx solid #ffdca8;
- border-radius: 12rpx;
- // padding: 18rpx 20rpx 10rpx 20rpx;
- margin-bottom: 12rpx;
- margin-top: 8rpx;
- background: #fff;
- position: relative;
- }
- .express-label {
- color: #bcbcbc;
- font-size: 24rpx;
- margin-bottom: 8rpx;
- display: block;
- }
- .express-row {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .express-value {
- color: #222;
- font-size: 28rpx;
- font-weight: 500;
- word-break: break-all;
- }
- .express-copy {
- color: #ff9c00;
- font-size: 26rpx;
- font-weight: 500;
- margin-left: 16rpx;
- }
- .modal-mask {
- position: fixed;
- left: 0; right: 0; top: 0; bottom: 0;
- background: rgba(0,0,0,0.35);
- z-index: 999;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .modal-box {
- width: 560rpx;
- background: #fff;
- border-radius: 32rpx;
- box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.08);
- padding: 56rpx 0 0 0;
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .modal-title {
- font-size: 36rpx;
- font-weight: bold;
- color: #222;
- text-align: center;
- margin-bottom: 18rpx;
- }
- .modal-content {
- font-size: 28rpx;
- color: #222;
- text-align: center;
- margin-bottom: 48rpx;
- }
- .modal-actions {
- width: 100%;
- display: flex;
- border-top: 1rpx solid #f0f0f0;
- height: 100rpx;
- }
- .modal-btn {
- flex: 1;
- border: none;
- outline: none;
- background: none;
- font-size: 32rpx;
- font-weight: 500;
- border-radius: 0 0 0 32rpx;
- height: 100rpx;
- line-height: 100rpx;
- }
- .modal-cancel {
- color: #999;
- background: #fff;
- border-bottom-left-radius: 32rpx;
- }
- .modal-confirm {
- color: #ff9c00;
- background: #fff;
- border-bottom-right-radius: 32rpx;
- }
- .cancel-tip {
- color: #bcbcbc;
- font-size: 26rpx;
- text-align: center;
- margin: 24rpx 0 0 0;
- }
- .info-divider {
- width: 100%;
- height: 1rpx;
- background: #f0f0f0;
- margin: 0;
- }
- .report-btn {
- width: 100%;
- margin: 24rpx 0 0 0;
- padding: 0;
- height: 80rpx;
- line-height: 80rpx;
- text-align: center;
- color: #ff9c00;
- background: #fff;
- border: 2rpx solid #ffd01e;
- border-radius: 44rpx;
- font-size: 28rpx;
- font-weight: bold;
- }
- .detail-info-card {
- margin-bottom: 48rpx;
- }
- </style>
|