Browse Source

feat(订单模块): 新增订单列表、订单详情及支付成功页面

新增订单列表页面,支持按状态筛选、下拉刷新和加载更多功能。新增订单详情页面,展示服务地址、宠物信息、服务项目及费用等详细信息。优化支付成功页面,调整布局和样式,提升用户体验。新增取消订单功能,并调整导航路径以适配新页面结构。
master
前端-胡立永 3 days ago
parent
commit
0c611f3c12
15 changed files with 1408 additions and 33 deletions
  1. +9
    -0
      api/system/user.js
  2. +18
    -0
      pages.json
  3. +2
    -2
      pages/index.vue
  4. +2
    -1
      pages/personalCenter/index.vue
  5. +91
    -0
      pages_order/components/order/OrderInfo.vue
  6. +71
    -0
      pages_order/components/order/ServiceAddress.vue
  7. +216
    -0
      pages_order/components/order/ServiceItems.vue
  8. +120
    -0
      pages_order/components/order/ServicePets.vue
  9. +116
    -0
      pages_order/components/order/ServiceRemarks.vue
  10. +241
    -0
      pages_order/order/orderDetail.vue
  11. +463
    -0
      pages_order/order/orderList.vue
  12. +59
    -30
      pages_order/order/payOrderSuccessful.vue
  13. BIN
      pages_order/static/order/f.png
  14. +0
    -0
      pages_order/static/task/m.png
  15. +0
    -0
      pages_order/static/task/wb.png

+ 9
- 0
api/system/user.js View File

@ -148,6 +148,15 @@ export function getPhoneNumber(data){
})
}
// 取消订单
export function cancelOrder(orderId){
return request({
url: `/h5/order/cancel/${orderId}`,
method: 'post',
headers:{ "isToken":true}
})
}


+ 18
- 0
pages.json View File

@ -357,6 +357,24 @@
"enablePullDownRefresh": false,
"navigationBarTextStyle": "white"
}
},
{
"path": "order/orderList",
"style": {
"navigationBarTitleText": "订单列表",
"navigationBarBackgroundColor": "#FFBF60",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "white"
}
},
{
"path": "order/orderDetail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationBarBackgroundColor": "#FFBF60",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "white"
}
}
]
}


+ 2
- 2
pages/index.vue View File

@ -624,8 +624,8 @@
}
} else {
uni.navigateTo({
// url: '/pages_order/order/payOrderSuccessful',
url: '/pages/newOrder/serviceNew',
url: '/pages_order/order/payOrderSuccessful',
// url: '/pages/newOrder/serviceNew',
// url: '/pages/newOrder/serviceNew2',
});
}


+ 2
- 1
pages/personalCenter/index.vue View File

@ -422,7 +422,8 @@
}
case 'order':{
uni.navigateTo({
url: `/pages/details/order`
// url: `/pages/details/order`
url: `/pages_order/order/orderList`
});
break;
}


+ 91
- 0
pages_order/components/order/OrderInfo.vue View File

@ -0,0 +1,91 @@
<template>
<view class="order-info-card">
<view class="card-title">
<text>其他信息</text>
</view>
<view class="info-content">
<view class="info-item">
<text class="info-label">订单编号:</text>
<text class="info-value">{{orderInfo.orderNumber}}</text>
</view>
<view class="info-item">
<text class="info-label">下单时间:</text>
<text class="info-value">{{orderInfo.orderTime}}</text>
</view>
<view class="info-item" v-if="orderInfo.paymentTime">
<text class="info-label">支付时间:</text>
<text class="info-value">{{orderInfo.paymentTime}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
orderInfo: {
type: Object,
default: () => ({
orderNumber: '',
orderTime: '',
paymentTime: ''
})
}
}
}
</script>
<style lang="scss" scoped>
.order-info-card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 8rpx;
height: 32rpx;
background-color: #FFAA48;
margin-right: 16rpx;
border-radius: 4rpx;
}
}
.info-content {
.info-item {
display: flex;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
.info-label {
font-size: 26rpx;
color: #666;
width: 140rpx;
}
.info-value {
font-size: 26rpx;
color: #333;
flex: 1;
}
}
}
</style>

+ 71
- 0
pages_order/components/order/ServiceAddress.vue View File

@ -0,0 +1,71 @@
<template>
<view class="service-address-card">
<view class="card-title">
<text>服务地址</text>
</view>
<view class="address-content">
<view class="address-text">{{address.address}}</view>
<view class="contact-text">{{address.contact}}</view>
</view>
</view>
</template>
<script>
export default {
props: {
address: {
type: Object,
default: () => ({
address: '',
contact: ''
})
}
}
}
</script>
<style lang="scss" scoped>
.service-address-card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 8rpx;
height: 32rpx;
background-color: #FFAA48;
margin-right: 16rpx;
border-radius: 4rpx;
}
}
.address-content {
padding: 20rpx;
background-color: #FFF9EF;
border-radius: 10rpx;
}
.address-text {
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
}
.contact-text {
font-size: 26rpx;
color: #666;
}
</style>

+ 216
- 0
pages_order/components/order/ServiceItems.vue View File

@ -0,0 +1,216 @@
<template>
<view class="service-items-card">
<view class="card-title">
<text>服务项目及费用</text>
</view>
<!-- 服务项目列表 -->
<view class="service-items-list">
<view class="service-item" v-for="(item, index) in items" :key="index">
<view class="item-header">
<view class="item-id">{{item.id}}</view>
<view class="item-name">{{item.name}}</view>
<view class="item-price">¥{{item.price.toFixed(2)}}</view>
</view>
<!-- 宠物名称 -->
<view class="item-pet">
<text>{{item.pet}}</text>
</view>
<!-- 定制服务 -->
<view class="custom-services" v-if="item.customServices && item.customServices.length > 0">
<view class="custom-service-item" v-for="(service, serviceIndex) in item.customServices" :key="serviceIndex">
<view class="service-name">- {{service.name}}</view>
<view class="service-price">¥{{service.price.toFixed(2)}} × {{service.quantity}} </view>
</view>
</view>
</view>
</view>
<!-- 费用合计 -->
<view class="cost-summary">
<view class="cost-item">
<text class="cost-label">费用合计</text>
<text class="cost-value">¥{{totalAmount.toFixed(2)}}</text>
</view>
<view class="cost-item discount" v-if="discount > 0">
<text class="cost-label">平台优惠</text>
<text class="cost-value">- ¥{{discount.toFixed(2)}}</text>
</view>
<view class="cost-item discount" v-if="memberDiscount > 0">
<text class="cost-label">会员优惠</text>
<text class="cost-value">- ¥{{memberDiscount.toFixed(2)}}</text>
</view>
<view class="cost-item total">
<text class="cost-label">应付金额</text>
<text class="cost-value">¥{{finalAmount.toFixed(2)}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: () => []
},
totalAmount: {
type: Number,
default: 0
},
discount: {
type: Number,
default: 0
},
memberDiscount: {
type: Number,
default: 0
},
finalAmount: {
type: Number,
default: 0
}
}
}
</script>
<style lang="scss" scoped>
.service-items-card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 8rpx;
height: 32rpx;
background-color: #FFAA48;
margin-right: 16rpx;
border-radius: 4rpx;
}
}
.service-items-list {
.service-item {
padding: 20rpx 0;
border-bottom: 1px solid #EEEEEE;
&:last-child {
border-bottom: none;
}
.item-header {
display: flex;
align-items: center;
margin-bottom: 10rpx;
.item-id {
font-size: 24rpx;
color: #999;
margin-right: 10rpx;
}
.item-name {
font-size: 28rpx;
color: #333;
flex: 1;
}
.item-price {
font-size: 28rpx;
color: #FF5252;
font-weight: bold;
}
}
.item-pet {
font-size: 24rpx;
color: #666;
margin-bottom: 10rpx;
}
.custom-services {
padding: 10rpx 0 10rpx 20rpx;
.custom-service-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6rpx;
.service-name {
font-size: 24rpx;
color: #666;
}
.service-price {
font-size: 24rpx;
color: #999;
}
}
}
}
}
.cost-summary {
margin-top: 30rpx;
padding-top: 20rpx;
border-top: 1px dashed #EEEEEE;
.cost-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
.cost-label {
font-size: 26rpx;
color: #666;
}
.cost-value {
font-size: 26rpx;
color: #333;
}
&.discount {
.cost-value {
color: #FF5252;
}
}
&.total {
margin-top: 20rpx;
padding-top: 20rpx;
border-top: 1px dashed #EEEEEE;
.cost-label {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.cost-value {
font-size: 32rpx;
font-weight: bold;
color: #FF5252;
}
}
}
}
</style>

+ 120
- 0
pages_order/components/order/ServicePets.vue View File

@ -0,0 +1,120 @@
<template>
<view class="service-pets-card">
<view class="card-title">
<text>服务宠物</text>
</view>
<view class="pets-list">
<view class="pet-item" v-for="(pet, index) in pets" :key="index">
<view class="pet-avatar">
<image :src="pet.avatar || '/static/images/personal/pet.png'" mode="aspectFill"></image>
<view class="pet-tag" v-if="pet.tag">
<text>{{pet.tag}}</text>
</view>
</view>
<view class="pet-details">
<view class="pet-name-gender" style="display: flex; align-items: center;">
<text class="pet-name">{{pet.name}}</text>
<view class="pet-gender" style="margin-left: 10rpx; display: flex; align-items: center;">
<image :src="pet.gender=='男生'?'/static/images/details/boy.svg':'/static/images/details/girl.svg'" style="width: 24rpx; height: 24rpx;" alt="sex"></image>
</view>
</view>
<text class="pet-service">专业喂养{{pet.serviceDays}}: {{pet.serviceDates.join(',')}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
pets: {
type: Array,
default: () => []
}
}
}
</script>
<style lang="scss" scoped>
.service-pets-card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 8rpx;
height: 32rpx;
background-color: #FFAA48;
margin-right: 16rpx;
border-radius: 4rpx;
}
}
.pets-list {
.pet-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.pet-avatar {
position: relative;
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.pet-tag {
position: absolute;
right: -10rpx;
bottom: -10rpx;
background-color: #FFAA48;
color: #FFFFFF;
font-size: 20rpx;
padding: 4rpx 8rpx;
border-radius: 10rpx;
line-height: 1;
}
}
.pet-details {
display: flex;
flex-direction: column;
.pet-name {
font-size: 28rpx;
color: #333;
font-weight: bold;
}
.pet-service {
font-size: 24rpx;
color: #666;
margin-top: 4rpx;
}
}
}
}
</style>

+ 116
- 0
pages_order/components/order/ServiceRemarks.vue View File

@ -0,0 +1,116 @@
<template>
<view class="service-remarks-card">
<view class="card-title">
<text>服务备注</text>
</view>
<view class="remarks-content">
<view class="payment-method">
<text class="label">付款方式:</text>
<text class="value">{{remarks.paymentMethod}}</text>
</view>
<view class="urgent-flag" v-if="remarks.isUrgent">
<view class="urgent-icon">
<image src="/static/images/details/girl.svg" style="width: 32rpx; height: 32rpx;"></image>
</view>
<text class="urgent-text">是否紧急预约</text>
</view>
<view class="notes-section" v-if="remarks.notes">
<text class="notes-text">{{remarks.notes}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
remarks: {
type: Object,
default: () => ({
paymentMethod: '',
isUrgent: false,
notes: ''
})
}
}
}
</script>
<style lang="scss" scoped>
.service-remarks-card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.card-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 8rpx;
height: 32rpx;
background-color: #FFAA48;
margin-right: 16rpx;
border-radius: 4rpx;
}
}
.remarks-content {
.payment-method {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.label {
font-size: 26rpx;
color: #666;
margin-right: 10rpx;
}
.value {
font-size: 26rpx;
color: #333;
}
}
.urgent-flag {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.urgent-icon {
margin-right: 10rpx;
}
.urgent-text {
font-size: 26rpx;
color: #FF5252;
}
}
.notes-section {
padding: 20rpx;
background-color: #FFF5E6;
border-radius: 10rpx;
.notes-text {
font-size: 26rpx;
color: #A94F20;
line-height: 1.5;
white-space: pre-wrap;
}
}
}
</style>

+ 241
- 0
pages_order/order/orderDetail.vue View File

@ -0,0 +1,241 @@
<template>
<view class="order-detail-page">
<!-- 订单内容区域 -->
<view class="order-detail-content">
<!-- 服务地址组件 -->
<service-address :address="orderDetail.address"></service-address>
<!-- 服务宠物组件 -->
<service-pets :pets="orderDetail.pets"></service-pets>
<!-- 服务项目及费用组件 -->
<service-items :items="orderDetail.items" :totalAmount="orderDetail.totalAmount"
:discount="orderDetail.discount" :finalAmount="orderDetail.finalAmount"></service-items>
<!-- 服务备注组件 -->
<service-remarks :remarks="orderDetail.remarks"></service-remarks>
<!-- 其他信息组件 -->
<order-info :orderInfo="orderDetail.orderInfo"></order-info>
</view>
<!-- 底部按钮区域 -->
<view class="order-detail-footer">
<view class="footer-btn cancel-btn" v-if="orderDetail.status === '1'">
<text>取消订单</text>
</view>
<view class="footer-btn pay-btn" v-if="orderDetail.status === '1'" @click="goToPay">
<text>去付款</text>
</view>
<view class="footer-btn contact-btn">
<text>联系客服</text>
</view>
</view>
<!-- 客服组件 -->
<Kefu></Kefu>
</view>
</template>
<script>
import Kefu from '@/pages/common/kefu.vue'
import ServiceAddress from '@/pages_order/components/order/ServiceAddress.vue'
import ServicePets from '@/pages_order/components/order/ServicePets.vue'
import ServiceItems from '@/pages_order/components/order/ServiceItems.vue'
import ServiceRemarks from '@/pages_order/components/order/ServiceRemarks.vue'
import OrderInfo from '@/pages_order/components/order/OrderInfo.vue'
import { getOrderList } from "@/api/system/user.js"
import { getOpenIdKey } from '@/utils/auth'
export default {
components: {
Kefu,
ServiceAddress,
ServicePets,
ServiceItems,
ServiceRemarks,
OrderInfo
},
data() {
return {
orderId: null,
orderDetail: {
status: '1', // 1-, 2-, 3-, 4-
address: {
address: '上海青浦区盈港路888号1-2号-东部公寓',
contact: '联系电话: 18629356678'
},
pets: [
{
name: '小咪',
avatar: '/static/images/personal/pet.png',
tag: '猫',
gender: '女生',
serviceDays: 2,
serviceDates: ['03-20', '03-22']
},
{
name: '小汪',
avatar: '/static/images/personal/pet.png',
tag: '狗',
gender: '男生',
serviceDays: 3,
serviceDates: ['03-20', '03-22', '03-25']
}
],
items: [
{
id: '07-07',
name: '专业喂养',
price: 75.00,
pet: '小咪',
quantity: 1
},
{
id: '07-08',
name: '专业喂养 + 定制服务1项',
price: 75.00,
pet: '小汪',
quantity: 1,
customServices: [
{
name: '专业喂养',
price: 75.00,
quantity: 1
},
{
name: '上门遛狗',
price: 40.00,
quantity: 1
}
]
},
{
id: '07-10',
name: '专业喂养 + 定制服务2项',
price: 95.00,
pet: '小汪',
quantity: 1,
customServices: [
{
name: '专业喂养',
price: 75.00,
quantity: 1
},
{
name: '上门遛狗',
price: 40.00,
quantity: 1
},
{
name: '梳毛',
price: 40.00,
quantity: 1
}
]
}
],
totalAmount: 290.00,
discount: 10.00,
memberDiscount: 20.00,
finalAmount: 260.00,
remarks: {
paymentMethod: '存于平台账户',
isUrgent: true,
notes: '* 到达05/2楼\n* 猫咪很胆小,请轻声说话,保持安静。猫粮放在门口柜子上,猫砂盆在卫生间。\n* 狗狗很活泼,喜欢玩球,球放在客厅的篮子里。'
},
orderInfo: {
orderNumber: 'fc241200396263',
orderTime: '2024-12-03 13:05:57',
paymentTime: '2024-12-03 13:06:06'
}
}
};
},
onLoad(options) {
if (options.id) {
this.orderId = options.id;
this.getOrderDetail();
}
},
methods: {
//
getOrderDetail() {
// API
//
/*
const params = {
openId: getOpenIdKey(),
orderId: this.orderId
};
getOrderDetail(params).then(res => {
if (res && res.code === 200) {
this.orderDetail = res.data;
}
}).catch(err => {
console.error('获取订单详情失败', err);
});
*/
// 使
console.log('获取订单详情,ID:', this.orderId);
},
//
goToPay() {
uni.navigateTo({
url: `/pages/details/order?id=${this.orderId}`
});
}
}
}
</script>
<style lang="scss" scoped>
.order-detail-page {
background-color: #f5f5f5;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.order-detail-content {
flex: 1;
padding: 20rpx;
}
.order-detail-footer {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 20rpx 30rpx;
background-color: #FFFFFF;
border-top: 1px solid #EEEEEE;
.footer-btn {
padding: 16rpx 30rpx;
border-radius: 30rpx;
font-size: 26rpx;
margin-left: 20rpx;
}
.cancel-btn {
background-color: #FFFFFF;
color: #666;
border: 1px solid #DDDDDD;
}
.pay-btn {
background-color: #FFAA48;
color: #FFFFFF;
}
.contact-btn {
background-color: #FFFFFF;
color: #666;
border: 1px solid #DDDDDD;
}
}
</style>

+ 463
- 0
pages_order/order/orderList.vue View File

@ -0,0 +1,463 @@
<template>
<view class="order-list-page">
<!-- 顶部标签栏 -->
<view class="order-tabs">
<view
v-for="(tab, index) in tabs"
:key="index"
class="tab-item"
:class="{active: currentTab === tab.value}"
@click="switchTab(tab.value)"
>
<text>{{tab.name}}</text>
</view>
</view>
<!-- 订单列表 -->
<scroll-view
scroll-y
class="order-list-scroll"
@scrolltolower="loadMore"
@refresherrefresh="refresh"
:refresher-enabled="true"
:refresher-triggered="refreshing"
>
<view class="order-list">
<!-- 订单卡片 -->
<view class="order-card" v-for="(order, index) in orderList" :key="index">
<view class="order-header">
<view class="order-status">
<text>{{order.statusText}}</text>
</view>
<view class="order-amount">
<text>金额</text>
<text class="amount-value">¥{{order.amount}}</text>
</view>
</view>
<!-- 宠物信息 -->
<view class="pet-info" v-for="(pet, petIndex) in order.pets" :key="petIndex">
<view class="pet-avatar">
<image :src="pet.avatar || '/static/images/personal/pet.png'" mode="aspectFill"></image>
<view class="pet-tag" v-if="pet.tag">
<text>{{pet.tag}}</text>
</view>
</view>
<view class="pet-details">
<view class="pet-name-gender" style="display: flex; align-items: center;">
<text class="pet-name">{{pet.name}}</text>
<view class="pet-gender" style="margin-left: 10rpx; display: flex; align-items: center;">
<image :src="pet.gender=='男生'?'/static/images/details/boy.svg':'/static/images/details/girl.svg'" style="width: 24rpx; height: 24rpx;" alt="sex"></image>
</view>
</view>
<text class="pet-service">{{pet.serviceTime}}</text>
</view>
</view>
<!-- 订单信息 -->
<view class="order-info">
<text class="order-time">下单时间: {{order.orderTime}}</text>
<view class="companion-info">
<text>伴宠师: {{order.companionName}}</text>
<text v-if="order.companionNote">({{order.companionNote}})</text>
</view>
</view>
<!-- 订单操作 -->
<view class="order-actions">
<view class="action-btn details-btn" @click="viewOrderDetails(order.id)">
<text>查看详情</text>
</view>
<view class="action-btn pay-btn" v-if="order.status === 'unpaid'" @click="goToPay(order.id)">
<text>去付款</text>
</view>
</view>
</view>
<!-- 加载更多 -->
<view class="loading-more" v-if="orderList.length > 0 && hasMore">
<text>加载中...</text>
</view>
<!-- 无更多数据 -->
<view class="no-more" v-if="orderList.length > 0 && !hasMore">
<text>没有更多订单了</text>
</view>
<!-- 无订单提示 -->
<view class="no-order" v-if="orderList.length === 0 && !loading">
<image src="/static/images/personal/no-data.png" mode="aspectFit" class="no-data-image"></image>
<text>暂无订单</text>
</view>
</view>
</scroll-view>
<!-- 客服组件 -->
<Kefu></Kefu>
</view>
</template>
<script>
import Kefu from '@/pages/common/kefu.vue'
import { getOrderList } from "@/api/system/user.js"
import { getOpenIdKey } from '@/utils/auth'
export default {
components: {
Kefu
},
data() {
return {
tabs: [
{ name: '全部', value: '' },
{ name: '待付款', value: '1' },
{ name: '已接单', value: '2' },
{ name: '服务中', value: '3' },
{ name: '已完成', value: '4' }
],
currentTab: '',
orderList: [],
page: 1,
size: 10,
hasMore: true,
loading: false,
refreshing: false,
// API
exampleData: [
{
id: '1',
status: 'unpaid',
statusText: '待付款',
amount: '264',
pets: [
{
name: '小咪',
avatar: '/static/images/personal/pet.png',
tag: '猫',
gender: '女生',
serviceTime: '专业喂养2天: 03-20,03-22'
},
{
name: '小汪',
avatar: '/static/images/personal/pet.png',
tag: '狗',
gender: '男生',
serviceTime: '专业喂养2天: 03-20,03-22'
}
],
orderTime: '2025-12-14 18:23:06',
companionName: '张三',
companionNote: '伴宠师名称暂不可见'
}
]
};
},
methods: {
//
switchTab(tabValue) {
if (this.currentTab === tabValue) return;
this.currentTab = tabValue;
this.orderList = [];
this.page = 1;
this.hasMore = true;
this.getOrderList();
},
//
refresh() {
this.refreshing = true;
this.page = 1;
this.orderList = [];
this.hasMore = true;
this.getOrderList().then(() => {
this.refreshing = false;
}).catch(() => {
this.refreshing = false;
});
},
//
loadMore() {
if (this.loading || !this.hasMore) return;
this.page++;
this.getOrderList();
},
//
viewOrderDetails(orderId) {
uni.navigateTo({
url: `/pages_order/order/orderDetail?id=${orderId}`
});
},
//
goToPay(orderId) {
uni.navigateTo({
url: `/pages/details/order?id=${orderId}`
});
},
//
getOrderList() {
if (this.loading) return Promise.reject();
this.loading = true;
//
const params = {
status: this.currentTab,
openId: getOpenIdKey(),
page: this.page,
size: this.size
};
// API
return new Promise((resolve, reject) => {
// API使API
setTimeout(() => {
try {
// API
if (this.page === 1) {
this.orderList = [...this.exampleData];
} else if (this.page < 3) {
this.orderList = [...this.orderList, ...this.exampleData];
} else {
this.hasMore = false;
}
// API
// getOrderList(params).then(res => {
// if (res && res.code === 200) {
// const newList = res.data.records || [];
// if (this.page === 1) {
// this.orderList = newList;
// } else {
// this.orderList = [...this.orderList, ...newList];
// }
// this.hasMore = newList.length === this.size;
// } else {
// this.hasMore = false;
// }
// this.loading = false;
// resolve();
// }).catch(err => {
// this.loading = false;
// reject(err);
// });
this.loading = false;
resolve();
} catch (err) {
this.loading = false;
reject(err);
}
}, 500);
});
}
},
onLoad() {
//
this.getOrderList();
}
}
</script>
<style lang="scss" scoped>
.order-list-page {
background-color: #f5f5f5;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.order-tabs {
display: flex;
justify-content: space-around;
align-items: center;
height: 88rpx;
background-color: #FFBF60;
color: #FFFFFF;
.tab-item {
padding: 0 20rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
position: relative;
&.active {
font-weight: bold;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background-color: #FFFFFF;
border-radius: 2rpx;
}
}
}
}
.order-list-scroll {
flex: 1;
width: 100%;
}
.order-list {
padding: 20rpx;
padding-bottom: 40rpx;
}
.order-card {
background-color: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.order-status {
background-color: #FFF5E6;
color: #FFAA48;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
}
.order-amount {
font-size: 28rpx;
color: #333;
.amount-value {
color: #FF5252;
font-weight: bold;
}
}
}
.pet-info {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.pet-avatar {
position: relative;
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.pet-tag {
position: absolute;
right: -10rpx;
bottom: -10rpx;
background-color: #FFAA48;
color: #FFFFFF;
font-size: 20rpx;
padding: 4rpx 8rpx;
border-radius: 10rpx;
line-height: 1;
}
}
.pet-details {
display: flex;
flex-direction: column;
.pet-name {
font-size: 28rpx;
color: #333;
font-weight: bold;
}
.pet-service {
font-size: 24rpx;
color: #666;
margin-top: 4rpx;
}
}
}
.order-info {
margin-bottom: 30rpx;
.order-time {
font-size: 24rpx;
color: #999;
display: block;
margin-bottom: 10rpx;
}
.companion-info {
font-size: 24rpx;
color: #999;
background-color: #F0F9FF;
padding: 16rpx;
border-radius: 10rpx;
}
}
.order-actions {
display: flex;
justify-content: flex-end;
align-items: center;
.action-btn {
padding: 16rpx 30rpx;
border-radius: 30rpx;
font-size: 26rpx;
margin-left: 20rpx;
}
.details-btn {
background-color: #FFFFFF;
color: #666;
border: 1px solid #DDDDDD;
}
.pay-btn {
background-color: #FFAA48;
color: #FFFFFF;
}
}
.loading-more, .no-more {
text-align: center;
padding: 20rpx 0;
color: #999;
font-size: 24rpx;
}
.no-order {
text-align: center;
padding: 100rpx 0;
color: #999;
font-size: 28rpx;
display: flex;
flex-direction: column;
align-items: center;
.no-data-image {
width: 200rpx;
height: 200rpx;
margin-bottom: 20rpx;
}
}
</style>

+ 59
- 30
pages_order/order/payOrderSuccessful.vue View File

@ -7,16 +7,23 @@
<view class="content-card">
<view class="card-item">
<view class="item-icon">
<image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/QR_Code.png" mode="aspectFit" :show-menu-by-longpress="true"></image>
<image src="/pages_order/static/order/f.png" mode="aspectFit" :show-menu-by-longpress="true"></image>
</view>
<view class="item-text">
<text class="item-title">请及时添加服务顾问的企业微信</text>
<view class="code">
<image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/QR_Code.png"
mode="aspectFit"
style="width: 260rpx; height:260rpx"/>
</view>
</view>
</view>
<view class="card-item">
<view class="item-icon">
<image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/cmdf.png" mode="aspectFit"></image>
<image src="/pages_order/static/order/f.png" mode="aspectFit"></image>
</view>
<view class="item-text">
<text class="item-title">完善服务档案</text>
@ -29,7 +36,7 @@
<view class="card-item">
<view class="item-icon">
<image src="https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/cmdf.png" mode="aspectFit"></image>
<image src="/pages_order/static/order/f.png" mode="aspectFit"></image>
</view>
<view class="item-text">
<text class="item-title">完善门锁信息</text>
@ -78,50 +85,73 @@
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.successful-page {
position: relative;
height: 100vh;
padding: 20rpx;
padding-bottom: 58px;
background-color: #f5f5f5;
.header {
background-color: #FFB13F;
padding: 20rpx 0;
text-align: center;
.title {
color: #FFFFFF;
font-size: 36rpx;
font-weight: bold;
}
}
.banner-image {
width: 100%;
background-color: #FFFFFF;
}
.content-card {
margin: 20rpx;
background-color: #FFFFFF;
border-radius: 20rpx;
overflow: hidden;
.card-item {
display: flex;
align-items: center;
padding: 30rpx 20rpx;
border-bottom: 1px solid #f0f0f0;
margin: 20rpx;
background-color: #FFFFFF;
border-radius: 20rpx;
position: relative;
&::after {
position: absolute;
content: '';
left: 40rpx;
top: 62rpx;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background-color: #FFB13Faa;
}
&:first-child {
.item-text {
display: flex;
flex-direction: column;
justify-content: center;;
align-items: center;
.item-title {
font-size: 28rpx;
color: #333;
font-weight: bold;
display: block;
}
.code {
padding: 20rpx 0;
}
}
&::after {
top: 190rpx;
}
}
&:last-child {
border-bottom: none;
}
.item-icon {
width: 80rpx;
height: 80rpx;
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
position: relative;
z-index: 2;
image {
width: 100%;
@ -131,7 +161,7 @@
.item-text {
flex: 1;
line-height: 50rpx;
.item-title {
font-size: 28rpx;
color: #333;
@ -149,7 +179,7 @@
.item-action {
.action-btn {
padding: 10rpx 30rpx;
padding: 16rpx 30rpx;
background-color: #FFB13F;
color: #FFFFFF;
border-radius: 30rpx;
@ -160,20 +190,19 @@
}
.back-home {
height: 58px;
height: 116rpx;
position: fixed;
bottom: 0;
width: 100%;
background-color: #FFFFFF;
width: calc(100% - 40rpx);
display: flex;
justify-content: center;
align-items: center;
.details-btn {
width: 90%;
border-radius: 6px;
border-radius: 40rpx;
background: #FFB13F;
font-size: 16px;
font-size: 32rpx;
color: #FFFFFF;
}
}


BIN
pages_order/static/order/f.png View File

Before After
Width: 60  |  Height: 60  |  Size: 965 B

pages_order/static/Group 213084@2x.png → pages_order/static/task/m.png View File


pages_order/static/Group@2x.png → pages_order/static/task/wb.png View File


Loading…
Cancel
Save