lanan-app/pages/rescue/businessManageOrder.vue
2025-10-23 13:04:29 +08:00

885 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 历史订单列表-->
<template>
<view class="content">
<view class="content-header">
<VNavigationBarVue title="订单信息"></VNavigationBarVue>
<!-- <view class="top-icon">
<view class="s-input">
<uni-icons type="search" color="#8E8E93" size="16"></uni-icons>
<input v-model="searchText" type="text" placeholder="搜索订单">
<uni-icons @click="searchText = ''" type="clear" color="#8E8E93"></uni-icons>
</view>
<view class="h-text" @click="handleSearch">搜索</view>
</view> -->
<!-- <view class="top-tap">
<view class="tap-box" :class="{'cc' : gindex == item.id }" v-for="(item,index) in arrtap" :key="index"
@click="getindex(item.id)">
<view style="margin-bottom: 4px;">{{item.text}}</view>
<view class="gang" v-if="item.id == gindex"></view>
</view>
</view> -->
</view>
<!-- 添加时间筛选选项卡 -->
<!-- <view class="tab-choose-class">
<view class="tab-content" @click="tabChoose(item, index)" v-for='(item, index) in ["当日", "当月", "全部", "自定义"]'
:key='index'>
<view class='tab-name-class'
:style='{ color: index + 1 == tabValue ? "#101A3E" : "#8D90A6", fontWeight: index + 1 == tabValue ? "bold" : "normal" }'>
{{ item }}
<view class="icon-tab" v-if='index == 3'>
<image src="@/static/icons/homeOrderCard/xialajiantou.svg" mode="scaleToFill"></image>
</view>
</view>
<view class="tab-icon"
:style='{ background: index + 1 == tabValue ? "linear-gradient( 180deg, #054DF3 0%, #55A3FF 100%)" : "" }'>
</view>
</view>
</view> -->
<!-- 自定义时间选择器 -->
<!-- <view class="example-body" v-show="tabValue==4" style="margin-bottom: 16rpx;">
<uni-datetime-picker v-model="range" type="daterange" @maskClick="maskClick" />
</view> -->
<view class="four-box-header_2">
<view class="four-box-header">
<view class="blue-line" style="margin-left: 20rpx; font-size: 30rpx; font-weight: bold; color: black;">
总计:{{ totalNum == null ? 0 : totalNum }}
</view>
</view>
<view class="four-box-header_2_right">
<text :class="['tab-item', { active: activeTab === 0 }]" @click="switchTab(0)">司机信息</text>
<text :class="['tab-item', { active: activeTab === 1 }]" @click="switchTab(1)">业务信息</text>
<text :class="['tab-item', { active: activeTab === 2 }]" @click="switchTab(2)">客户信息</text>
</view>
</view>
<view class="dil">
<!-- 初始加载状态 -->
<view class="ques" v-if="initialLoading">
<view class="loading-container">
<view class="loading-spinner"></view>
<text class="loading-text">加载中,请稍候...</text>
</view>
</view>
<!-- 非加载中且无数据状态 -->
<view class="ques" v-else-if="!initialLoading && orderList.length == 0">
<image src="../../static/quesheng.png" mode=""></image>
</view>
<view v-else>
<order-card-vue @refresh="getlist" :status="gindex" v-for="(item,index) in orderList" :key="index"
:orderData="item" :brandList="brandList" :staffList="staffList"
:activeTab="activeTab"></order-card-vue>
<!-- 底部加载更多状态 -->
<view v-if="loadingMore" class="loading-more">
<view class="loading-spinner mini"></view>
<text>正在加载更多...</text>
</view>
<view v-if="!hasMore" class="no-more-data">
<text>没有更多数据了</text>
</view>
</view>
<view style="width: 100%; height: 60px;"></view>
</view>
<tabBar msg="1"></tabBar>
</view>
</template>
<script>
import tabBar from '../../components/tabBar/tabBar.vue'
import VNavigationBarVue from '../../components/VNavigationBar.vue';
import OrderCardVue from '../../components/orderCard/OrderCard.vue';
import request from '../../utils/request';
export default {
data() {
return {
// 搜索内容
searchText: '',
searchKeyword: null,
gindex: 1,
brandList: [],
staffList: [],
orderList: [
// {
// rescueTypeStr: '扣车',
// rescuePosition: '四川省泸州市江阳区酒谷大道四段18号泸州',
// rescueStatus: 2,
// rescueStatusStr: '待救援',
// driverName: '先伟',
// driverCarNum: '川E69752',
// distance: 12800,
// needTime: 26,
// rescueTime: '2024-08-12 08:42'
// }
],
totalNum: null,
total: 0,
pageNum: 1, //第几页
pageSize: 10, //一页多少张
totalPages: 0, //总数
arrtap: [{
text: '已接单',
id: 'null'
},
{
text: '待支付',
id: 2
},
{
text: '待取车',
id: 3
},
{
text: '救援中',
id: 1
},
{
text: '已完成',
id: 5
}
],
arrbox: [],
activeTab: 0, // 默认显示司机端
loading: true, // 加载状态控制
initialLoading: true, // 初始加载状态
loadingMore: false, // 加载更多状态(触底加载)
hasMore: true, // 是否有更多数据
scrollTop: 0, // 保存滚动位置
channel: '', // 渠道
source : '', // 来源
timeType: 'day', // day | month | ...
tabValue: 1,
range: [],
startTimeStr: null,
endTimeStr: null,
}
},
components: {
tabBar,
VNavigationBarVue,
OrderCardVue
},
// onLoad(option) {
// this.gindex = option.id
// this.getlist()
// this.getBrandList()
// this.getStaffList()
// },
onLoad({dateType='',channel='',source=''}){
this.timeType = dateType
this.channel = decodeURIComponent(channel)
this.source = decodeURIComponent(source)
// this.fetchOrders()
this.getlist()
},
onReachBottom() {
console.log('触底加载');
if (this.pageNum >= this.totalPages) {
this.hasMore = false;
} else if (!this.loadingMore) {
this.loadingMore = true;
this.pageNum++;
this.getlist();
}
},
onPageScroll(e) {
// 保存页面滚动位置
this.scrollTop = e.scrollTop;
},
watch: {
range(newval) {
if (newval && newval.length === 2) {
this.startTimeStr = newval[0];
this.endTimeStr = newval[1];
// 自定义时间选择完成后触发加载
this.pageNum = 1;
this.orderList = [];
this.hasMore = true;
this.initialLoading = true;
this.getlist();
}
}
},
methods: {
fetchOrders(page=1){
const params = {
pageNum:page,
pageSize:20,
timeType:this.dateType, // 本日/本月…
channel:this.channel,
source :this.source
}
let data = {
// rescueStatus: this.gindex,
pageSize: this.pageSize,
pageNum: this.pageNum,
timeType: this.dateType,
startTimeStr: this.startTimeStr,
endTimeStr: this.endTimeStr,
channel:this.channel,
source :this.source
}
if (this.searchKeyword) {
data.licenseNum = this.searchKeyword;
}
request({
url: '/app/rescueInfo/getRescueList',
method: 'get',
params: data
}).then((res) => {
console.log('list', res);
if (res.code == 200) {
if (this.pageNum != 1) {
// 保存当前滚动位置
const currentScrollTop = this.scrollTop;
// 追加数据
this.orderList = this.orderList.concat(res.rows);
// 数据更新后恢复滚动位置
this.$nextTick(() => {
uni.pageScrollTo({
scrollTop: currentScrollTop,
duration: 0
});
});
} else {
this.orderList = res.rows;
}
this.totalNum = res.total
let total = res.total;
this.totalPages = Math.ceil(total / this.pageSize);
this.hasMore = this.pageNum < this.totalPages;
}
}).catch((error) => {
console.error('获取数据失败', error);
uni.showToast({
title: '数据加载失败',
icon: 'none'
});
}).finally(() => {
this.initialLoading = false;
this.loadingMore = false;
});
},
// 切换选项卡
switchTab(index) {
this.activeTab = index;
},
tabChoose(item, index) {
this.tabValue = index + 1;
if (1 == this.tabValue) {
this.timeType = "day";
} else if (2 == this.tabValue) {
this.timeType = "month";
} else if (3 == this.tabValue) {
this.timeType = "all";
} else if (4 == this.tabValue) {
this.timeType = "more";
this.range = [];
// 点击自定义时立即清空数据并显示无数据状态
this.orderList = [];
this.hasMore = false;
this.initialLoading = false;
return; // 不立即发起请求
}
// 非自定义选项或自定义已选时间后触发加载
this.pageNum = 1;
this.orderList = [];
this.hasMore = true;
this.initialLoading = true;
this.getlist();
},
handleSearch() {
this.searchKeyword = this.searchText.trim();
this.pageNum = 1; // 重置页码
this.orderList = []; // 清空当前列表
this.hasMore = true;
this.initialLoading = true; // 关键:设置为初始加载状态
this.getlist(); // 重新获取数据
},
getBrandList() {
let data = {
pageSize: 1000,
pageNum: 1,
}
request({
url: '/base/carBrand/page',
method: 'get',
params: data
}).then((res) => {
console.log('list', res);
if (res.code == 200) {
this.brandList = res.data.records
}
})
},
getStaffList() {
let data = {
pageSize: 1000,
pageNum: 1,
}
request({
url: '/company/staff/list',
method: 'get',
params: data
}).then((res) => {
console.log('list', res);
if (res.code == 200) {
this.staffList = res.data
}
})
},
godetail(id) {
uni.navigateTo({
url: '/pages/details/details?id=' + id
})
},
getlist() {
let data = {
pageNum : this.pageNum,
pageSize : this.pageSize,
timeType : this.timeType,
channel : this.channel,
source : this.source,
startTimeStr : this.startTimeStr,
endTimeStr : this.endTimeStr
// rescueStatus : this.gindex,
}
if (this.searchKeyword) {
data.licenseNum = this.searchKeyword;
}
request({
url: '/app/rescueInfo/getRescueList',
method: 'get',
params: data
}).then((res) => {
console.log('list', res);
if (res.code == 200) {
if (this.pageNum != 1) {
// 保存当前滚动位置
const currentScrollTop = this.scrollTop;
// 追加数据
this.orderList = this.orderList.concat(res.rows);
// 数据更新后恢复滚动位置
this.$nextTick(() => {
uni.pageScrollTo({
scrollTop: currentScrollTop,
duration: 0
});
});
} else {
this.orderList = res.rows;
}
this.totalNum = res.total
let total = res.total;
this.totalPages = Math.ceil(total / this.pageSize);
this.hasMore = this.pageNum < this.totalPages;
}
}).catch((error) => {
console.error('获取数据失败', error);
uni.showToast({
title: '数据加载失败',
icon: 'none'
});
}).finally(() => {
this.initialLoading = false;
this.loadingMore = false;
});
},
getindex(index) {
this.orderList = [];
this.gindex = index;
this.pageNum = 1;
this.hasMore = true;
this.initialLoading = true;
this.getlist();
},
}
}
</script>
<style scoped lang="scss">
.content {
width: 100%;
height: calc(100vh);
background-color: #F7F8FC;
box-sizing: border-box;
}
.content-header {
background-color: #327DFB;
padding-bottom: 10rpx;
}
.top-icon {
box-sizing: border-box;
width: 100%;
padding: 5px 14px;
display: flex;
justify-content: space-between;
align-items: center;
}
.dil {
background-color: #F7F8FC;
box-sizing: border-box;
padding: 8px 12px 15px 12px;
display: flex;
flex-direction: column;
row-gap: 10px;
}
.h-text {
width: 124rpx;
height: 56rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 28rpx;
font-size: 28rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
.s-input {
width: 78%;
height: 56rpx;
background: #fff;
border-radius: 50px;
box-sizing: border-box;
display: flex;
align-items: center;
padding: 0px 10px;
input {
margin-left: 5px;
flex: 1;
width: 0;
font-size: 14px;
color: #999999;
}
}
.top-tap {
width: 100%;
background: #327DFB;
display: flex;
align-items: center;
box-sizing: border-box;
margin-top: 10rpx;
}
.tap-box {
width: 20%;
font-size: 28rpx;
font-weight: 400;
color: #fff;
text-align: center;
position: relative;
padding-top: 24rpx;
padding-bottom: 24rpx;
}
.gang {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
width: 60%;
height: 6rpx;
border-radius: 12px;
background: linear-gradient(87deg, #fff 0%, #fff 100%);
}
.d-box {
width: 100%;
// height: 100px;
background: white;
border-radius: 10px;
margin-bottom: 15px;
box-sizing: border-box;
padding: 8px;
position: relative;
overflow: hidden;
padding-top: 30px;
}
.d-y-top {
position: absolute;
top: 0px;
left: 0px;
width: 40px;
height: 20px;
border-radius: 0px 0px 6px 0px;
background-color: #339DFF;
color: white;
font-size: 12px;
text-align: center;
}
.t-right {
width: 100%;
display: flex;
justify-content: flex-end;
.bq {
width: 55px;
height: 20px;
background: #FFD7D7;
border-radius: 4px;
font-size: 12px;
font-weight: 400;
color: #FF4C4C;
display: flex;
justify-content: center;
align-items: center;
}
.bq2 {
width: 55px;
height: 20px;
background: #CDE2FF;
border-radius: 4px;
font-size: 12px;
font-weight: 400;
color: #3289FF;
display: flex;
justify-content: center;
align-items: center;
}
}
.d-left {
margin-left: 10px;
display: flex;
font-size: 16px;
font-weight: bold;
color: #666666;
margin-bottom: 10px;
}
.t-left {
margin-left: 10px;
display: flex;
font-size: 12px;
font-weight: 400;
color: #666666;
margin-bottom: 5px;
}
.x-left {
margin-left: 10px;
display: flex;
justify-content: space-between;
font-size: 12px;
font-weight: 400;
color: #666666;
}
.cc {
font-weight: bold;
}
.hong {
font-size: 16px;
font-weight: 400;
color: #F85021;
}
.ques {
margin: 0px auto;
margin-top: 160rpx;
width: 80%;
image {
width: 100%;
}
}
.boxt {
// height: 110px;
width: 100%;
background-color: white;
border-radius: 6px;
margin-top: 14px;
overflow: hidden;
display: flex;
box-sizing: border-box;
padding-bottom: 15px;
}
.boxt-left {
width: 50%;
height: 100%;
}
.left-lan {
width: 50px;
height: 25px;
display: flex;
justify-content: center;
align-items: center;
background-color: #207EFE;
font-size: 14px;
color: white;
border-radius: 0px 0px 6px 0px;
}
.text1 {
margin-left: 24px;
margin-top: 5px;
color: #333333;
font-size: 16px;
font-weight: bold;
color: #333333;
}
.lanzi {
font-weight: bold;
color: #4C98FF;
}
.text2 {
margin-left: 24px;
margin-top: 5px;
color: #333333;
font-size: 16px;
font-weight: 400;
color: #333333;
}
.boxt-right {
width: 50%;
height: 100%;
position: relative;
}
.zhtai {
position: absolute;
top: 10px;
right: 10px;
width: 60px;
height: 25px;
box-sizing: border-box;
background: #FFD7D7;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
color: #FF4C4C;
font-size: 14px;
}
.dianhua {
position: absolute;
bottom: -110px;
right: 10px;
display: flex;
font-size: 14px;
font-weight: 400;
color: #3289FF;
}
.ticon {
width: 12px;
height: 13px;
margin-right: 5px;
image {
width: 100%;
height: 100%;
}
}
/* 添加时间筛选选项卡样式 */
.tab-choose-class {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 20rpx 16rpx 20rpx;
background-color: #fff;
border-bottom: 1rpx solid #F5F5F5;
.tab-content {
font-size: 28rpx;
display: flex;
flex-direction: column;
align-items: center;
.tab-name-class {
display: flex;
align-items: center;
.icon-tab {
display: flex;
align-items: center;
justify-content: center;
width: 32rpx;
height: 32rpx;
image {
width: 100%;
height: 100%;
}
}
}
}
.tab-icon {
width: 66rpx;
height: 8rpx;
margin-top: 8rpx;
}
}
.example-body {
background-color: #fff;
padding: 0 20rpx;
}
/* 添加选项卡样式 */
.four-box-header_2 {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
// padding: 20rpx 0 0 0;
}
.four-box-header_2_right {
width: 60%;
display: flex;
justify-content: space-around;
align-items: center;
padding: 20rpx 0;
.tab-item {
font-size: 28rpx;
font-weight: normal;
color: #a1a6aa;
position: relative;
padding: 0rpx 20rpx;
cursor: pointer;
transition: all 0.3s ease;
&.active {
font-weight: bold;
color: #000000;
&::after {
content: '';
position: absolute;
bottom: -10rpx;
left: 50%;
transform: translateX(-50%);
width: 33.33%;
height: 6rpx;
background: linear-gradient(90deg, #054DF3 0%, #55A3FF 100%);
border-radius: 3rpx 3rpx 0 0;
}
}
}
}
.loading-container {
/* position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.9); */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-spinner {
position: relative;
width: 60px;
height: 60px;
border: 4px solid #f3f3f3;
border-top: 4px solid #327DFB;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 15px;
display: flex;
justify-content: center;
align-items: center;
}
.loading-text {
font-size: 16px;
color: #666;
}
.loading-icon {
width: 35px;
height: 35px;
position: absolute;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-more {
display: flex;
justify-content: center;
align-items: center;
padding: 20rpx;
color: #999;
font-size: 26rpx;
.mini {
width: 30px;
height: 30px;
border-width: 2px;
margin-right: 10rpx;
}
}
.no-more-data {
text-align: center;
padding: 20rpx;
color: #999;
font-size: 26rpx;
}
</style>