refactor(order): 订单页重新美化

This commit is contained in:
Kroytz committed 2026-07-24 14:21:30 +08:00
1 parent 15f3b09f6d
commit 9681a18bd1
2 files changed
+314 -137

No files matched your search

+2
View File
@@ -23,6 +23,8 @@
"style" : "style" :
{ {
"navigationBarTitleText": "订单", "navigationBarTitleText": "订单",
"navigationBarBackgroundColor": "#fff3e6",
"backgroundColor": "#fff3e6",
"enablePullDownRefresh": true "enablePullDownRefresh": true
} }
+312 -137
View File
@@ -1,220 +1,395 @@
<template> <template>
<uv-navbar <view class="order-page">
:fixed="false" <uv-navbar
:title="title" :fixed="false"
left-arrow title="我的订单"
@leftClick="$onClickLeft" bgColor="transparent"
/> leftIcon=""
<view class="container order-page"> />
<view class="bg-white">
<uv-tabs :list="tabList" :current="current" @change="change" keyName="name" :scrollable="false"></uv-tabs> <view class="order-tabs">
<uv-tabs
:list="tabList"
:current="current"
@change="change"
keyName="name"
:scrollable="false"
lineWidth="28"
lineHeight="6"
lineColor="#F28C38"
:activeStyle="{ color: '#2b2b2b', fontWeight: '700', fontSize: '28rpx' }"
:inactiveStyle="{ color: '#9a9590', fontSize: '28rpx' }"
/>
</view> </view>
<view class="order-page__list d-flex flex-column w-100">
<view class="order-item" v-for="(item, index) in orders" :key="index"> <view class="order-list">
<list-cell :hover="false"> <uv-empty v-if="!orders.length" mode="order" text="暂无相关订单" />
<view class="w-100 d-flex align-items-center"> <view
<view class="flex-fill d-flex flex-column"> v-for="(item, index) in orders"
<view class="font-size-lg text-color-base order-item__shop"> :key="index"
{{ item.shop.name }} class="order-card"
</view> @tap="detail(item.orderId)"
<view class="font-size-sm text-color-assist">取餐号:{{ item.numberId }}</view> >
<view class="font-size-sm text-color-assist">订单编号:{{ item.orderId }}</view> <view class="order-card__head">
</view> <view class="order-card__shop">
<view class="font-size-lg text-color-primary"> <text class="order-card__shop-name">{{ item.shop.name }}</text>
{{ item.statusDto.title }} <view class="order-card__tag" v-if="item.orderType">
{{ item.orderType === 'takeout' ? '外卖' : '自取' }}
</view> </view>
</view> </view>
</list-cell> <text class="order-card__status">{{ item.statusDto.title }}</text>
<list-cell :hover="false" last> </view>
<view class="w-100 d-flex flex-column">
<view class="w-100 text-truncate font-size-lg text-color-base order-item__goods"> <view class="order-card__meta">
<view class="flex order-item__goods-row mb-2" v-for="(good,index) in item.cartInfo" :key="index"> <text>取餐号:{{ item.numberId || '--' }}</text>
<image :src="good.image" mode="aspectFill" class="order-item__thumb"></image> <text>订单号:{{ item.orderId }}</text>
<view class="flex flex-column"> </view>
<view class="font-size-medium mt-1 text-color-base">{{ good.title }}</view>
<view class="font-size-sm mt-1">{{ good.spec }}</view> <view class="order-card__goods">
<view class="font-size-sm mt-2">×{{ good.number }} ¥{{ good.price }}</view> <view
</view> v-for="(good, gIndex) in item.cartInfo"
:key="gIndex"
class="order-good"
>
<image
v-if="good.image"
:src="good.image"
mode="aspectFill"
class="order-good__img"
/>
<view v-else class="order-good__img order-good__img--placeholder" />
<view class="order-good__body">
<text class="order-good__name">{{ good.title }}</text>
<text v-if="good.spec" class="order-good__spec">{{ good.spec }}</text>
<view class="order-good__row">
<text>×{{ good.number }}</text>
<text class="order-good__price">¥{{ good.price }}</text>
</view> </view>
</view> </view>
<view class="d-flex justify-content-between align-items-center order-item__meta">
<view class="font-size-sm text-color-assist">
{{formatDateTime(item.createTime) }}
</view>
<view class="d-flex font-size-sm text-color-base align-items-center">
<view class="order-item__summary">共{{ goodsNum(item.cartInfo) }}件商品,实付</view>
<view class="font-size-lg">¥{{ item.payPrice }}</view>
</view>
</view>
<view class="d-flex align-items-center justify-content-end order-item__actions">
<button
v-if="item.paid > 0 && item.status < 2 && item.refundStatus == 0"
class="order-item__btn"
plain
size="mini"
@tap.stop="receive(item)"
>确认收到餐</button>
<button class="order-item__btn" plain size="mini" @tap="detail(item.orderId)">订单详情</button>
</view>
</view> </view>
</list-cell> </view>
<view class="order-card__footer">
<text class="order-card__time">{{ formatDateTime(item.createTime) }}</text>
<view class="order-card__pay">
<text>共{{ goodsNum(item.cartInfo) }}件,实付</text>
<text class="order-card__amount">¥{{ item.payPrice }}</text>
</view>
</view>
<view class="order-card__actions" @tap.stop>
<button
v-if="item.paid > 0 && item.status < 2 && item.refundStatus == 0"
class="order-card__btn order-card__btn--plain"
size="mini"
@tap="receive(item)"
>确认收到餐</button>
<button
class="order-card__btn order-card__btn--primary"
size="mini"
@tap="detail(item.orderId)"
>订单详情</button>
</view>
</view> </view>
</view> </view>
<uv-empty v-if="orders.length == 0" mode="order"></uv-empty>
</view> </view>
</template> </template>
<script setup> <script setup>
import { import { ref, computed } from 'vue'
ref,
computed
} from 'vue'
import { useMainStore } from '@/store/store' import { useMainStore } from '@/store/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { onLoad,onPullDownRefresh,onReachBottom} from '@dcloudio/uni-app' import { onLoad, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
import { formatDateTime,kmUnit } from '@/utils/util' import { formatDateTime } from '@/utils/util'
import { import { orderGetOrders, orderReceive } from '@/api/order'
orderGetOrders,
orderReceive
} from '@/api/order'
const main = useMainStore() const main = useMainStore()
const { isLogin } = storeToRefs(main) const { isLogin } = storeToRefs(main)
const title = ref('我的订单')
const page = ref(1) const page = ref(1)
const pageSize = ref(10) const pageSize = ref(10)
const orders = ref([]) const orders = ref([])
const tabList = ref([{ const tabList = ref([
type: -1, { type: -1, name: '全部' },
name: '全部', { type: 0, name: '待支付' },
}, { { type: 1, name: '进行中' },
type: 0, { type: 4, name: '已完成' },
name: '待支付', { type: -3, name: '退款单' }
}, { ])
type: 1,
name: '进行中'
}, {
type: 4,
name: '已完成'
}, {
type: -3,
name: '退款单'
}]
)
const current = ref(0) const current = ref(0)
const type = ref(-1) const type = ref(-1)
const goodsNum = computed(() => { //计算单个饮品添加到购物车的数量 const goodsNum = computed(() => {
return (goods) => { return (goods) => {
let num = 0; let num = 0
goods.forEach(good => num += parseInt(good.number)) ;(goods || []).forEach((good) => (num += parseInt(good.number)))
return num; return num
} }
}) })
onLoad(() => { onLoad(() => {
if(!isLogin.value) { if (!isLogin.value) {
uni.navigateTo({url: '/pages/components/pages/login/login'}) uni.navigateTo({ url: '/pages/components/pages/login/login' })
} }
getOrders(false) getOrders(false)
}) })
onPullDownRefresh(() => { onPullDownRefresh(() => {
getOrders(false) getOrders(true)
}) })
onReachBottom(() => { onReachBottom(() => {
getOrders(false) getOrders(false)
}) })
// tab栏切换
const change = (e) => { const change = (e) => {
//console.log('e;',e.type)
//console.log('e.index;',e.index)
type.value = e.type type.value = e.type
current.value = e.index
getOrders(true) getOrders(true)
} }
const getOrders = async(isRefresh = false) => { const getOrders = async (isRefresh = false) => {
uni.showLoading({ uni.showLoading({ title: '加载中' })
title: '加载中' if (isRefresh) {
})
if(isRefresh) {
orders.value = [] orders.value = []
page.value = 1 page.value = 1
} }
let ordersData = await orderGetOrders({page:page.value, limit:pageSize.value,type:type.value}); const ordersData = await orderGetOrders({
page: page.value,
if(ordersData) { limit: pageSize.value,
type: type.value
})
if (ordersData) {
orders.value = orders.value.concat(ordersData) orders.value = orders.value.concat(ordersData)
page.value += 1 page.value += 1
} }
uni.stopPullDownRefresh(); uni.stopPullDownRefresh()
uni.hideLoading() uni.hideLoading()
} }
const detail = (id) => { const detail = (id) => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/components/pages/orders/detail?id=' + id url: '/pages/components/pages/orders/detail?id=' + id
}) })
} }
// 确认收到货
const receive = async(order) => { const receive = async (order) => {
let data = await orderReceive({uni:order.orderId}); const data = await orderReceive({ uni: order.orderId })
if (data) { if (data) {
await getOrders(true) await getOrders(true)
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// 订单页局部 token(与 uni.scss 全局变量配合) $bg-top: #fff3e6;
$order-list-padding-x: $spacing-row-base; $bg-mid: #fff8f0;
$order-list-padding-bottom: 0; $bg-bottom: #ffffff;
$order-item-gap: $spacing-row-lg; $accent: #f28c38;
$order-section-gap: $spacing-row-base; $accent-deep: #ff6817;
$order-btn-gap: $spacing-row-base; $text-main: #2b2b2b;
$order-summary-gap: $spacing-row-base; $text-sub: #9a9590;
$order-thumb-size: 160rpx; $card-radius: 24rpx;
$order-thumb-radius: 8rpx;
.order-page { .order-page {
--order-thumb-size: #{$order-thumb-size}; min-height: 100vh;
padding: 0 24rpx 40rpx;
&__list { box-sizing: border-box;
padding: $order-list-padding-x; background: linear-gradient(180deg, $bg-top 0%, $bg-mid 42%, $bg-bottom 100%);
padding-bottom: $order-list-padding-bottom;
}
} }
.order-item { .order-tabs {
margin-bottom: $order-item-gap; margin-bottom: 20rpx;
padding: 8rpx 8rpx 4rpx;
border-radius: $card-radius;
background: #fff;
box-shadow: 0 8rpx 24rpx rgba(180, 120, 60, 0.08);
}
.order-list {
padding-bottom: 20rpx;
}
.order-card {
margin-bottom: 20rpx;
padding: 28rpx 24rpx 20rpx;
border-radius: $card-radius;
background: #fff;
box-shadow: 0 8rpx 24rpx rgba(180, 120, 60, 0.08);
&__head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
}
&__shop { &__shop {
margin-bottom: $order-section-gap; display: flex;
align-items: center;
gap: 12rpx;
min-width: 0;
flex: 1;
} }
&__goods { &__shop-name {
margin-bottom: $order-section-gap; font-size: 30rpx;
font-weight: 700;
color: $text-main;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
&__thumb { &__tag {
flex-shrink: 0; flex-shrink: 0;
width: var(--order-thumb-size); padding: 4rpx 12rpx;
height: var(--order-thumb-size); border-radius: 999rpx;
margin-right: $spacing-row-lg; font-size: 20rpx;
border-radius: $order-thumb-radius; color: #fff;
background: linear-gradient(90deg, #ff9b20, #ff6817);
}
&__status {
flex-shrink: 0;
font-size: 26rpx;
font-weight: 600;
color: $accent;
} }
&__meta { &__meta {
margin-bottom: $order-item-gap; display: flex;
flex-direction: column;
gap: 6rpx;
margin-top: 12rpx;
font-size: 22rpx;
color: $text-sub;
} }
&__summary { &__goods {
margin-right: $order-summary-gap; margin-top: 20rpx;
padding-top: 8rpx;
border-top: 1rpx solid #f3ebe3;
} }
&__btn + &__btn { &__footer {
margin-left: $order-btn-gap; display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
margin-top: 16rpx;
}
&__time {
font-size: 22rpx;
color: $text-sub;
}
&__pay {
display: flex;
align-items: baseline;
gap: 8rpx;
font-size: 22rpx;
color: $text-main;
}
&__amount {
font-size: 32rpx;
font-weight: 700;
color: $accent-deep;
}
&__actions {
display: flex;
justify-content: flex-end;
gap: 16rpx;
margin-top: 20rpx;
padding-top: 16rpx;
border-top: 1rpx solid #f3ebe3;
}
&__btn {
margin: 0;
padding: 0 28rpx;
height: 56rpx;
line-height: 52rpx;
border-radius: 999rpx;
font-size: 24rpx;
&::after {
border: none;
}
&--plain {
color: $accent;
background: #fff;
border: 2rpx solid $accent !important;
}
&--primary {
color: #fff;
background: linear-gradient(90deg, #ff9b20, #ff6817);
border: none;
}
}
}
.order-good {
display: flex;
padding: 16rpx 0;
&__img {
width: 128rpx;
height: 128rpx;
margin-right: 20rpx;
border-radius: 18rpx;
flex-shrink: 0;
background: #fff3e6;
&--placeholder {
background: linear-gradient(135deg, #fff3e6, #f5e6d4);
}
}
&__body {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
&__name {
font-size: 28rpx;
font-weight: 700;
color: $text-main;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__spec {
margin-top: 8rpx;
font-size: 22rpx;
color: $text-sub;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__row {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: auto;
padding-top: 10rpx;
font-size: 24rpx;
color: $text-sub;
}
&__price {
font-size: 28rpx;
font-weight: 700;
color: $text-main;
} }
} }
</style> </style>