chuangte_bike_newxcx/page_shanghu/guanli/admin_order.vue
2026-04-28 14:01:46 +08:00

709 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="page">
<u-navbar :is-back="false" title="订单管理" :border-bottom="false" :background="bgc" title-color='#2E4975'
title-size='36' height='45'></u-navbar>
<view class="top_box">
<view class="left_text">
时间范围
</view>
<view class="timebox">
<view class="left_time" hover-class="is-hover" hover-stay-time="80" @click="time1=true">
{{firsTime}}
</view>
-
<view class="right_time" hover-class="is-hover" hover-stay-time="80" @click="time2=true">
{{lasTime}}
</view>
</view>
</view>
<view class="top_box top_box_second">
<view class="left_text select_left" hover-class="is-hover" hover-stay-time="80" @click="shows=true">
{{tit}}
<view class="iconfont icon-xiangxia1"></view>
</view>
<view class="sear_ipt">
<input type="text" v-model="searchKeyword" placeholder="请输入内容" class="input" placeholder-style="color:#C7CDD3" @input="search()">
</view>
</view>
<view class="tap">
<view class="tap_cont" :hover-class="tabListLoading ? '' : 'is-hover'" hover-stay-time="80" :class="[zhuangtai==''?'act1':'', tabListLoading?'tap_cont--disabled':'']" @click="changeidx('')">
全部
</view>
<view class="tap_cont" :hover-class="tabListLoading ? '' : 'is-hover'" hover-stay-time="80" :class="[zhuangtai=='PROCESSING'?'act1':'', tabListLoading?'tap_cont--disabled':'']" @click="changeidx('PROCESSING')">
进行中
</view>
<view class="tap_cont tap_cont_lg" :hover-class="tabListLoading ? '' : 'is-hover'" hover-stay-time="80" :class="[zhuangtai=='RIDE_WAIT_PAY'?'act1':'', tabListLoading?'tap_cont--disabled':'']" @click="changeidx('RIDE_WAIT_PAY')">
骑行待支付
</view>
<view class="tap_cont" :hover-class="tabListLoading ? '' : 'is-hover'" hover-stay-time="80" :class="[zhuangtai=='WAIT_VERIFY'?'act1':'', tabListLoading?'tap_cont--disabled':'']" @click="changeidx('WAIT_VERIFY')">
待审核
</view>
<view class="tap_cont" :hover-class="tabListLoading ? '' : 'is-hover'" hover-stay-time="80" :class="[zhuangtai=='FINISHED'?'act1':'', tabListLoading?'tap_cont--disabled':'']" @click="changeidx('FINISHED')">
已完成
</view>
</view>
<u-mask :show="show" :z-index='100' />
<u-picker mode="time" v-model="time1" :params="params" @confirm="confirm1" :default-time='pickertime'></u-picker>
<u-picker mode="time" v-model="time2" :params="params" @confirm="confirm2" :default-time='pickertime'></u-picker>
<scroll-view class="warp_box" @scrolltolower="handqixing" scroll-y refresher-enabled @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing" refresher-default-style="black">
<view class="swiper-item">
<view class="card" hover-class="card-hover" hover-stay-time="80" v-for="(item,index) in allList" :key="index" @click="toOrderDetail(item.deviceSn,item.id,item)">
<view class="line"></view>
<view class="top_info">
<view class="top_info_left">
<text v-if="item.timeout == false">{{item.no}}</text>
<text v-else class="text-danger">{{item.no}}</text>
<text class="text-danger" v-if="item.timeout == true"> ·超时</text>
<zhima-no-deposit-badge class="deposit-badge" v-if="item.payChannelApiType === ChannelApiType.ZHIMA_DEPOSIT_ONLY.value" />
</view>
<view class="top_info_right status-processing" v-if="item.status=='PROCESSING'">
<view class="yuan"></view>
进行中
</view>
<view class="top_info_right status-wait-pay" v-if="item.status== 'WAIT_PAY'">
<view class="yuan"></view>
押金待支付
</view>
<view class="top_info_right status-finished" v-if="item.status=='FINISHED'">
<view class="yuan"></view>
已完成
</view>
<view class="top_info_right status-canceled" v-if="item.status=='CANCELED'">
<view class="yuan"></view>
已取消
</view>
<view class="top_info_right status-ride-wait-pay" v-if="item.status=='RIDE_WAIT_PAY'">
<view class="yuan"></view>
骑行待支付
</view>
<view class="top_info_right status-wait-verify" v-if="item.status=='WAIT_VERIFY'">
<view class="yuan"></view>
待审核
</view>
</view>
<view class="lines"></view>
<view class="order_info">
<view class="info_li">
<view class="half_info_li" v-if="item.status=='PROCESSING'">
实收金额:<span class="amount-text">0元</span>
</view>
<view class="half_info_li" v-else>
实收金额:<span class="amount-text">{{ item.actualReceivedAmount.toFixed(2)}}</span>
</view>
<view class="half_info_li">
用户手机号:<span>{{item.userPhone == null ? '--' : item.userPhone}}</span>
</view>
</view>
<view class="info_li">
<view class="half_info_li">
车辆编号:<span>{{item.deviceSn == null ? '--' : item.deviceSn}}</span>
</view>
<view class="half_info_li" v-if="item.deviceVehicleNum">
车牌号:<span>{{item.deviceVehicleNum}}</span>
</view>
<view class="half_info_li" v-else>
车牌号:<span>--</span>
</view>
</view>
<view class="info_li">
<view class="half_info_li">
订单费用:<span>{{item.totalFee}}元</span>
</view>
<view class="half_info_li">
人工退款:<span v-if="item.payAdminRefund>0" class="text-danger">{{item.payAdminRefund.toFixed(2)}}元</span>
<span v-else>0.00元</span>
</view>
</view>
<view class="info_li">
<view class="half_info_li" v-if="item.startTime">
开始时间:<span>{{formatDate(item.startTime)}}</span>
</view>
<view class="half_info_li" v-else>
开始时间:<span>无</span>
</view>
<view class="half_info_li">
租赁时长:<span>{{formatDatess(item.startTime,item.endTime)}}</span>
</view>
</view>
</view>
</view>
<view class="no-more-orders">
当前没有更多订单啦...
</view>
</view>
</scroll-view>
<u-select v-model="shows" :list="list" title='添加方式' @confirm="searchconfirm"></u-select>
<TabBar :indexs='3'></TabBar>
</view>
</template>
<script>
import { ChannelApiType } from '@/common/enums/channel';
import ZhimaNoDepositBadge from '@/components/zhima-no-deposit-badge/zhima-no-deposit-badge.vue';
import TabBar from '@/page_shanghu/components/tab-bar/tab-bar.vue';
let timerId;
let timerId1;
export default {
components: {
TabBar,
ZhimaNoDepositBadge
},
data() {
return {
ChannelApiType,
bgc: {
backgroundColor: "#F7FAFE",
},
params: {
year: true,
month: true,
day: true,
hour: false,
minute: false,
second: false
},
pickertime: '',
time1: false,
time2: false,
lasTime: '',
firsTime: '',
searchKeyword: '',
curtitidx: '',
swiperHeight: 400,
allList: [],
ingList: [],
reprement: [],
alreadyList: [],
show: false,
showfz: false,
showgj: false,
showtk: false,
orderInfo: {},
initialValues: {},
isRefreshing: false,
areaId: false,
tit: '车牌号',
shows: false,
list: [{
value: '1',
label: '手机号'
},
{
value: '2',
label: '车牌号'
}],
typeidx: '2',
passList: [],
dispatchFee: 0,
manageFee: 0,
ridingFee: 0,
appointmentFee: 0,
reason: '',
pageNum: 1,
isback: false,
zhuangtai:'',
total:'',
wateringListone:[],
pageSize:20,
/** tab 切换拉取列表进行中时禁止再次切换 */
tabListLoading: false
}
},
onLoad() {
if (uni.getStorageSync('adminAreaid')) {
this.areaId = uni.getStorageSync('adminAreaid')
this.orderList()
}
},
onShow() {
this.$store.dispatch('jiance');
},
watch: {
},
computed: {
userId() {
return this.$store.getters.userId
},
},
computed: {
formattedPayedAmount() {
// 假设item是组件的一个响应式对象
if (!this.item) return '¥0.00'
const payedAmount = parseFloat(this.item.payedAmount) || 0
const payRefunded = parseFloat(this.item.payRefunded) || 0
const payRefunding = parseFloat(this.item.payRefunding) || 0
const actualAmount = payedAmount - (payRefunded + payRefunding)
return `¥${actualAmount.toFixed(2)}`
}
},
onReachBottom() {
},
methods: {
// 下拉刷新
onRefresh() {
this.isRefreshing = true
this.pageNum = 1
this.orderList()
setTimeout(() => {
this.isRefreshing = false
}, 1000)
},
formatPayedAmount(payedAmount, payRefunded, payRefunding) {
if (!payedAmount) return '0.00元'
const amount = parseFloat(payedAmount) || 0
const refunded = parseFloat(payRefunded) || 0
const refunding = parseFloat(payRefunding) || 0
const actualAmount = amount - (refunded + refunding)
return `${actualAmount.toFixed(2)}元`
},
handqixing() {
console.log(this.total,this.allList.length)
if(this.total > this.allList.length){
this.orderList()
}
},
formatDatess(startTime, endTime) {
if (!startTime) return "0秒" // 如果没有开始时间返回0
// 解析时间无效时间则返回0
const start = new Date(startTime)
const end = endTime ? new Date(endTime) : new Date()
if (isNaN(start.getTime()) || isNaN(end.getTime())) return "0秒"
// 计算时间差(毫秒)
let diffMs = end - start
if (diffMs < 0) return "0秒" // 结束时间早于开始时间
// 计算各时间单位
const diffDays = Math.floor(diffMs / 86400000) // 天
diffMs %= 86400000
const diffHours = Math.floor(diffMs / 3600000) // 小时
diffMs %= 3600000
const diffMinutes = Math.floor(diffMs / 60000) // 分钟
diffMs %= 60000
const diffSeconds = Math.floor(diffMs / 1000) // 秒
// 智能拼接结果忽略0值单位但至少显示"X秒"
const parts = []
if (diffDays > 0) parts.push(`${diffDays}天`)
if (diffHours > 0) parts.push(`${diffHours}时`)
if (diffMinutes > 0) parts.push(`${diffMinutes}分`)
parts.push(`${diffSeconds}秒`) // 始终显示秒
return parts.join("")
},
formatDate(value) {
if (!value) return ''
let date = new Date(value)
let month = date.getMonth() + 1 // 月份从0开始计数所以加1
let day = date.getDate()
let hours = date.getHours()
let minutes = date.getMinutes()
// 确保月份、日期、小时和分钟都是两位数
month = month < 10 ? '0' + month : month
day = day < 10 ? '0' + day : day
hours = hours < 10 ? '0' + hours : hours
minutes = minutes < 10 ? '0' + minutes : minutes
return `${month}-${day} ${hours}:${minutes}`
},
searchconfirm(e) {
this.typeidx = e[0].value
this.tit = e[0].label
},
toOrderDetail(id,orid,item) {
uni.navigateTo({
url: '/page_shanghu/guanli/order_detail?id=' + id + '&orid=' + orid + '&ksitem=' + item.startTime + '&endtime=' + item.endTime
})
},
checkAndUpdate(key) {
clearTimeout(timerId)
timerId = setTimeout(() => {
let inputValue = parseFloat(this.orderInfo[key]);
let initialValue = parseFloat(this.initialValues[key]);
if (inputValue > initialValue) {
this.orderInfo[key] = initialValue;
}
}, 500)
},
showtks(item) {
this.orderInfo = item
this.show = true
this.showtk = true
this.initialValues.dispatchFee = this.orderInfo.dispatchFee
this.initialValues.manageFee = this.orderInfo.manageFee
this.initialValues.ridingFee = this.orderInfo.ridingFee
this.initialValues.appointmentFee = this.orderInfo.appointmentFee
},
closetk() {
this.show = false
this.showtk = false
this.orderInfo = {}
},
showgjs(item) {
this.orderInfo = item
this.show = true
this.showgj = true
},
closegj() {
this.show = false
this.showgj = false
this.orderInfo = {}
},
showfzs(item) {
this.orderInfo = item
this.show = true
this.showfz = true
},
orderList() {
let data = {}
if (this.typeidx == 1) {
data = {
userPhone: this.searchKeyword,
status: this.zhuangtai,
createDateRange:this.firsTime == '' ? '' : this.lasTime == '' ? '' : this.firsTime + ',' + this.lasTime,
areaId: this.areaId,
pageSize: this.pageSize,
pageNum: this.pageNum,
isAsc:'desc',
orderByColumn:'createTime'
};
} else if (this.typeidx == 2) { // 修改条件为 this.typeidx == 2
data = {
deviceVehicleNum: this.searchKeyword,
type: '1',
status:this.zhuangtai,
createDateRange:this.firsTime == '' ? '' : this.lasTime == '' ? '' : this.firsTime + ',' + this.lasTime,
areaId: this.areaId,
pageSize: this.pageSize,
pageNum: this.pageNum,
isAsc:'desc',
orderByColumn:'createTime'
};
}
return this.$u.get('/bst/order/list?', data).then((res) => {
if (res.code === 200) {
this.total = res.total
if(this.pageNum == 1){
this.allList = res.rows
}else{
this.allList = this.allList.concat(res.rows)
}
this.pageNum++
this.curtitidx = 0
this.$forceUpdate()
}
})
},
async changeidx(idx) {
if (this.tabListLoading) return
this.tabListLoading = true
this.zhuangtai = idx
this.pageNum = 1
this.allList = []
this.ingList = []
this.reprement = []
this.alreadyList = []
try {
await this.orderList()
} finally {
this.tabListLoading = false
}
},
confirm1(e) {
console.log(e, 'eeeeeeee');
this.firsTime = e.year + '-' + e.month + '-' + e.day
this.pageNum = 1
this.orderList()
},
confirm2(e) {
this.lasTime = e.year + '-' + e.month + '-' + e.day
this.pageNum = 1
this.orderList()
},
search() {
this.pageNum = 1
this.allList = []
this.ingList = []
this.reprement = []
this.alreadyList = []
clearTimeout(timerId1)
timerId1 = setTimeout(() => {
this.pageNum = 1
this.orderList()
}, 500)
// 根据关键字过滤 this.classlist
},
}
}
</script>
<style lang="scss">
page {
background-color: #F8F9FA;
}
.page {
width: 750rpx;
background: #F8F9FA;
padding-bottom: 24rpx;
box-sizing: border-box;
}
.is-hover {
opacity: 0.88;
transform: scale(0.98);
}
.top_box {
width: 710rpx;
background: #FFFFFF;
border-radius: 20rpx;
padding: 22rpx 24rpx;
margin: 20rpx auto 0;
box-shadow: 0rpx 8rpx 24rpx rgba(0, 0, 0, 0.05);
box-sizing: border-box;
display: flex;
align-items: center;
}
.top_box_second {
margin-top: 16rpx;
}
.left_text {
width: 180rpx;
font-size: 28rpx;
font-weight: 600;
color: #1D2129;
display: flex;
align-items: center;
}
.select_left {
justify-content: flex-start;
}
.sear_ipt {
flex: 1;
}
.sear_ipt .input {
width: 100%;
height: 72rpx;
line-height: 72rpx;
border: 2rpx solid #E5E6EB;
border-radius: 8rpx;
background: #FFFFFF;
padding: 0 20rpx;
box-sizing: border-box;
font-size: 26rpx;
color: #4E5969;
}
.timebox {
flex: 1;
display: flex;
align-items: center;
column-gap: 10rpx;
color: #86909C;
font-size: 24rpx;
}
.left_time,
.right_time {
flex: 1;
height: 72rpx;
line-height: 72rpx;
text-align: center;
border: 2rpx solid #E5E6EB;
border-radius: 8rpx;
background: #FFFFFF;
font-size: 26rpx;
color: #4E5969;
}
.tap {
width: 710rpx;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 12rpx;
margin: 20rpx auto 0;
}
.tap_cont {
height: 60rpx;
line-height: 60rpx;
padding: 0 24rpx;
border-radius: 999rpx;
border: 2rpx solid #E5E6EB;
background: #FFFFFF;
color: #4E5969;
font-size: 24rpx;
font-weight: 500;
transition: all 0.25s ease;
}
.tap_cont_lg {
padding: 0 28rpx;
}
.tap .act1 {
background: #2C8AF0;
color: #FFFFFF;
border-color: #2C8AF0;
box-shadow: 0rpx 6rpx 16rpx rgba(47, 84, 235, 0.25);
}
.tap_cont--disabled {
opacity: 0.55;
pointer-events: none;
}
.warp_box {
height: 61vh;
overflow: scroll;
background: #F8F9FA;
margin-top: 16rpx;
}
.swiper-item {
padding: 0 20rpx 12rpx;
box-sizing: border-box;
}
.card {
margin-bottom: 16rpx;
background: #FFFFFF;
border-radius: 20rpx;
overflow: hidden;
box-shadow: 0rpx 8rpx 24rpx rgba(0, 0, 0, 0.05);
transition: all 0.2s ease;
}
.card-hover {
transform: translateY(4rpx);
box-shadow: 0rpx 4rpx 16rpx rgba(0, 0, 0, 0.06);
}
.line {
height: 10rpx;
background: #F5F7FA;
}
.top_info {
padding: 24rpx 24rpx 18rpx;
display: flex;
align-items: center;
}
.top_info_left {
flex: 1;
display: flex;
align-items: center;
font-size: 26rpx;
font-weight: 600;
color: #1D2129;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.deposit-badge {
margin-left: 12rpx;
}
.top_info_right {
display: flex;
align-items: center;
padding: 6rpx 14rpx;
border-radius: 999rpx;
font-size: 22rpx;
font-weight: 600;
}
.top_info_right .yuan {
width: 10rpx;
height: 10rpx;
border-radius: 50%;
margin-right: 8rpx;
}
.status-processing {
background: rgba(24, 144, 255, 0.14);
color: #1890FF;
}
.status-processing .yuan { background: #1890FF; }
.status-finished {
background: rgba(54, 211, 153, 0.14);
color: #36D399;
}
.status-finished .yuan { background: #36D399; }
.status-wait-pay,
.status-canceled,
.status-ride-wait-pay,
.status-wait-verify {
background: rgba(78, 89, 105, 0.14);
color: #4E5969;
}
.status-wait-pay .yuan,
.status-canceled .yuan,
.status-ride-wait-pay .yuan,
.status-wait-verify .yuan { background: #4E5969; }
.lines {
height: 2rpx;
background: #EEF0F3;
margin: 0 24rpx;
}
.order_info {
padding: 20rpx 24rpx 24rpx;
display: flex;
flex-direction: column;
row-gap: 14rpx;
}
.info_li {
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 16rpx;
}
.half_info_li {
font-size: 24rpx;
color: #4E5969;
display: flex;
align-items: center;
min-width: 0;
}
.half_info_li span {
margin-left: 8rpx;
color: #1D2129;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.amount-text {
color: #FF4D4F !important;
font-size: 30rpx;
font-weight: 700 !important;
}
.text-danger {
color: #FF4D4F !important;
}
.no-more-orders {
width: 100%;
text-align: center;
color: #86909C;
margin: 24rpx 0 20rpx;
font-size: 24rpx;
padding: 12rpx 0;
}
</style>