| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- const api = require('../../../api/index.js');
-
- Page({
- data: {
- // 地图中心坐标
- longitude: 0,
- latitude: 0,
-
- // 标记点(包含起点、终点)
- markers: [],
-
- // 轨迹线(实际轨迹)- 核心修改:将颜色改为红色(#ff0000)
- polyline: [{
- points: [],
- color: "#999999", // 已走过的路线颜色:灰色
- width: 6,
- dottedLine: false
- }],
-
- // 规划路线 - 优化:改为灰色(#999999),与已走路线形成对比
- plannedRoute: [{
- points: [],
- color: "#2f693c", // 未走的规划路线颜色:绿色
- width: 4,
- dottedLine: false,
- arrowLine: true
- }],
-
- // 追踪状态
- isTracking: false,
-
- // 信息提示文本
- infoText: "",
-
- // 位置更新计时器
- locationTimer: null,
-
- // 终点位置
- destination: null,
-
- // 路线规划状态
- routePlanned: false,
-
- // 腾讯位置服务Key
- qqMapKey: 'VRGBZ-ZFRHB-SKIUP-NHHJ3-TXGJT-ZIFG3',
-
- // 偏离阈值(米)和偏离状态
- deviationThreshold: 50, // 超过50米视为偏离
- isDeviated: false,
-
- // 重新规划相关
- isReplanning: false, // 是否正在重新规划
- deviationCount: 0, // 连续偏离计数
- replanThreshold: 3, // 连续偏离多少次后重新规划
- orderdata:{},
- optionsid:'',
- showVerification: false,
- phoneNumber: "138****6789",
- userdata:[]
- },
-
- onLoad(options) {
- this.setData({
- userdata:wx.getStorageSync('user')
- })
-
- console.log(options);
- this.setData({
- optionsid:options.id
- })
- // 初始化地图,获取当前位置
- this.getworkorder()
- // 引入SDK核心类
- this.qqmapsdk = require('../../../libs/qqmap-wx-jssdk.min.js');
- // 初始化SDK
- this.mapSdk = new this.qqmapsdk({
- key: this.data.qqMapKey
- });
- },
-
- getworkorder(){
- let data = {
- workorderId:this.data.optionsid
- }
- api.request(`/sysworkorder/selectworkorderId`, 'post',data,{ isPublic: false })
- .then((data) => {
- console.log(data.data);
- if (data.code==200) {
- this.setData({
- orderdata:data.data
- })
- this.initMap();
- }
- })
- .catch((err) => {
- console.error('请求失败:', err);
- });
- },
-
- onUnload() {
- // 页面卸载时停止追踪
- this.stopTracking();
- },
-
- // 初始化地图
- initMap() {
- const that = this;
-
- // 获取用户当前位置
- wx.getLocation({
- type: 'gcj02', // 腾讯地图坐标体系
- success(res) {
- const longitude = res.longitude;
- const latitude = res.latitude;
-
- // 设置地图中心为当前位置
- that.setData({
- longitude,
- latitude,
- // 初始化起点标记
- markers: [{
- id: 0,
- longitude,
- latitude,
- iconPath: "https://esos-iot.bjdexn.cn/myminio/project/0b0593293af54ea097b168cea479c25c.png",
- width: 30,
- height: 30,
- title: "起点"
- }],
- // 初始化轨迹线起点(颜色已在data中设置为红色)
- polyline: [{
- points: [{longitude, latitude}],
- color: "#ff0000", // 与data中保持一致,确保初始颜色正确
- width: 6,
- dottedLine: false
- }]
- });
-
- that.showInfo("已获取当前位置");
- that.setDestination();
- },
- fail(err) {
- console.error("获取位置失败:", err);
- that.showInfo("请授权位置权限以使用地图功能");
-
- // 引导用户开启权限
- wx.openSetting({
- success(res) {
- if (res.authSetting['scope.userLocation']) {
- that.initMap();
- }
- }
- });
- }
- });
- },
-
- // 规划路线 - 通用方法,可被初始规划和重新规划调用
- planRoute(isReplan = false) {
- const that = this;
- const { longitude, latitude, destination } = this.data;
-
- if (!destination) {
- this.showInfo("请先设置终点");
- return;
- }
-
- // 如果是重新规划,更新状态
- if (isReplan) {
- this.setData({ isReplanning: true });
- this.showInfo("正在重新规划路线...");
- } else {
- this.showInfo("正在规划路线...");
- }
-
- // 调用腾讯地图路线规划API
- this.mapSdk.direction({
- mode: 'driving', // 驾车模式,可选值:'driving', 'walking', 'transit'
- policy:'REAL_TRAFFIC',
- from: {
- latitude: latitude,
- longitude: longitude
- },
- to: {
- latitude: destination.latitude,
- longitude: destination.longitude
- },
- success(res) {
- console.log("路线规划结果:", res);
-
- if (res.status === 0 && res.result.routes.length > 0) {
- var result = res.result
- var route = result.routes[0]
- // 提取路线点
- var coors = route.polyline, pl = [];
- //坐标解压(返回的点串坐标,通过前向差分进行压缩)
- var kr = 1000000;
- for (var i = 2; i < coors.length; i++) {
- coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
- }
- //将解压后的坐标放入点串数组pl中
- for (var i = 0; i < coors.length; i += 2) {
- pl.push({ latitude: coors[i], longitude: coors[i + 1] })
- }
-
- // 更新路线数据(规划路线颜色已设为灰色)
- that.setData({
- plannedRoute: [{
- name: that.data.orderdata.addressName,
- points: pl,
- color: '#2f693c', // 与data中保持一致,确保规划路线颜色正确
- width: 6,
- borderColor: '#2f693c',
- borderWidth: 1
- }],
- routePlanned: true,
- isReplanning: false,
- deviationCount: 0 // 重置偏离计数
- });
-
- // 显示规划结果
- const message = isReplan
- ? `已重新规划路线,距离${(result.routes[0].distance/1000).toFixed(1)}公里,约${Math.ceil(result.routes[0].duration)}分钟`
- : `路线规划完成,距离${(result.routes[0].distance/1000).toFixed(1)}公里,约${Math.ceil(result.routes[0].duration)}分钟`;
-
- that.showInfo(message);
-
- } else {
- that.setData({ isReplanning: false });
- that.showInfo("路线规划失败,请重试");
- }
- },
- fail(err) {
- console.error("路线规划失败:", err);
- that.setData({ isReplanning: false });
- that.showInfo("路线规划失败,请检查网络");
- }
- });
- },
-
- // 设置终点位置
- setDestination() {
- // 更新终点标记
- const newMarkers = [...this.data.markers.filter(marker => marker.id !== 1)];
- newMarkers.push({
- name: this.data.orderdata.addressName,
- id: 1,
- latitude: this.data.orderdata.latitude, // 终点纬度
- longitude: this.data.orderdata.longitude, // 终点经度
- iconPath: "https://esos-iot.bjdexn.cn/myminio/project/6dc37b15321b462f9ab59c47263dd224.png",
- width: 30,
- height: 30,
- title: "终点"
- });
-
- this.setData({
- markers: newMarkers,
- destination: { longitude: this.data.orderdata.longitude, latitude: this.data.orderdata.latitude }
- });
-
- this.showInfo("已设置终点位置");
- this.planRoute(); // 初始规划路线
- // this.startTracking(); // 实时监控位置
- },
-
- // 显示信息提示
- showInfo(text) {
- this.setData({ infoText: text });
-
- // 3秒后自动隐藏非状态类信息
- if (!text.includes("正在") && !text.includes("距离") && !text.includes("偏离")) {
- setTimeout(() => {
- this.setData({ infoText: "" });
- }, 3000);
- }
- },
-
- // 导航功能
- navigation(){
- // 使用在腾讯位置服务申请的key
- const key = this.data.qqMapKey;
- // 调用插件的app的名称
- const referer = '晟运智慧运维';
- // 是否启用智能规划
- const enableAI = true;
- // 是否开启导航功能
- const navigation = 1;
- // 终点(建议替换为orderdata中的实际终点,当前为示例值)
- const endPoint = JSON.stringify({
- name: this.data.orderdata.addressName || '目的地',
- latitude: this.data.orderdata.latitude,
- longitude: this.data.orderdata.longitude,
- });
- // 个性化图层
- const layerStyle = 1;
- wx.navigateTo({
- url: `plugin://route-plan/index?key=${key}&referer=${referer}&endPoint=${endPoint}&enableAI=${enableAI}&navigation=${navigation}&layerStyle=${layerStyle}`,
- });
- },
-
- // 开始追踪位置
- startTracking() {
- if (this.data.isTracking) return;
-
- const that = this;
- this.setData({ isTracking: true });
-
- // 定期获取位置并检查是否偏离路线
- this.setData({
- locationTimer: setInterval(() => {
- wx.getLocation({
- type: 'gcj02',
- success(res) {
- const newPoint = {
- longitude: res.longitude,
- latitude: res.latitude
- };
-
- // 更新当前位置和轨迹(颜色保持红色)
- const updatedPolyline = [...that.data.polyline];
- updatedPolyline[0].points.push(newPoint);
-
- // 更新起点标记位置
- const updatedMarkers = [...that.data.markers];
- updatedMarkers[0] = {
- ...updatedMarkers[0],
- longitude: res.longitude,
- latitude: res.latitude
- };
-
- that.setData({
- longitude: res.longitude,
- latitude: res.latitude,
- polyline: updatedPolyline,
- markers: updatedMarkers
- });
-
- // 检查是否偏离规划路线
- if (that.data.routePlanned && !that.data.isReplanning) {
- that.checkDeviation(newPoint);
- }
- },
- fail(err) {
- console.error("获取位置失败:", err);
- that.showInfo("位置获取失败,请检查权限");
- }
- });
- }, 3000) // 每3秒更新一次位置
- });
-
- this.showInfo("开始追踪位置");
- },
-
- // 停止追踪
- stopTracking() {
- if (this.data.locationTimer) {
- clearInterval(this.data.locationTimer);
- this.setData({
- locationTimer: null,
- isTracking: false
- });
- this.showInfo("已停止追踪");
- }
- },
-
- // 检查是否偏离路线
- checkDeviation(currentPoint) {
- const { plannedRoute, deviationThreshold, deviationCount, replanThreshold } = this.data;
- const routePoints = plannedRoute[0].points;
-
- if (!routePoints || routePoints.length < 2) return;
-
- // 计算当前位置到路线的最短距离
- let minDistance = Infinity;
-
- // 检查当前点到路线上每一段线段的距离
- for (let i = 0; i < routePoints.length - 1; i++) {
- const distance = this.calculateDistanceToLine(
- currentPoint,
- routePoints[i],
- routePoints[i + 1]
- );
-
- if (distance < minDistance) {
- minDistance = distance;
- }
- }
-
- // 判断是否偏离
- const isDeviated = minDistance > deviationThreshold;
-
- if (isDeviated) {
- // 增加连续偏离计数
- const newDeviationCount = deviationCount + 1;
- this.setData({
- isDeviated,
- deviationCount: newDeviationCount
- });
-
- // 显示偏离信息
- this.showInfo(`已偏离路线 ${minDistance.toFixed(1)} 米,连续偏离 ${newDeviationCount}/${replanThreshold} 次`);
-
- // 播放提示音
- wx.playBackgroundAudio({
- dataUrl: 'http://ws.stream.qqmusic.qq.com/M500001VfvsJ21xFqb.mp3?guid=ffffffff82def4af4b12b3cd9337d38&uin=346897220&vkey=6292F51C65348166B851686B2C059D76205E4241C44E5823713D649EF6471BA681DC27D5269A1E&fromtag=46',
- title: '偏离提醒',
- coverImgUrl: ''
- });
-
- // 达到重新规划阈值,且不在重新规划中
- if (newDeviationCount >= replanThreshold && !this.data.isReplanning) {
- this.planRoute(true); // 重新规划路线,传入true标识
- }
- } else {
- // 回到路线上,重置偏离计数
- this.setData({
- isDeviated,
- deviationCount: 0
- });
-
- if (this.data.isDeviated) {
- this.showInfo("已回到规划路线");
- }
- }
- },
-
- // 计算点到线段的距离(米)
- calculateDistanceToLine(point, lineStart, lineEnd) {
- // 经纬度转弧度
- const toRadians = (degree) => degree * Math.PI / 180;
-
- // 地球半径(米)
- const R = 6371000;
-
- // 转换为弧度
- const lat1 = toRadians(point.latitude);
- const lon1 = toRadians(point.longitude);
- const lat2 = toRadians(lineStart.latitude);
- const lon2 = toRadians(lineStart.longitude);
- const lat3 = toRadians(lineEnd.latitude);
- const lon3 = toRadians(lineEnd.longitude);
-
- // 计算线段长度
- const a = this.haversineDistance(lat1, lon1, lat2, lon2);
- const b = this.haversineDistance(lat1, lon1, lat3, lon3);
- const c = this.haversineDistance(lat2, lon2, lat3, lon3);
-
- // 如果点在线段延长线上,返回最近端点的距离
- if (b * b >= a * a + c * c) {
- return a;
- }
- if (a * a >= b * b + c * c) {
- return b;
- }
-
- // 计算点到线段的垂直距离
- const s = (a + b + c) / 2;
- const area = Math.sqrt(Math.abs(s * (s - a) * (s - b) * (s - c)));
- return (2 * area) / c;
- },
-
- // 使用haversine公式计算两点间距离(米)
- haversineDistance(lat1, lon1, lat2, lon2) {
- const R = 6371000; // 地球半径(米)
- const dLat = lat2 - lat1;
- const dLon = lon2 - lon1;
-
- const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
- Math.cos(lat1) * Math.cos(lat2) *
- Math.sin(dLon / 2) * Math.sin(dLon / 2);
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
-
- return R * c;
- },
-
- // 显示验证码弹窗
- showVerificationPopup() {
- this.setData({ showVerification: true });
- },
-
- // 关闭弹窗
- onPopupClose() {
- this.setData({ showVerification: false });
- setTimeout(() => {
- const slideComponent = this.selectComponent("#mySlideConfirm");
- // 2. 调用组件的reset方法
- slideComponent.reset();
- }, 1000);
- },
-
- // 确认验证码
- onCodeConfirm(e) {
- console.log("确认验证码:", e.detail.code);
- // 验证逻辑...
- this.setData({ showVerification: false });
- },
-
- // 重新发送验证码
- onResendCode() {
- console.log("重新发送验证码");
- // 重新发送逻辑...
- },
-
- // 验证码输入完成
- onCodeComplete(e) {
- console.log("验证码输入完成:", e.detail.code);
- // 自动验证逻辑...
- let data = {
- carId:this.data.optionsid,
- verifyCode: e.detail.code,
- workorderId:this.data.orderdata.workorderId
- }
- api.request(`/sysworkorder/submitworkorder`, 'post',data,{ isPublic: false })
- .then((data) => {
- console.log(data.data);
- if (data.code==200) {
- this.getworkorder();
- setTimeout(() => {
- const slideComponent = this.selectComponent("#mySlideConfirm");
- // 2. 调用组件的reset方法
- slideComponent.reset();
- }, 5000);
-
- }
- })
- .catch((err) => {
- setTimeout(() => {
- const slideComponent = this.selectComponent("#mySlideConfirm");
- // 2. 调用组件的reset方法
- slideComponent.reset();
- }, 5000);
- console.error('请求失败:', err);
- });
- },
- onSlideSuccess(e){
- console.log(e.currentTarget.dataset.type);
-
- // 3. 更新页面状态,隐藏按钮和提示
- let data = {
- carId:this.data.optionsid,
- verifyCode:'MNBJ4H',
- workorderId:this.data.orderdata.workorderId
- }
- api.request(`/sysworkorder/submitworkorder`, 'post',data,{ isPublic: false })
- .then((data) => {
- console.log(data.data);
- if (data.code==200) {
- if (e.currentTarget.dataset.type==2) {
- let objdata ={
- workorderId:this.data.orderdata.workorderId
- }
- api.request(`/sysworkorder/createverify`, 'post',objdata,{ isPublic: false })
- .then((data) => {
- console.log(data.data);
- if (data.code==200) {
-
- }
- })
- .catch((err) => {
-
- console.error('请求失败:', err);
- });
- }
- this.getworkorder();
- setTimeout(() => {
- const slideComponent = this.selectComponent("#mySlideConfirm");
- // 2. 调用组件的reset方法
- slideComponent.reset();
- }, 5000);
-
- }
- })
- .catch((err) => {
- setTimeout(() => {
- const slideComponent = this.selectComponent("#mySlideConfirm");
- // 2. 调用组件的reset方法
- slideComponent.reset();
- }, 5000);
- console.error('请求失败:', err);
- });
- },
- ontelephone(e){
- console.log(e.currentTarget.dataset.phone);
- const phoneNumber = e.currentTarget.dataset.phone;
- wx.showModal({
- title: '确认拨打电话',
- content: '是否拨打' + phoneNumber + '?',
- success: (res) => {
- if (res.confirm) {
- wx.makePhoneCall({
- phoneNumber: phoneNumber
- });
- }
- }
- });
- }
- });
|