From 80c0aa2a864071ad77d6c7de7c508348b2eb2fee Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期六, 25 四月 2026 14:46:20 +0800
Subject: [PATCH] app

---
 app/pages/index/index.vue | 1594 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 1,515 insertions(+), 79 deletions(-)

diff --git a/app/pages/index/index.vue b/app/pages/index/index.vue
index 123f636..7427c91 100644
--- a/app/pages/index/index.vue
+++ b/app/pages/index/index.vue
@@ -1,111 +1,1547 @@
 <template>
-	<view class="index">
-		<view class="index_list">
-			<view class="index_list_item">
-				<view class="index_list_item_info">
-					<text>SHE浜嬩欢涓婃姤</text>
-					<text>FAC/NM</text>
+	<view class="hall-page">
+		<view class="hall-page__header" :style="{ paddingTop: statusBarHeight + 'px' }">
+			<view class="hall-page__user-row">
+				<view class="hall-page__user">
+					<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>
-				<image src="/static/bg_a.png" mode="widthFix"></image>
+				<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="centerUserInfo.fullImgUrl || '/static/image/ic_pic@2x.png'" mode="aspectFill"></image>
+					<text class="hall-page__name">{{ centerUserInfo.name }}</text>
+				</view>
 			</view>
-			<view class="index_list_item">
-				<view class="index_list_item_info">
-					<text>璺岀粖婊戦闄╀笂鎶�</text>
-					<text>TAG</text>
+
+			<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">{{ userInfo.auditStatus === 3 ? item.value : '-' }}</text>
+					<text class="hall-page__stat-label">{{ item.label }}</text>
 				</view>
-				<image src="/static/bg_b.png" mode="widthFix"></image>
+			</view>
+
+			<view class="hall-page__tabs">
+				<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">{{ userInfo.auditStatus === 3 ? tab.count : '' }}</text>
+					<view v-if="activeTab === tab.value" class="hall-page__tab-line"></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>
+				</view>
 			</view>
 		</view>
+
+		<view v-if="showFilterPopup" class="filter-popup" :style="{ top: headerHeight + 'px', bottom: tabbarHeight + 'px' }" @click="toggleFilterPopup(false)">
+			<view class="filter-popup__panel" @click.stop>
+				<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>
+				</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>
+					<button class="filter-popup__button filter-popup__button--confirm" hover-class="filter-popup__button--hover" @click="confirmFilters">纭</button>
+				</view>
+			</view>
+		</view>
+
+		<scroll-view class="hall-page__body" scroll-y :style="bodyStyle">
+			<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 && 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.remainMinutes }}</text>
+							<text class="order-card__time-sub">鍒嗛挓</text>
+						</view>
+						<view v-if="activeTab === 'hall'" class="order-card__price-wrap">
+							<text class="order-card__price">楼{{ (item.driverFee / 100).toFixed(1) }}</text>
+						</view>
+						<view v-else class="order-card__price-wrap order-card__price-wrap--serial-only">
+							<text v-if="item.code" class="order-card__serial">#{{ index + 1 }}</text>
+						</view>
+					</view>
+
+					<view class="order-card__meta">
+						<view class="order-card__tags">
+							<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' && item.urgentAmount" class="order-card__extra">鍚姞鎬ヂ{ item.urgentAmount / 100 }}</text>
+					</view>
+
+					<view class="order-card__route">
+						<view class="order-card__route-side">
+							<text class="order-card__distance-top">{{ item.depositDistance }}</text>
+							<view class="order-card__line"></view>
+							<text class="order-card__distance-bottom">{{ item.takeDistance }}</text>
+						</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.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>
+							</view>
+							<view class="order-card__route-item order-card__route-item--destination">
+								<view class="order-card__route-texts">
+									<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>
+							</view>
+						</view>
+					</view>
+
+					<view class="order-card__goods" v-if="item.items && item.items.length > 0">
+						<text class="order-card__goods-text">{{ item.items ? item.items.map(i => `${i.name}*${i.quantity}`).join('銆�') : '鏃�' }}</text>
+						<text class="order-card__goods-arrow">鈱�</text>
+					</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="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="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="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="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="handleShowPickupCode(item)">瀛樹欢鐮�</button>
+						</template>
+						<button v-else class="order-card__button" hover-class="order-card__button--hover" @click="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>
+			</view>
+		</scroll-view>
+		
+		<!-- 鍙栨秷璁㈠崟 -->
+		<u-modal
+			:show="show"
+			showCancelButton
+			@cancel="show = false"
+			cancelColor="#666666"
+			confirmColor="#0055FF"
+			title="鍙栨秷璁㈠崟纭"
+			@confirm="confirmCancelOrder">
+			<view style="text-align: center;color: #333333;font-size: 28rpx;font-weight: 400;">
+				鎮ㄤ粖鏃ヨ繕鍙彇娑� {{ 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>{{ activeTab === 'delivering' ? '瀛樹欢鐮�' : '鍙栬揣鐮�' }}</text>
+					<image src="/static/image/ic_close@2x.png" mode="widthFix" @click="show1 = false"></image>
+				</view>
+				<view class="qrcode-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="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 {
-		computed: {
-			...mapState(['userInfo'])
-		},
 		data() {
 			return {
-				title: 'Hello'
+				tts: null,
+				show: false,
+				show1: false,
+				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',
+				categoryList: [],
+				filterSections: [
+					{ key: 'sort', title: '鎺掑簭', options: ['缁煎悎鎺掑簭', '璺濈鏈�杩�'] },
+					{ key: 'level', title: '鐗╁搧绛夌骇', options: ['涓嶉檺'] },
+					{ key: 'distance', title: '浣嶇疆鑼冨洿', options: ['涓嶉檺', '500m', '1km', '2km', '3km', '4km', '5km', '6km', '7km'] }
+				],
+				selectedFilters: {
+					sort: '缁煎悎鎺掑簭',
+					level: '涓嶉檺',
+					distance: '涓嶉檺'
+				},
+				stats: [
+					{ value: '-', label: '鏈嶅姟鍒�' },
+					{ value: '-', label: '浠婃棩棰勮浣i噾' },
+					{ value: '-', label: '浠婃棩鎺ュ崟' }
+				],
+				tabs: [
+					{ label: '鎶㈠崟澶у巺', value: 'hall' },
+					{ label: '寰呭彇璐�', value: 'pickup' },
+					{ label: '閰嶉�佷腑', value: 'delivering' }
+				],
+				orderList: [],
+				pickupOrderList: [],
+				deliveringOrderList: [],
+				hallPage: 1,
+				hallPageSize: 10,
+				hallLoading: false,
+				hallHasMore: true,
+				pickupLoading: false,
+				deliveringLoading: false,
+				activeOrderCount: null
 			}
 		},
-		onLoad() {
 
+		watch: {
+			activeTab(newVal) {
+				this.loadOrdersByTab(newVal)
+			}
 		},
-		methods: {
-			jump(type) {
-				switch (type) {
-					case 1:
-						uni.navigateTo({
-							url: '/pages/reporting_she/reporting_she'
-						})
-						break;
-					case 2:
-						uni.navigateTo({
-							url: '/pages/riskReporting/riskReporting'
-						})
-						break;
-					case 3:
-						uni.navigateTo({
-							url: '/pages/report_dca/report_dca'
-						})
-						break;
+
+		onLoad() {
+			const systemInfo = uni.getSystemInfoSync()
+			const safeBottom = systemInfo.safeAreaInsets ? systemInfo.safeAreaInsets.bottom || 0 : 0
+			const windowHeight = systemInfo.windowHeight || 0
+			this.statusBarHeight = systemInfo.statusBarHeight || 0
+			this.headerHeight = this.statusBarHeight + uni.upx2px(308)
+			this.tabbarHeight = uni.upx2px(100) + safeBottom
+			this.scrollHeight = Math.max(windowHeight - this.headerHeight, 0)
+			this.loadOrdersByTab(this.activeTab)
+		},
+
+		onShow() {
+			this.getCenterInfo()
+			this.getCategoryListData()
+			this.getActiveOrderCount()
+		},
+
+		onReachBottom() {
+			if (this.activeTab === 'hall') {
+				this.hallPage++
+				this.getHallOrders()
+			}
+		},
+
+		computed: {
+			...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,
+					pickup: this.pickupOrderList,
+					delivering: this.deliveringOrderList
 				}
+
+				return orderMap[this.activeTab] || []
+			},
+
+			bodyStyle() {
+				return {
+					marginTop: this.headerHeight + 'px',
+					height: this.scrollHeight + 'px'
+				}
+			}
+		},
+
+		onReady() {
+			this.initTTS() // 椤甸潰娓叉煋瀹屾垚鍒濆鍖栬闊�
+		},
+
+		methods: {
+			getActiveOrderCount() {
+				this.$u.api.activeOrderCount().then(res => {
+					if (res.code === 200) {
+						this.activeOrderCount = res.data
+					}
+				}).catch((err) => {
+					this.activeOrderCount = null
+				})
+			},
+
+			handleGrabOrder(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) {
+				uni.navigateTo({
+					url: `/pages/order-detail/order-detail?id=${item.id}&index=${index + 1}`
+				})
+			},
+
+			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 (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.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.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.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.getCenterInfo()
+					}
+				})
+			},
+
+			toDriverCertification() {
+				uni.navigateTo({
+					url: '/pages/driver-certification/driver-certification'
+				})
+			},
+
+			toggleFilterPopup(show) {
+				this.showFilterPopup = show
+			},
+
+			selectFilter(key, option) {
+				this.selectedFilters = {
+					...this.selectedFilters,
+					[key]: option
+				}
+			},
+
+			resetFilters() {
+				this.selectedFilters = {
+					sort: '缁煎悎鎺掑簭',
+					level: '涓嶉檺',
+					distance: '涓嶉檺'
+				}
+				this.showFilterPopup = false
+				if (this.activeTab === 'hall') {
+					this.hallPage = 1
+					this.hallHasMore = true
+					this.orderList = []
+					this.getHallOrders()
+				}
+			},
+
+			confirmFilters() {
+				this.showFilterPopup = false
+				if (this.activeTab === 'hall') {
+					this.hallPage = 1
+					this.hallHasMore = true
+					this.orderList = []
+					this.getHallOrders()
+				}
+			},
+
+			initTTS() {
+				if (uni.getSystemInfoSync().platform !== 'android') {
+					console.log('浠呮敮鎸佸畨鍗�')
+					return
+				}
+
+				try {
+					// 瀵煎叆瀹夊崜鍘熺敓绫�
+					const TextToSpeech = plus.android.importClass('android.speech.tts.TextToSpeech')
+					const Locale = plus.android.importClass('java.util.Locale')
+
+					// 鍒涘缓TTS
+					this.tts = new TextToSpeech(plus.android.runtimeMainActivity(), {
+						onInit: (status) => {
+							if (status == 0) {
+								// 璁剧疆涓枃
+								this.tts.setLanguage(Locale.CHINA)
+								console.log('璇煶鍒濆鍖栨垚鍔�')
+							}
+						}
+					})
+				} catch (e) {
+					console.log('鍒濆鍖栧け璐�', e)
+				}
+			},
+
+			speak(text) {
+				if (!this.tts) {
+					uni.showToast({
+						title: '璇煶鏈噯澶囧ソ',
+						icon: 'none'
+					})
+					return
+				}
+
+				try {
+					// 瀹夊崜鍘熺敓鎾姤锛圦UEUE_FLUSH = 绔嬪嵆鎾姤锛屾墦鏂笂涓�鏉★級
+					this.tts.speak(text, 0, null)
+				} catch (err) {
+					console.log('鎾姤澶辫触', err)
+				}
+			},
+
+			stopSpeak() {
+				if (this.tts) this.tts.stop()
+			}
+		},
+
+		onUnload() {
+			if (this.tts) {
+				this.tts.stop()
+				this.tts.shutdown()
 			}
 		}
 	}
 </script>
 
 <style lang="scss" scoped>
-	.index {
-		width: 100vw;
-		padding: 30rpx;
-		box-sizing: border-box;
-		height: calc(100vh - 44px - 50px);
-		background: linear-gradient( 180deg, #B5D2FF 0%, #FFFFFF 100%);
-		.index_list {
-			width: 100%;
-			display: flex;
-			flex-direction: column;
-			margin-top: 12rpx;
-			.index_list_item {
+	.hall-page {
+		position: relative;
+		height: 100vh;
+		background: #f5f6f8;
+		overflow: hidden;
+
+		.qrcode {
+			padding: 36rpx 30rpx;
+			box-sizing: border-box;
+			.qrcode-title {
 				width: 100%;
-				height: 200rpx;
-				margin-bottom: 30rpx;
-				position: relative;
-				.index_list_item_info {
-					width: 100%;
-					height: 100%;
-					padding: 0 48rpx;
-					box-sizing: border-box;
-					display: flex;
-					justify-content: center;
-					flex-direction: column;
-					position: relative;
-					z-index: 99;
-					text {
-						&:nth-child(1) {
-							font-weight: bold;
-							font-size: 34rpx;
-							color: #FFFFFF;
-						}
-						&:nth-child(2) {
-							font-weight: 400;
-							font-size: 26rpx;
-							color: rgba(255,255,255,0.6);
-							margin-top: 10rpx;
-						}
-					}
-				}
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
 				image {
-					width: 100%;
-					height: 100%;
-					position: absolute;
-					top: 0;
-					left: 0;
+					width: 28rpx;
+					height: 28rpx;
+				}
+				text {
+					font-weight: 600;
+					font-size: 32rpx;
+					color: #111111;
 				}
 			}
+			.qrcode-image {
+				width: 100%;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				margin-top: 60rpx;
+				image {
+					width: 400rpx;
+					height: 400rpx;
+				}
+			}
+			.qrcode-btn {
+				width: 100%;
+				height: 88rpx;
+				line-height: 88rpx;
+				text-align: center;
+				background: #106EFA;
+				border-radius: 50rpx;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				margin-top: 68rpx;
+
+				&--hover {
+					opacity: 0.92;
+					transform: translateY(2rpx);
+				}
+			}
+		}
+
+		.photo-deliver {
+			padding: 32rpx 28rpx calc(env(safe-area-inset-bottom) + 28rpx);
+			background: #ffffff;
+			box-sizing: border-box;
+			border-top-left-radius: 20rpx;
+			border-top-right-radius: 20rpx;
+			overflow: hidden;
+
+			&__header {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+			}
+
+			&__title {
+				font-size: 34rpx;
+				font-weight: 700;
+				color: #111111;
+			}
+
+			&__close,
+			&__close-placeholder {
+				width: 36rpx;
+				height: 36rpx;
+				flex-shrink: 0;
+			}
+
+			&__close-placeholder {
+				opacity: 0;
+			}
+
+			&__section {
+				margin-top: 56rpx;
+
+				&--remark {
+					margin-top: 46rpx;
+				}
+			}
+
+			&__label-row {
+				display: flex;
+				align-items: center;
+				flex-wrap: wrap;
+			}
+
+			&__label,
+			&__remark-title {
+				font-size: 28rpx;
+				font-weight: 700;
+				color: #23262d;
+			}
+
+			&__required {
+				margin-left: 4rpx;
+				font-size: 28rpx;
+				font-weight: 700;
+				color: #ff3b30;
+			}
+
+			&__hint {
+				margin-left: 12rpx;
+				font-size: 24rpx;
+				color: #a8adb7;
+			}
+
+			&__photos {
+				display: flex;
+				gap: 18rpx;
+				margin-top: 30rpx;
+			}
+
+			&__upload-card,
+			&__preview-card {
+				position: relative;
+				width: 160rpx;
+				height: 160rpx;
+				border-radius: 8rpx;
+				overflow: hidden;
+			}
+
+			&__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%;
+			}
+
+			&__preview-mask {
+				position: absolute;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				height: 48rpx;
+				background: rgba(0, 0, 0, 0.46);
+			}
+
+			&__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: 32rpx;
+				font-weight: 700;
+				color: #ffffff;
+				border: 0;
+				padding: 0;
+
+				&::after {
+					border: 0;
+				}
+
+				&--hover {
+					opacity: 0.92;
+				}
+			}
+		}
+
+		&__header {
+			position: fixed;
+			left: 0;
+			top: 0;
+			right: 0;
+			z-index: 10;
+			background: linear-gradient(180deg, #2473f5 0%, #1e6fef 100%);
+			box-shadow: 0 12rpx 24rpx rgba(36, 115, 245, 0.08);
+		}
+
+		&__user-row {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 20rpx 24rpx 0;
+		}
+
+		&__user {
+			display: flex;
+			align-items: center;
+			gap: 14rpx;
+		}
+
+		&__avatar {
+			width: 42rpx;
+			height: 42rpx;
+			border-radius: 50%;
+			border: 2rpx solid rgba(255, 255, 255, 0.7);
+		}
+
+		&__name {
+			font-size: 28rpx;
+			font-weight: 500;
+			color: #ffffff;
+		}
+
+		&__status {
+			display: flex;
+			align-items: center;
+			padding: 10rpx 16rpx;
+			border-radius: 999rpx;
+			background: rgba(255, 255, 255, 0.16);
+			backdrop-filter: blur(10rpx);
+		}
+
+		&__status-dot {
+			width: 14rpx;
+			height: 14rpx;
+			border-radius: 50%;
+			background: #32d74b;
+			margin-right: 10rpx;
+
+			&--offline {
+				background: #ff3b30;
+			}
+		}
+
+		&__status-text,
+		&__status-arrow {
+			font-size: 24rpx;
+			color: #ffffff;
+		}
+
+		&__status-arrow {
+			font-size: 18rpx;
+			margin-left: 8rpx;
+		}
+
+		&__stats {
+			display: flex;
+			justify-content: space-between;
+			padding: 34rpx 36rpx 28rpx;
+		}
+
+		&__stat-item {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			min-width: 160rpx;
+		}
+
+		&__stat-value {
+			font-size: 52rpx;
+			line-height: 1;
+			font-weight: 700;
+			color: #ffffff;
+		}
+
+		&__stat-label {
+			margin-top: 12rpx;
+			font-size: 26rpx;
+			color: rgba(255, 255, 255, 0.86);
+		}
+
+		&__tabs {
+			display: flex;
+			align-items: center;
+			height: 88rpx;
+			padding: 0 18rpx;
+			background: #ffffff;
+		}
+
+		&__tab {
+			position: relative;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			height: 100%;
+			padding: 0 18rpx;
+			font-size: 32rpx;
+			color: #8b9099;
+		}
+
+		&__tab--active {
+			color: #242933;
+			font-weight: 700;
+		}
+
+		&__tab-text {
+			font-size: inherit;
+			color: inherit;
+		}
+
+		&__tab-count {
+			margin-left: 6rpx;
+			font-size: 28rpx;
+			color: #8b9099;
+		}
+
+		&__tab-line {
+			position: absolute;
+			left: 18rpx;
+			right: 18rpx;
+			bottom: 0;
+			height: 5rpx;
+			border-radius: 999rpx;
+			background: #2473f5;
+		}
+
+		&__filter {
+			margin-left: auto;
+			display: flex;
+			align-items: center;
+			gap: 6rpx;
+			padding-right: 10rpx;
+		}
+
+		&__filter-text {
+			font-size: 28rpx;
+			color: #9aa1ab;
+
+			&--active {
+				color: #106efa;
+			}
+		}
+		&__filter-icon {
+			width: 28rpx;
+			height: 28rpx;
+		}
+
+		&__body {
+			box-sizing: border-box;
+			background-color: #F6F9FF;
+		}
+
+		&__list {
+			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 {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			height: 100%;
+			padding-bottom: env(safe-area-inset-bottom);
+			box-sizing: border-box;
+		}
+
+		&__empty-icon {
+			width: 320rpx;
+			height: 320rpx;
+		}
+	}
+
+	.filter-popup {
+		position: fixed;
+		left: 0;
+		right: 0;
+		z-index: 20;
+		background: rgba(0, 0, 0, 0.24);
+
+		&__panel {
+			display: flex;
+			flex-direction: column;
+			height: 100%;
+			background: #ffffff;
+			border-bottom-left-radius: 28rpx;
+			border-bottom-right-radius: 28rpx;
+		}
+
+		&__content {
+			flex: 1;
+			overflow-y: auto;
+			padding: 22rpx 18rpx 0;
+		}
+
+		&__section {
+			margin-bottom: 28rpx;
+		}
+
+		&__title {
+			display: block;
+			margin-bottom: 20rpx;
+			font-size: 28rpx;
+			font-weight: 700;
+			color: #252b33;
+		}
+
+		&__options {
+			display: flex;
+			flex-wrap: wrap;
+			gap: 18rpx 20rpx;
+		}
+
+		&__option {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 226rpx;
+			height: 74rpx;
+			border-radius: 10rpx;
+			background: #f5f5f5;
+			border: 2rpx solid transparent;
+			box-sizing: border-box;
+
+			&--active {
+				background: #edf5ff;
+				border-color: #3d8cff;
+			}
+		}
+
+		&__option-text {
+			font-size: 28rpx;
+			color: #4b515a;
+
+			.filter-popup__option--active & {
+				font-weight: 600;
+				color: #2678ff;
+			}
+		}
+
+		&__actions {
+			flex-shrink: 0;
+			display: flex;
+			gap: 24rpx;
+			padding: 8rpx 18rpx 26rpx;
+		}
+
+		&__button {
+			flex: 1;
+			height: 92rpx;
+			line-height: 92rpx;
+			border-radius: 999rpx;
+			font-size: 34rpx;
+			font-weight: 700;
+			border: 0;
+			padding: 0;
+
+			&::after {
+				border: 0;
+			}
+
+			&--reset {
+				background: #ebebeb;
+				color: #777d86;
+			}
+
+			&--confirm {
+				background: linear-gradient(180deg, #2d82ff 0%, #206ef6 100%);
+				color: #ffffff;
+			}
+
+			&--hover {
+				opacity: 0.92;
+			}
+		}
+	}
+
+	.order-card {
+		margin-bottom: 20rpx;
+		padding: 20rpx;
+		border-radius: 24rpx;
+		background: #ffffff;
+		box-shadow: 0 10rpx 24rpx rgba(26, 44, 81, 0.04);
+
+		&__head {
+			display: flex;
+			justify-content: space-between;
+			align-items: flex-start;
+		}
+
+		&__time-main {
+			font-size: 42rpx;
+			font-weight: 700;
+			color: #ff8d27;
+		}
+
+		&__time-sub {
+			margin-left: 8rpx;
+			font-size: 28rpx;
+			color: #a3a8b2;
+		}
+
+		&__price-wrap {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			gap: 8rpx;
+
+			&--serial-only {
+				justify-content: flex-start;
+				min-width: 54rpx;
+			}
+		}
+
+		&__serial {
+			font-size: 38rpx;
+			font-weight: 700;
+			line-height: 1;
+			color: #2c3139;
+		}
+
+		&__price {
+			font-size: 44rpx;
+			font-weight: 700;
+			color: #ff3b30;
+		}
+
+		&__meta {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			gap: 16rpx;
+			margin-top: 12rpx;
+		}
+
+		&__extra {
+			flex-shrink: 0;
+			font-size: 24rpx;
+			color: #a0a5af;
+		}
+
+		&__tags {
+			display: flex;
+			flex: 1;
+			flex-wrap: wrap;
+			gap: 10rpx;
+		}
+
+		&__tag-wrap {
+			display: flex;
+			align-items: center;
+		}
+
+		&__tag-icon {
+			width: 108rpx;
+			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: none;
+				background: linear-gradient(319deg, #EE9D0E 0%, #FF4E4E 100%);
+				color: #ffffff;
+			}
+
+			&--red {
+				border-color: #ff6c57;
+				color: #ff6c57;
+			}
+
+			&--blue-light {
+				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 {
+			display: flex;
+			margin-top: 20rpx;
+		}
+
+		&__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: 86rpx;
+			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: 16rpx;
+
+			&--destination {
+				margin-top: 20rpx;
+			}
+		}
+
+		&__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;
+		}
+
+		&__nav {
+			width: 48rpx;
+			height: 48rpx;
+			flex-shrink: 0;
+		}
+
+		&__goods {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			height: 70rpx;
+			padding: 0 20rpx;
+			margin-top: 20rpx;
+			border-radius: 16rpx;
+			background: #f4f5f7;
+		}
+
+		&__goods-text {
+			flex: 1;
+			font-size: 28rpx;
+			color: #7a818d;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+
+		&__goods-arrow {
+			margin-left: 12rpx;
+			font-size: 24rpx;
+			color: #a4a9b1;
+		}
+
+		&__button {
+			margin-top: 24rpx;
+			width: 100%;
+			height: 88rpx;
+			line-height: 88rpx;
+			border-radius: 999rpx;
+			background: linear-gradient(180deg, #2b7fff 0%, #1f6ff3 100%);
+			font-size: 34rpx;
+			font-weight: 700;
+			color: #ffffff;
+			border: 0;
+			padding: 0;
+
+			&::after {
+				border: 0;
+			}
+
+			&--hover {
+				opacity: 0.92;
+			}
+		}
+
+		&__actions {
+			margin-top: 24rpx;
+
+			&--pickup,
+			&--delivering {
+				display: flex;
+				align-items: center;
+				gap: 22rpx;
+			}
+		}
+
+		&__icon-actions {
+			display: flex;
+			align-items: center;
+			gap: 20rpx;
+			flex-shrink: 0;
+
+			&--single {
+				gap: 0;
+			}
+		}
+
+		&__icon-action {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			justify-content: center;
+			width: 74rpx;
+		}
+
+		&__action-icon {
+			width: 40rpx;
+			height: 40rpx;
+			border-radius: 8rpx;
+			background: #f7f8fa;
+		}
+
+		&__action-text {
+			margin-top: 8rpx;
+			font-size: 26rpx;
+			line-height: 1;
+			color: #5b616b;
+		}
+
+		&__button--code {
+			flex: 1;
+			margin-top: 0;
 		}
 	}
 </style>

--
Gitblit v1.9.3