1349 lines
44 KiB
Vue
1349 lines
44 KiB
Vue
<template>
|
||
<view class="main">
|
||
<view class="content">
|
||
<view class="trafficState">
|
||
<view class="positionBox">
|
||
<view class="startItem" @click="handleChangeService(startObj)">{{
|
||
startObj.name || ""
|
||
}}</view>
|
||
<image
|
||
class="reachIcon"
|
||
src="/static/images/home/reachIcon.png"
|
||
@click="handleChangeStartEnd"
|
||
/>
|
||
<view class="endItem" @click="handleChangeService(endObj)">{{
|
||
endObj.name || ""
|
||
}}</view>
|
||
</view>
|
||
<view class="searchBtn" @click="handleTrafficSearch">路况查询</view>
|
||
</view>
|
||
|
||
<!-- 下面的信息 -->
|
||
<view class="bottomBox">
|
||
<view class="boxTop">
|
||
<view class="leftTop">
|
||
<span class="boldText">{{ detailObj.distanceNumber || "-" }}</span>
|
||
<span class="unit" style="margin: 0 4rpx">公里</span>
|
||
<span class="line"></span>
|
||
<span class="boldText" style="margin-right: 4rpx">{{
|
||
detailObj.hour || "0"
|
||
}}</span>
|
||
<span class="unit" style="margin-right: 8rpx">小时</span>
|
||
<span class="boldText">{{ detailObj.minute || "0" }}</span>
|
||
<span class="unit" style="margin-left: 4rpx">分</span>
|
||
<span class="line"></span>
|
||
<span class="boldText"
|
||
><span style="font-size: 24rpx; margin-right: 4rpx">¥</span
|
||
>{{ detailObj.tolls || "" }}</span
|
||
>
|
||
</view>
|
||
|
||
<view class="rightTop" @click="handleToMap(currentService)">
|
||
<image
|
||
class="navigationIcon"
|
||
src="https://eshangtech.com/ShopICO/discovery/navigationIcon.png"
|
||
/>
|
||
导航
|
||
</view>
|
||
</view>
|
||
|
||
<view class="roadConditions">
|
||
<view class="roadTop">
|
||
<image
|
||
class="stateIcon"
|
||
src="/static/images/home/trafficState1.png"
|
||
/>
|
||
<span class="stateText" :style="{ color: '#01a157' }"
|
||
>该路线全线畅通</span
|
||
>
|
||
</view>
|
||
<view class="progress">
|
||
<view
|
||
class="have"
|
||
:style="{
|
||
width:
|
||
detailObj && detailObj.haveProgress
|
||
? detailObj.haveProgress + '%'
|
||
: '',
|
||
}"
|
||
></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 横向线 -->
|
||
<!-- <view class="horizontal"></view> -->
|
||
|
||
<!-- 服务区列表 -->
|
||
<view class="serviceBox">
|
||
<view class="serviceTitle">沿途服务区</view>
|
||
|
||
<view class="serviceList">
|
||
<view
|
||
class="serviceItem"
|
||
v-for="(item, index) in detailObj.servicePart"
|
||
:key="index"
|
||
@click="handleGoServiceDetail(item.SERVERPART_ID)"
|
||
>
|
||
<view class="leftItem">
|
||
<view class="leftImgBox">
|
||
<image
|
||
class="leftImg"
|
||
:src="
|
||
item.ImageLits && item.ImageLits.length > 0
|
||
? item.ImageLits[0]
|
||
: '/static/images/discovery/defaultIcon.png'
|
||
"
|
||
/>
|
||
</view>
|
||
<view class="detailBox">
|
||
<view class="detailTop">
|
||
<view class="topLeft">
|
||
<span class="detailName">{{ item.SERVERPART_NAME }}</span>
|
||
<span class="detailState">营业中</span>
|
||
</view>
|
||
<!-- <view class="topRight">
|
||
<span class="chargeType">快充</span>
|
||
<span class="chargeValue">空4/8</span>
|
||
</view> -->
|
||
</view>
|
||
<view class="detailBottom">
|
||
<div class="distanceBox">
|
||
<div class="distanceLeft">
|
||
<image
|
||
class="distanceIcon"
|
||
src="/static/images/home/address.png"
|
||
/>
|
||
<span class="distanceNumber"
|
||
>{{ item.SERVERPART_DISTANCEGD || "-" }}km</span
|
||
>
|
||
</div>
|
||
<span class="line"></span>
|
||
<span class="address">{{
|
||
item.SERVERPART_ADDRESS || "-"
|
||
}}</span>
|
||
</div>
|
||
<div
|
||
class="typeList"
|
||
v-if="item.ServerpartInfo.SERVERPART_TARGET"
|
||
>
|
||
<div
|
||
class="typeItem"
|
||
v-for="(
|
||
subItem, subIndex
|
||
) in item.ServerpartInfo.SERVERPART_TARGET.split(',')"
|
||
:key="subIndex"
|
||
>
|
||
{{
|
||
SERVERPART_TARGETOBJ && subItem
|
||
? SERVERPART_TARGETOBJ[subItem]
|
||
: ""
|
||
}}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- <span class="label"
|
||
>服务区特色:{{
|
||
item.ServerpartInfo.SERVERPART_INFO || ""
|
||
}}</span
|
||
>
|
||
<span class="value"></span> -->
|
||
</view>
|
||
|
||
<view class="chargeBox">
|
||
<view class="chargeItem">
|
||
<view class="chargeItemLabel">理想</view>
|
||
<view class="chargeItemValue">
|
||
空<span class="empty">0</span
|
||
><span class="sum">/12</span>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="chargeItem">
|
||
<view class="chargeItemLabel">阳光电源</view>
|
||
<view class="chargeItemValue">
|
||
空<span class="empty">0</span
|
||
><span class="sum">/12</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- <view class="rightItem" @click="handleToMap(item)">
|
||
<view class="navigationTop">
|
||
<image
|
||
class="navigationIcon"
|
||
src="https://eshangtech.com/ShopICO/discovery/navigationIcon.png"
|
||
/>
|
||
导航
|
||
</view>
|
||
<span class="longText"
|
||
>{{ item.SERVERPART_DISTANCEGD }}公里</span
|
||
>
|
||
</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 充换电app跳转 -->
|
||
<view class="goAppBox" @click="handleGo" v-if="false">
|
||
<div class="appLeft">
|
||
<image
|
||
class="goAppIcon"
|
||
src="https://eshangtech.com/ShopICO/ahyd-user/images/home/anhuiAPPIcon.png"
|
||
/>
|
||
<span class="appName">安徽充换电APP</span>
|
||
</div>
|
||
|
||
<div class="appRight">
|
||
<span class="search">查看</span>
|
||
<image class="searchIcon" src="/static/images/home/rightArrow.png" />
|
||
</div>
|
||
</view>
|
||
|
||
<view class="goTest" @click="handleGoTest" v-if="loginType !== 'min'">
|
||
<span>跳转测试页面</span>
|
||
</view>
|
||
<!-- <view>{{ JSON.stringify(userInfo) }}</view> -->
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import serverInfo from "./serverInfo.js";
|
||
// const CryptoJS = require("crypto-js");
|
||
// import md5 from "js-md5";
|
||
import {
|
||
handleGetNearService,
|
||
handleHavePointInMin,
|
||
handleHavePointInApp,
|
||
hanldeHavePointInIos,
|
||
} from "../../utils/publicMethods";
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
startObj: {}, // 起点的数据对象
|
||
endObj: {}, // 终点的数据对象
|
||
currentService: "", // 当前服务区信息
|
||
howLong: "", // 多少公里
|
||
hour: "", // 花费小时
|
||
minute: "", // 花费分钟
|
||
money: "", // 花费钱
|
||
serviceList: [], // 沿途服务区列表
|
||
detailObj: {
|
||
distanceNumber: "",
|
||
hour: "",
|
||
minutes: "",
|
||
tolls: "",
|
||
haveProgress: "",
|
||
},
|
||
userObj: {
|
||
name: "我的位置",
|
||
seatInfo: {}, // 用户当前的经纬度位置
|
||
},
|
||
endPointObj: {},
|
||
seatInfo: "",
|
||
loginType: "",
|
||
SERVERPART_TARGETOBJ: {},
|
||
userInfo: {}, //用户信息
|
||
};
|
||
},
|
||
onLoad() {
|
||
let type = uni.getStorageSync("loginType");
|
||
this.loginType = type;
|
||
let _this = this;
|
||
if (type === "min") {
|
||
handleHavePointInMin().then((res) => {
|
||
_this.handleGetOnLoad();
|
||
});
|
||
} else if (type === "android") {
|
||
handleHavePointInApp().then((res) => {});
|
||
} else {
|
||
hanldeHavePointInIos();
|
||
}
|
||
// 拿到枚举
|
||
this.handleSERVERPART_TARGETOBJ();
|
||
|
||
// 理想的数据对接的方法
|
||
// this.handleGetLXData();
|
||
},
|
||
onShow() {
|
||
let _this = this;
|
||
// 判断服务区是否已经改变了
|
||
let res = uni.getStorageSync("currentService");
|
||
// 存在了经纬度
|
||
if (res) {
|
||
// 不等于的时候就是改变了
|
||
if (res.SERVERPART_ID !== this.endObj.SERVERPART_ID) {
|
||
let res = uni.getStorageSync("currentService");
|
||
|
||
this.currentService = res;
|
||
console.log("res", res);
|
||
this.endPointObj = {
|
||
...res,
|
||
longitude: res.SERVERPART_X,
|
||
latitude: res.SERVERPART_Y,
|
||
name: res.SERVERPART_NAME,
|
||
};
|
||
this.seatInfo = JSON.parse(uni.getStorageSync("seatInfo"));
|
||
this.userObj = {
|
||
...this.userObj,
|
||
longitude: this.seatInfo.longitude,
|
||
latitude: this.seatInfo.latitude,
|
||
};
|
||
console.log("seatInfo", this.seatInfo);
|
||
// 给起点和终点赋值
|
||
this.startObj = this.userObj;
|
||
this.endObj = this.endPointObj;
|
||
|
||
this.handleTrafficSearch();
|
||
}
|
||
} else {
|
||
if (this.loginType === "min") {
|
||
} else if (this.loginType === "android") {
|
||
plus.geolocation.getCurrentPosition(
|
||
async function (position) {
|
||
let res = position.coords;
|
||
let seatInfo = {
|
||
latitude: res.latitude,
|
||
longitude: res.longitude,
|
||
};
|
||
uni.setStorageSync("seatInfo", JSON.stringify(seatInfo));
|
||
uni.setStorageSync("actualLocation", JSON.stringify(seatInfo));
|
||
_this.seat = seatInfo;
|
||
_this.handleGetOnLoad();
|
||
},
|
||
function (error) {
|
||
// handleHavePointInApp();
|
||
console.error("获取位置失败:", error.message);
|
||
}
|
||
);
|
||
}
|
||
}
|
||
|
||
let userInfo = uni.getStorageSync("userInfo");
|
||
this.userInfo = userInfo;
|
||
},
|
||
methods: {
|
||
//理想的数据对接的方法
|
||
async handleGetLXData() {
|
||
console.log("inLX");
|
||
// 请求token的参数
|
||
let TimeStamp = this.generateTimeStamp();
|
||
let SeqData = this.generateSeq();
|
||
let req = {
|
||
OperatorID: "78109626X",
|
||
OperatorSecret: "Xh2vLq1Pz9zF7wK3",
|
||
};
|
||
// 自己的
|
||
// WzafxE5FAlx1W/tLxTUnk4HsTPzwl3G2MT6ZrKZ3uM4PmVJXT6SXZ+usDs4o+hjeTuxYShduMRpLdmX1//deMg==
|
||
|
||
// 示例结果
|
||
// "mVzuGBqEHBcQDeTVlf3vojqbl0+8pLu8tyS/1NZnqoqfe+crGYs JKmeuvsR+MUPrbF8DIWHP9zb/dhIkSEf2VA=="
|
||
// 先给对象进行加密
|
||
let encryptionReq = this.aesEncrypt(req);
|
||
console.log("encryptionReq", encryptionReq);
|
||
// let sigObj = {
|
||
// OperatorID: "78109626X",
|
||
// Data: encryptionReq,
|
||
// TimeStamp: TimeStamp,
|
||
// Seq: SeqData,
|
||
// };
|
||
// let sigObj = `78109626X${encryptionReq}${TimeStamp}${SeqData}`;
|
||
let sigObj = `123456789il7BOBSEjFdzpyKzfOFpvg/SelCP802RItKYFPfSLRxJ3jfObVI9hvYOEktPAYW2nd7S8MBcyHYyacHKbISq5iTmDzG+ivnR+SZJv3USNTYVMz9rCQVSxdOcLlqsJauko79NnwQJbzDTyLooYolwz75qBOH2/xOMirpeEqRJrF/EQjWekJmGk9RtboXePu2rka+Xm51syBPhiXJAqOGfbfaFu9tNqs/e2Vjja/ltE1MOlqvxfXQ6da6HrThsm5id4ClZFli0acRfrsPLRixS/IQYtksxghvJwbqOsbIsITail9Ayy4tKcogeEZiOO+4Ed264NSKmk713wKwJLAFjCFogBx8GE3OBz4pqcAn/ydA=201607291424000001`;
|
||
const Md5Sig = this.hmacMd5Signature(sigObj);
|
||
console.log("Md5Sig", Md5Sig);
|
||
|
||
// 2DB0EA3945FC9EE5CDBFE32FAC04727E
|
||
// 745166E8C43C84D37FFECOF529C4136F 示例结果
|
||
|
||
// 78109626X 组织机构代码(OperatorID)
|
||
// Xh2vLq1Pz9zF7wK3 运营商秘钥(OperatorSecret)
|
||
// bT8sWn2Aq0Jv6GvD 签名秘钥(SigSecret)
|
||
// fK7YzAq1R8Vp9hL0 数据加密秘钥(DataSecret)
|
||
// z3XnWl8FQ2pTm5Ba 初始化向量(DataSecretIV)
|
||
|
||
let lastReq = {
|
||
OperatorID: "78109626X",
|
||
Data: encryptionReq,
|
||
TimeStamp: TimeStamp,
|
||
Seq: "0001",
|
||
Sig: Md5Sig,
|
||
};
|
||
console.log("lastReq", lastReq);
|
||
|
||
// 获取token
|
||
const token = await new Promise((resolve, reject) => {
|
||
uni.request({
|
||
url: `https://iot-openapi-ontest-b.chehejia.com/lcp-inter-evio-service/evcs/v1/evio/query_token`,
|
||
data: lastReq,
|
||
method: "POST",
|
||
header: {
|
||
"Content-Type": "application/json;charset=utf-8", //自定义请求头信息
|
||
},
|
||
success(res) {
|
||
console.log("res", res);
|
||
// resolve(res.data.route.paths[0]);
|
||
resolve(res);
|
||
},
|
||
});
|
||
});
|
||
console.log("token", token);
|
||
},
|
||
|
||
generateTimeStamp() {
|
||
const date = new Date();
|
||
// 格式化为 yyyyMMdd HHmmss 格式
|
||
const year = date.getFullYear();
|
||
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
||
const day = date.getDate().toString().padStart(2, "0");
|
||
const hours = date.getHours().toString().padStart(2, "0");
|
||
const minutes = date.getMinutes().toString().padStart(2, "0");
|
||
const seconds = date.getSeconds().toString().padStart(2, "0");
|
||
return `${year}${month}${day} ${hours}${minutes}${seconds}`;
|
||
},
|
||
|
||
generateSeq() {
|
||
const currentSecond = Math.floor(Date.now() / 1000); // 获取当前秒的时间戳
|
||
let seq = 0;
|
||
// 你可以将自增序列保存到本地存储或全局变量中,以下是示例
|
||
const lastSecond = wx.getStorageSync("lastSecond"); // 获取上次记录的秒数
|
||
const lastSeq = wx.getStorageSync("lastSeq"); // 获取上次记录的 Seq
|
||
if (lastSecond === currentSecond) {
|
||
// 如果当前秒与上次记录的秒相同,增加序列
|
||
seq = (lastSeq + 1) % 10000; // 保证序列不超过 9999
|
||
} else {
|
||
// 如果不在同一秒内,重置序列为 0001
|
||
seq = 1;
|
||
}
|
||
// 存储当前秒和自增序列
|
||
wx.setStorageSync("lastSecond", currentSecond);
|
||
wx.setStorageSync("lastSeq", seq);
|
||
return seq.toString().padStart(4, "0"); // 返回 4 位自增序列,补齐为 0001 格式
|
||
},
|
||
// 数据加密的方法
|
||
aesEncrypt(data) {
|
||
// fK7YzAq1R8Vp9hL0 数据加密秘钥(DataSecret)
|
||
// z3XnWl8FQ2pTm5Ba 初始化向量(DataSecretIV)
|
||
|
||
// 将密钥和初始向量转为 WordArray 格式
|
||
const keyWords = CryptoJS.enc.Utf8.parse("fK7YzAq1R8Vp9hL0");
|
||
const ivWords = CryptoJS.enc.Utf8.parse("z3XnWl8FQ2pTm5Ba");
|
||
console.log("keyWords", keyWords);
|
||
console.log("ivWords", ivWords);
|
||
|
||
const jsonData = JSON.stringify(data);
|
||
|
||
// 使用 AES 加密,设置 CBC 模式和 PKCS5Padding 填充方式
|
||
const encrypted = CryptoJS.AES.encrypt(jsonData, keyWords, {
|
||
iv: ivWords,
|
||
mode: CryptoJS.mode.CBC,
|
||
padding: CryptoJS.pad.Pkcs7,
|
||
});
|
||
// 返回加密后的数据(Base64 编码)
|
||
return encrypted.toString();
|
||
},
|
||
// 签名方法
|
||
hmacMd5Signature(data) {
|
||
// 78109626X 组织机构代码(OperatorID)
|
||
// Xh2vLq1Pz9zF7wK3 运营商秘钥(OperatorSecret)
|
||
// bT8sWn2Aq0Jv6GvD 签名秘钥(SigSecret)
|
||
// fK7YzAq1R8Vp9hL0 数据加密秘钥(DataSecret)
|
||
// z3XnWl8FQ2pTm5Ba 初始化向量(DataSecretIV)
|
||
|
||
// 步骤a 在签名密钥 (SigSecret) 后面添加0来创建一个长为64字节的字符串 (str)
|
||
// let str = CryptoJS.enc.Utf8.parse("bT8sWn2Aq0Jv6GvD"); // 使用 CryptoJS 处理密钥
|
||
let str = "1234567890abcdef";
|
||
let targetLength = 64;
|
||
|
||
// 计算当前 SigSecret 的字节长度
|
||
let currentLength = new TextEncoder().encode(str).length;
|
||
|
||
// 如果当前长度小于64字节,则在后面补充 0
|
||
if (currentLength < targetLength) {
|
||
let padding = "0".repeat(targetLength - currentLength);
|
||
str += padding;
|
||
}
|
||
console.log("str", str);
|
||
|
||
// 步骤b 将上一步生成的字符串 (str) 与 ipad(0x36) 做异或运算,形成结果字符串 (istr);
|
||
const ipad = "0x36";
|
||
let byteArray = new TextEncoder().encode(str);
|
||
let istrArray = byteArray.map((byte) => byte ^ ipad);
|
||
let istr = String.fromCharCode(...istrArray);
|
||
console.log("istr", istr);
|
||
|
||
istr += data;
|
||
|
||
// 步骤c 将消息内容data 附加到第二步的结果字符串 (istr)的末尾
|
||
const innerMessage = istr;
|
||
|
||
// 步骤d 做MD5 运算于第三步生成的数据流 (istr)
|
||
const innerMd5 = md5(innerMessage);
|
||
|
||
// 步骤e 将第一步生成的字符串 (str) 与 opad(0x5c) 做异或运算,形成结果字符串 (ostr);
|
||
const opad = "\0x5c"; // opad 填充
|
||
let opadbyteArray = new TextEncoder().encode(str);
|
||
let opadistrArray = opadbyteArray.map((byte) => byte ^ opad);
|
||
let ostr = String.fromCharCode(...opadistrArray);
|
||
|
||
// 步骤f 再将第四步的结果 (istr) 附加到第五步的结果字符串 (ostr) 的末尾;
|
||
// const outerMessage = CryptoJS.enc.Utf8.parse(ostr + innerMd5);
|
||
const outerMessage = `${ostr}${innerMd5}`;
|
||
|
||
// 步骤g 对 outerMessage 进行 MD5 运算,输出最终签名
|
||
const finalMd5 = md5(outerMessage);
|
||
return finalMd5;
|
||
},
|
||
// 跳转测试页面
|
||
handleGoTest() {
|
||
uni.scanCode({
|
||
success: function (res) {
|
||
uni.navigateTo({
|
||
url: `/pages/thirdParty/testPage?url=${res.result}`,
|
||
});
|
||
},
|
||
});
|
||
},
|
||
// 跳转安徽充换电
|
||
handleGo() {
|
||
uni.navigateTo({
|
||
url: `/pages/thirdParty/chargAndSwapp`,
|
||
});
|
||
},
|
||
// 跳转地图服务区详情
|
||
handleGoServiceDetail(id) {
|
||
uni.navigateTo({
|
||
url: `/pages/serviceDetail/mapDetail/index?servicePartId=${id}`,
|
||
});
|
||
},
|
||
// 解服务区的一个枚举
|
||
async handleSERVERPART_TARGETOBJ() {
|
||
let SERVERPART_TARGET = await this.$api.$get(
|
||
"/EShangApiMain/FrameWork/GetFieldEnumTree",
|
||
{ FieldExplainField: "SERVERPART_TARGET" }
|
||
);
|
||
let list = this.$utils.wrapTreeNode(SERVERPART_TARGET.Result_Data.List);
|
||
let obj = {};
|
||
if (list && list.length > 0) {
|
||
list.forEach((item) => {
|
||
obj[String(item.value)] = item.label;
|
||
});
|
||
}
|
||
this.SERVERPART_TARGETOBJ = obj;
|
||
},
|
||
// 把onLoad需要调用的内容变成一个方法 可以方便调用
|
||
async handleGetOnLoad() {
|
||
if (this.seatInfo) {
|
||
} else {
|
||
this.seatInfo = JSON.parse(uni.getStorageSync("seatInfo"));
|
||
}
|
||
let res = uni.getStorageSync("currentService");
|
||
if (res) {
|
||
} else {
|
||
res = await handleGetNearService(this);
|
||
}
|
||
|
||
this.endPointObj = {
|
||
...res,
|
||
longitude: res.SERVERPART_X,
|
||
latitude: res.SERVERPART_Y,
|
||
name: res.SERVERPART_NAME,
|
||
};
|
||
this.currentService = res;
|
||
// this.endName = this.currentService.ServerPart_Name;
|
||
this.userObj = {
|
||
...this.userObj,
|
||
longitude: this.seatInfo.longitude,
|
||
latitude: this.seatInfo.latitude,
|
||
};
|
||
// 给起点和终点赋值
|
||
this.startObj = this.userObj;
|
||
this.endObj = this.endPointObj;
|
||
},
|
||
// 切换出发点和 终点
|
||
handleChangeStartEnd() {
|
||
let middleObj = this.endObj;
|
||
this.endObj = JSON.parse(JSON.stringify(this.startObj));
|
||
this.startObj = middleObj;
|
||
},
|
||
// 路况查询
|
||
async handleTrafficSearch() {
|
||
let _this = this;
|
||
|
||
if (!(this.seatInfo.longitude && this.seatInfo.latitude)) {
|
||
if (this.loginType === "min") {
|
||
handleHavePointInMin().then((res) => {
|
||
_this.handleGetOnLoad();
|
||
});
|
||
} else if (this.loginType === "android") {
|
||
handleHavePointInApp().then((res) => {});
|
||
} else {
|
||
hanldeHavePointInIos();
|
||
}
|
||
return;
|
||
}
|
||
|
||
this.handleDelete();
|
||
uni.showLoading({
|
||
title: "加载中...",
|
||
});
|
||
// 高德key
|
||
const key = "6e96a801bcea5290d3dcbf100358a6b3";
|
||
// 起点经纬度
|
||
const start = `${this.startObj.longitude},${this.startObj.latitude}`;
|
||
// 终点经纬度
|
||
const end = `${this.endObj.longitude},${this.endObj.latitude}`;
|
||
// 拿到途径点的所有坐标
|
||
let routePoint = "";
|
||
|
||
// 拿到当前位置 跟服务区的距离
|
||
let req = {
|
||
Province_Code: "340000",
|
||
longitude: this.seatInfo.longitude || "",
|
||
latitude: this.seatInfo.latitude || "",
|
||
};
|
||
let serviceArea = await this.$api.$get(
|
||
"/CommercialApi/BaseInfo/GetServerpartList",
|
||
req
|
||
);
|
||
let serviceList = serviceArea.Result_Data.List;
|
||
|
||
console.log("start", start);
|
||
console.log("this.endObj", this.endObj);
|
||
|
||
const data = await new Promise((resolve, reject) => {
|
||
uni.request({
|
||
url: `https://restapi.amap.com/v3/direction/driving?key=${key}&origin=${start}&destination=${this.endObj.longitude},${this.endObj.latitude}&strategy=0`,
|
||
method: "GET",
|
||
success(res) {
|
||
if (
|
||
res.data &&
|
||
res.data.route &&
|
||
res.data.route.paths &&
|
||
res.data.route.paths.length > 0
|
||
) {
|
||
resolve(res.data.route.paths[0] || {});
|
||
} else {
|
||
resolve(undefined);
|
||
}
|
||
},
|
||
});
|
||
});
|
||
let distance =
|
||
data && data.distance ? (data.distance / 1000).toFixed(2) : 0; // 公里
|
||
// 耗时
|
||
let duration = data && data.duration ? Math.ceil(data.duration / 60) : 0; // 分钟
|
||
// 收费金额
|
||
let tolls = data && data.tolls ? data.tolls : 0; // 收费金额
|
||
// 转一下时间的格式
|
||
let timeObj = _this.handleChangeTimeRule(duration);
|
||
|
||
// 通畅个数
|
||
let smoothAcount = 0;
|
||
// 全部个数
|
||
let allAcount = 0;
|
||
|
||
//拿到是否通畅的数据
|
||
if (data && data.steps && data.steps.length > 0) {
|
||
data.steps.forEach((item) => {
|
||
if (item.tmcs && item.tmcs.length > 0) {
|
||
item.tmcs.forEach((subItem) => {
|
||
if (subItem.status === "畅通") {
|
||
smoothAcount += 1;
|
||
}
|
||
allAcount += 1;
|
||
});
|
||
}
|
||
if (routePoint) {
|
||
routePoint += `;${item.polyline}`;
|
||
} else {
|
||
routePoint = `${item.polyline}`;
|
||
}
|
||
});
|
||
}
|
||
|
||
let areaList = routePoint.split(";");
|
||
let newAreaList = [];
|
||
if (areaList && areaList.length > 0) {
|
||
areaList.forEach((item) => {
|
||
let [long, lat] = item.split(",");
|
||
let newLong = this.extractFourDecimals(long);
|
||
let newLat = this.extractFourDecimals(lat);
|
||
newAreaList.push(`${newLong},${newLat}`);
|
||
});
|
||
}
|
||
// 途径的服务区
|
||
let serviceAreaList = [];
|
||
if (serverInfo.cityCoordinate && newAreaList && newAreaList.length > 0) {
|
||
for (let key in serverInfo.cityCoordinate) {
|
||
if (
|
||
newAreaList.indexOf(serverInfo.cityCoordinate[key]) !== -1 &&
|
||
key !== this.endObj.SERVERPART_NAME
|
||
) {
|
||
serviceAreaList.push(key);
|
||
}
|
||
}
|
||
}
|
||
|
||
let list = [];
|
||
|
||
if (serviceAreaList && serviceAreaList.length > 0) {
|
||
serviceAreaList.forEach((item) => {
|
||
if (serviceList && serviceList.length > 0) {
|
||
serviceList.forEach((subItem) => {
|
||
if (item === subItem.SERVERPART_NAME) {
|
||
list.push(subItem);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
// 下面的距离变成高速实际距离 不再是直线距离
|
||
if (list && list.length > 0) {
|
||
for (let i = 0; i < list.length; i++) {
|
||
let itemEnd = `${list[i].SERVERPART_X},${list[i].SERVERPART_Y}`;
|
||
const res = await new Promise((resolve, reject) => {
|
||
uni.request({
|
||
url: `https://restapi.amap.com/v3/direction/driving?key=${key}&origin=${start}&destination=${itemEnd}&strategy=0`,
|
||
method: "GET",
|
||
success(res) {
|
||
if (
|
||
res.data &&
|
||
res.data.route &&
|
||
res.data.route.paths &&
|
||
res.data.route.paths.length > 0
|
||
) {
|
||
resolve(res.data.route.paths[0] || {});
|
||
} else {
|
||
resolve(undefined);
|
||
}
|
||
},
|
||
});
|
||
});
|
||
if (res) {
|
||
list[i].SERVERPART_DISTANCEGD = (
|
||
Number(res.distance) / 1000
|
||
).toFixed(2);
|
||
}
|
||
}
|
||
}
|
||
|
||
_this.detailObj = {
|
||
distanceNumber: distance,
|
||
hour: timeObj.hourStr,
|
||
minutes: timeObj.minuteStr,
|
||
tolls: tolls,
|
||
haveProgress: ((smoothAcount / allAcount) * 100).toFixed(2),
|
||
servicePart: list,
|
||
};
|
||
|
||
uni.hideLoading();
|
||
},
|
||
// 转成几时几分
|
||
handleChangeTimeRule(minutes) {
|
||
if (isNaN(minutes) || minutes < 0) {
|
||
return undefined;
|
||
}
|
||
|
||
const hours = Math.floor(minutes / 60); // 小时部分
|
||
const remainingMinutes = minutes % 60; // 剩余分钟部分
|
||
|
||
// 构建返回字符串
|
||
const hourStr = hours > 0 ? `${hours}` : "";
|
||
const minuteStr = remainingMinutes > 0 ? `${remainingMinutes}` : "";
|
||
return {
|
||
hourStr: hourStr,
|
||
minuteStr: minuteStr,
|
||
};
|
||
},
|
||
//只取小数点后四位
|
||
extractFourDecimals(str) {
|
||
if (!str) {
|
||
return "";
|
||
}
|
||
// 正则匹配小数部分
|
||
const match = str.toString().match(/^(-?\d+)(\.\d{0,2})?/);
|
||
if (match) {
|
||
return match[1] + (match[2] || ""); // 拼接整数部分和截取的小数部分
|
||
}
|
||
},
|
||
// 初始化页面数据
|
||
handleDelete() {
|
||
this.detailObj = {
|
||
distanceNumber: "",
|
||
hour: "",
|
||
minutes: "",
|
||
tolls: "",
|
||
haveProgress: "",
|
||
};
|
||
},
|
||
// 改变终点
|
||
handleChangeService(obj) {
|
||
if (obj.SERVERPART_ID) {
|
||
uni.navigateTo({ url: "/pages/newMap/index/index" });
|
||
}
|
||
},
|
||
// 跳转去地图
|
||
handleToMap(obj) {
|
||
uni.openLocation({
|
||
latitude: obj.latitude ? obj.latitude * 1 : obj.SERVERPART_Y * 1,
|
||
longitude: obj.longitude ? obj.longitude * 1 : obj.SERVERPART_X * 1,
|
||
scale: 16, // 缩放比例
|
||
name: obj.SERVERPART_NAME,
|
||
// address: "", // 这个可能会影响地图的定位,所以可以选择不填
|
||
success(data) {
|
||
console.log(data);
|
||
},
|
||
fail(err) {
|
||
console.log(err);
|
||
},
|
||
});
|
||
},
|
||
// 跳转充换电app
|
||
handleGoApp() {
|
||
if (this.loginType === "min") {
|
||
uni.navigateTo({
|
||
url: "weixin://dl/officialaccounts",
|
||
});
|
||
} else if (this.loginType === "android") {
|
||
var Intent = plus.android.importClass("android.content.Intent");
|
||
var Uri = plus.android.importClass("android.net.Uri");
|
||
var main = plus.android.runtimeMainActivity();
|
||
var intent = new Intent(
|
||
Intent.ACTION_VIEW,
|
||
Uri.parse("your-app-scheme://")
|
||
);
|
||
main.startActivity(intent);
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.main {
|
||
width: 100%;
|
||
min-height: 100vh;
|
||
background: #f6f7f8;
|
||
box-sizing: border-box;
|
||
padding: 12px 16px 24rpx;
|
||
.content {
|
||
width: 100%;
|
||
.trafficState {
|
||
width: 100%;
|
||
background: #ffffff;
|
||
border-radius: 8rpx;
|
||
border: 2rpx solid #f3f3f3;
|
||
box-sizing: border-box;
|
||
padding: 16px;
|
||
.positionBox {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.reachIcon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
|
||
.startItem,
|
||
.endItem {
|
||
width: calc(((100% - 32px) / 2));
|
||
text-align: center;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 36rpx;
|
||
color: #130f05;
|
||
line-height: 48rpx;
|
||
text-align: center;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
.searchBtn {
|
||
width: 100%;
|
||
background: #ba922f;
|
||
border-radius: 8rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 32rpx;
|
||
color: #ffffff;
|
||
line-height: 44rpx;
|
||
text-align: justify;
|
||
font-style: normal;
|
||
padding: 9px 0;
|
||
margin-top: 24px;
|
||
}
|
||
}
|
||
|
||
.bottomBox {
|
||
width: 100%;
|
||
background: #ffffff;
|
||
border-radius: 8rpx;
|
||
border: 2rpx solid #f3f3f3;
|
||
box-sizing: border-box;
|
||
padding: 12px 16px;
|
||
margin-top: 12px;
|
||
.boxTop {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
.leftTop {
|
||
display: flex;
|
||
align-items: center;
|
||
.boldText {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: bold;
|
||
font-size: 32rpx;
|
||
color: #130f05;
|
||
line-height: 44rpx;
|
||
text-align: justify;
|
||
font-style: normal;
|
||
}
|
||
.unit {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #130f05;
|
||
line-height: 36rpx;
|
||
text-align: right;
|
||
font-style: normal;
|
||
}
|
||
.line {
|
||
display: inline-block;
|
||
width: 2rpx;
|
||
height: 22rpx;
|
||
background: #716f69;
|
||
margin: 0 12px;
|
||
}
|
||
}
|
||
.rightTop {
|
||
border-radius: 16px;
|
||
// border: 1px solid #ae8d3e;
|
||
padding: 14rpx 24rpx;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #ba922f;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
display: flex;
|
||
align-items: center;
|
||
.navigationIcon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.roadConditions {
|
||
width: 100%;
|
||
margin-top: 8px;
|
||
.roadTop {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
.stateIcon {
|
||
width: 18px;
|
||
height: 18px;
|
||
margin-right: 8px;
|
||
}
|
||
.stateText {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 22rpx;
|
||
line-height: 32rpx;
|
||
text-align: justify;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
.progress {
|
||
width: 100%;
|
||
height: 10px;
|
||
background: #bee4d2;
|
||
border-radius: 6px;
|
||
margin-top: 6px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
.have {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
height: 100%;
|
||
background: #29c07a;
|
||
border-radius: 6px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.horizontal {
|
||
width: 100%;
|
||
height: 2px;
|
||
background: #f3f3f3;
|
||
margin: 20px 0 16px 0;
|
||
}
|
||
|
||
.serviceBox {
|
||
margin-top: 40rpx;
|
||
.serviceTitle {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 28rpx;
|
||
color: #130f05;
|
||
line-height: 40rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
.serviceList {
|
||
margin-top: 8px;
|
||
width: 100%;
|
||
.serviceItem {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 24rpx;
|
||
.leftItem {
|
||
width: 100%;
|
||
// height: 144rpx;
|
||
// width: calc(100% - 70px);
|
||
display: flex;
|
||
// align-items: center;
|
||
align-items: flex-start;
|
||
.leftImgBox {
|
||
width: 144rpx;
|
||
height: 144rpx;
|
||
overflow: hidden;
|
||
border-radius: 4px;
|
||
margin-right: 10px;
|
||
.leftImg {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
.detailBox {
|
||
width: calc(100% - 164rpx);
|
||
// height: 144rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: flex-start;
|
||
.detailTop {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
.topLeft {
|
||
display: flex;
|
||
align-items: center;
|
||
.detailName {
|
||
display: inline-block;
|
||
max-width: 400rpx;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 28rpx;
|
||
color: #130f05;
|
||
line-height: 40rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.detailState {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 22rpx;
|
||
color: #01a157;
|
||
line-height: 32rpx;
|
||
text-align: justify;
|
||
font-style: normal;
|
||
padding: 2rpx 3px;
|
||
background: #e9f8ee;
|
||
border-radius: 2rpx;
|
||
margin-left: 8rpx;
|
||
}
|
||
}
|
||
.topRight {
|
||
.chargeType {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 22rpx;
|
||
color: #ffffff;
|
||
line-height: 32rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
padding: 2rpx 8rpx;
|
||
background: #ba922f;
|
||
border-radius: 4rpx 0rpx 0rpx 4rpx;
|
||
}
|
||
.chargeValue {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #ba922f;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
padding: 2rpx 8rpx;
|
||
border-radius: 0rpx 4rpx 4rpx 0rpx;
|
||
background: #f8f4ea;
|
||
}
|
||
}
|
||
}
|
||
.detailBottom {
|
||
width: 100%;
|
||
margin-top: 8rpx;
|
||
.distanceBox {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
.distanceLeft {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 150rpx;
|
||
.distanceIcon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
.distanceNumber {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716f69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
|
||
.line {
|
||
display: inline-block;
|
||
width: 2rpx;
|
||
height: 22rpx;
|
||
background: #e7e7e6;
|
||
margin: 0 12px;
|
||
}
|
||
.address {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716f69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
display: inline-block;
|
||
max-width: 250rpx;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
|
||
.typeList {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
overflow-x: auto;
|
||
margin-top: 16rpx;
|
||
.typeItem {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716f69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
padding: 4rpx 8rpx;
|
||
background: #f5f6f7;
|
||
border-radius: 4rpx;
|
||
margin-right: 12rpx;
|
||
}
|
||
}
|
||
|
||
// .label {
|
||
// font-family: PingFangSC, PingFang SC;
|
||
// font-weight: 400;
|
||
// font-size: 24rpx;
|
||
// color: #716f69;
|
||
// line-height: 36rpx;
|
||
// text-align: justify;
|
||
// font-style: normal;
|
||
// width: 100%;
|
||
// display: -webkit-box; /* 必须设置 */
|
||
// -webkit-box-orient: vertical; /* 垂直排列子元素 */
|
||
// -webkit-line-clamp: 3; /* 限制显示的行数 */
|
||
// overflow: hidden; /* 超出内容隐藏 */
|
||
// text-overflow: ellipsis; /* 超出部分显示省略号 */
|
||
// word-break: break-all; /* 强制换行,防止长单词溢出 */
|
||
// }
|
||
// .value {
|
||
// font-family: PingFangSC, PingFang SC;
|
||
// font-weight: 400;
|
||
// font-size: 24rpx;
|
||
// color: #130f05;
|
||
// line-height: 36rpx;
|
||
// text-align: right;
|
||
// font-style: normal;
|
||
// }
|
||
}
|
||
|
||
.chargeBox {
|
||
width: 100%;
|
||
margin-top: 8rpx;
|
||
.chargeItem {
|
||
width: 100%;
|
||
padding: 8rpx;
|
||
background: #f6f6f6;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
border-radius: 8rpx;
|
||
box-sizing: border-box;
|
||
padding: 0 16rpx;
|
||
margin-bottom: 14rpx;
|
||
.chargeItemLabel {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #130f05;
|
||
line-height: 40rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
.chargeItemValue {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #130f05;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
.empty {
|
||
font-family: DINAlternate, DINAlternate;
|
||
font-weight: bold;
|
||
font-size: 24rpx;
|
||
color: #130f05;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
margin: 0 4rpx;
|
||
}
|
||
.sum {
|
||
font-family: DINAlternate, DINAlternate;
|
||
font-weight: bold;
|
||
font-size: 24rpx;
|
||
color: #716f69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.rightItem {
|
||
width: 70px;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
.navigationTop {
|
||
border-radius: 16px;
|
||
border: 1px solid #ae8d3e;
|
||
padding: 14rpx 24rpx;
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #ba922f;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
display: flex;
|
||
align-items: center;
|
||
.navigationIcon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
}
|
||
.longText {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 20rpx;
|
||
color: #787879;
|
||
line-height: 28rpx;
|
||
text-align: justify;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.goAppBox {
|
||
margin-top: 24rpx;
|
||
width: 100%;
|
||
height: 120rpx;
|
||
background: #ffffff;
|
||
border-radius: 6rpx;
|
||
box-sizing: border-box;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
.appLeft {
|
||
display: flex;
|
||
align-items: center;
|
||
.goAppIcon {
|
||
width: 72rpx;
|
||
height: 72rpx;
|
||
margin-right: 16rpx;
|
||
border-radius: 50%;
|
||
}
|
||
.appName {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 28rpx;
|
||
color: #130f05;
|
||
line-height: 40rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
|
||
.appRight {
|
||
display: flex;
|
||
align-items: center;
|
||
.search {
|
||
font-family: PingFangSC, PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 24rpx;
|
||
color: #716f69;
|
||
line-height: 36rpx;
|
||
text-align: left;
|
||
font-style: normal;
|
||
}
|
||
.searchIcon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-left: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
.goTest {
|
||
padding: 12px 0;
|
||
}
|
||
}
|
||
}
|
||
</style>
|