-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathfixVpnCauseMapBuseBug.js
71 lines (69 loc) · 5.21 KB
/
fixVpnCauseMapBuseBug.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
*情况说明:最开始一直以为boss上的查询自己所在地点到面试地点的公交的功能有bug,总是规划路线失败,结果这个一调试,发现是自己的经纬度有问题导致的。
*程序猿嘛,开机VPN必须是挂着的,这就导致了boss获取到了错误的经纬度,然后因为ip是国外的,自然就没法规划到路线了,要解决也很简单,把VPN关了就行。
*不过这就不程序猿了,所以以下就是魔法手段了。同样是使用油猴脚本,毕竟如果是用书签脚本,没开一个新页面都得执行一下脚本,这操作并不美丽,优雅。(书签脚本当然也行,不过这工作我就不做了)
*注意:这个脚本并不是通用的,需要手动设置(hard code)一下自己的经纬度和城市(不是不能实现代码层面动态获取,但就得增加一堆代码,感觉这个bug其实还是比较少人会遇到,需求不大,偷懒不想干,而且本来就是拿来给自己用的,肯定够用就行)
*这里代码的难点就难在如何去调用网站本身已有的方法,把修正后的经纬度传给规划公交路线的方法,让它生成正确的路线,但方法本身就是包含在一个个闭包内,并且一般也不会暴露出去,你自己写的脚本一般拿不到这些方法,
*而普遍的做法可能就是脚本里要自己复制出一份网站的方法,然后在自己的脚本上下文里调用,这个工作量可够大了,而且未必能成功。当然这里并不需要这么麻烦
*我的思考过程就是先看网络请求或者找到根据点击的方法,或者各种提示词先找到绘制公交路线的方法,就好比这里会有个无可用规划路线的提示语,这就是很好的入口点,直接控制台全局搜索源码,
*找到调用部分,然后断点调试,发现华点,打印this发现是vue实例对象(过程肯定没有这么简单),这就有趣了,vue2的组件实例是可以在dom对象身上获取得到的(document.querySelector('xxx').__vue__),
*所以只要你找到正确的dom,就可以拿得到真正的this了,同样你也拿到了绘制公交路线的方法,剩下部分就easy了。不过实际调试过程还是发现有另一个问题存在,因为地图部分是弹窗iframe,所以如果脚本直接运行,
*试图找到this所在的dom,你会发现document.querySelector('xxx')获取不到元素,但你明明看得到页面有这个dom(有时候你在控制台却可以打印出来,这就是另一个知识点了——对于iframe,控制台底下是用top,iframe的层级可以选择的,层级对了,你就可以获取得到dom),
*所以这里还得去遍历页面所有的iframe,找到正确的iframe,同时因为调用了高德地图的api,还要同时把高德的包给返回出去,不然到时候调用报没定义的错
*/
(function() {
'use strict';
//需要自己hard code部分
let jwd = [113.1, 23.1];
let city = '广州';
//需要自己hard code部分
//给地图加上点击事件监听,用来触发我们的脚本,需要延时执行,因为后续地图是用iframe打开的,不延时,后续获取不到dom
document.querySelector('.job-location-map.js-open-map').addEventListener('click', ()=>setTimeout(getBusLine,2000));
// 递归查找包含指定元素的 iframe
function findIframeWithElement(element) {
return new Promise((resolve,reject)=>{
if (!element) {
console.log('输入错误')
reject('输入错误')
}
var iframes = document.querySelectorAll('iframe');
let loop = setInterval(()=>{
for (var i = 0; i < iframes.length; i++) {
var iframeDoc = iframes[i].contentDocument || iframes[i].contentWindow.document;
if(iframeDoc.readyState === 'complete' && iframeDoc.querySelector(element)){
clearInterval(loop);
loop = null;
resolve({
AMap:iframes[i].contentWindow.AMap,
target:iframeDoc.querySelector(element)
});
}
}
},500)
})
}
async function getBusLine(){
// 查找包含 path-plan-search 元素的 iframe
let {target, AMap} = await findIframeWithElement('.path-plan-search')
// 如果找不到 target,则等待一段时间后再尝试,毕竟iframe可能没加载得那么快
if (!target || !AMap) {
setTimeout(getBusLine, 500);
return;
}
//因为boss直聘的地图弹窗是用vue2做的,所以可以dom通过获取vue组件实例
var that = target.__vue__;
var n = new AMap.LngLat(...jwd);
if(!that.endAddress.longitude){
setTimeout(getBusLine, 500);
return;
}
var a = new AMap.LngLat(that.endAddress.longitude, that.endAddress.latitude);
that.$emit("on-plan", {
planType: that.currentPlanType,
startPoint: n,
endPoint: a,
startPointCity: city,
endPointCity: (that.endAddress && that.endAddress.cityName)
});
}
})()