收藏
回答

运行正常 为啥无法上传?

报错提示
message:Error: 非法的文件,错误信息:invalid file: pages/index/Order-Processing.js, 1:3179, SyntaxError: Unexpected token ?"use strict";const e=require("../../common/vendor.js"),t=require("../../utils/config.js"),s={data:()=>({keyword:"",searchType:"order_no",showTypePicker:!1,searchTypes:[{label:"订单号",key:"order_no"},{label:"客户姓名",key:"nickname"},{label:"手机号",key:"mobile"},{label:"商品名称",key:"goods_name"}],orderList:[],page:1,total:0,loading:!1,refreshing:!1,noMore:!1,currentStatus:-1,shipPopup:null,shipOrder:null,shipMode:1,shipGoodsList:[],shipping:!1,shipForm:{express_id:null,express_name:"",express_no:"",remark:""},expressList:[],expressLoading:!1,showExpressPicker:!1,logisticsPopup:null,logisticsPackages:[],logisticsPkgIndex:0,currentTrack:null,logisticsLoading:!1,showAfterSaleSheet:!1,afterSaleOrder:null,cancelPopup:null,cancelOrder:null,cancelGoodsList:[],cancelSelectedIds:[],tabList:[{name:"全部",status:-1,countKey:"total",count:0},{name:"待到货",status:1,countKey:"pending",count:0},{name:"待补款",status:2,countKey:"unpai... [20260408 17:27:55][wx3ea54ec4fa7cf43a]
appid: wx3ea54ec4fa7cf43a
openid: o6zAJs9Kr1RwvyYPUf4FQkAJn-pY
ideVersion: 2.01.2510260
osType: win32-x64
time: 2026-04-08 17:29:19
<template>
	<view class="content">
		<!-- 搜索栏 -->
		<view class="search-box">
			<view class="search-row">
				<view class="search-select" @click="showTypePicker = true">
					<text>{{currentTypeLabel}}</text>
					<uv-icon name="arrow-down" size="22rpx" color="#666"></uv-icon>
				</view>
				<input class="search-input" v-model="keyword" :placeholder="currentPlaceholder"
					confirm-type="search" @confirm="onSearch" />
				<view class="search-btn" @click="onSearch">搜索</view>
			</view>
		</view>


		<!-- 搜索类型选择器 -->
		<view class="type-mask" v-if="showTypePicker" @click="showTypePicker=false"></view>
		<view class="type-sheet" :class="{show: showTypePicker}">
			<view class="type-sheet-title">选择搜索类型</view>
			<view class="type-sheet-item" v-for="t in searchTypes" :key="t.key"
				:class="{active: searchType === t.key}"
				@click="onSelectType(t)">
				{{t.label}}
				<uv-icon v-if="searchType === t.key" name="checkmark" color="#0D69EF" size="32rpx"></uv-icon>
			</view>
			<view class="type-sheet-cancel" @click="showTypePicker=false">取消</view>
		</view>


		<!-- 状态 Tab -->
		<uv-sticky offset-top="0" bgColor="#fff">
			<uv-tabs :list="tabListDisplay" lineWidth="70rpx" lineColor="#0D69EF" @click="changeTab"></uv-tabs>
		</uv-sticky>


		<!-- 订单列表 -->
		<scroll-view scroll-y class="order-scroll" @scrolltolower="loadMore"
			refresher-enabled @refresherrefresh="onRefresh" :refresher-triggered="refreshing">
			<view class="order-list">
				<view class="order-card" v-for="order in orderList" :key="order.id"
					@click="goDetail(order)">
					<!-- 头部 -->
					<view class="order-head">
						<view class="order-head-left">
							<text class="order-member">{{order.member_info && order.member_info.nickname || '-'}}</text>
							<text class="order-store" v-if="order.store_info">{{order.store_info.name}}</text>
						</view>
						<text class="order-status-tag" :class="'s'+order.order_status">
							{{statusMap[order.order_status] || '-'}}
						</text>
					</view>
					<!-- 订单号 -->
					<view class="order-no-row">
						<text class="order-no">{{order.order_id}}</text>
						<text class="order-type-tag">{{orderTypeMap[order.order_type] || '普通订单'}}</text>
						<text v-if="hasPartialCancelled(order.goods_list)" class="partial-cancel-tag">部分取消</text>
						<text v-if="order.shipping_info && order.shipping_info.length > 0 && order.order_status === 3" class="partial-ship-tag">部分发货</text>
					</view>
					<!-- 商品列表(最多展示2个) -->
					<view class="goods-row" v-for="(g, gi) in (order.goods_list || []).slice(0, 2)" :key="gi">
						<uv-image :src="g.goods_image" radius="8rpx" width="100rpx" height="100rpx" mode="aspectFill"></uv-image>
						<view class="goods-info">
							<text class="goods-name ellipsis1">{{g.goods_name}}</text>
							<text class="goods-spec" v-if="g.spec_data && typeof g.spec_data === 'object' && Object.keys(g.spec_data).length">
								{{formatSpec(g.spec_data)}}
							</text>
							<view class="goods-price-row">
								<text class="goods-price">¥{{g.goods_price}}</text>
								<text class="goods-num">×{{g.goods_num}}</text>
							</view>
						</view>
					</view>
					<view class="more-goods" v-if="(order.goods_list || []).length > 2">
						<text>共{{order.goods_list.length}}件商品</text>
					</view>
					<!-- 底部 -->
					<view class="order-foot">
						<text class="order-time">{{order.order_time}}</text>
						<view class="order-amount">
							<text class="amount-label">实付</text>
							<text class="amount-val">¥{{order.actual_payment}}</text>
						</view>
					</view>
					<!-- 操作按钮 -->
					<view class="order-actions" v-if="getActions(order).length" @click.stop>
						<template v-for="(act, ai) in getActions(order)" :key="ai">
							<view v-if="act.action === 'afterSale'" class="action-btn outline after-sale-btn"
								@click="openAfterSaleSheet(order)">
								售后操作
								<uv-icon name="arrow-down" size="20rpx" color="#666" style="margin-left:4rpx"></uv-icon>
							</view>
							<view v-else class="action-btn" :class="act.type"
								@click="handleAction(act, order)">
								{{act.label}}
							</view>
						</template>
					</view>
				</view>
			</view>


			<view class="load-tip" v-if="orderList.length > 0">
				<text v-if="loading">加载中...</text>
				<text v-else-if="noMore">没有更多了</text>
			</view>
			<view class="empty-box" v-if="!loading && orderList.length === 0">
				<uv-empty mode="order" text="暂无订单"></uv-empty>
			</view>
		</scroll-view>


		<!-- 发货弹窗 -->
		<uv-popup ref="shipPopup" mode="bottom" round="20rpx" :safeAreaInsetBottom="true">
			<view class="ship-popup">
				<view class="ship-popup-header">
					<view>
						<text class="ship-popup-title">订单发货</text>
						<text class="ship-popup-no">{{shipOrder && shipOrder.order_id}}</text>
					</view>
					<uv-icon name="close" size="36rpx" color="#999" @click="shipPopup.close()"></uv-icon>
				</view>


				<!-- 发货模式 -->
				<view class="ship-mode-row">
					<view class="ship-mode-item" :class="{ active: shipMode === 1 }" @click="setShipMode(1)">
						<view class="ship-mode-dot" :class="{ active: shipMode === 1 }"></view>
						<text>整单发货</text>
					</view>
					<view class="ship-mode-item" :class="{ active: shipMode === 2, disabled: !canSplitShip }"
						@click="canSplitShip && setShipMode(2)">
						<view class="ship-mode-dot" :class="{ active: shipMode === 2 }"></view>
						<text>多包裹发货</text>
					</view>
				</view>


				<scroll-view scroll-y style="max-height: 60vh;">
					<!-- 分单模式:商品选择 -->
					<view v-if="shipMode === 2" class="split-goods-section">
						<view class="split-tip">选择本次要发货的商品</view>
						<view v-for="g in shipGoodsList" :key="g.id"
							class="split-goods-item"
							:class="{ selected: g._selected, disabled: g.status === 2 || g._availableQty <= 0 }"
							@click="g.status !== 2 && g._availableQty > 0 && (g._selected = !g._selected)">
							<view class="check-box" :class="{ checked: g._selected }">
								<uv-icon v-if="g._selected" name="checkmark" size="22rpx" color="#fff"></uv-icon>
							</view>
							<uv-image :src="g.goods_image" width="88rpx" height="88rpx" radius="8rpx" mode="aspectFill" style="flex-shrink:0"></uv-image>
							<view class="split-goods-info">
								<view class="split-goods-name-row">
									<text class="split-goods-name">{{g.goods_name}}</text>
									<text v-if="g.status === 2" class="tag-cancelled">已取消</text>
									<text v-else-if="g._shippedQty >= g.goods_num" class="tag-shipped">已发完</text>
									<text v-else-if="g._shippedQty > 0" class="tag-partial">部分发货</text>
								</view>
								<text class="split-goods-spec" v-if="g.spec_data && Object.keys(g.spec_data).length">
									{{Object.entries(g.spec_data).map(([k,v])=>k+':'+v).join(' ')}}
								</text>
								<view class="split-goods-qty-row" v-if="g._selected">
									<text class="split-qty-label">发货数量</text>
									<view class="qty-ctrl">
										<view class="qty-btn" @click.stop="g.ship_qty > 1 && g.ship_qty--"></view>
										<text class="qty-num">{{g.ship_qty}}</text>
										<view class="qty-btn" @click.stop="g.ship_qty < g._availableQty && g.ship_qty++"></view>
									</view>
									<text class="qty-hint">可发 {{g._availableQty}}</text>
								</view>
								<view class="split-goods-qty-row" v-else>
									<text class="qty-hint">总数 {{g.goods_num}},已发 {{g._shippedQty}},可发 {{g._availableQty}}</text>
								</view>
							</view>
						</view>
					</view>


					<!-- 整单模式:商品预览 -->
					<view v-else class="whole-goods-section">
						<view v-for="g in shipGoodsList" :key="g.id"
							class="whole-goods-item" :class="{ cancelled: g.status === 2, shipped: g._availableQty <= 0 && g.status !== 2 }">
							<uv-image :src="g.goods_image" width="80rpx" height="80rpx" radius="8rpx" mode="aspectFill" style="flex-shrink:0"></uv-image>
							<view class="whole-goods-info">
								<view class="whole-goods-name-row">
									<text class="whole-goods-name">{{g.goods_name}}</text>
									<text v-if="g.status === 2" class="tag-cancelled">已取消</text>
									<text v-else-if="g._availableQty <= 0" class="tag-shipped">已发完</text>
									<text v-else-if="g._shippedQty > 0" class="tag-partial">部分发货</text>
								</view>
								<text class="whole-goods-spec" v-if="g.spec_data && Object.keys(g.spec_data).length">
									{{Object.entries(g.spec_data).map(([k,v])=>k+':'+v).join(' ')}}
								</text>
								<view class="whole-goods-price-row">
									<text class="whole-goods-price">¥{{g.goods_price}}</text>
									<text class="whole-goods-qty">x{{g.goods_num}}</text>
									<text class="whole-goods-shipped" v-if="g._shippedQty > 0">已发 {{g._shippedQty}}</text>
								</view>
							</view>
						</view>
					</view>


					<!-- 快递信息 -->
					<view class="ship-form-section">
						<view class="ship-form-item" @click="showExpressPicker = true">
							<text class="ship-form-label">快递公司 <text class="req">*</text></text>
							<view class="ship-form-input-row">
								<text :class="shipForm.express_name ? 'ship-form-val' : 'ship-form-placeholder'">
									{{shipForm.express_name || '请选择快递公司'}}
								</text>
								<uv-icon name="arrow-down" size="24rpx" color="#ccc"></uv-icon>
							</view>
						</view>
						<view class="ship-form-item">
							<text class="ship-form-label">快递单号 <text class="req">*</text></text>
							<input class="ship-form-input" v-model="shipForm.express_no" placeholder="请输入快递单号" />
						</view>
						<view class="ship-form-item">
							<text class="ship-form-label">发货备注</text>
							<input class="ship-form-input" v-model="shipForm.remark" placeholder="选填" />
						</view>
					</view>
				</scroll-view>


				<view class="ship-popup-footer">
					<view class="ship-cancel-btn" @click="shipPopup.close()">取消</view>
					<view class="ship-confirm-btn" :class="{ loading: shipping }" @click="confirmShip">
						{{shipping ? '发货中...' : '确认发货'}}
					</view>
				</view>
			</view>
		</uv-popup>


		<!-- 快递公司选择 -->
		<view class="type-mask" v-if="showExpressPicker" @click="showExpressPicker = false"></view>
		<view class="type-sheet" :class="{ show: showExpressPicker }">
			<view class="type-sheet-title">选择快递公司</view>
			<view v-if="expressLoading" class="type-sheet-loading">
				<uv-loading-icon mode="circle" size="40rpx"></uv-loading-icon>
			</view>
			<view v-else class="type-sheet-item" v-for="e in expressList" :key="e.id"
				:class="{ active: shipForm.express_id === e.id }"
				@click="selectExpress(e)">
				{{e.name}}
				<uv-icon v-if="shipForm.express_id === e.id" name="checkmark" color="#0D69EF" size="32rpx"></uv-icon>
			</view>
			<view class="type-sheet-cancel" @click="showExpressPicker = false">取消</view>
		</view>


		<!-- 物流弹窗 -->
		<uv-popup ref="logisticsPopup" mode="bottom" round="20rpx" :safeAreaInsetBottom="true">
			<view class="cancel-popup">
				<view class="cancel-popup-header">
					<view>
						<text class="cancel-popup-title">查看物流</text>
						<text class="cancel-popup-no" v-if="logisticsPackages.length">共 {{logisticsPackages.length}} 个包裹</text>
					</view>
					<uv-icon name="close" size="36rpx" color="#999" @click="logisticsPopup.close()"></uv-icon>
				</view>


				<!-- 多包裹切换 -->
				<scroll-view v-if="logisticsPackages.length > 1" scroll-x class="pkg-scroll">
					<view class="pkg-list">
						<view v-for="(pkg, pi) in logisticsPackages" :key="pi"
							class="pkg-card" :class="{ active: logisticsPkgIndex === pi }"
							@click="selectPackage(pi)">
							<text class="pkg-company">{{pkg.express_company_name}}</text>
							<text class="pkg-no">{{pkg.express_code}}</text>
							<text class="pkg-time" v-if="pkg.shipping_time">{{pkg.shipping_time}}</text>
						</view>
					</view>
				</scroll-view>


				<!-- 单包裹信息头 -->
				<view v-else-if="logisticsPackages.length === 1" class="single-pkg-info">
					<text class="single-pkg-company">{{logisticsPackages[0].express_company_name}}</text>
					<text class="single-pkg-no">{{logisticsPackages[0].express_code}}</text>
				</view>


				<scroll-view scroll-y style="max-height: 55vh;">
					<view v-if="logisticsLoading" class="loading-row">
						<uv-loading-icon mode="circle" size="40rpx"></uv-loading-icon>
					</view>
					<view v-else-if="currentTrack && currentTrack.data && currentTrack.data.length">
						<view class="logistics-list">
							<view class="logistics-item" v-for="(item, i) in currentTrack.data" :key="i"
								:class="{ first: i === 0 }">
								<view class="logistics-dot-wrap">
									<view class="logistics-dot" :class="{ active: i === 0 }"></view>
									<view class="logistics-line" v-if="i < currentTrack.data.length - 1"></view>
								</view>
								<view class="logistics-content">
									<text class="logistics-time">{{item.time || item.ftime}}</text>
									<text class="logistics-context">{{item.context}}</text>
								</view>
							</view>
						</view>
					</view>
					<view v-else class="logistics-empty">
						<view v-if="currentTrack">
							<text class="logistics-no">快递单号:{{currentTrack.nu}}</text>
							<text class="logistics-company">快递公司:{{currentTrack.company}}</text>
							<text class="logistics-msg">{{currentTrack.message || '暂无物流信息'}}</text>
						</view>
						<uv-empty v-else-if="!logisticsLoading" mode="search" text="暂无物流信息" iconSize="120rpx"></uv-empty>
					</view>
				</scroll-view>
			</view>
		</uv-popup>


		<!-- 售后操作 sheet -->
		<view class="type-mask" v-if="showAfterSaleSheet" @click="showAfterSaleSheet=false"></view>
		<view class="type-sheet" :class="{ show: showAfterSaleSheet }">
			<view class="type-sheet-title">售后操作</view>
			<view class="type-sheet-item" @click="doAfterSale('refundWithReturn')">退货退款</view>
			<view class="type-sheet-item" @click="doAfterSale('refundOnly')">仅退款</view>
			<view class="type-sheet-item" @click="doAfterSale('exchange')">换货</view>
			<view class="type-sheet-cancel" @click="showAfterSaleSheet=false">取消</view>
		</view>


		<!-- 取消订单弹窗 -->
		<uv-popup ref="cancelPopup" mode="bottom" round="20rpx" :safeAreaInsetBottom="true">
			<view class="cancel-popup">
				<view class="cancel-popup-header">
					<view>
						<text class="cancel-popup-title">取消订单商品</text>
						<text class="cancel-popup-no">{{cancelOrder && cancelOrder.order_id}}</text>
					</view>
					<uv-icon name="close" size="36rpx" color="#999" @click="cancelPopup.close()"></uv-icon>
				</view>
				<scroll-view scroll-y style="max-height: 55vh;">
					<view class="cancel-goods-list">
						<view v-for="g in cancelGoodsList" :key="g.id"
							class="cancel-goods-item"
							:class="{ selected: cancelSelectedIds.includes(g.id), disabled: g.status === 2 }"
							@click="g.status !== 2 && toggleCancelGoods(g.id)">
							<view class="check-box" :class="{ checked: cancelSelectedIds.includes(g.id) }">
								<uv-icon v-if="cancelSelectedIds.includes(g.id)" name="checkmark" size="22rpx" color="#fff"></uv-icon>
							</view>
							<uv-image :src="g.goods_image" width="96rpx" height="96rpx" radius="8rpx" mode="aspectFill" style="flex-shrink:0"></uv-image>
							<view class="cancel-goods-info">
								<view class="cancel-goods-name-row">
									<text class="cancel-goods-name">{{g.goods_name}}</text>
									<text v-if="g.status === 2" class="cancelled-tag">已取消</text>
								</view>
								<text class="cancel-goods-spec" v-if="g.spec_data && Object.keys(g.spec_data).length">
									{{Object.entries(g.spec_data).map(([k,v])=>k+':'+v).join(' ')}}
								</text>
								<view class="cancel-goods-price-row">
									<text class="cancel-goods-price">¥{{g.goods_price}}</text>
									<text class="cancel-goods-qty">x{{g.goods_num}}</text>
								</view>
							</view>
						</view>
					</view>
				</scroll-view>
				<view class="cancel-popup-footer">
					<text class="cancel-selected-tip" v-if="cancelSelectedIds.length">已选 {{cancelSelectedIds.length}} 件</text>
					<text class="cancel-selected-tip" v-else>请选择要取消的商品</text>
					<view class="cancel-confirm-btn"
						:class="{ disabled: !cancelSelectedIds.length }"
						@click="confirmCancelOrder">
						确认取消
					</view>
				</view>
			</view>
		</uv-popup>
	</view>
</template>


<script>
	import allConfig from "@/utils/config.js"


	export default {
		data() {
			return {
				keyword: '',
				searchType: 'order_no',
				showTypePicker: false,
				searchTypes: [
					{ label: '订单号', key: 'order_no' },
					{ label: '客户姓名', key: 'nickname' },
					{ label: '手机号', key: 'mobile' },
					{ label: '商品名称', key: 'goods_name' },
				],
				orderList: [],
				page: 1,
				total: 0,
				loading: false,
				refreshing: false,
				noMore: false,
				currentStatus: -1,


				shipPopup: null,
				shipOrder: null,
				shipMode: 1,
				shipGoodsList: [],
				shipping: false,
				shipForm: { express_id: null, express_name: '', express_no: '', remark: '' },


				expressList: [],
				expressLoading: false,
				showExpressPicker: false,


				logisticsPopup: null,
				logisticsPackages: [],
				logisticsPkgIndex: 0,
				currentTrack: null,
				logisticsLoading: false,


				showAfterSaleSheet: false,
				afterSaleOrder: null,


				cancelPopup: null,
				cancelOrder: null,
				cancelGoodsList: [],
				cancelSelectedIds: [],


				tabList: [
					{ name: '全部',   status: -1countKey: 'total',     count: 0 },
					{ name: '待到货', status: 1,   countKey: 'pending',   count: 0 },
					{ name: '待补款', status: 2,   countKey: 'unpaid',    count: 0 },
					{ name: '待发货', status: 3,   countKey: 'unshipped', count: 0 },
					{ name: '已发货', status: 4,   countKey: 'shipped',   count: 0 },
					{ name: '售后中', status: 5,   countKey: 'aftersale', count: 0 },
					{ name: '已完成', status: 6,   countKey: 'completed', count: 0 },
					{ name: '已退款', status: 7,   countKey: 'refunded'count: 0 },
					{ name: '已取消', status: 8,   countKey: 'cancelled', count: 0 },
					{ name: '已报损', status: 9,   countKey: 'damaged',   count: 0 },
					{ name: '售后记录',status: 10, countKey: 'sales',     count: 0 },
					{ name: '售后订单',status: 11, countKey: 'sale',      count: 0 },
				],
				statusMap: { 1:'待到货', 2:'待补款', 3:'待发货', 4:'已发货', 5:'售后中', 6:'已完成', 7:'已退款', 8:'已取消', 9:'已报损', 10:'售后记录', 11:'售后订单' },
				orderTypeMap: { 1:'正常订单', 2:'售后订单', 3:'换货订单' },


				CANCEL_ROLES: ['superAdmin', 'admin', 'dzAdmin', 'cw', 'hg'],
				AFTERSALE_ROLES: ['superAdmin', 'admin', 'dzAdmin', 'cw'],
				AUDIT_ROLES: ['superAdmin', 'admin', 'cw', 'ckxd', 'hg', 'sy', 'shsh'],
			}
		},
		computed: {
			currentTypeLabel() {
				const t = this.searchTypes.find(item => item.key === this.searchType)
				return t ? t.label : '订单号'
			},
			currentPlaceholder() {
				return `请输入${this.currentTypeLabel}`
			},
			tabListDisplay() {
				return this.tabList.map(t => ({ ...t, name: `${t.name}(${t.count})` }))
			},
			canSplitShip() {
				const list = this.shipOrder?.goods_list || []
				const available = list.filter(g => g.status !== 2)
				if (available.length === 0) return false
				if (available.length === 1 && available[0].goods_num === 1) return false
				return true
			},
		},
		onShow() {
			this.fetchStatusCount()
			this.resetAndLoad()
		},
		methods: {
			baseUrl(path) {
				// #ifdef APP-PLUS||MP-WEIXIN
				return allConfig + path
				// #endif
				return path
			},
			formatSpec(specData) {
				if (!specData || typeof specData !== 'object') return ''
				if (Array.isArray(specData)) return ''
				return Object.entries(specData).map(([k, v]) => `${k}${v}`).join('  ')
			},
			hasPartialCancelled(goodsList) {
				if (!goodsList || !goodsList.length) return false
				const cancelledCount = goodsList.filter(g => g.status === 2).length
				return cancelledCount > 0 && cancelledCount < goodsList.length
			},
			onSelectType(t) {
				this.searchType = t.key
				this.keyword = ''
				this.showTypePicker = false
			},
			onSearch() {
				this.resetAndLoad()
			},
			onRefresh() {
				this.refreshing = true
				this.resetAndLoad()
			},
			loadMore() {
				if (this.noMore || this.loading) return
				this.page++
				this.fetchOrders()
			},
			changeTab(e) {
				this.currentStatus = this.tabList[e.index].status
				this.resetAndLoad()
			},
			goDetail(order) {
				uni.navigateTo({ url: `/pagesA/order/order-details?id=${order.id}` })
			},
			resetAndLoad() {
				this.page = 1
				this.noMore = false
				this.orderList = []
				this.fetchOrders()
			},
			fetchStatusCount() {
				const token = uni.getStorageSync('TOKEN')
				uni.request({
					url: this.baseUrl('/prod/admin/order/Orders/statusCount'),
					method: 'POST',
					header: { 'authori-zation': token },
					success: (res) => {
						if (res.data.code === 200) {
							const d = res.data.data
							this.tabList.forEach(tab => {
								tab.count = d[tab.countKey] ?? 0
							})
						}
					}
				})
			},
			fetchOrders() {
				if (this.loading) return
				this.loading = true
				const token = uni.getStorageSync('TOKEN')
				let url = this.baseUrl('/prod/admin/order/Orders/index')
				url += `?page=${this.page}&limit=10&orderBy=id&orderType=desc`
				url += `&order_status=${this.currentStatus}`
				if (this.keyword) url += `&${this.searchType}=${encodeURIComponent(this.keyword)}`
				uni.request({
					url, method: 'GET',
					header: { 'authori-zation': token },
					success: (res) => {
						if (res.data.code === 200) {
							const d = res.data.data
							const list = d.data || []
							this.total = d.total || 0
							this.orderList = this.page === 1 ? list : [...this.orderList, ...list]
							this.noMore = this.orderList.length >= this.total
						}
					},
					complete: () => { this.loading = false; this.refreshing = false }
				})
			},
			getUserRoles() {
				const info = uni.getStorageSync('userInfo')
				if (!info) return []
				const roleList = info.roleList || []
				return roleList.map(r => r.code || r.name || r)
			},
			hasRole(roles) {
				const userRoles = this.getUserRoles()
				if (!userRoles.length) return false
				return roles.some(r => userRoles.includes(r))
			},
			getActions(order) {
				const s = order.order_status
				const actions = []


				actions.push({ label: '详情', type: 'outline', action: 'detail' })


				if (s === 1) {
					actions.push({ label: '立即补款', type: 'primary', action: 'payment' })
					actions.push({ label: '预售退款', type: 'outline', action: 'presaleRefund' })
					actions.push({ label: '信息修改', type: 'outline', action: 'edit' })
					if (this.hasRole(this.CANCEL_ROLES))
						actions.push({ label: '取消订单', type: 'danger', action: 'cancel' })
				} else if (s === 2) {
					actions.push({ label: '立即补款', type: 'primary', action: 'payment' })
					actions.push({ label: '信息修改', type: 'outline', action: 'edit' })
					if (this.hasRole(this.CANCEL_ROLES))
						actions.push({ label: '取消订单', type: 'danger', action: 'cancel' })
				} else if (s === 3) {
					actions.push({ label: '信息修改', type: 'outline', action: 'edit' })
					if (this.hasRole(this.CANCEL_ROLES))
						actions.push({ label: '取消订单', type: 'danger', action: 'cancel' })
					actions.push({ label: '立即发货', type: 'primary', action: 'ship' })
				} else if (s === 4) {
					actions.push({ label: '查看物流', type: 'outline', action: 'logistics' })
					actions.push({ label: '确认收货', type: 'outline', action: 'confirmReceipt' })
					if (this.hasRole(this.AFTERSALE_ROLES)) {
						actions.push({ label: '售后操作', type: 'outline', action: 'afterSale' })
					}
				} else if (s === 5) {
					actions.push({ label: '查看物流', type: 'outline', action: 'logistics' })
					if (this.hasRole(this.AUDIT_ROLES))
						actions.push({ label: '审核售后', type: 'primary', action: 'auditAfterSale' })
				} else if (s === 6) {
					actions.push({ label: '售后操作', type: 'outline', action: 'afterSale' })
				}


				return actions
			},
			handleAction(act, order) {
				if (act.action === 'detail') {
					uni.navigateTo({ url: `/pagesA/order/order-details?id=${order.id}` })
				} else if (act.action === 'ship') {
					this.openShipPopup(order)
				} else if (act.action === 'cancel') {
					this.cancelOrder = order
					this.cancelGoodsList = order.goods_list || []
					this.cancelSelectedIds = []
					this.cancelPopup.open()
				} else if (act.action === 'edit') {
					uni.navigateTo({ url: `/pagesA/order/order-edit?id=${order.id}` })
				} else if (act.action === 'payment') {
					uni.navigateTo({ url: `/pagesA/order/order-payment?id=${order.id}` })
				} else if (act.action === 'presaleRefund') {
					uni.navigateTo({ url: `/pagesA/order/presale-refund?id=${order.id}` })
				} else if (act.action === 'logistics') {
					this.openLogisticsPopup(order)
				} else if (act.action === 'confirmReceipt') {
					uni.showModal({
						title: '确认收货',
						content: `确认订单 ${order.order_id} 已收货?`,
						success: (res) => { if (res.confirm) this.doConfirmReceipt(order) }
					})
				} else if (act.action === 'refundWithReturn') {
					uni.navigateTo({ url: `/pagesA/order/after-sale?id=${order.id}&type=refundWithReturn` })
				} else if (act.action === 'refundOnly') {
					uni.navigateTo({ url: `/pagesA/order/after-sale?id=${order.id}&type=refundOnly` })
				} else if (act.action === 'exchange') {
					uni.navigateTo({ url: `/pagesA/order/after-sale?id=${order.id}&type=exchange` })
				} else if (act.action === 'auditAfterSale') {
					uni.navigateTo({ url: `/pagesA/order/after-sale-audit?id=${order.id}` })
				}
			},
			doConfirmReceipt(order) {
				const token = uni.getStorageSync('TOKEN')
				uni.request({
					url: this.baseUrl(`/prod/admin/order/Orders/update?id=${order.id}`),
					method: 'PUT',
					header: { 'authori-zation': token, 'content-type': 'application/json' },
					data: { order_status: 6 },
					success: (res) => {
						if (res.data.code === 200) {
							uni.showToast({ title: '确认收货成功', icon: 'success' })
							this.resetAndLoad()
						} else {
							uni.showToast({ title: res.data.message || '操作失败', icon: 'none' })
						}
					}
				})
			},
			getShippedQty(g, shippingInfoItem) {
				if (!shippingInfoItem) return 0
				return shippingInfoItem
					.filter(s => s.order_item_id === g.id)
					.reduce((sum, s) => sum + (s.shipped_quantity || 0), 0)
			},
			fetchExpressList() {
				if (this.expressList.length) return
				this.expressLoading = true
				const token = uni.getStorageSync('TOKEN')
				uni.request({
					url: this.baseUrl('/prod/admin/setting/ExpressCompany/index?page=1&pageSize=100'),
					method: 'GET',
					header: { 'authori-zation': token },
					success: (res) => {
						if (res.data.code === 200) this.expressList = res.data.data.data || []
					},
					complete: () => { this.expressLoading = false }
				})
			},
			selectExpress(e) {
				this.shipForm.express_id = e.id
				this.shipForm.express_name = e.name
				this.showExpressPicker = false
			},
			setShipMode(mode) {
				this.shipMode = mode
				this.shipGoodsList.forEach(g => { g._selected = false; g.ship_qty = 1 })
			},
			openShipPopup(order) {
				this.shipOrder = order
				this.shipMode = 1
				this.shipForm = { express_id: null, express_name: '', express_no: '', remark: '' }
				this.fetchExpressList()
				const infoItem = order.shipping_info_item || []
				this.shipGoodsList = (order.goods_list || []).map(g => {
					const shipped = this.getShippedQty(g, infoItem)
					const available = Math.max(0, g.goods_num - shipped)
					return { ...g, _selected: false, ship_qty: Math.min(1, available), _shippedQty: shipped, _availableQty: available }
				})
				this.shipPopup.open()
			},
			confirmShip() {
				if (!this.shipForm.express_name) return uni.showToast({ title: '请选择快递公司', icon: 'none' })
				if (!this.shipForm.express_no.trim()) return uni.showToast({ title: '请输入快递单号', icon: 'none' })


				if (this.shipMode === 2) {
					const selected = this.shipGoodsList.filter(g => g._selected)
					if (!selected.length) return uni.showToast({ title: '请选择要发货的商品', icon: 'none' })
				}


				this.shipping = true
				const token = uni.getStorageSync('TOKEN')
				const data = {
					id: this.shipOrder.id,
					express_company_id: this.shipForm.express_id,
					express_company_name: this.shipForm.express_name,
					express_code: this.shipForm.express_no,
					remark: this.shipForm.remark,
					shipping_mode: this.shipMode,
					shipping_type: 1,
				}
				if (this.shipMode === 2) {
					data.selected_goods = this.shipGoodsList
						.filter(g => g._selected)
						.map(g => ({ goods_id: g.goods_id, order_item_id: g.id, shipping_qty: g.ship_qty }))
				}
				uni.request({
					url: this.baseUrl('/prod/admin/order/Orders/ship'),
					method: 'POST',
					header: { 'authori-zation': token, 'content-type': 'application/json' },
					data,
					success: (res) => {
						if (res.data.code === 200) {
							uni.showToast({ title: '发货成功', icon: 'success' })
							this.shipPopup.close()
							this.resetAndLoad()
						} else {
							uni.showToast({ title: res.data.message || '操作失败', icon: 'none' })
						}
					},
					fail: () => uni.showToast({ title: '网络错误', icon: 'none' }),
					complete: () => { this.shipping = false }
				})
			},
			openLogisticsPopup(order) {
				const pkgs = order.shipping_info || []
				this.logisticsPackages = pkgs
				this.logisticsPkgIndex = 0
				this.currentTrack = null
				this.logisticsPopup.open()
				if (pkgs.length > 0) {
					this.loadPackageTracks(0)
				}
			},
			selectPackage(index) {
				if (this.logisticsPkgIndex === index) return
				this.logisticsPkgIndex = index
				this.currentTrack = null
				this.loadPackageTracks(index)
			},
			loadPackageTracks(index) {
				const pkg = this.logisticsPackages[index]
				if (!pkg) return
				this.logisticsLoading = true
				const token = uni.getStorageSync('TOKEN')
				uni.request({
					url: this.baseUrl(`/prod/admin/order/Orders/shippingInfo?order_id=${pkg.id}`),
					method: 'GET',
					header: { 'authori-zation': token },
					success: (res) => {
						if (res.data.code === 200) {
							this.currentTrack = res.data.data
						} else {
							uni.showToast({ title: res.data.message || '获取失败', icon: 'none' })
						}
					},
					fail: () => uni.showToast({ title: '网络错误', icon: 'none' }),
					complete: () => { this.logisticsLoading = false }
				})
			},
			openAfterSaleSheet(order) {
				this.afterSaleOrder = order
				this.showAfterSaleSheet = true
			},
			doAfterSale(type) {
				this.showAfterSaleSheet = false
				const order = this.afterSaleOrder
				if (!order) return
				uni.navigateTo({ url: `/pagesA/order/after-sale?id=${order.id}&type=${type}` })
			},
			toggleCancelGoods(id) {
				const idx = this.cancelSelectedIds.indexOf(id)
				if (idx > -1) this.cancelSelectedIds.splice(idx, 1)
				else this.cancelSelectedIds.push(id)
			},
			confirmCancelOrder() {
				if (!this.cancelSelectedIds.length) return uni.showToast({ title: '请选择要取消的商品', icon: 'none' })
				uni.showModal({
					title: '确认取消',
					content: `确认取消选中的 ${this.cancelSelectedIds.length} 件商品?`,
					success: (res) => {
						if (!res.confirm) return
						const token = uni.getStorageSync('TOKEN')
						uni.request({
							url: this.baseUrl('/prod/admin/order/Orders/cancelOrder'),
							method: 'POST',
							header: { 'authori-zation': token, 'content-type': 'application/json' },
							data: {
								order_id: this.cancelOrder.id,
								goods_ids: this.cancelSelectedIds,
							},
							success: (r) => {
								if (r.data.code === 200) {
									uni.showToast({ title: '取消成功', icon: 'success' })
									this.cancelPopup.close()
									this.resetAndLoad()
								} else {
									uni.showToast({ title: r.data.message || '操作失败', icon: 'none' })
								}
							},
							fail: () => uni.showToast({ title: '网络错误', icon: 'none' })
						})
					}
				})
			},
		}
	}
</script>


<style lang="scss" scoped>
	page { background: #f7f8f8; }
	.content { height: 100vh; display: flex; flex-direction: column; }
	.search-box {
		padding: 16rpx 24rpx; background: #fff;
		.search-row {
			display: flex; align-items: center; background: #f7f8f8;
			border-radius: 12rpx; overflow: hidden; height: 80rpx;
		}
		.search-select {
			display: flex; align-items: center; gap: 8rpx;
			padding: 0 20rpx; height: 100%; white-space: nowrap;
			font-size: 26rpx; color: #333; border-right: 1rpx solid #e5e5e5;
			flex-shrink: 0;
		}
		.search-input {
			flex: 1; height: 100%; padding: 0 16rpx;
			font-size: 26rpx; color: #1a1a1a; background: transparent;
		}
		.search-btn {
			padding: 0 28rpx; height: 100%; background: #0D69EF;
			color: #fff; font-size: 26rpx;
			display: flex; align-items: center; justify-content: center;
			flex-shrink: 0;
		}
	}
	.order-scroll { flex: 1; overflow: hidden; }
	.order-list { padding: 0 24rpx; }


	.order-card {
		background: #fff; border-radius: 16rpx; margin-top: 20rpx; overflow: hidden;
		.order-head {
			display: flex; align-items: center; justify-content: space-between;
			padding: 20rpx 24rpx; border-bottom: 1rpx solid #f5f5f5;
			.order-head-left { display: flex; align-items: center; gap: 16rpx; }
			.order-member { font-size: 28rpx; font-weight: 600; color: #1a1a1a; }
			.order-store { font-size: 22rpx; color: #999; }
		}
		.order-no-row {
			display: flex; align-items: center; gap: 16rpx;
			padding: 12rpx 24rpx; border-bottom: 1rpx solid #f9f9f9;
			.order-no { font-size: 22rpx; color: #999; flex: 1; }
			.order-type-tag {
				font-size: 20rpx; padding: 4rpx 12rpx; border-radius: 6rpx;
				color: #0D69EF; background: rgba(13,105,239,0.08);
			}
			.partial-cancel-tag {
				font-size: 20rpx; padding: 4rpx 12rpx; border-radius: 6rpx;
				color: #ff7a00; background: rgba(255,122,0,0.1);
			}
			.partial-ship-tag {
				font-size: 20rpx; padding: 4rpx 12rpx; border-radius: 6rpx;
				color: #f53f3f; background: rgba(245,63,63,0.1);
			}
		}
		.goods-row {
			display: flex; gap: 20rpx; padding: 20rpx 24rpx;
			border-bottom: 1rpx solid #f9f9f9;
			.goods-info { flex: 1; display: flex; flex-direction: column; gap: 8rpx; }
			.goods-name { font-size: 26rpx; color: #333; }
			.goods-spec { font-size: 22rpx; color: #999; }
			.goods-price-row { display: flex; align-items: center; justify-content: space-between; }
			.goods-price { font-size: 26rpx; font-weight: 600; color: #333; }
			.goods-num { font-size: 24rpx; color: #999; }
		}
		.more-goods {
			padding: 8rpx 24rpx; font-size: 22rpx; color: #999;
			border-bottom: 1rpx solid #f9f9f9;
		}
		.order-foot {
			display: flex; align-items: center; justify-content: space-between;
			padding: 16rpx 24rpx; background: #fafafa;
			.order-time { font-size: 22rpx; color: #999; }
			.order-amount { display: flex; align-items: baseline; gap: 6rpx; }
			.amount-label { font-size: 22rpx; color: #999; }
			.amount-val { font-size: 30rpx; font-weight: 700; color: #1a1a1a; }
		}
		.order-actions {
			display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 12rpx;
			padding: 16rpx 24rpx; border-top: 1rpx solid #f5f5f5;
			.action-btn {
				font-size: 24rpx; padding: 10rpx 24rpx; border-radius: 40rpx;
				white-space: nowrap; flex-shrink: 0;
				display: flex; align-items: center;
				&.primary { color: #0D69EF; border: 1rpx solid #0D69EF; }
				&.outline { color: #666; border: 1rpx solid #ccc; }
				&.danger { color: #F56C6C; border: 1rpx solid #F56C6C; }
			}
		}
	}


	.order-status-tag {
		font-size: 22rpx; padding: 4rpx 14rpx; border-radius: 20rpx;
		&.s1  { color: #F7A600; background: rgba(247,166,0,0.1); }   // 待到货
		&.s2  { color: #F7A600; background: rgba(247,166,0,0.1); }   // 待补款
		&.s3  { color: #F56C6C; background: rgba(245,108,108,0.1); } // 售后订单
		&.s4  { color: #0D69EF; background: rgba(13,105,239,0.1); }  // 待发货
		&.s5  { color: #0D69EF; background: rgba(13,105,239,0.1); }  // 已发货
		&.s6  { color: #F56C6C; background: rgba(245,108,108,0.1); } // 售后中
		&.s7  { color: #0EB836; background: rgba(14,184,54,0.1); }   // 已完成
		&.s8  { color: #999; background: #f5f5f5; }                  // 已退款
		&.s9  { color: #999; background: #f5f5f5; }                  // 已取消
		&.s10 { color: #999; background: #f5f5f5; }                  // 已报损
		&.s11 { color: #F56C6C; background: rgba(245,108,108,0.1); } // 售后记录
	}


	.load-tip { text-align: center; padding: 20rpx 0 40rpx; font-size: 24rpx; color: #999; }
	.empty-box { padding-top: 200rpx; }


	.tab-item {
		display: flex; align-items: baseline; gap: 4rpx; white-space: nowrap;
		.tab-count { font-size: 20rpx; color: #999; }
	}


	.ship-popup {
		background: #fff; padding-bottom: env(safe-area-inset-bottom);
	}
	.ship-popup-header {
		display: flex; align-items: flex-start; justify-content: space-between;
		padding: 32rpx 32rpx 20rpx; border-bottom: 1rpx solid #f0f0f0;
		.ship-popup-title { font-size: 30rpx; font-weight: 600; color: #1a1a1a; display: block; margin-bottom: 6rpx; }
		.ship-popup-no { font-size: 22rpx; color: #999; display: block; }
	}
	.ship-mode-row {
		display: flex; gap: 24rpx; padding: 20rpx 32rpx;
		border-bottom: 1rpx solid #f5f5f5;
		.ship-mode-item {
			display: flex; align-items: center; gap: 10rpx;
			font-size: 28rpx; color: #333;
			&.active { color: #0D69EF; font-weight: 600; }
			&.disabled { color: #ccc; }
		}
		.ship-mode-dot {
			width: 32rpx; height: 32rpx; border-radius: 50%;
			border: 2rpx solid #ccc; background: #fff; flex-shrink: 0;
			display: flex; align-items: center; justify-content: center;
			&.active { border-color: #0D69EF; background: #0D69EF; }
			&.active::after { content: ''; width: 14rpx; height: 14rpx; border-radius: 50%; background: #fff; }
		}
	}
	/* 整单商品预览 */
	.whole-goods-section { padding: 16rpx 32rpx 0; }
	.whole-goods-item {
		display: flex; align-items: center; gap: 16rpx;
		padding: 16rpx 0; border-bottom: 1rpx solid #f5f5f5;
		&:last-child { border-bottom: none; }
		&.cancelled { opacity: 0.45; }
		&.shipped { opacity: 0.55; }
		.whole-goods-info { flex: 1; display: flex; flex-direction: column; gap: 6rpx; }
		.whole-goods-name-row { display: flex; align-items: center; gap: 10rpx; }
		.whole-goods-name { font-size: 26rpx; color: #1a1a1a; font-weight: 500; flex: 1; }
		.whole-goods-spec { font-size: 22rpx; color: #999; }
		.whole-goods-price-row { display: flex; align-items: center; gap: 12rpx; }
		.whole-goods-price { font-size: 26rpx; color: #F56C6C; font-weight: 600; }
		.whole-goods-qty { font-size: 22rpx; color: #bbb; }
		.whole-goods-shipped { font-size: 22rpx; color: #0EB836; margin-left: auto; }
	}
	/* 分单商品选择 */
	.split-goods-section { padding: 16rpx 24rpx 0; }
	.split-tip { font-size: 24rpx; color: #999; margin-bottom: 12rpx; padding: 0 8rpx; }
	.split-goods-item {
		display: flex; align-items: flex-start; gap: 16rpx;
		padding: 20rpx; margin-bottom: 16rpx;
		border-radius: 14rpx; border: 2rpx solid #f0f0f0; background: #fafafa;
		&.selected { border-color: #0D69EF; background: rgba(13,105,239,0.04); }
		&.disabled { opacity: 0.45; }
		.check-box {
			width: 40rpx; height: 40rpx; border-radius: 8rpx; flex-shrink: 0; margin-top: 4rpx;
			border: 2rpx solid #ddd; background: #fff;
			display: flex; align-items: center; justify-content: center;
			&.checked { background: #0D69EF; border-color: #0D69EF; }
		}
		.split-goods-info { flex: 1; display: flex; flex-direction: column; gap: 8rpx; }
		.split-goods-name-row { display: flex; align-items: center; gap: 10rpx; flex-wrap: wrap; }
		.split-goods-name { font-size: 26rpx; font-weight: 500; color: #1a1a1a; flex: 1; }
		.split-goods-spec { font-size: 22rpx; color: #999; }
		.split-goods-qty-row { display: flex; align-items: center; gap: 16rpx; }
		.split-qty-label { font-size: 24rpx; color: #555; }
		.qty-ctrl { display: flex; align-items: center; gap: 12rpx; }
		.qty-btn {
			width: 48rpx; height: 48rpx; background: #f0f0f0; border-radius: 8rpx;
			display: flex; align-items: center; justify-content: center;
			font-size: 28rpx; color: #444;
		}
		.qty-num { font-size: 28rpx; font-weight: 600; color: #1a1a1a; min-width: 32rpx; text-align: center; }
		.qty-hint { font-size: 22rpx; color: #999; }
	}
	/* 快递表单 */
	.ship-form-section { padding: 20rpx 32rpx 0; }
	.ship-form-item {
		display: flex; align-items: center; padding: 24rpx 0;
		border-bottom: 1rpx solid #f5f5f5;
		&:last-child { border-bottom: none; }
		.ship-form-label { font-size: 28rpx; color: #333; width: 160rpx; flex-shrink: 0; .req { color: #F56C6C; } }
		.ship-form-input { flex: 1; font-size: 28rpx; color: #1a1a1a; }
		.ship-form-input-row { flex: 1; display: flex; align-items: center; justify-content: flex-end; gap: 8rpx; }
		.ship-form-val { font-size: 28rpx; color: #1a1a1a; text-align: right; }
		.ship-form-placeholder { font-size: 28rpx; color: #c0c0c0; text-align: right; }
	}
	.type-sheet-loading { display: flex; justify-content: center; padding: 40rpx; }
	/* 底部按钮 */
	.ship-popup-footer {
		display: flex; gap: 20rpx; padding: 20rpx 32rpx 32rpx;
		border-top: 1rpx solid #f0f0f0;
		.ship-cancel-btn {
			flex: 1; height: 88rpx; border-radius: 44rpx; background: #f5f5f5; color: #666;
			display: flex; align-items: center; justify-content: center; font-size: 30rpx;
		}
		.ship-confirm-btn {
			flex: 2; height: 88rpx; border-radius: 44rpx;
			background: linear-gradient(135deg, #1a7aff, #0D69EF); color: #fff;
			display: flex; align-items: center; justify-content: center; font-size: 30rpx; font-weight: 600;
			box-shadow: 0 4rpx 16rpx rgba(13,105,239,0.3);
			&.loading { background: #a0c4ff; box-shadow: none; }
		}
	}
	/* 状态标签 */
	.tag-cancelled { font-size: 20rpx; color: #fff; background: #bbb; padding: 2rpx 10rpx; border-radius: 6rpx; flex-shrink: 0; }
	.tag-shipped { font-size: 20rpx; color: #fff; background: #0EB836; padding: 2rpx 10rpx; border-radius: 6rpx; flex-shrink: 0; }
	.tag-partial { font-size: 20rpx; color: #fff; background: #ff7a00; padding: 2rpx 10rpx; border-radius: 6rpx; flex-shrink: 0; }


	/* 取消订单商品列表 */
	.cancel-popup {
		background: #fff;
		padding-bottom: env(safe-area-inset-bottom);
	}
	.cancel-popup-header {
		display: flex; align-items: flex-start; justify-content: space-between;
		padding: 32rpx 32rpx 20rpx; border-bottom: 1rpx solid #f0f0f0;
		.cancel-popup-title { font-size: 30rpx; font-weight: 600; color: #1a1a1a; display: block; margin-bottom: 6rpx; }
		.cancel-popup-no { font-size: 22rpx; color: #999; display: block; }
	}
	.cancel-goods-list { padding: 16rpx 24rpx 8rpx; }
	.cancel-goods-item {
		display: flex; align-items: center; gap: 16rpx;
		padding: 20rpx; margin-bottom: 16rpx;
		border-radius: 14rpx; border: 2rpx solid #f0f0f0; background: #fafafa;
		transition: all 0.15s;
		&.selected { border-color: #0D69EF; background: rgba(13,105,239,0.04); }
		&.disabled { opacity: 0.45; }
		.check-box {
			width: 40rpx; height: 40rpx; border-radius: 8rpx; flex-shrink: 0;
			border: 2rpx solid #ddd; background: #fff;
			display: flex; align-items: center; justify-content: center;
			&.checked { background: #0D69EF; border-color: #0D69EF; }
		}
		.cancel-goods-info { flex: 1; display: flex; flex-direction: column; gap: 6rpx; overflow: hidden; }
		.cancel-goods-name-row { display: flex; align-items: center; gap: 10rpx; flex-wrap: wrap; }
		.cancel-goods-name { font-size: 26rpx; font-weight: 500; color: #1a1a1a; line-height: 1.4; flex: 1; }
		.cancelled-tag {
			font-size: 20rpx; color: #fff; background: #bbb;
			padding: 2rpx 10rpx; border-radius: 6rpx; flex-shrink: 0;
		}
		.cancel-goods-spec { font-size: 22rpx; color: #999; }
		.cancel-goods-price-row { display: flex; align-items: center; gap: 12rpx; }
		.cancel-goods-price { font-size: 26rpx; color: #F56C6C; font-weight: 600; }
		.cancel-goods-qty { font-size: 22rpx; color: #bbb; }
	}
	.cancel-popup-footer {
		display: flex; align-items: center; justify-content: space-between;
		padding: 20rpx 32rpx 32rpx; border-top: 1rpx solid #f0f0f0;
		.cancel-selected-tip { font-size: 26rpx; color: #999; }
		.cancel-confirm-btn {
			background: #F56C6C; color: #fff;
			height: 80rpx; padding: 0 48rpx; border-radius: 40rpx;
			display: flex; align-items: center; justify-content: center;
			font-size: 28rpx; font-weight: 500;
			&.disabled { background: #ddd; color: #bbb; }
		}
	}


	/* 物流 */
	.loading-row { display: flex; align-items: center; justify-content: center; padding: 60rpx; }
	.pkg-scroll { border-bottom: 1rpx solid #f0f0f0; }
	.pkg-list { display: flex; gap: 16rpx; padding: 20rpx 24rpx; white-space: nowrap; }
	.pkg-card {
		display: inline-flex; flex-direction: column; gap: 6rpx;
		padding: 16rpx 24rpx; border-radius: 12rpx;
		border: 2rpx solid #eee; background: #fafafa; flex-shrink: 0;
		&.active { border-color: #0D69EF; background: rgba(13,105,239,0.05); }
		.pkg-company { font-size: 24rpx; color: #333; font-weight: 500; }
		.pkg-no { font-size: 22rpx; color: #999; }
		.pkg-time { font-size: 20rpx; color: #bbb; }
	}
	.single-pkg-info {
		display: flex; align-items: center; gap: 16rpx;
		padding: 16rpx 32rpx; border-bottom: 1rpx solid #f0f0f0;
		.single-pkg-company { font-size: 26rpx; color: #333; font-weight: 500; }
		.single-pkg-no { font-size: 24rpx; color: #999; }
	}
	.logistics-list { padding: 24rpx 32rpx; }
	.logistics-item {
		display: flex; gap: 20rpx; padding-bottom: 32rpx;
		.logistics-dot-wrap { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
		.logistics-dot { width: 20rpx; height: 20rpx; border-radius: 50%; background: #ccc; flex-shrink: 0; margin-top: 6rpx; }
		.logistics-line { flex: 1; width: 2rpx; background: #eee; margin-top: 8rpx; min-height: 40rpx; }
		.logistics-content { flex: 1; display: flex; flex-direction: column; gap: 8rpx; }
		.logistics-time { font-size: 22rpx; color: #999; }
		.logistics-context { font-size: 26rpx; color: #333; line-height: 1.6; }
		&.first .logistics-dot { background: #0D69EF; }
		&.first .logistics-content { color: #1a1a1a; font-weight: 500; }
	}
	.logistics-empty {
		padding: 40rpx 32rpx; display: flex; flex-direction: column; gap: 16rpx;
		.logistics-no, .logistics-company { font-size: 26rpx; color: #555; }
		.logistics-msg { font-size: 26rpx; color: #999; margin-top: 8rpx; }
	}


	.type-mask {
		position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 9998;
	}
	.type-sheet {
		position: fixed; bottom: 0; left: 0; width: 100%;
		background: #fff; border-radius: 24rpx 24rpx 0 0;
		z-index: 9999; padding-bottom: env(safe-area-inset-bottom);
		transform: translateY(100%); transition: transform 0.25s ease;
		&.show { transform: translateY(0); }
		.type-sheet-title {
			text-align: center; font-size: 28rpx; color: #999;
			padding: 28rpx 0 16rpx; border-bottom: 1rpx solid #f5f5f5;
		}
		.type-sheet-item {
			display: flex; align-items: center; justify-content: space-between;
			padding: 32rpx 48rpx; font-size: 30rpx; color: #1a1a1a;
			border-bottom: 1rpx solid #f9f9f9;
			&.active { color: #0D69EF; font-weight: 600; }
		}
		.type-sheet-cancel {
			text-align: center; padding: 32rpx; font-size: 30rpx; color: #999;
		}
	}
</style>


回答关注问题邀请回答
收藏

1 个回答

登录 后发表内容