From aef22e4a0cf0287d011ab27f04b0f9ee1be0d729 Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期二, 28 四月 2026 21:25:51 +0800
Subject: [PATCH] Merge branch 'master' of http://139.186.142.91:10010/r/productDev/gtzxinglijicun
---
app/pages/index/index.vue | 1528 +++++++++++++++++++++++++++++----------------------------
1 files changed, 776 insertions(+), 752 deletions(-)
diff --git a/app/pages/index/index.vue b/app/pages/index/index.vue
index b9b40e1..d373554 100644
--- a/app/pages/index/index.vue
+++ b/app/pages/index/index.vue
@@ -1,35 +1,35 @@
<template>
<view class="hall-page">
<view class="hall-page__header" :style="{ paddingTop: statusBarHeight + 'px' }">
- <view class="hall-page__user-row">
+ <view class="hall-page__user-row" @click="handleUserClick">
<view class="hall-page__user">
- <image class="hall-page__avatar" src="/static/image/login_bg@2x.png" mode="aspectFill"></image>
- <text class="hall-page__name">姹ゅ瓙鏂�</text>
+ <image class="hall-page__avatar" :src="centerUserInfo.fullImgUrl || '/static/image/ic_pic@2x.png'" mode="aspectFill"></image>
+ <text class="hall-page__name">{{ centerUserInfo.name }}</text>
</view>
- <view class="hall-page__status">
- <view class="hall-page__status-dot"></view>
- <text class="hall-page__status-text">鎺ュ崟涓�</text>
+ <view class="hall-page__status" v-if="userInfo.auditStatus === 3" @click="openStatusPicker">
+ <view class="hall-page__status-dot" :class="{ 'hall-page__status-dot--offline': acceptingStatus === 0 }"></view>
+ <text class="hall-page__status-text">{{ acceptingStatus === 1 ? '鎺ュ崟涓�' : '宸蹭笅绾�' }}</text>
<text class="hall-page__status-arrow">鈻�</text>
</view>
<view class="hall-page__user" style="opacity: 0;">
- <image class="hall-page__avatar" src="/static/image/login_bg@2x.png" mode="aspectFill"></image>
- <text class="hall-page__name">姹ゅ瓙鏂�</text>
+ <image class="hall-page__avatar" :src="centerUserInfo.fullImgUrl || '/static/image/ic_pic@2x.png'" mode="aspectFill"></image>
+ <text class="hall-page__name">{{ centerUserInfo.name }}</text>
</view>
</view>
<view class="hall-page__stats">
<view v-for="item in stats" :key="item.label" class="hall-page__stat-item">
- <text class="hall-page__stat-value">{{ item.value }}</text>
+ <text class="hall-page__stat-value">{{ userInfo.auditStatus === 3 ? item.value : '-' }}</text>
<text class="hall-page__stat-label">{{ item.label }}</text>
</view>
</view>
<view class="hall-page__tabs">
- <view v-for="tab in tabs" :key="tab.value" class="hall-page__tab" :class="{ 'hall-page__tab--active': activeTab === tab.value }" @click="activeTab = tab.value">
+ <view v-for="tab in displayTabs" :key="tab.value" class="hall-page__tab" :class="{ 'hall-page__tab--active': activeTab === tab.value }" @click="activeTab = tab.value">
<text class="hall-page__tab-text">{{ tab.label }}</text>
- <text v-if="tab.count" class="hall-page__tab-count">{{ tab.count }}</text>
+ <text v-if="tab.count" class="hall-page__tab-count">{{ userInfo.auditStatus === 3 ? tab.count : '' }}</text>
<view v-if="activeTab === tab.value" class="hall-page__tab-line"></view>
- </view>
+ </view>
<view class="hall-page__filter" @click="toggleFilterPopup(true)">
<text class="hall-page__filter-text" :class="{ 'hall-page__filter-text--active': showFilterPopup }">绛涢��</text>
<image :src="showFilterPopup ? '/static/image/ic_shaixuan_sel@2x.png' : '/static/image/ic_shaixuan@2x.png'" mode="widthFix" class="hall-page__filter-icon"></image>
@@ -39,20 +39,22 @@
<view v-if="showFilterPopup" class="filter-popup" :style="{ top: headerHeight + 'px', bottom: tabbarHeight + 'px' }" @click="toggleFilterPopup(false)">
<view class="filter-popup__panel" @click.stop>
- <view v-for="section in filterSections" :key="section.key" class="filter-popup__section">
- <text class="filter-popup__title">{{ section.title }}</text>
- <view class="filter-popup__options">
- <view
- v-for="option in section.options"
- :key="option"
- class="filter-popup__option"
- :class="{ 'filter-popup__option--active': selectedFilters[section.key] === option }"
- @click="selectFilter(section.key, option)"
- >
- <text class="filter-popup__option-text">{{ option }}</text>
+ <scroll-view class="filter-popup__content" scroll-y>
+ <view v-for="section in filterSections" :key="section.key" class="filter-popup__section">
+ <text class="filter-popup__title">{{ section.title }}</text>
+ <view class="filter-popup__options">
+ <view
+ v-for="option in section.options"
+ :key="option"
+ class="filter-popup__option"
+ :class="{ 'filter-popup__option--active': selectedFilters[section.key] === option }"
+ @click="selectFilter(section.key, option)"
+ >
+ <text class="filter-popup__option-text">{{ option }}</text>
+ </view>
</view>
</view>
- </view>
+ </scroll-view>
<view class="filter-popup__actions">
<button class="filter-popup__button filter-popup__button--reset" hover-class="filter-popup__button--hover" @click="resetFilters">閲嶇疆</button>
@@ -62,96 +64,106 @@
</view>
<scroll-view class="hall-page__body" scroll-y :style="bodyStyle">
- <view v-if="currentOrderList.length" class="hall-page__list">
- <view v-for="item in currentOrderList" :key="item.id" class="order-card" @click="openDetailPopup(item)">
+ <view class="hall-page__verified" v-if="userInfo.auditStatus !== 3">
+ <image src="/static/image/default_unverified@2x.png" mode="widthFix"></image>
+ <button @click="toDriverCertification">鍘昏璇�</button>
+ </view>
+ <view v-else-if="userInfo.auditStatus === 3 && acceptingStatus === 1 && currentOrderList.length" class="hall-page__list">
+ <view v-for="(item, index) in currentOrderList" :key="item.id" class="order-card" @click="goToOrderDetail(item, index)">
<view class="order-card__head">
- <view class="order-card__time">
- <text class="order-card__time-main">{{ item.time }}</text>
+ <view class="order-card__time" v-if="item.remainMinutes > 0">
+ <text class="order-card__time-main">{{ formatRemainTime(item.remainMinutes) }}</text>
<text class="order-card__time-sub">閫佽揪</text>
</view>
+ <view class="order-card__time" v-else>
+ <text class="order-card__time-main">閰嶉�佸凡瓒呮椂锛岃灏藉揩閫佽揪</text>
+ </view>
<view v-if="activeTab === 'hall'" class="order-card__price-wrap">
- <text v-if="item.serialNo" class="order-card__serial">#{{ item.serialNo }}</text>
- <text class="order-card__price">{{ item.price }}</text>
+ <text class="order-card__price">楼{{ item.platformRewardAmount ? (item.driverFee + item.platformRewardAmount) / 100 : (item.driverFee / 100).toFixed(2) }}</text>
</view>
<view v-else class="order-card__price-wrap order-card__price-wrap--serial-only">
- <text v-if="item.serialNo" class="order-card__serial">#{{ item.serialNo }}</text>
+ <text v-if="item.code" class="order-card__serial">#{{ index + 1 }}</text>
</view>
</view>
<view class="order-card__meta">
<view class="order-card__tags">
- <view v-for="tag in item.tags" :key="tag.text" class="order-card__tag-wrap">
- <image
- v-if="getTagImage(tag.text)"
- class="order-card__tag-icon"
- :src="getTagImage(tag.text)"
- mode="widthFix"
- ></image>
- <text v-else class="order-card__tag" :class="tag.type ? 'order-card__tag--' + tag.type : ''">{{ tag.text }}</text>
- </view>
+ <image v-if="item.isUrgent === 1" class="order-card__tag-img" src="/static/image/ic_jisuda@2x.png" mode="widthFix"></image>
+ <image v-else class="order-card__tag-img" src="/static/image/ic_biaosuda@2x.png" mode="widthFix"></image>
+ <text v-if="item.isValuable === true" class="order-card__tag order-card__tag--orange">璐甸噸鐗╁搧</text>
+ <text v-else class="order-card__tag order-card__tag--blue">{{ item.goodLevelName }}</text>
</view>
- <text v-if="activeTab === 'hall'" class="order-card__extra">鍚姞鎬ヂ{ item.extra }}</text>
+ <text v-if="activeTab === 'hall' && item.platformRewardAmount" class="order-card__extra">鍚姞鎬ヂ{ (item.platformRewardAmount / 100).toFixed(2) }}</text>
</view>
<view class="order-card__route">
<view class="order-card__route-side">
- <text class="order-card__distance-top">{{ item.distanceTop }}</text>
+ <view class="order-card__distance-block order-card__distance-block--top">
+ <text class="order-card__distance-value">{{ formatDistanceParts(item.depositDistance).value }}</text>
+ <text class="order-card__distance-unit">{{ formatDistanceParts(item.depositDistance).unit }}</text>
+ </view>
<view class="order-card__line"></view>
- <text class="order-card__distance-bottom">{{ item.distanceBottom }}</text>
+ <view class="order-card__distance-block order-card__distance-block--bottom">
+ <text class="order-card__distance-value">{{ formatDistanceParts(item.takeDistance).value }}</text>
+ <text class="order-card__distance-unit">{{ formatDistanceParts(item.takeDistance).unit }}</text>
+ </view>
</view>
<view class="order-card__route-main">
<view class="order-card__route-item">
<view class="order-card__route-texts">
- <text class="order-card__route-title">{{ item.fromName }}</text>
- <text class="order-card__route-desc">{{ item.fromAddress }}</text>
+ <text class="order-card__route-title">{{ item.depositShopName }}澶ц嫃鎵撴墦绠�</text>
+ <text class="order-card__route-desc">{{ item.depositShopAddress }}</text>
</view>
- <image src="/static/image/ic_daohang@2x.png" mode="widthFix" class="order-card__nav"></image>
+ <image src="/static/image/ic_daohang@2x.png" mode="widthFix" class="order-card__nav" @click.stop="navigateToAddress(item, 'deposit')"></image>
</view>
<view class="order-card__route-item order-card__route-item--destination">
<view class="order-card__route-texts">
- <text class="order-card__route-title">{{ item.toName }}</text>
- <text class="order-card__route-desc">{{ item.toAddress }}</text>
+ <template v-if="item.takeShopId">
+ <text class="order-card__route-title">{{ item.takeName }}</text>
+ <text class="order-card__route-desc">{{ item.takeAddress }}</text>
+ </template>
+ <text v-else class="order-card__route-title">{{ item.takeAddress }}</text>
</view>
- <image src="/static/image/ic_daohang@2x.png" mode="widthFix" class="order-card__nav"></image>
+ <image src="/static/image/ic_daohang@2x.png" mode="widthFix" class="order-card__nav" @click.stop="navigateToAddress(item, 'take')"></image>
</view>
</view>
</view>
- <view class="order-card__goods">
- <text class="order-card__goods-text">{{ item.goods }}</text>
- <text class="order-card__goods-arrow">鈱�</text>
+ <view class="order-card__goods" v-if="item.items && item.items.length > 0" @click.stop="toggleGoodsExpand(item.id)">
+ <text class="order-card__goods-text">{{ getGoodsText(item.items, item.id) }}</text>
+ <u-icon v-if="getGoodsText(item.items, item.id).length > 20" name="arrow-down" :class="{ 'order-card__goods-arrow--expanded': expandedGoodsIds.includes(item.id) }" size="12" color="#a4a9b1"></u-icon>
</view>
<view class="order-card__actions" :class="'order-card__actions--' + activeTab">
<template v-if="activeTab === 'pickup'">
<view class="order-card__icon-actions">
- <view class="order-card__icon-action" @click.stop="show = true">
+ <view class="order-card__icon-action" @click.stop="handleCancelOrder(item)">
<image class="order-card__action-icon" src="/static/image/ic_cancle@2x.png" mode="aspectFit"></image>
<text class="order-card__action-text">鍙栨秷</text>
</view>
- <view class="order-card__icon-action" @click.stop>
+ <view class="order-card__icon-action" @click.stop="handleCall(item)">
<image class="order-card__action-icon" src="/static/image/ic_call@2x.png" mode="aspectFit"></image>
<text class="order-card__action-text">鑱旂郴</text>
</view>
</view>
- <button class="order-card__button order-card__button--code" hover-class="order-card__button--hover" @click.stop="show1 = true">鍙栬揣鐮�</button>
+ <button class="order-card__button order-card__button--code" hover-class="order-card__button--hover" @click.stop="handleShowPickupCode(item)">鍙栬揣鐮�</button>
</template>
<template v-else-if="activeTab === 'delivering'">
<view class="order-card__icon-actions order-card__icon-actions--single">
- <view class="order-card__icon-action" @click.stop>
+ <view class="order-card__icon-action" @click.stop="handleCall(item)">
<image class="order-card__action-icon" src="/static/image/ic_call@2x.png" mode="aspectFit"></image>
<text class="order-card__action-text">鑱旂郴</text>
</view>
</view>
- <button class="order-card__button order-card__button--code" hover-class="order-card__button--hover" @click.stop>瀛樹欢鐮�</button>
+ <button class="order-card__button order-card__button--code" hover-class="order-card__button--hover" @click.stop="handleShowPickupCode(item)">瀛樹欢鐮�</button>
</template>
- <button v-else class="order-card__button" hover-class="order-card__button--hover" @click.stop="openDetailPopup(item)">绔嬪嵆鎶㈠崟</button>
+ <button v-else class="order-card__button" hover-class="order-card__button--hover" @click.stop="handleGrabOrder(item)">绔嬪嵆鎶㈠崟</button>
</view>
</view>
</view>
<view v-else class="hall-page__empty">
- <image class="hall-page__empty-icon" src="/static/image/default_nodata_grey@2x.png" mode="aspectFit"></image>
+ <image class="hall-page__empty-icon" :src="acceptingStatus === 0 ? '/static/image/default_nodata_grey@2x.png' : '/static/image/default_nodata@2x.png'" mode="aspectFit"></image>
</view>
</scroll-view>
@@ -162,173 +174,124 @@
@cancel="show = false"
cancelColor="#666666"
confirmColor="#0055FF"
- title="鍙栨秷璁㈠崟纭">
+ title="鍙栨秷璁㈠崟纭"
+ @confirm="confirmCancelOrder">
<view style="text-align: center;color: #333333;font-size: 28rpx;font-weight: 400;">
- 鎮ㄤ粖鏃ヨ繕鍙彇娑� X 娆¤鍗曪紝娆℃暟鐢ㄥ敖鍚庝粖鏃ュ皢鏃犳硶鎺ュ崟锛屾槸鍚︾‘璁ゅ彇娑堬紵
+ 鎮ㄤ粖鏃ヨ繕鍙彇娑� {{ cancelRemain }} 娆¤鍗曪紝娆℃暟鐢ㄥ敖鍚庝粖鏃ュ皢鏃犳硶鎺ュ崟锛屾槸鍚︾‘璁ゅ彇娑堬紵
+ </view>
+ </u-modal>
+
+ <!-- 绔嬪嵆鎶㈠崟 -->
+ <u-modal
+ :show="showGrabModal"
+ showCancelButton
+ @cancel="showGrabModal = false"
+ cancelColor="#666666"
+ confirmColor="#0055FF"
+ title="娓╅Θ鎻愮ず"
+ @confirm="confirmGrabOrder">
+ <view style="text-align: center;color: #333333;font-size: 28rpx;font-weight: 400;">
+ {{ selectedGrabOrder && selectedGrabOrder.hasOversized === 1 ? '鏈鍗曟湁鐗瑰ぇ浠跺昂瀵歌鏉庯紝璇风‘璁ゆ槸鍚︾户缁姠鍗曪紵' : '鏄惁纭鎺ュ崟锛�' }}
</view>
</u-modal>
- <!-- 鍙栬揣鐮� -->
+ <!-- 鍙栬揣鐮�/瀛樹欢鐮� -->
<u-popup :show="show1" round="20" mode="bottom">
<view class="qrcode">
<view class="qrcode-title">
<image src="/static/image/ic_close@2x.png" mode="widthFix" style="opacity: 0;"></image>
- <text>鍙栬揣鐮�</text>
+ <text>{{ activeTab === 'delivering' ? '瀛樹欢鐮�' : '鍙栬揣鐮�' }}</text>
<image src="/static/image/ic_close@2x.png" mode="widthFix" @click="show1 = false"></image>
</view>
<view class="qrcode-image">
- <image src="/static/logo.png" mode="widthFix"></image>
+ <image v-if="selectedPickupOrder && selectedPickupOrder.driverVerifyCode" :src="'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=' + selectedPickupOrder.driverVerifyCode" mode="widthFix"></image>
</view>
<view class="qrcode-btn" hover-class="qrcode-btn--hover" @click="show1 = false">鍏抽棴</view>
</view>
</u-popup>
- <!-- 璁㈠崟璇︽儏 -->
- <u-popup :show="showOrderDetail" round="20" mode="bottom" :overlayStyle="{ background: 'rgba(0, 0, 0, 0.32)' }" @close="showOrderDetail = false">
- <view class="order-detail" :style="{ height: 'calc(100vh - ' + statusBarHeight + 'px)' }">
- <scroll-view class="order-detail__scroll" scroll-y>
- <view v-if="isStatusDetail" class="order-detail__map-section">
- <view class="order-detail__map">
- <image class="order-detail__map-image" mode="aspectFill"></image>
- <view class="order-detail__map-bubble">{{ detailOrder.mapTips }}</view>
- </view>
- <view class="order-detail__status-bar">
- <view class="order-detail__status-left">
- <image class="order-detail__status-icon" mode="aspectFit"></image>
- <text class="order-detail__status-name">{{ detailOrder.statusText }}</text>
- </view>
- <view class="order-detail__status-right">
- <text v-if="detailOrder.showCancelTag" class="order-detail__cancel-tag">鍙栨秷璁㈠崟</text>
- <text class="order-detail__status-no">#{{ detailOrder.serialNo }}</text>
- </view>
- </view>
- </view>
-
- <view class="order-detail__content">
- <view class="order-detail__head">
- <view class="order-detail__time-wrap">
- <text class="order-detail__time">{{ detailOrder.time }}</text>
- <text class="order-detail__time-sub">閫佽揪</text>
- </view>
- <view class="order-detail__price-wrap">
- <text class="order-detail__price">{{ detailOrder.price }}</text>
- <text class="order-detail__extra">鍚姞鎬ヂ{ detailOrder.extra }}</text>
- </view>
- </view>
-
- <view v-if="isStatusDetail" class="order-detail__qrcode-section">
- <view class="order-detail__qrcode-box">
- <image class="order-detail__qrcode-image" src="/static/logo.png" mode="aspectFit"></image>
- </view>
- <text class="order-detail__qrcode-value">{{ detailOrder.qrcodeValue }}</text>
- <text class="order-detail__qrcode-label">{{ detailOrder.qrcodeLabel }}</text>
- </view>
-
- <view class="order-detail__tags">
- <view v-for="tag in detailOrder.tags" :key="tag.text" class="order-detail__tag-wrap">
- <image
- v-if="getTagImage(tag.text)"
- class="order-detail__tag-icon"
- :src="getTagImage(tag.text)"
- mode="widthFix"
- ></image>
- <text v-else class="order-detail__tag" :class="tag.type ? 'order-detail__tag--' + tag.type : ''">{{ tag.text }}</text>
- </view>
- </view>
-
- <view class="order-detail__route">
- <view class="order-detail__route-side">
- <text class="order-detail__distance-top">{{ detailOrder.distanceTop }}</text>
- <view class="order-detail__line"></view>
- <text class="order-detail__distance-bottom">{{ detailOrder.distanceBottom }}</text>
- </view>
- <view class="order-detail__route-main">
- <view class="order-detail__route-item">
- <view class="order-detail__route-texts">
- <text class="order-detail__route-title">{{ detailOrder.fromName }}</text>
- <text class="order-detail__route-desc">{{ detailOrder.fromAddress }}</text>
- </view>
- <view class="order-detail__route-actions">
- <image class="order-detail__route-icon" src="/static/image/ic_c1all@2x.png" mode="aspectFit"></image>
- <image class="order-detail__route-icon" src="/static/image/ic_daohang@2x.png" mode="aspectFit"></image>
- </view>
- </view>
- <view class="order-detail__route-item order-detail__route-item--destination">
- <view class="order-detail__route-texts">
- <text class="order-detail__route-title">{{ detailOrder.toName }}</text>
- <text class="order-detail__route-desc">{{ detailOrder.toAddress }}</text>
- </view>
- <view class="order-detail__route-actions">
- <image class="order-detail__route-icon order-detail__route-icon--phone" src="/static/image/ic_c1all@2x.png" mode="aspectFit"></image>
- <image class="order-detail__route-icon" src="/static/image/ic_daohang@2x.png" mode="aspectFit"></image>
- </view>
- </view>
- </view>
- </view>
-
- <view class="order-detail__section">
- <text class="order-detail__section-title">瀹㈡埛淇℃伅</text>
- <view class="order-detail__customer">
- <text class="order-detail__customer-text">{{ detailOrder.customer.name }}锛堟墜鏈哄彿{{ detailOrder.customer.phone }}锛�</text>
- <image class="order-detail__customer-icon" src="/static/image/ic_c1all@2x.png" mode="aspectFit"></image>
- </view>
- </view>
-
- <view class="order-detail__section">
- <text class="order-detail__section-title">鐗╁搧娓呭崟锛堝叡{{ detailOrder.goodsList.length }}浠讹級</text>
- <view class="order-detail__goods-list">
- <view v-for="goods in detailOrder.goodsList" :key="goods.name" class="order-detail__goods-item">
- <text class="order-detail__goods-name">{{ goods.name }}</text>
- <text class="order-detail__goods-count">x{{ goods.count }}</text>
- </view>
- </view>
- </view>
-
- <view class="order-detail__section order-detail__section--photos">
- <text class="order-detail__section-title">鐗╁搧淇℃伅</text>
- <text class="order-detail__goods-category">{{ detailOrder.goodsCategory }}</text>
- <view class="order-detail__photos">
- <view v-for="(photo, index) in detailOrder.photos" :key="index" class="order-detail__photo-item">
- <image class="order-detail__photo" :src="photo" mode="aspectFill"></image>
- </view>
- </view>
- </view>
- </view>
- </scroll-view>
-
- <view class="order-detail__footer">
- <view class="order-detail__cancel" @click="showOrderDetail = false">
- <image class="order-detail__cancel-icon" src="/static/image/ic_close2@2x.png" mode="aspectFit"></image>
- </view>
- <button v-if="!isStatusDetail" class="order-detail__confirm" hover-class="order-detail__confirm--hover">纭鎶㈠崟</button>
- <button v-else class="order-detail__confirm order-detail__confirm--status" hover-class="order-detail__confirm--hover">
- <image class="order-detail__confirm-icon" mode="aspectFit"></image>
- <text>{{ detailPopupType === 'pickup' ? '鎷嶇収鍙栬揣' : '鎷嶇収閫佽揪' }}</text>
- </button>
+ <u-popup :show="showPhotoDeliverPopup" round="20" mode="bottom">
+ <view class="photo-deliver">
+ <view class="photo-deliver__header">
+ <image class="photo-deliver__close-placeholder" mode="aspectFit"></image>
+ <text class="photo-deliver__title">鎷嶇収閫佽揪</text>
+ <image class="photo-deliver__close" mode="aspectFit" @click="showPhotoDeliverPopup = false"></image>
</view>
+
+ <view class="photo-deliver__section">
+ <view class="photo-deliver__label-row">
+ <text class="photo-deliver__label">鎷嶆憚閫佽揪鐓х墖</text>
+ <text class="photo-deliver__required">*</text>
+ <text class="photo-deliver__hint">鏈�澶�3寮犵収鐗�</text>
+ </view>
+
+ <view class="photo-deliver__photos">
+ <view class="photo-deliver__upload-card">
+ <image class="photo-deliver__upload-icon" mode="aspectFit"></image>
+ <text class="photo-deliver__upload-text">鐐瑰嚮鎷嶇収</text>
+ </view>
+
+ <view class="photo-deliver__preview-card">
+ <image class="photo-deliver__preview-image" mode="aspectFill"></image>
+ <view class="photo-deliver__preview-mask">
+ <text class="photo-deliver__preview-delete">鍒犻櫎</text>
+ </view>
+ </view>
+ </view>
+ </view>
+
+ <view class="photo-deliver__section photo-deliver__section--remark">
+ <text class="photo-deliver__remark-title">澶囨敞淇℃伅</text>
+ <textarea class="photo-deliver__textarea" maxlength="200" placeholder="璇疯緭鍏�" placeholder-style="color: #c7cbd3;" />
+ </view>
+
+ <button class="photo-deliver__submit" hover-class="photo-deliver__submit--hover" @click="showPhotoDeliverPopup = false">纭閫佽揪</button>
</view>
</u-popup>
+
+ <u-picker
+ :show="showStatusPicker"
+ confirmColor="#10B2FA"
+ keyName="text"
+ :columns="[statusOptions]"
+ @confirm="confirmStatus"
+ @cancel="showStatusPicker = false" />
</view>
</template>
<script>
+ import { mapState } from 'vuex'
export default {
data() {
return {
tts: null,
show: false,
show1: false,
- showOrderDetail: false,
- detailPopupType: 'hall',
+ showGrabModal: false,
+ selectedGrabOrder: null,
+ selectedCancelOrder: null,
+ cancelRemain: 0,
+ selectedPickupOrder: null,
+ showPhotoDeliverPopup: false,
+ routeInfo: null,
statusBarHeight: 0,
headerHeight: 0,
tabbarHeight: 0,
scrollHeight: 0,
showFilterPopup: false,
+ acceptingStatus: 0,
+ showStatusPicker: false,
+ statusOptions: [
+ { text: '涓婄嚎', value: 1 },
+ { text: '涓嬬嚎', value: 0 }
+ ],
+ centerUserInfo: {},
activeTab: 'hall',
+ expandedGoodsIds: [],
+ categoryList: [],
filterSections: [
- { key: 'sort', title: '鎺掑簭', options: ['缁煎悎鎺掑簭', '绂绘垜鏈�杩�'] },
- { key: 'level', title: '鐗╁搧绛夌骇', options: ['涓嶉檺', '鏅�氱墿鍝�', '璐甸噸鐗╁搧', '澶т欢鐗╁搧', '鐗规畩鐗╁搧', '鍏朵粬鐗╁搧'] },
+ { key: 'sort', title: '鎺掑簭', options: ['缁煎悎鎺掑簭', '璺濈鏈�杩�'] },
+ { key: 'level', title: '鐗╁搧绛夌骇', options: ['涓嶉檺'] },
{ key: 'distance', title: '浣嶇疆鑼冨洿', options: ['涓嶉檺', '500m', '1km', '2km', '3km', '4km', '5km', '6km', '7km'] }
],
selectedFilters: {
@@ -336,152 +299,32 @@
level: '涓嶉檺',
distance: '涓嶉檺'
},
- detailOrder: {
- time: '45鍒嗛挓鍐�',
- price: '楼20.5',
- extra: '3.0',
- serialNo: 1,
- statusText: '鎶㈠崟澶у巺',
- qrcodeValue: '767889',
- qrcodeLabel: '鍙栬揣鐮�',
- mapTips: '鍓╀綑3.2km锛岀害4鍒嗛挓',
- showCancelTag: false,
- tags: [
- { text: '鏍囬�熻揪', type: 'blue' },
- { text: '璐甸噸鐗╁搧', type: 'orange' }
- ],
- distanceTop: '349m',
- distanceBottom: '12.5km',
- fromName: '涓搧蹇繍鍗楃珯鏃楄埌搴�',
- fromAddress: '鑾茶姳璺�200鍙疯幉鑺变骇涓氬洯F鏍�401',
- toName: '浣宠嫅宸撮粠閮藉競3鏈�10鏍�301瀹�',
- toAddress: '娲炲涵婀栬矾涓庢箹鍖楄矾浜ゅ弶鍙hタ150绫�',
- customer: {
- name: '鍒樺厛鐢�',
- phone: '2878'
- },
- goodsList: [
- { name: '澶т欢琛屾潕', count: 1 },
- { name: '涓欢琛屾潕', count: 2 },
- { name: '灏忎欢琛屾潕', count: 3 },
- { name: '鑳屽寘', count: 2 }
- ],
- goodsCategory: '鏂囦欢',
- photos: ['/static/logo.png', '/static/logo.png', '/static/logo.png']
- },
stats: [
- { value: '4.2', label: '鏈嶅姟鍒�' },
- { value: '234.3', label: '浠婃棩棰勮浣i噾' },
- { value: '13', label: '浠婃棩鎺ュ崟' }
+ { value: '-', label: '鏈嶅姟鍒�' },
+ { value: '-', label: '浠婃棩棰勮浣i噾' },
+ { value: '-', label: '浠婃棩鎺ュ崟' }
],
tabs: [
{ label: '鎶㈠崟澶у巺', value: 'hall' },
- { label: '寰呭彇璐�', value: 'pickup', count: 2 },
- { label: '閰嶉�佷腑', value: 'delivering', count: 2 }
+ { label: '寰呭彇璐�', value: 'pickup' },
+ { label: '閰嶉�佷腑', value: 'delivering' }
],
- orderList: [
- {
- id: 1,
- time: '45鍒嗛挓鍐�',
- price: '楼20.5',
- extra: '3.0',
- tags: [
- { text: '鏋侀�熻揪', type: 'blue' },
- { text: '璐甸噸鐗╁搧', type: 'orange' }
- ],
- distanceTop: '349m',
- distanceBottom: '12.5km',
- fromName: '涓搧蹇繍鍗楃珯鏃楄埌搴�',
- fromAddress: '鑾茶姳璺�200鍙疯幉鑺变骇涓氬洯F鏍�401',
- toName: '浣宠嫅宸撮粠閮藉競3鏈�10鏍�301瀹�',
- toAddress: '娲炲涵婀栬矾涓庢箹鍖楄矾浜ゅ弶鍙hタ150绫�',
- goods: '澶т欢琛屾潕*1銆佷腑浠惰鏉�*2銆佸皬浠惰鏉�*3銆佽儗鍖�*1'
- },
- {
- id: 2,
- time: '45鍒嗛挓鍐�',
- price: '楼20.5',
- extra: '3.0',
- tags: [
- { text: '鏋侀�熻揪', type: 'red' },
- { text: '澶т欢鐗╁搧', type: 'blue-light' }
- ],
- distanceTop: '349m',
- distanceBottom: '12.5km',
- fromName: '涓搧蹇繍鍗楃珯鏃楄埌搴�(鍚堣偉鍗楃珯鍖楀箍鍦�',
- fromAddress: '鑾茶姳璺�200鍙疯幉鑺变骇涓氬洯F鏍�401',
- toName: '浣宠嫅宸撮粠閮藉競3鏈�10鏍�301瀹�',
- toAddress: '娲炲涵婀栬矾涓庢箹鍖楄矾浜ゅ弶鍙hタ150绫�',
- goods: '澶т欢琛屾潕*1'
- },
- {
- id: 3,
- time: '45鍒嗛挓鍐�',
- price: '楼20.5',
- extra: '3.0',
- tags: [
- { text: '鏋侀�熻揪', type: 'red' },
- { text: '澶т欢鐗╁搧', type: 'blue-light' }
- ],
- distanceTop: '349m',
- distanceBottom: '12.5km',
- fromName: '涓搧蹇繍鍗楃珯鏃楄埌搴�(鍚堣偉鍗楃珯鍖楀箍鍦�',
- fromAddress: '鑾茶姳璺�200鍙疯幉鑺变骇涓氬洯F鏍�401',
- toName: '浣宠嫅宸撮粠閮藉競3鏈�10鏍�301瀹�',
- toAddress: '娲炲涵婀栬矾涓庢箹鍖楄矾浜ゅ弶鍙hタ150绫�',
- goods: '澶т欢琛屾潕*1'
- }
- ],
- pickupOrderList: [
- {
- id: 101,
- serialNo: 1,
- statusText: '寰呭彇璐�',
- qrcodeValue: '767889',
- qrcodeLabel: '鍙栬揣鐮�',
- mapTips: '鍓╀綑3.2km锛岀害4鍒嗛挓',
- showCancelTag: true,
- time: '45鍒嗛挓鍐�',
- price: '楼20.5',
- extra: '3.0',
- tags: [
- { text: '鏍囬�熻揪', type: 'blue' },
- { text: '璐甸噸鐗╁搧', type: 'orange' }
- ],
- distanceTop: '349m',
- distanceBottom: '12.5km',
- fromName: '涓搧蹇繍鍗楃珯鏃楄埌搴�',
- fromAddress: '鑾茶姳璺�200鍙疯幉鑺变骇涓氬洯F鏍�401',
- toName: '灏忛搧鏃犲咖瀛�',
- toAddress: '娲炲涵婀栬矾涓庢箹鍖楄矾浜ゅ弶鍙hタ150绫�',
- goods: '澶т欢琛屾潕*1銆佷腑浠惰鏉�*2銆佸皬浠惰鏉�*3銆佽儗鍖�*1'
- }
- ],
- deliveringOrderList: [
- {
- id: 201,
- serialNo: 1,
- statusText: '閰嶉�佷腑',
- qrcodeValue: '767889',
- qrcodeLabel: '瀛樹欢鐮�',
- mapTips: '鍓╀綑3.2km锛岀害4鍒嗛挓',
- showCancelTag: false,
- time: '45鍒嗛挓鍐�',
- price: '楼20.5',
- extra: '3.0',
- tags: [
- { text: '鏍囬�熻揪', type: 'blue' },
- { text: '璐甸噸鐗╁搧', type: 'orange' }
- ],
- distanceTop: '349m',
- distanceBottom: '12.5km',
- fromName: '涓搧蹇繍鍗楃珯鏃楄埌搴�',
- fromAddress: '鑾茶姳璺�200鍙疯幉鑺变骇涓氬洯F鏍�401',
- toName: '灏忛搧鏃犲咖瀛�',
- toAddress: '娲炲涵婀栬矾涓庢箹鍖楄矾浜ゅ弶鍙hタ150绫�',
- goods: '澶т欢琛屾潕*1銆佷腑浠惰鏉�*2銆佸皬浠惰鏉�*3銆佽儗鍖�*1'
- }
- ]
+ orderList: [],
+ pickupOrderList: [],
+ deliveringOrderList: [],
+ hallPage: 1,
+ hallPageSize: 10,
+ hallLoading: false,
+ hallHasMore: true,
+ pickupLoading: false,
+ deliveringLoading: false,
+ activeOrderCount: null
+ }
+ },
+
+ watch: {
+ activeTab(newVal) {
+ this.loadOrdersByTab(newVal)
}
},
@@ -493,13 +336,39 @@
this.headerHeight = this.statusBarHeight + uni.upx2px(308)
this.tabbarHeight = uni.upx2px(100) + safeBottom
this.scrollHeight = Math.max(windowHeight - this.headerHeight, 0)
+ if (this.userInfo.auditStatus === 99) return;
+ this.acceptingStatus = this.userInfo.acceptingStatus || 0
+ this.loadOrdersByTab(this.activeTab)
+ },
+
+ onShow() {
+ this.getCenterInfo()
+ this.getCategoryListData()
+ this.getActiveOrderCount()
+ },
+
+ onReachBottom() {
+ if (this.acceptingStatus === 0) return;
+ if (this.activeTab === 'hall') {
+ this.hallPage++
+ this.getHallOrders()
+ }
},
computed: {
- isStatusDetail() {
- return this.detailPopupType === 'pickup' || this.detailPopupType === 'delivering'
- },
+ ...mapState(['userInfo', 'token']),
+ displayTabs() {
+ return this.tabs.map(tab => {
+ if (tab.value === 'pickup') {
+ return { ...tab, count: this.activeOrderCount?.grabbedCount }
+ } else if (tab.value === 'delivering') {
+ return { ...tab, count: this.activeOrderCount?.deliveringCount }
+ }
+ return tab
+ })
+ },
+
currentOrderList() {
const orderMap = {
hall: this.orderList,
@@ -523,17 +392,344 @@
},
methods: {
- openDetailPopup(item) {
- this.detailPopupType = this.activeTab
- this.detailOrder = {
- ...this.detailOrder,
- ...item,
- customer: item.customer || this.detailOrder.customer,
- goodsList: item.goodsList || this.detailOrder.goodsList,
- goodsCategory: item.goodsCategory || this.detailOrder.goodsCategory,
- photos: item.photos || this.detailOrder.photos
+ formatRemainTime(minutes) {
+ if (!minutes) return 0
+ if (minutes === 0) {
+ return '閰嶉�佸凡瓒呮椂'
}
- this.showOrderDetail = true
+ if (minutes >= 60) {
+ return (minutes / 60).toFixed(2) + '灏忔椂鍐�'
+ }
+ return minutes + '鍒嗛挓鍐�'
+ },
+
+ getGoodsText(items, itemId) {
+ if (!items || items.length === 0) return '鏃�'
+ const text = items.map(i => `${i.name}*${i.quantity}`).join('銆�')
+ if (text.length > 20 && !this.expandedGoodsIds.includes(itemId)) {
+ return text.substring(0, 20) + '...'
+ }
+ return text
+ },
+
+ toggleGoodsExpand(id) {
+ const index = this.expandedGoodsIds.indexOf(id)
+ if (index > -1) {
+ this.expandedGoodsIds.splice(index, 1)
+ } else {
+ this.expandedGoodsIds.push(id)
+ }
+ },
+
+ formatDistanceParts(distance) {
+ if (distance === null || distance === undefined || distance === '') {
+ return { value: '--', unit: '' }
+ }
+
+ if (typeof distance === 'number') {
+ if (distance >= 1000) {
+ return { value: (distance / 1000).toFixed(1), unit: 'km' }
+ }
+ return { value: String(Math.round(distance)), unit: 'm' }
+ }
+
+ const text = String(distance).trim()
+ const match = text.match(/^([\d.]+)\s*([a-zA-Z\u4e00-\u9fa5]*)$/)
+ if (match) {
+ return {
+ value: match[1],
+ unit: match[2] || ''
+ }
+ }
+
+ return { value: text, unit: '' }
+ },
+
+ navigateToAddress(item, type) {
+ let latitude, longitude, name, address
+ if (type === 'deposit') {
+ latitude = item.depositLat
+ longitude = item.depositLng
+ name = item.depositShopName
+ address = item.depositShopAddress
+ } else {
+ latitude = item.takeLat
+ longitude = item.takeLng
+ name = item.takeName
+ address = item.takeAddress
+ }
+ if (!latitude || !longitude) {
+ uni.showToast({ title: '鍦板潃鍧愭爣缂哄け', icon: 'none' })
+ return
+ }
+ uni.openLocation({
+ latitude,
+ longitude,
+ name,
+ address,
+ success: () => {},
+ fail: (err) => {
+ uni.showToast({ title: '鎵撳紑鍦板浘澶辫触', icon: 'none' })
+ console.error('openLocation fail:', err)
+ }
+ })
+ },
+
+ handleUserClick() {
+ uni.navigateTo({
+ url: '/pages/test/test'
+ })
+ },
+ getActiveOrderCount() {
+ this.$u.api.activeOrderCount().then(res => {
+ if (res.code === 200) {
+ this.activeOrderCount = res.data
+ }
+ }).catch((err) => {
+ this.activeOrderCount = null
+ })
+ },
+
+ handleGrabOrder(item) {
+ console.log(item)
+ this.selectedGrabOrder = item
+ this.showGrabModal = true
+ },
+
+ confirmGrabOrder() {
+ if (!this.selectedGrabOrder) return
+ this.$u.api.grabOrder({ orderId: this.selectedGrabOrder.id }).then(res => {
+ this.showGrabModal = false
+ if (res.code === 200) {
+ uni.showToast({ title: '鎶㈠崟鎴愬姛', icon: 'success' })
+ this.hallPage = 1
+ this.hallHasMore = true
+ this.orderList = []
+ this.getHallOrders()
+ this.getActiveOrderCount()
+ this.getCenterInfo()
+ } else {
+ uni.showToast({ title: res.message || '鎶㈠崟澶辫触', icon: 'none' })
+ }
+ }).catch(() => {
+ this.showGrabModal = false
+ })
+ },
+
+ handleCancelOrder(item) {
+ this.selectedCancelOrder = item
+ this.$u.api.cancelLimit().then(res => {
+ if (res.code === 200) {
+ this.cancelRemain = res.data.remain
+ }
+ }).finally(() => {
+ this.show = true
+ })
+ },
+
+ confirmCancelOrder() {
+ if (!this.selectedCancelOrder) return
+ this.$u.api.cancelOrder({ orderId: this.selectedCancelOrder.id }).then(res => {
+ this.show = false
+ if (res.code === 200) {
+ uni.showToast({ title: '鍙栨秷鎴愬姛', icon: 'success' })
+ this.getPickupOrders()
+ this.getCenterInfo()
+ this.getActiveOrderCount()
+ } else {
+ uni.showToast({ title: res.message || '鍙栨秷澶辫触', icon: 'none' })
+ }
+ }).catch(() => {
+ this.show = false
+ })
+ },
+
+ handleCall(item) {
+ if (item.contactPhone) {
+ uni.makePhoneCall({
+ phoneNumber: item.contactPhone
+ })
+ }
+ },
+
+ handleShowPickupCode(item) {
+ this.selectedPickupOrder = item
+ this.show1 = true
+ },
+
+ goToOrderDetail(item, index) {
+ let url = `/pages/order-detail/order-detail?id=${item.id}`
+ if (this.activeTab === 'pickup' || this.activeTab === 'delivering') {
+ url += `&index=${index + 1}`
+ }
+ uni.navigateTo({ url })
+ },
+
+ getCenterInfo() {
+ this.$u.api.centerInfo().then(res => {
+ if (res.code === 200) {
+ this.acceptingStatus = res.data.acceptingStatus
+ this.centerUserInfo = {
+ fullImgUrl: res.data.fullImgUrl,
+ name: res.data.name
+ }
+ this.stats = [
+ { value: res.data.score, label: '鏈嶅姟鍒�' },
+ { value: res.data.todayCommission, label: '浠婃棩棰勮浣i噾' },
+ { value: res.data.todayOrderCount, label: '浠婃棩鎺ュ崟' }
+ ]
+ }
+ })
+ },
+
+ getCategoryListData() {
+ this.$u.api.getCategoryList({ type: 3 }).then(res => {
+ if (res.code === 200) {
+ this.categoryList = res.data || []
+ this.filterSections.forEach(section => {
+ if (section.key === 'level') {
+ section.options = ['涓嶉檺', ...this.categoryList.map(item => item.name)]
+ }
+ })
+ }
+ })
+ },
+
+ loadOrdersByTab(tab) {
+ if (this.userInfo.auditStatus === 99) return;
+ if (this.acceptingStatus === 0) return;
+ if (tab === 'hall') {
+ this.hallPage = 1
+ this.hallHasMore = true
+ this.orderList = []
+ this.getHallOrders()
+ } else if (tab === 'pickup') {
+ this.pickupOrderList = []
+ this.getPickupOrders()
+ } else if (tab === 'delivering') {
+ this.deliveringOrderList = []
+ this.getDeliveringOrders()
+ }
+ },
+
+ getHallOrders() {
+ if (this.acceptingStatus === 0) return;
+ if (this.hallLoading || !this.hallHasMore) {
+ return
+ }
+ this.hallLoading = true
+
+ let distance = null
+ if (this.selectedFilters.distance !== '涓嶉檺') {
+ const distanceText = this.selectedFilters.distance
+ if (distanceText.includes('km')) {
+ distance = parseInt(distanceText) * 1000
+ } else {
+ distance = parseInt(distanceText)
+ }
+ }
+
+ const sortTypeMap = {
+ '缁煎悎鎺掑簭': 1,
+ '璺濈鏈�杩�': 2
+ }
+ const sortType = this.selectedFilters.sort !== '涓嶉檺' ? (sortTypeMap[this.selectedFilters.sort] || null) : null
+
+ let gradeId = null
+ if (this.selectedFilters.level !== '涓嶉檺') {
+ const selectedCategory = this.categoryList.find(item => item.name === this.selectedFilters.level)
+ if (selectedCategory) {
+ gradeId = selectedCategory.id
+ }
+ }
+
+ console.log('鎺ュ崟澶у巺:', { distance, gradeId, sortType })
+ this.$u.api.grabOrderHall({
+ capacity: this.hallPageSize,
+ page: this.hallPage,
+ model: {
+ distance: distance,
+ gradeId: gradeId,
+ sortType: sortType
+ }
+ }).then(res => {
+ console.log('鎺ュ崟澶у巺', res)
+ this.hallLoading = false
+ if (res.code === 200) {
+ const list = res.data.records || []
+ this.orderList = this.hallPage === 1 ? list : this.orderList.concat(list)
+ this.hallHasMore = list.length >= this.hallPageSize
+ }
+ }).catch((err) => {
+ this.hallLoading = false
+ })
+ },
+
+ getPickupOrders() {
+ if (this.acceptingStatus === 0) return;
+ if (this.pickupLoading) return
+ this.pickupLoading = true
+ this.$u.api.activeOrders({ status: 3 }).then(res => {
+ console.log('寰呭彇璐�:', res)
+ this.pickupLoading = false
+ if (res.code === 200) {
+ this.pickupOrderList = res.data.records || res.data || []
+ }
+ }).catch((err) => {
+ this.pickupLoading = false
+ })
+ },
+
+ getDeliveringOrders() {
+ if (this.acceptingStatus === 0) return;
+ if (this.deliveringLoading) return
+ this.deliveringLoading = true
+ this.$u.api.activeOrders({ status: 4 }).then(res => {
+ console.log('閰嶉�佷腑:', res)
+ this.deliveringLoading = false
+ if (res.code === 200) {
+ this.deliveringOrderList = res.data || []
+ }
+ }).catch((err) => {
+ this.deliveringLoading = false
+ })
+ },
+
+ openStatusPicker() {
+ this.showStatusPicker = true
+ },
+
+ confirmStatus(e) {
+ this.showStatusPicker = false
+ const selectedValue = e.value[0]
+ this.$u.api.updateAcceptingStatus({ status: selectedValue.value }).then(res => {
+ if (res.code === 200) {
+ this.acceptingStatus = selectedValue.value
+ this.getCenterInfo()
+ if (this.acceptingStatus === 0) {
+ this.orderList = []
+ this.pickupOrderList = []
+ this.deliveringOrderList = []
+ } else {
+ if (this.activeTab === 'pickup') {
+ this.getPickupOrders()
+ } else if (this.activeTab === 'delivering') {
+ this.getDeliveringOrders()
+ } else {
+ this.hallPage = 1
+ this.hallHasMore = true
+ this.orderList = []
+ this.getHallOrders()
+ }
+ }
+ }
+ })
+ },
+
+ toDriverCertification() {
+ uni.navigateTo({
+ url: '/pages/driver-certification/driver-certification'
+ })
},
toggleFilterPopup(show) {
@@ -548,24 +744,33 @@
},
resetFilters() {
+ this.showFilterPopup = false
+ if (this.userInfo.auditStatus === 99) return;
this.selectedFilters = {
sort: '缁煎悎鎺掑簭',
level: '涓嶉檺',
distance: '涓嶉檺'
}
+ if (this.activeTab === 'hall') {
+ this.hallPage = 1
+ this.hallHasMore = true
+ this.orderList = []
+ this.getHallOrders()
+ }
},
confirmFilters() {
this.showFilterPopup = false
- },
-
- getTagImage(tagText) {
- const tagImageMap = {
- '鏋侀�熻揪': '/static/image/ic_jisuda@2x.png',
- '鏍囬�熻揪': '/static/image/ic_biaosuda@2x.png'
+ if (this.userInfo.auditStatus === 99) {
+ this.hallHasMore = true
+ return
}
-
- return tagImageMap[tagText] || ''
+ if (this.activeTab === 'hall') {
+ this.hallPage = 1
+ this.hallHasMore = true
+ this.orderList = []
+ this.getHallOrders()
+ }
},
initTTS() {
@@ -631,7 +836,7 @@
height: 100vh;
background: #f5f6f8;
overflow: hidden;
-
+
.qrcode {
padding: 36rpx 30rpx;
box-sizing: border-box;
@@ -680,422 +885,154 @@
}
}
- .order-detail {
- display: flex;
- flex-direction: column;
+ .photo-deliver {
+ padding: 32rpx 28rpx calc(env(safe-area-inset-bottom) + 28rpx);
background: #ffffff;
- border-top-left-radius: 28rpx;
- border-top-right-radius: 28rpx;
+ box-sizing: border-box;
+ border-top-left-radius: 20rpx;
+ border-top-right-radius: 20rpx;
overflow: hidden;
- &__scroll {
- flex: 1;
- min-height: 0;
- }
-
- &__map-section {
- background: #ffffff;
- }
-
- &__map {
- position: relative;
- height: 330rpx;
- background: linear-gradient(180deg, #eef5ff 0%, #dbe9ff 100%);
- overflow: hidden;
- }
-
- &__map-image {
- width: 100%;
- height: 100%;
- opacity: 0.2;
- }
-
- &__map-bubble {
- position: absolute;
- left: 26rpx;
- bottom: 44rpx;
- padding: 12rpx 18rpx;
- border-radius: 12rpx;
- background: rgba(255, 255, 255, 0.96);
- box-shadow: 0 10rpx 20rpx rgba(33, 92, 182, 0.08);
- font-size: 26rpx;
- font-weight: 500;
- color: #2f6ff2;
- }
-
- &__status-bar {
+ &__header {
display: flex;
+ align-items: center;
justify-content: space-between;
- align-items: center;
- padding: 0 24rpx;
- height: 92rpx;
- background: #d9e8ff;
}
- &__status-left,
- &__status-right {
- display: flex;
- align-items: center;
- }
-
- &__status-icon {
- width: 28rpx;
- height: 28rpx;
- margin-right: 12rpx;
- border-radius: 6rpx;
- background: #7ea7ef;
- }
-
- &__status-name,
- &__status-no {
+ &__title {
font-size: 34rpx;
font-weight: 700;
- color: #2b3139;
+ color: #111111;
}
- &__cancel-tag {
- padding: 8rpx 16rpx;
- margin-right: 18rpx;
- border: 2rpx solid #6ea6ff;
- border-radius: 999rpx;
- font-size: 24rpx;
- color: #1d73ff;
- background: rgba(255, 255, 255, 0.72);
+ &__close,
+ &__close-placeholder {
+ width: 36rpx;
+ height: 36rpx;
+ flex-shrink: 0;
}
- &__content {
- padding: 28rpx 24rpx 36rpx;
+ &__close-placeholder {
+ opacity: 0;
}
- &__head {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
+ &__section {
+ margin-top: 56rpx;
+
+ &--remark {
+ margin-top: 46rpx;
+ }
}
- &__time-wrap {
+ &__label-row {
display: flex;
align-items: center;
+ flex-wrap: wrap;
}
- &__time {
- font-size: 42rpx;
- font-weight: 700;
- color: #ff8d27;
- }
-
- &__time-sub {
- margin-left: 8rpx;
+ &__label,
+ &__remark-title {
font-size: 28rpx;
- color: #a4a9b2;
+ font-weight: 700;
+ color: #23262d;
}
- &__price-wrap {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- }
-
- &__price {
- font-size: 44rpx;
+ &__required {
+ margin-left: 4rpx;
+ font-size: 28rpx;
font-weight: 700;
color: #ff3b30;
}
- &__extra {
- margin-top: 6rpx;
+ &__hint {
+ margin-left: 12rpx;
font-size: 24rpx;
- color: #a0a5af;
- }
-
- &__tags {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- gap: 10rpx;
- margin-top: 14rpx;
- }
-
- &__tag-wrap {
- display: flex;
- align-items: center;
- }
-
- &__tag-icon {
- width: 108rpx;
- height: 40rpx;
- }
-
- &__tag {
- padding: 4rpx 10rpx;
- border-radius: 8rpx;
- font-size: 22rpx;
- line-height: 1.2;
- border: 1rpx solid #2473f5;
- color: #2473f5;
-
- &--orange {
- border-color: #ff9c45;
- background: #ff9c45;
- color: #ffffff;
- }
- }
-
- &__route {
- display: flex;
- margin-top: 20rpx;
- padding-bottom: 26rpx;
- border-bottom: 1rpx solid #edf0f3;
- }
-
- &__route-side {
- width: 64rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- flex-shrink: 0;
- }
-
- &__distance-top,
- &__distance-bottom {
- font-size: 22rpx;
- font-weight: 600;
- color: #555b66;
- text-align: center;
- }
-
- &__line {
- position: relative;
- width: 4rpx;
- flex: 1;
- min-height: 92rpx;
- margin: 10rpx 0;
- border-radius: 999rpx;
- background: #d8dbe1;
-
- &::before,
- &::after {
- content: '';
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- width: 14rpx;
- height: 14rpx;
- border-radius: 50%;
- background: #6a6f79;
- }
-
- &::before {
- top: -4rpx;
- }
-
- &::after {
- bottom: -4rpx;
- }
- }
-
- &__route-main {
- flex: 1;
- }
-
- &__route-item {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- gap: 18rpx;
-
- &--destination {
- margin-top: 24rpx;
- }
- }
-
- &__route-texts {
- flex: 1;
- min-width: 0;
- }
-
- &__route-title {
- display: block;
- font-size: 40rpx;
- font-weight: 700;
- color: #2d3139;
- line-height: 1.3;
- }
-
- &__route-desc {
- display: block;
- margin-top: 8rpx;
- font-size: 28rpx;
- color: #9ea4ae;
- line-height: 1.4;
- }
-
- &__route-actions {
- display: flex;
- align-items: center;
- gap: 12rpx;
- flex-shrink: 0;
- }
-
- &__route-icon,
- &__customer-icon {
- width: 48rpx;
- height: 48rpx;
- border: 2rpx dashed #c9ced6;
- border-radius: 8rpx;
- background: #f7f8fa;
- }
-
- &__cancel-icon {
- width: 40rpx;
- height: 40rpx;
- }
-
- &__qrcode-section {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 34rpx 0 8rpx;
- border-bottom: 1rpx solid #edf0f3;
- }
-
- &__qrcode-box {
- width: 260rpx;
- height: 260rpx;
- padding: 16rpx;
- border: 2rpx solid #edf0f3;
- border-radius: 12rpx;
- box-sizing: border-box;
- }
-
- &__qrcode-image {
- width: 100%;
- height: 100%;
- }
-
- &__qrcode-value {
- margin-top: 18rpx;
- font-size: 44rpx;
- font-weight: 700;
- color: #31363f;
- }
-
- &__qrcode-label {
- margin-top: 8rpx;
- font-size: 26rpx;
- color: #b0b4bc;
- }
-
- &__section {
- padding: 28rpx 0;
- border-bottom: 1rpx solid #edf0f3;
-
- &--photos {
- border-bottom: 0;
- }
- }
-
- &__section-title {
- display: block;
- font-size: 32rpx;
- font-weight: 700;
- color: #2b3139;
- }
-
- &__customer {
- margin-top: 28rpx;
- display: flex;
- justify-content: space-between;
- align-items: center;
- gap: 20rpx;
- }
-
- &__customer-text {
- flex: 1;
- font-size: 32rpx;
- color: #41464f;
- line-height: 1.5;
- }
-
- &__goods-list {
- margin-top: 22rpx;
- }
-
- &__goods-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 10rpx 0;
- }
-
- &__goods-name {
- font-size: 32rpx;
- color: #41464f;
- }
-
- &__goods-count {
- font-size: 30rpx;
- color: #a1a6af;
- }
-
- &__goods-category {
- display: block;
- margin-top: 24rpx;
- font-size: 32rpx;
- color: #41464f;
+ color: #a8adb7;
}
&__photos {
display: flex;
- gap: 16rpx;
- margin-top: 22rpx;
+ gap: 18rpx;
+ margin-top: 30rpx;
}
- &__photo-item {
- width: 120rpx;
- height: 120rpx;
- border-radius: 12rpx;
+ &__upload-card,
+ &__preview-card {
+ position: relative;
+ width: 160rpx;
+ height: 160rpx;
+ border-radius: 8rpx;
overflow: hidden;
- background: #f3f5f8;
}
- &__photo {
+ &__upload-card {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ border: 2rpx dashed #c9ced6;
+ background: #ffffff;
+ box-sizing: border-box;
+ }
+
+ &__upload-icon {
+ width: 52rpx;
+ height: 52rpx;
+ }
+
+ &__upload-text {
+ margin-top: 14rpx;
+ font-size: 26rpx;
+ color: #9da3ae;
+ }
+
+ &__preview-card {
+ background: #eef1f5;
+ }
+
+ &__preview-image {
width: 100%;
height: 100%;
}
- &__footer {
- display: flex;
- align-items: center;
- gap: 18rpx;
- padding: 18rpx 24rpx calc(env(safe-area-inset-bottom) + 18rpx);
- background: #ffffff;
- box-shadow: 0 -8rpx 24rpx rgba(16, 27, 49, 0.04);
- }
-
- &__cancel {
- width: 176rpx;
- height: 100rpx;
- border-radius: 50rpx;
- background: #E5E5E5;
+ &__preview-mask {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
display: flex;
justify-content: center;
align-items: center;
- flex-shrink: 0;
+ height: 48rpx;
+ background: rgba(0, 0, 0, 0.46);
}
- &__confirm {
- flex: 1;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 14rpx;
- height: 100rpx;
- line-height: 100rpx;
+ &__preview-delete {
+ font-size: 26rpx;
+ color: #ffffff;
+ }
+
+ &__textarea {
+ width: 100%;
+ height: 110rpx;
+ margin-top: 24rpx;
+ padding: 28rpx 24rpx;
+ border-radius: 12rpx;
+ background: #f7f8fa;
+ box-sizing: border-box;
+ font-size: 30rpx;
+ color: #2c3139;
+ }
+
+ &__submit {
+ width: 100%;
+ height: 88rpx;
+ line-height: 88rpx;
+ margin-top: 86rpx;
border-radius: 50rpx;
- background: #106EFA;
- font-size: 36rpx;
- font-weight: 600;
+ background: #106efa;
+ font-size: 32rpx;
+ font-weight: 700;
color: #ffffff;
border: 0;
padding: 0;
@@ -1107,12 +1044,6 @@
&--hover {
opacity: 0.92;
}
- }
-
- &__confirm-icon {
- width: 32rpx;
- height: 32rpx;
- flex-shrink: 0;
}
}
@@ -1167,6 +1098,10 @@
border-radius: 50%;
background: #32d74b;
margin-right: 10rpx;
+
+ &--offline {
+ background: #ff3b30;
+ }
}
&__status-text,
@@ -1278,7 +1213,34 @@
}
&__list {
- padding: 22rpx 30rpx calc(22rpx + env(safe-area-inset-bottom)) 30rpx;
+ padding: 30rpx;
+ }
+
+ &__verified {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ image {
+ width: 320rpx;
+ height: 320rpx;
+ }
+ button {
+ width: 160rpx;
+ height: 64rpx;
+ line-height: 64rpx;
+ text-align: center;
+ padding: 0 !important;
+ border: 0 !important;
+ background: #106EFA;
+ border-radius: 50rpx;
+ margin-top: 40rpx;
+ font-weight: 400;
+ font-size: 28rpx;
+ color: #FFFFFF;
+ }
}
&__empty {
@@ -1301,20 +1263,23 @@
left: 0;
right: 0;
z-index: 20;
- background: rgba(0, 0, 0, 0.24);
&__panel {
+ display: flex;
+ flex-direction: column;
height: 100%;
- padding: 22rpx 0 26rpx;
background: #ffffff;
border-bottom-left-radius: 28rpx;
border-bottom-right-radius: 28rpx;
- box-sizing: border-box;
+ }
+
+ &__content {
+ flex: 1;
overflow-y: auto;
+ padding: 22rpx 18rpx 0;
}
&__section {
- padding: 0 18rpx;
margin-bottom: 28rpx;
}
@@ -1360,9 +1325,10 @@
}
&__actions {
+ flex-shrink: 0;
display: flex;
gap: 24rpx;
- padding: 8rpx 18rpx 0;
+ padding: 8rpx 18rpx 26rpx;
}
&__button {
@@ -1476,17 +1442,25 @@
height: 40rpx;
}
+ &__tag-img {
+ width: 108rpx;
+ height: 40rpx;
+ }
+
&__tag {
padding: 4rpx 10rpx;
border-radius: 8rpx;
font-size: 22rpx;
line-height: 1.2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
border: 1rpx solid #2473f5;
color: #2473f5;
&--orange {
- border-color: #ff9c45;
- background: #ff9c45;
+ border: none;
+ background: linear-gradient(319deg, #EE9D0E 0%, #FF4E4E 100%);
color: #ffffff;
}
@@ -1499,6 +1473,15 @@
border-color: #74a9ff;
color: #74a9ff;
}
+
+ &--blue {
+ background: rgba(16,178,250,0.08);
+ border-radius: 15rpx;
+ border: 2rpx solid #106EFA;
+ font-weight: 400;
+ font-size: 22rpx;
+ color: #106EFA;
+ }
}
&__route {
@@ -1507,29 +1490,56 @@
}
&__route-side {
- width: 64rpx;
+ width: 70rpx;
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
+ padding: 14rpx 0 8rpx;
+ border-radius: 26rpx;
+ background: #f6f7f9;
+ margin-right: 20rpx;
}
- &__distance-top,
- &__distance-bottom {
- font-size: 22rpx;
- font-weight: 600;
- color: #555b66;
+ &__distance-block {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ line-height: 1;
+
+ &--top {
+ margin-bottom: 6rpx;
+ }
+
+ &--bottom {
+ margin-top: 6rpx;
+ }
+ }
+
+ &__distance-value {
+ font-size: 26rpx;
+ font-weight: 700;
+ color: #333333;
text-align: center;
+ }
+
+ &__distance-unit {
+ margin-top: 6rpx;
+ font-size: 18rpx;
+ font-weight: 500;
+ color: #8c939f;
+ text-align: center;
+ text-transform: lowercase;
}
&__line {
position: relative;
- width: 4rpx;
+ width: 100%;
flex: 1;
- min-height: 86rpx;
- margin: 10rpx 0;
- border-radius: 999rpx;
- background: #d8dbe1;
+ min-height: 62rpx;
+ margin: 8rpx 0;
+ background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='26' viewBox='0 0 20 26'%3E%3Cpath fill='%238C939F' d='M10 0C5.03 0 1 3.99 1 8.92c0 6.31 7.28 12.87 8.07 13.57a1.4 1.4 0 0 0 1.86 0C11.72 21.79 19 15.23 19 8.92 19 3.99 14.97 0 10 0Zm0 12.24a3.32 3.32 0 1 1 0-6.64 3.32 3.32 0 0 1 0 6.64Z'/%3E%3C/svg%3E") center center no-repeat;
+ background-size: 20rpx 26rpx;
&::before,
&::after {
@@ -1537,18 +1547,19 @@
position: absolute;
left: 50%;
transform: translateX(-50%);
- width: 14rpx;
- height: 14rpx;
- border-radius: 50%;
- background: #6a6f79;
+ width: 2rpx;
+ border-radius: 999rpx;
+ background: #cfd4dc;
}
&::before {
- top: -4rpx;
+ top: 0;
+ height: 18rpx;
}
&::after {
- bottom: -4rpx;
+ bottom: 0;
+ height: 24rpx;
}
}
@@ -1573,19 +1584,27 @@
}
&__route-title {
+ width: 500rpx;
display: block;
font-size: 40rpx;
font-weight: 700;
color: #2d3139;
line-height: 1.3;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
&__route-desc {
+ width: 500rpx;
display: block;
margin-top: 8rpx;
font-size: 28rpx;
color: #9ea4ae;
line-height: 1.4;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
&__nav {
@@ -1618,6 +1637,11 @@
margin-left: 12rpx;
font-size: 24rpx;
color: #a4a9b1;
+ transition: transform 0.3s;
+
+ &--expanded {
+ transform: rotate(180deg);
+ }
}
&__button {
--
Gitblit v1.9.3