chuangte_bike_newxcx/page_user/huanbike.vue

996 lines
20 KiB
Vue
Raw Normal View History

2025-04-01 21:35:30 +08:00
<template>
<view class="page">
<u-navbar title="换车骑行" :border-bottom="false" :background="bgc" title-color='#000' title-size='36' height='45'
back-icon-color='#000'></u-navbar>
<view class="tits">
<image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image>
点击扫码或输入想换的车辆编号
</view>
<view class="iptbox">
<view class="qrcode" @click="qrcode()">
<image src="https://api.ccttiot.com/smartmeter/img/static/uy7BNwAMIKwvstqFnRhs" mode=""></image>
</view>
<input type="text" class="ips" v-model="bikesn" placeholder="请扫描设备上的二维码" style="margin-left: 32rpx;"
placeholder-class="my-placeholder" />
</view>
<view class="conts_box">
<view class="cont_li">
<view class="left">
<view class="km">
2025-04-10 08:57:21 +08:00
可继续行驶{{orderobj.deviceRemainEndurance == null ? '--' : orderobj.deviceRemainEndurance}}公里
2025-04-01 21:35:30 +08:00
</view>
<view class="speed">
2025-04-10 08:57:21 +08:00
<view class="speeds" :style="{ width: orderobj.deviceRemainingPower + '%' }"></view>
2025-04-01 21:35:30 +08:00
</view>
<view class="NO">
2025-04-10 08:57:21 +08:00
SN{{orderobj.deviceSn}}
2025-04-01 21:35:30 +08:00
</view>
</view>
<view class="right">
<image src="https://lxnapi.ccttiot.com/bike/img/static/uqKmFMF9YHTX8lAQARSd" mode=""></image>
</view>
</view>
<view class="cont_li" style="margin-top: 10rpx;">
<view class="left" style="font-size: 32rpx;font-weight: 600;">
已骑行
</view>
<view class="right" style="font-size: 32rpx;font-weight: 600;">
2025-04-10 08:57:21 +08:00
{{timeRemaining}}
2025-04-01 21:35:30 +08:00
</view>
</view>
<view class="cont_li" style="margin-top: 10rpx;">
<view class="left" style="font-size: 32rpx;font-weight: 600;">
预估金额
</view>
<view class="right" style="font-size: 32rpx;font-weight: 600;">
2025-04-10 08:57:21 +08:00
{{feiyong}}
2025-04-01 21:35:30 +08:00
</view>
</view>
<view class="txtss">
扫码开锁后将自动合并订单骑行时间将继续计时
</view>
</view>
<view class="cont_box">
<view class="tit">
<image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image>
请选择换车原因
</view>
<view class="choose_li">
<view class="li_cont" @click="checkIdx = 1">
<view class="img_box">
<image src="https://api.ccttiot.com/smartmeter/img/static/uGWN8B6dfaSc7ACKxb7r" mode=""
v-if="checkIdx == 1"></image>
</view>
电量不足
</view>
<view class="li_cont" @click="checkIdx = 2">
<view class="img_box">
<image src="https://api.ccttiot.com/smartmeter/img/static/uGWN8B6dfaSc7ACKxb7r" mode=""
v-if="checkIdx == 2"></image>
</view>
车辆损坏
</view>
</view>
</view>
<view class="cont_box" v-show="checkIdx == 2">
<view class="tit">
<image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image>
请输入车辆故障原因
</view>
<view class="input-container">
<view class="placeholder" v-if="!textValue">请输入故障原因</view>
<textarea class="custom-textarea" v-model="textValue" style="border: none;"></textarea>
</view>
</view>
2025-04-10 08:57:21 +08:00
<view class="cont_box" v-show="checkIdx == 2 || orderobj.orderAreaReturnVerify == true">
2025-04-01 21:35:30 +08:00
<view class="tit">
<image src="https://lxnapi.ccttiot.com/bike/img/static/uByIrgaV23PDGZWReKHW" mode=""></image>
2025-04-11 18:23:16 +08:00
请对车辆部位拍摄视频
2025-04-01 21:35:30 +08:00
</view>
2025-04-11 18:23:16 +08:00
<!-- <view class="icon">
2025-04-01 21:35:30 +08:00
<view class="imgbox" v-for="(item, index) in imglist " :key="index">
<image :src="item" mode=""></image>
</view>
<view class="imgbox" @click="btn">
<image src="https://api.ccttiot.com/smartmeter/img/static/uY8CPw9YE6JxPzcHUaqf" mode=""></image>
</view>
2025-04-11 18:23:16 +08:00
</view> -->
<view class="vadio_png1">
<image @click="recordVideo" class="backimg" src="https://api.ccttiot.com/smartmeter/img/static/uTwV4aH6HbxqmM1ssvTs" mode="" v-if="videoUrl==''"></image>
<video class="vad" :src="videoUrl" controls="controls" style="width: 100%;" v-if="videoUrl!=''"></video>
</view>
<view class="tip_txt" style="font-weight: 500;font-size: 32rpx;color: #3D3D3D;margin-top: 30rpx;">
保持车辆录像的完整清晰,不要随意拍摄确保视频中车辆出境并且出现车牌号
2025-04-01 21:35:30 +08:00
</view>
</view>
2025-04-10 08:57:21 +08:00
<view class="btns" @click="subs()">
2025-04-01 21:35:30 +08:00
提交
</view>
</view>
</template>
<script>
export default {
data() {
return {
bgc: {
backgroundColor: "#fff",
},
textValue: '',
currentCount: 0,
imglist: [],
token: '',
upurl: '',
checkIdx: 1,
videoUrl: '',
ordersn:'',
orderid:'',
2025-04-10 08:57:21 +08:00
bikesn:'',
orderobj:{},
feiyong:'',
timeRemaining: "",
latitude:'',
2025-04-11 18:23:16 +08:00
longitude:'',
videoPath:'',
2025-04-01 21:35:30 +08:00
}
},
onLoad(e) {
console.log(e);
this.ordersn = e.sn
this.orderid = e.orderid
2025-04-10 08:57:21 +08:00
this.getQiniuToken()
this.getdingdan()
this.getfeiyong()
2025-04-01 21:35:30 +08:00
},
onShow() {
2025-04-10 08:57:21 +08:00
uni.getLocation({
type: 'wgs84',
success: (res) => {
this.latitude = res.latitude
this.longitude = res.longitude
},
fail: (err) => {
console.error('获取位置失败:', err)
}
})
2025-04-01 21:35:30 +08:00
},
computed: {
},
methods: {
2025-04-11 18:23:16 +08:00
recordVideo() {
// 调用录像API
uni.chooseVideo({
sourceType: ['camera'], // 指定使用相机录像
camera: 'back', // 指定使用后置摄像头可选值有front、back
maxDuration: 15, // 最大录制时长(秒)
success: (res) => {
// 获取视频录制文件的临时路径
this.videoPath = res.tempFilePath;
console.log(res.tempFilePath);
this.upload()
},
fail: (err) => {
console.log('录像失败:', err);
}
});
},
upload(){
uni.showLoading({
title:'上传中'
})
let _this=this
let math='static/'+_this.$u.guid(20)
wx.uploadFile({
url: 'https://up-z2.qiniup.com',
name: 'file',
filePath: this.videoPath,
formData: {
token: _this.token, //后端返回的token
key:'bike/video/'+math
},
success: function(res) {
uni.hideLoading()
console.log(res,'resres');
let str = JSON.parse(res.data)
console.log(str.key)
_this.videoUrl = 'https://api.ccttiot.com/' + str.key
// console.log(_this.userImgs)
// _this.imglist.push(_this.userImgs)
}
});
},
2025-04-10 08:57:21 +08:00
// 点击进行换车
subs(){
uni.showLoading({
title: '换车中...'
})
let reason = ''
let faultPicture = ''
if(this.checkIdx == 1){
reason = 'LOW_POWER'
}else{
reason = 'DEVICE_FAULT'
}
2025-04-11 18:23:16 +08:00
// if(this.imglist.length > 0){
// faultPicture = this.imglist.join(',')
// }
2025-04-10 08:57:21 +08:00
let data = {
orderId:this.orderid,
deviceSn:this.bikesn,
reason:reason,
faultDetail:this.textValue,
2025-04-11 18:23:16 +08:00
faultPicture:this.videoUrl,
2025-04-10 08:57:21 +08:00
lat:this.latitude,
lon:this.longitude
}
this.$u.put(`/app/order/changeDevice`,data).then(res =>{
if(res.code == 200){
uni.hideLoading()
uni.showToast({
title: '换车成功',
icon: 'success',
duration: 1000
})
setTimeout(()=>{
uni.navigateBack()
},1000)
}else{
uni.hideLoading()
uni.showToast({
title: res.msg,
icon: 'none',
duration: 1000
})
}
})
},
// 获取当前进行中订单 startTime
getdingdan(){
this.$u.get(`/app/orderDevice/mineUsing`).then(res =>{
if(res.code == 200){
if(res.data){
this.orderobj = res.data
if(res.data.startTime){
this.timeRemaining = this.calculateTimeRemaining()
}
}
}
})
},
calculateTimeRemaining() {
const targetDate = new Date(this.orderobj.startTime)
const now = new Date()
const diffMs = now - targetDate
const diffHours = Math.floor(diffMs / (1000 * 60 * 60))
const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60))
return `${diffHours} 小时 ${diffMinutes} 分钟`
},
// 计算订单费用
getfeiyong(){
let data = {
orderId:this.orderid
}
this.$u.post(`/app/order/calcFee`,data).then(res =>{
if(res.code == 200){
this.feiyong = res.data.ridingFee
}
})
},
2025-04-01 21:35:30 +08:00
getQiniuToken() {
this.$u.get("/common/qiniuToken").then((res) => {
if (res.code == 200) {
this.token = res.data
}
})
},
btn() {
let _this = this
let math = 'static/' + _this.$u.guid(20)
uni.chooseImage({
count: 9,
type: 'all',
success(res) {
const tempFilePaths = res.tempFiles
wx.uploadFile({
url: 'https://up-z2.qiniup.com',
name: 'file',
filePath: tempFilePaths[0].path,
formData: {
token: _this.token, //后端返回的token
key: 'smartmeter/img/' + math
},
success: function (res) {
let str = JSON.parse(res.data)
_this.userImgs = 'https://api.ccttiot.com/' + str.key
_this.imglist.push(_this.userImgs)
}
})
}
})
},
qrcode() {
uni.scanCode({
onlyFromCamera: true,
scanType: ['qrCode'],
success: res => {
console.log(res);
function getQueryParam(url, paramName) {
let regex = new RegExp(`[?&]${paramName}=([^&]*)`)
let results = regex.exec(url)
return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null
}
let sceneValue = res.result
let decodedValue = decodeURIComponent(sceneValue)
this.bikesn = getQueryParam(decodedValue, 's')
},
fail: err => {
console.error('扫描失败:', err)
uni.showToast({
title: '扫描失败',
icon: 'none'
})
}
})
},
}
}
</script>
<style lang="scss">
page {
background-color: #F7FAFE;
}
.page {
padding-bottom: 100rpx;
// width: 750rpx;
width: 750rpx;
// height: 530rpx;
// background: linear-gradient( 180deg, #4297F3 0%, rgba(255,255,255,0) 100%), #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
padding-bottom: 200rpx;
.tip_box {
padding: 44rpx 36rpx;
font-weight: 400;
font-size: 32rpx;
color: #FFFFFF;
background: #4297F3;
}
.vadio_png1 {
position: relative;
width: 672rpx;
height: 370rpx;
.backimg {
width: 672rpx;
height: 370rpx;
}
.tip_img {
position: absolute;
top: 72rpx;
left: 210rpx;
width: 252rpx;
height: 194rpx;
z-index: 11;
}
.vad {
width: 672rpx;
height: 370rpx;
border-radius: 40rpx;
z-index: 1;
}
.glass {
position: absolute;
top: 0;
left: 0;
width: 672rpx;
height: 370rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 40rpx;
// box-shadow: 0 rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10rpx);
-webkit-backdrop-filter: blur(10rpx);
/* For Safari */
// border: 1rpx solid rgba(255, 255, 255, 0.3);
z-index: 10;
}
}
.cont {
width: 100%;
padding: 0 39rpx;
.tip_txt {
margin-top: 38rpx;
width: 100%;
font-weight: 400;
font-size: 28rpx;
color: #3D3D3D;
}
.vadio_png {
margin-top: 52rpx;
image {
width: 672rpx;
height: 370rpx;
}
}
.btn {
position: fixed;
bottom: 100rpx;
left: 38rpx;
// margin-top: 128rpx;
display: flex;
align-items: center;
justify-content: center;
width: 680rpx;
height: 90rpx;
background: rgba(100, 182, 167, 0.5);
border-radius: 54rpx 54rpx 54rpx 54rpx;
z-index: 10;
font-weight: 500;
font-size: 40rpx;
color: #FFFFFF;
}
.act1 {
background: #4297F3;
}
}
.maskloadpage {
position: fixed;
padding: 46rpx;
bottom: 0;
width: 752rpx;
height: 780rpx;
background: #FFFFFF;
border-radius: 40rpx 40rpx 0rpx 0rpx;
z-index: 101;
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.15);
.maskpage0 {
.top_info {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
image {
margin-right: 16rpx;
width: 50rpx;
height: 50rpx;
}
.masktxt {
font-weight: 500;
font-size: 44rpx;
color: #3D3D3D;
}
}
.masktips {
margin-top: 20rpx;
width: 100%;
text-align: center;
font-weight: 400;
font-size: 32rpx;
color: #3D3D3D;
}
.tipsimg {
margin-top: 60rpx;
display: flex;
// align-items: center;
justify-content: center;
width: 100%;
image {
width: 554rpx;
height: 262rpx;
}
}
}
.maskpage1 {
.top_info {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
image {
margin-right: 16rpx;
width: 50rpx;
height: 50rpx;
}
.masktxt {
font-weight: 500;
font-size: 44rpx;
color: #3D3D3D;
}
}
.masktips {
margin-top: 20rpx;
width: 100%;
text-align: center;
font-weight: 400;
font-size: 32rpx;
color: #3D3D3D;
}
.tipsimg {
margin-top: 60rpx;
display: flex;
// align-items: center;
justify-content: center;
width: 100%;
image {
width: 554rpx;
height: 262rpx;
}
}
.btn_box {
width: 750rpx;
padding: 0 36rpx;
position: absolute;
bottom: 60rpx;
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
.btn3 {
// margin-right: 16rpx;
display: flex;
align-items: center;
justify-content: center;
width: 300rpx;
height: 90rpx;
background: #4C97E7;
border-radius: 45rpx 45rpx 45rpx 45rpx;
font-weight: 500;
font-size: 40rpx;
color: #FFFFFF;
}
.btn4 {
display: flex;
align-items: center;
justify-content: center;
width: 300rpx;
height: 90rpx;
border-radius: 45rpx 45rpx 45rpx 45rpx;
border: 2rpx solid #808080;
font-weight: 500;
font-size: 40rpx;
color: #808080;
}
}
}
}
.btns {
position: fixed;
bottom: 70rpx;
left: 34rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 40rpx;
color: #FFFFFF;
width: 680rpx;
height: 90rpx;
background: #4297F3;
border-radius: 54rpx 54rpx 54rpx 54rpx;
z-index: 100;
}
.iptbox {
display: flex;
align-items: center;
flex-wrap: nowrap;
padding: 22rpx;
margin: 28rpx auto 0;
width: 680rpx;
height: 88rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.15);
border-radius: 20rpx 20rpx 20rpx 20rpx;
.qrcode {
padding-right: 20rpx;
border-right: 2rpx solid #D8D8D8;
image {
width: 54rpx;
height: 54rpx;
}
}
.ips {
width: 630rpx;
}
image {
width: 18rpx;
height: 32rpx;
}
.my-placeholder {
font-weight: 400;
font-size: 32rpx;
color: #808080;
}
}
.conts_box {
width: 680rpx;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
margin-top: 38rpx;
background: #FFFFFF;
box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08);
border-radius: 20rpx 20rpx 20rpx 20rpx;
padding-bottom: 20rpx;
.txtss {
margin-top: 18rpx;
padding-left: 20rpx;
width: 100%;
font-weight: 500;
font-size: 28rpx;
color: #808080;
}
.cont_li {
width: 100%;
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
.left {
padding-left: 20rpx;
display: flex;
flex-wrap: wrap;
font-weight: 600;
font-size: 36rpx;
color: #3D3D3D;
.km {
font-weight: 400;
font-size: 28rpx;
color: #3D3D3D;
}
.speed {
margin-top: 18rpx;
width: 226rpx;
height: 22rpx;
background: #ccc;
border-radius: 16rpx 16rpx 16rpx 16rpx;
.speeds {
// width: 90%;
height: 100%;
background: #4297F3;
border-radius: 16rpx 16rpx 16rpx 16rpx;
}
}
.NO {
width: 100%;
font-weight: 400;
font-size: 24rpx;
color: #3D3D3D;
margin-top: 18rpx;
}
}
.right {
padding-right: 20rpx;
font-weight: 600;
font-size: 36rpx;
color: #3D3D3D;
image {
width: 244rpx;
height: 196rpx;
}
}
}
}
.tits {
width: 680rpx;
margin: 0 auto;
margin-top: 38rpx;
font-size: 36rpx;
color: #3D3D3D;
display: flex;
flex-wrap: nowrap;
align-items: center;
image {
margin-right: 12rpx;
width: 24rpx;
height: 24rpx;
}
}
.cont_box {
margin: 0 auto;
padding: 24rpx 32rpx;
width: 680rpx;
margin-top: 38rpx;
background: #FFFFFF;
box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08);
border-radius: 20rpx 20rpx 20rpx 20rpx;
2025-04-11 18:23:16 +08:00
.vadio_png1{
position: relative;
width: 100%;
height: 340rpx;
margin-top: 30rpx;
.backimg{
width: 100%;
height: 340rpx;
}
.tip_img{
position: absolute;
top: 72rpx;
left: 210rpx;
width: 252rpx;
height: 194rpx;
z-index: 11;
}
.vad{
width: 100%;
height: 370rpx;
border-radius: 40rpx;
z-index: 1;
}
.glass{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 340rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 40rpx;
// box-shadow: 0 rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10rpx);
-webkit-backdrop-filter: blur(10rpx); /* For Safari */
// border: 1rpx solid rgba(255, 255, 255, 0.3);
z-index: 10;
}
}
2025-04-01 21:35:30 +08:00
.tit {
width: 100%;
display: flex;
flex-wrap: nowrap;
align-items: center;
image {
margin-right: 12rpx;
width: 24rpx;
height: 24rpx;
}
}
.choose_li {
margin-top: 34rpx;
width: 100%;
display: flex;
flex-wrap: nowrap;
align-items: center;
// justify-content: space-between;
.li_cont {
width: 50%;
display: flex;
flex-wrap: nowrap;
.img_box {
margin-right: 30rpx;
width: 38rpx;
height: 38rpx;
border-radius: 50%;
border: 2rpx solid #3D3D3D;
}
}
}
.tip {
display: flex;
flex-wrap: nowrap;
// align-items: center;
font-weight: 700;
font-size: 32rpx;
color: #3D3D3D;
line-height: 44rpx;
.ipnt {
margin-top: 10rpx;
margin-right: 12rpx;
color: #FF4444;
font-size: 48rpx;
}
}
.iptbox {
display: flex;
align-items: center;
margin-top: 30rpx;
width: 592rpx;
height: 80rpx;
border-radius: 20rpx 20rpx 20rpx 20rpx;
border: 2rpx solid #979797;
.ips {
margin-left: 30rpx;
width: 80%;
}
.iptbtn {
display: flex;
align-items: center;
justify-content: center;
width: 112rpx;
height: 80rpx;
background: #4297F3;
border-radius: 20rpx 20rpx 20rpx 20rpx;
image {
width: 37rpx;
height: 37rpx;
}
}
}
.txt {
margin-top: 18rpx;
font-weight: 400;
font-size: 28rpx;
color: #3D3D3D;
}
.icon {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-top: 40rpx;
.imgbox {
width: 33%;
image {
width: 142rpx;
height: 142rpx;
}
}
}
.checkbox {
display: flex;
flex-wrap: wrap;
.check_li {
position: relative;
margin-right: 10rpx;
margin-top: 18rpx;
display: flex;
align-items: center;
justify-content: center;
width: 142rpx;
height: 65rpx;
border-radius: 20rpx 20rpx 20rpx 20rpx;
border: 2rpx solid #C7C7C7;
image {
position: absolute;
right: 0;
bottom: 0;
width: 40rpx;
height: 20rpx;
}
}
.check_li:nth-child(4n) {
margin-right: 0;
}
.act1 {
// background-image: url(https://api.ccttiot.com/smartmeter/img/static/uaqN5qdoGNCs7Dumzr3F);
width: 142rpx;
height: 65rpx;
// background-size: cover;
border: 2rpx solid #1E807A;
// background: #4C97E7;
}
}
.input-container {
position: relative;
width: 612rpx;
height: 248rpx;
background: #FFFFFF;
box-shadow: 0rpx 16rpx 40rpx 0rpx rgba(42, 130, 228, 0.1);
border-radius: 20rpx;
margin-top: 40rpx;
overflow: hidden;
padding-right: 38rpx;
box-sizing: border-box;
border: 2rpx solid #C7C7C7;
}
.placeholder {
position: absolute;
top: 18rpx;
left: 38rpx;
color: #999;
/* placeholder颜色 */
pointer-events: none;
/* 确保点击事件可以穿透到textarea上 */
}
.custom-textarea {
width: 100%;
height: 100%;
/* 设置一个合适高度 */
padding-top: 18rpx;
/* 为placeholder留出空间 */
padding-left: 38rpx;
box-sizing: border-box;
border: 1px solid #ccc;
}
.word-count {
position: absolute;
right: 10px;
bottom: 10px;
font-size: 12px;
color: #999;
}
}
}
</style>