Browse Source

refactor(订单列表): 优化订单列表页面结构和样式,调整API调用逻辑

- 重构订单列表页面的HTML结构和CSS样式,提升页面可读性和用户体验
- 调整订单列表API调用逻辑,使用实际API替换模拟数据
- 修复订单状态显示问题,确保订单状态与标签栏一致
- 优化代码结构,删除冗余代码,提升代码可维护性
master
前端-胡立永 1 day ago
parent
commit
f9b115c8cd
7 changed files with 840 additions and 655 deletions
  1. +81
    -79
      api/system/user.js
  2. +2
    -0
      pages/details/feed.vue
  3. +2
    -0
      pages/details/walk.vue
  4. +536
    -417
      pages/newOrder/confirmOrder.vue
  5. +1
    -0
      pages/newOrder/serviceNew.vue
  6. +173
    -159
      pages_order/order/orderList.vue
  7. +45
    -0
      utils/serviceTime.js

+ 81
- 79
api/system/user.js View File

@ -3,152 +3,154 @@ import request from '@/utils/request'
// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {
const data = {
oldPassword,
newPassword
}
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
params: data
})
const data = {
oldPassword,
newPassword
}
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
params: data
})
}
// 查询用户个人信息
export function getUserProfile() {
return request({
url: '/system/user/profile',
method: 'get'
})
return request({
url: '/system/user/profile',
method: 'get'
})
}
// 修改用户个人信息
export function updateUserProfile(data) {
return request({
url: '/system/user/profile',
method: 'put',
data: data
})
return request({
url: '/system/user/profile',
method: 'put',
data: data
})
}
// 用户头像上传
export function uploadAvatar(data) {
return upload({
url: '/system/user/profile/avatar',
name: data.name,
filePath: data.filePath
})
return upload({
url: '/system/user/profile/avatar',
name: data.name,
filePath: data.filePath
})
}
// 人员列表
export function getStaffList(){
export function getStaffList() {
return request({
url: '/h5/staff/list',
method: 'get'
url: '/h5/staff/list',
method: 'get'
})
}
// 产品列表
export function getProductList(data){
export function getProductList(data) {
return request({
url: '/no-auth/product/list',
method: 'post',
data:data
url: '/no-auth/product/list',
method: 'post',
data: data
})
}
// 产品详情
export function getProductDetails(data){
export function getProductDetails(data) {
return request({
url: `/no-auth/product/detail/${data}`,
method: 'get',
url: `/no-auth/product/detail/${data}`,
method: 'get',
})
}
// 字典
export function getDictList(type){
export function getDictList(type) {
return request({
url: `/h5/system/dict/data/type/${type}`,
method: 'get'
url: `/h5/system/dict/data/type/${type}`,
method: 'get'
})
}
//获取openId
export function getOpenId(code){
export function getOpenId(code) {
return request({
url: `/no-auth/wechat/getOpenId?code=${code}`,
method: 'get'
url: `/no-auth/wechat/getOpenId?code=${code}`,
method: 'get'
})
}
// 创建订单
export function createOrder(data){
export function createOrder(data) {
return request({
url: `/no-auth/appointment/add`,
method: 'post',
data:data
url: `/no-auth/appointment/add`,
method: 'post',
data: data
})
}
// 创建订单新
export function createOrderNew(data){
export function createOrderNew(data) {
return request({
url: `/h5/appointment/add`,
method: 'post',
headers:{ "isToken":true},
data:data
url: `/h5/appointment/add`,
method: 'post',
headers: {
"isToken": true
},
data: data
})
}
export function getOrderList(data){
export function getOrderList(params) {
return request({
url: `/h5/order/listByOpenid?status=${data.status}&openid=${data.openId}&page=${data.page}&size=${data.size}`,
method: 'get'
url: `/h5/order/listByOpenid`,
method: 'get',
params,
})
}
export function getBannerList(){
export function getBannerList() {
return request({
url: `/h5/system/dict/data/type/sys_banner`,
method: 'get'
url: `/h5/system/dict/data/type/sys_banner`,
method: 'get'
})
}
export function getCity(){
export function getCity() {
return request({
url: `/h5/system/config/order.city.list`,
method: 'get'
url: `/h5/system/config/order.city.list`,
method: 'get'
})
}
export function getCouponList(){
export function getCouponList() {
return request({
url: `/h5/coupon/list`,
headers:{ "isToken":true},
method: 'get'
url: `/h5/coupon/list`,
headers: {
"isToken": true
},
method: 'get'
})
}
export function receiveCoupon(data){
export function receiveCoupon(data) {
return request({
url: `/h5/coupon/get`,
headers:{ "isToken":true},
method: 'post',
data
url: `/h5/coupon/get`,
headers: {
"isToken": true
},
method: 'post',
data
})
}
export function getCouponListNoAuth(){
export function getCouponListNoAuth() {
return request({
url: `/no-auth/h5/coupon/list`,
method: 'get'
url: `/no-auth/h5/coupon/list`,
method: 'get'
})
}
//获取手机号
export function getPhoneNumber(data){
export function getPhoneNumber(data) {
return request({
url: `/no-auth/wechat/getPhoneNumber`,
method: 'post',
data
url: `/no-auth/wechat/getPhoneNumber`,
method: 'post',
data
})
}
}

+ 2
- 0
pages/details/feed.vue View File

@ -123,6 +123,8 @@
"skuId": this.skus[0].id,
"quantity": 1
}
this.$store.commit('setPosition', {})
this.buyInfo.teacher = null
this.$globalData.newOrderData={
currentAddress:{},
currentPets:[],


+ 2
- 0
pages/details/walk.vue View File

@ -122,6 +122,8 @@
"skuId": this.skus[0].id,
"quantity": 1
}
this.$store.commit('setPosition', {})
this.buyInfo.teacher = null
this.$globalData.newOrderData={
currentAddress:{},
currentPets:[],


+ 536
- 417
pages/newOrder/confirmOrder.vue
File diff suppressed because it is too large
View File


+ 1
- 0
pages/newOrder/serviceNew.vue View File

@ -217,6 +217,7 @@
needPreFamiliarize:[],
defaultPhoto:'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/personal/pet/catdog.png',
companionLevel: 'junior', //
companionLevelList: ['', 'junior', 'senior'], //
popupTitle: '',
popupLevel: '',
}


+ 173
- 159
pages_order/order/orderList.vue View File

@ -2,43 +2,34 @@
<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)"
>
<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"
>
<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">
<text>{{ tabs[order.status - 1].name }}</text>
<view class="order-status">
<text>{{order.statusText}}</text>
<text v-if="order.teacherId">指定伴宠师下单</text>
<text v-else>系统下单</text>
</view>
<view class="order-amount">
<text>金额</text>
<text class="amount-value">¥{{order.amount}}</text>
<text class="amount-value">¥{{order.payAmount}}</text>
</view>
</view>
<!-- 宠物信息 -->
<view class="pet-info" v-for="(pet, petIndex) in order.pets" :key="petIndex">
<view class="pet-info" v-for="(pet, petIndex) in order.petVOList" :key="petIndex">
<view class="pet-avatar">
<image :src="pet.avatar || '/static/images/personal/pet.png'" mode="aspectFill"></image>
<image :src="pet.photo || '/static/images/personal/pet.png'" mode="aspectFill"></image>
<view class="pet-tag" v-if="pet.tag">
<text>{{pet.tag}}</text>
</view>
@ -46,27 +37,30 @@
<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 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>
<text class="order-time">下单时间: {{order.createTime}}</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" v-if="order.status == 0"
@click="$refs.cancelOrderPopup.open()">
<view class="action-btn details-btn" v-if="order.status == 0"
@click="$refs.cancelOrderPopup.open()">
<text>取消订单</text>
</view>
<view class="action-btn details-btn" @click="viewOrderDetails(order.id)">
@ -80,17 +74,17 @@
</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>
@ -100,27 +94,27 @@
</scroll-view>
<!-- 取消订单弹窗 -->
<cancel-order-popup
ref="cancelOrderPopup"
@cancel="handleCancelOrder"
></cancel-order-popup>
<cancel-order-popup ref="cancelOrderPopup" @cancel="handleCancelOrder"></cancel-order-popup>
<!-- 客服组件 -->
<Kefu></Kefu>
<!-- 伴宠师选择弹窗 -->
<companion-select-popup
ref="companionSelectPopup"/>
<companion-select-popup ref="companionSelectPopup" />
</view>
</template>
<script>
import Kefu from '@/pages/common/kefu.vue'
import { getOrderList } from "@/api/system/user.js"
import { getOpenIdKey } from '@/utils/auth'
import {
getOrderList
} from "@/api/system/user.js"
import {
getOpenIdKey
} from '@/utils/auth'
import CancelOrderPopup from '@/pages_order/components/order/CancelOrderPopup.vue'
import CompanionSelectPopup from '@/pages_order/components/order/CompanionSelectPopup.vue'
// import { getOrderServiceText, getProductNameText } from '@/utils/serviceTime.js'
export default {
components: {
Kefu,
@ -129,14 +123,28 @@
},
data() {
return {
tabs: [
{ name: '全部', value: '' },
{ name: '待付款', value: '0' },
{ name: '已接单', value: '1' },
{ name: '服务中', value: '2' },
{ name: '已完成', value: '3' }
tabs: [{
name: '全部',
value: -1
},
{
name: '待付款',
value: 0
},
{
name: '已接单',
value: 1
},
{
name: '服务中',
value: 2
},
{
name: '已完成',
value: 3
}
],
currentTab: '',
currentTab: -1,
orderList: [],
page: 1,
size: 10,
@ -145,46 +153,43 @@
refreshing: false,
currentOrder: null,
// API
exampleData: [
{
id: '1',
status: '0',
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: '伴宠师名称暂不可见'
}
]
exampleData: [{
id: '1',
status: '0',
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;
// if (this.currentTab === tabValue) return;
this.currentTab = tabValue;
this.orderList = [];
this.page = 1;
this.hasMore = true;
this.getOrderList();
},
//
refresh() {
this.refreshing = true;
@ -197,37 +202,37 @@
this.refreshing = false;
});
},
handleCancelOrder(){
},
handleCancelOrder() {
},
//
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,
@ -236,47 +241,46 @@
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);
// 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;
// }
// this.loading = false;
// resolve();
// } catch (err) {
// this.loading = false;
// reject(err);
// }
// }, 500);
// });
// API
return getOrderList(params).then(res => {
if (res.content) {
const newList = res.content || [];
if (this.page === 1) {
this.orderList = newList;
} else {
this.orderList = [...this.orderList, ...newList];
}
}, 500);
this.hasMore = newList.length === this.size;
} else {
this.hasMore = false;
}
this.loading = false;
resolve();
}).catch(err => {
this.loading = false;
reject(err);
});
},
@ -301,7 +305,7 @@
display: flex;
flex-direction: column;
}
.order-tabs {
display: flex;
justify-content: space-around;
@ -309,7 +313,7 @@
height: 88rpx;
background-color: #FFBF60;
color: #FFFFFF;
.tab-item {
padding: 0 20rpx;
height: 100%;
@ -318,10 +322,10 @@
justify-content: center;
font-size: 28rpx;
position: relative;
&.active {
font-weight: bold;
&::after {
content: '';
position: absolute;
@ -336,67 +340,72 @@
}
}
}
.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;
background-color: #FFF4E5;
padding: 30rpx;
padding-bottom: 20rpx;
.order-status {
background-color: #FFF5E6;
color: #FFAA48;
color: #A94F20;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
background-color: #FFE0BF;
margin-right: auto;
margin-left: 20rpx;
}
.order-amount {
font-size: 28rpx;
color: #333;
.amount-value {
color: #FF5252;
font-weight: bold;
}
}
}
.pet-info {
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding: 30rpx;
padding-bottom: 20rpx;
padding-top: 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;
@ -409,17 +418,17 @@
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;
@ -427,17 +436,19 @@
}
}
}
.order-info {
margin-bottom: 30rpx;
padding: 30rpx;
padding-bottom: 20rpx;
padding-top: 20rpx;
.order-time {
font-size: 24rpx;
color: #999;
display: block;
margin-bottom: 10rpx;
}
.companion-info {
font-size: 24rpx;
color: #999;
@ -446,38 +457,41 @@
border-radius: 10rpx;
}
}
.order-actions {
padding: 30rpx;
padding-top: 20rpx;
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 {
.loading-more,
.no-more {
text-align: center;
padding: 20rpx 0;
color: #999;
font-size: 24rpx;
}
.no-order {
text-align: center;
padding: 100rpx 0;
@ -486,7 +500,7 @@
display: flex;
flex-direction: column;
align-items: center;
.no-data-image {
width: 200rpx;
height: 200rpx;


+ 45
- 0
utils/serviceTime.js View File

@ -0,0 +1,45 @@
import dayjs from "dayjs";
export function getOrderServiceText(petId, orderServiceList) {
let YYYY = undefined
return orderServiceList
.filter(service => service.petId == petId) //过滤
.map(service => dayjs(service.serviceDate)) //转成时间
.sort((a, b) => a.valueOf() - b.valueOf()) //排序
.map((service, i) => {
// if(YYYY && YYYY.format('YYYY-MM') == service.format('YYYY-MM')){
// return service.format('DD')
// }
// if(YYYY && YYYY.format('YYYY') == service.format('YYYY')){
// return service.format('MM-DD')
// }
// YYYY = service
return service.format('MM-DD')
})
}
export function getProductNameText(petId, productList, orderServiceList) {
let orderService = orderServiceList.filter(service => service.petId == petId)
let list = (productList
.filter(product => orderService.filter(service => service.id == product.orderServiceId).length > 0)
.map(product => product.productName))
return [...new Set(list)]
}
export default {
getProductNameText,
getOrderServiceText,
}

Loading…
Cancel
Save