perf: 添加定位签到

This commit is contained in:
kuaifan 2024-11-10 00:35:04 +08:00
parent 016bc41180
commit 74405f1a2a
10 changed files with 211 additions and 137 deletions

View File

@ -207,6 +207,9 @@ class UserBot extends AbstractModel
if (!in_array('locat', $setting['modes'])) { if (!in_array('locat', $setting['modes'])) {
return '暂未开放定位签到。'; return '暂未开放定位签到。';
} }
if (empty($extra)) {
return '当前客户端版本低所需版本≥v0.39.75)。';
}
if ($extra['type'] === 'bd') { if ($extra['type'] === 'bd') {
// todo 判断距离 // todo 判断距离
} else { } else {

View File

@ -723,7 +723,6 @@ webhook地址最长仅支持255个字符。
请填写百度地图AK 请填写百度地图AK
请选择允许签到位置 请选择允许签到位置
请选择有效的签到位置 请选择有效的签到位置
暂未开启签到功能。
暂未开放定位签到。 暂未开放定位签到。
错误的定位签到。 错误的定位签到。
获取地图快照失败 获取地图快照失败

View File

@ -1764,13 +1764,6 @@ WiFi签到延迟时长为±1分钟。
以后再说 以后再说
立即更新 立即更新
签到地点
选择附近地点
搜索地点
附近没有找到地点
定位失败
签到地点
选择附近地点 选择附近地点
搜索地点 搜索地点
附近没有找到地点 附近没有找到地点
@ -1791,3 +1784,6 @@ WiFi签到延迟时长为±1分钟。
请先填写百度地图AK 请先填写百度地图AK
你当前是负责人,确定要转为协助人员吗? 你当前是负责人,确定要转为协助人员吗?
仅支持移动端App
暂未开放定位签到。
错误的定位签到。

View File

@ -25955,18 +25955,6 @@
"id": "Kata Bijak: (%T1)", "id": "Kata Bijak: (%T1)",
"ru": "Душеподъемная цитата: (%T1)" "ru": "Душеподъемная цитата: (%T1)"
}, },
{
"key": "签到地点",
"zh": "",
"zh-CHT": "簽到地點",
"en": "Check-in Location",
"ko": "출석 장소",
"ja": "チェックイン場所",
"de": "Eingetragener Ort",
"fr": "Lieu d'enregistrement",
"id": "Lokasi Check-in",
"ru": "Место регистрации"
},
{ {
"key": "选择附近地点", "key": "选择附近地点",
"zh": "", "zh": "",
@ -26279,4 +26267,4 @@
"id": "Anda saat ini adalah orang yang bertanggung jawab. Apakah Anda yakin ingin beralih menjadi asisten?", "id": "Anda saat ini adalah orang yang bertanggung jawab. Apakah Anda yakin ingin beralih menjadi asisten?",
"ru": "Вы в данный момент являетесь ответственным лицом. Уверены, что хотите перейти в помощники?" "ru": "Вы в данный момент являетесь ответственным лицом. Уверены, что хотите перейти в помощники?"
} }
] ]

View File

@ -290,7 +290,9 @@ class BaiduMapPicker {
*/ */
initMap() { initMap() {
// 初始化地图 // 初始化地图
this.map = new BMap.Map('map-container'); this.map = new BMap.Map('map-container', {
enableMapClick: false
});
// 初始化本地搜索,移除地图渲染 // 初始化本地搜索,移除地图渲染
this.localSearch = new BMap.LocalSearch(this.map, { this.localSearch = new BMap.LocalSearch(this.map, {
@ -320,9 +322,7 @@ class BaiduMapPicker {
this.bindEvents(); this.bindEvents();
// 初始化时自动定位 // 初始化时自动定位
Loader.show();
this.getCurrentLocation().then((point) => { this.getCurrentLocation().then((point) => {
Loader.hide();
if (point === null) { if (point === null) {
this.locationError(); this.locationError();
} }
@ -348,10 +348,7 @@ class BaiduMapPicker {
// 地图定位点击事件 // 地图定位点击事件
const mapLocation = document.getElementById('map-location'); const mapLocation = document.getElementById('map-location');
mapLocation.addEventListener('click', () => { mapLocation.addEventListener('click', () => {
Loader.show() this.getCurrentLocation();
this.getCurrentLocation().then(() => {
Loader.hide()
});
}); });
} }
@ -361,7 +358,9 @@ class BaiduMapPicker {
*/ */
getCurrentLocation() { getCurrentLocation() {
return new Promise(resolve => { return new Promise(resolve => {
Loader.show()
App.getLocation().then(res => { App.getLocation().then(res => {
Loader.hide()
if (App.isJson(res) && res.longitude && res.latitude) { if (App.isJson(res) && res.longitude && res.latitude) {
const bd09_coord = CoordTransform.wgs84toBd09(res.longitude, res.latitude); const bd09_coord = CoordTransform.wgs84toBd09(res.longitude, res.latitude);
const point = new BMap.Point(bd09_coord[0], bd09_coord[1]); const point = new BMap.Point(bd09_coord[0], bd09_coord[1]);
@ -381,9 +380,13 @@ class BaiduMapPicker {
*/ */
updateCurrentPoint(point) { updateCurrentPoint(point) {
this.currentPoint = point; this.currentPoint = point;
this.map.centerAndZoom(this.currentPoint, this.params.zoom); if (Math.abs(this.map.getZoom() - this.params.zoom) > 1) {
this.map.centerAndZoom(this.currentPoint, this.params.zoom);
} else {
this.map.setCenter(this.currentPoint);
}
this.updateMarker(this.currentPoint); this.updateMarker(this.currentPoint);
this.searchNearby(); this.searchAddress();
} }
/** /**
@ -403,95 +406,134 @@ class BaiduMapPicker {
* 搜索地址 * 搜索地址
*/ */
searchAddress() { searchAddress() {
const keyword = document.getElementById('search-input').value; const keyword = `${document.getElementById('search-input').value}`.trim();
this.searchNearby(keyword ? [keyword] : []); if (keyword) {
this.searchKeyword(this.currentPoint, keyword);
} else {
this.searchLocation(this.currentPoint);
}
} }
/** /**
* 搜索附近的地点 * 通过关键词搜索附近的地点
* @param keywords * @param centerPoint
* @param keyword
* @param retryCount * @param retryCount
*/ */
searchNearby(keywords = [], retryCount = 0) { searchKeyword(centerPoint, keyword, retryCount = 0) {
// 当前位置未获取
if (this.currentPoint === null) {
return;
}
// 清除之前的搜索结果 // 清除之前的搜索结果
this.localSearch.clearResults(); this.localSearch.clearResults();
// 搜索附近的关键词
if (keywords.length === 0) {
keywords = ["写字楼", "公司", "银行", "餐馆", "商场", "超市", "学校", "医院", "公交站", "地铁站"]
}
// 定义一个随机数,用于判断定时器是否过期 // 定义一个随机数,用于判断定时器是否过期
this.searchRandom = Math.random(); this.searchRandom = Math.random();
// 设置搜索完成回调 // 设置搜索完成回调
Loader.show(); Loader.show();
this.localSearch.setSearchCompleteCallback((results) => { this.localSearch.setSearchCompleteCallback(result => {
Loader.hide(); Loader.hide();
if (this.localSearch.getStatus() !== BMAP_STATUS_SUCCESS) { if (this.localSearch.getStatus() !== BMAP_STATUS_SUCCESS) {
// 搜索失败 // 搜索失败10次重试
if (retryCount < 60) { if (retryCount < 10) {
const tmpRand = this.searchRandom; const tmpRand = this.searchRandom;
Loader.show(); Loader.show();
setTimeout(() => { setTimeout(() => {
Loader.hide(); Loader.hide();
tmpRand === this.searchRandom && this.searchNearby(keywords, ++retryCount); tmpRand === this.searchRandom && this.searchKeyword(centerPoint, keyword, ++retryCount);
}, 1000) }, 300)
return; return;
} }
} }
// 搜索结果 // 搜索结果
document.getElementById('address-list').style.display = 'block'; const pois = [];
const array = []; for (let i = 0; i < result.getCurrentNumPois(); i++) {
if (results instanceof Array) { const poi = result.getPoi(i);
results.some(result => { if (!poi.point) {
if (!result) { continue;
return false; }
} poi.distance = this.params.point ? this.map.getDistance(this.params.point, poi.point) : null;
for (let i = 0; i < result.getCurrentNumPois(); i++) { poi.distance_current = this.map.getDistance(centerPoint, poi.point);
const poi = result.getPoi(i); pois.push(poi);
poi.distance = this.params.point ? this.map.getDistance(this.params.point, poi.point) : null;
array.push(poi);
}
});
} }
this.updatePoiList(array); this.updatePoiList(pois);
}); });
// 执行搜索 // 执行搜索
this.localSearch.searchNearby(keywords, this.currentPoint, this.params.radius); this.localSearch.searchNearby(keyword, centerPoint, this.params.radius);
}
/**
* 通过坐标搜索附近的地点
* @param point
*/
searchLocation(point) {
const geoc = new BMap.Geocoder();
Loader.show();
geoc.getLocation(point, (result) => {
Loader.hide();
const pois = [];
if (result) {
// 搜索结果
const surroundingPois = result.surroundingPois || [];
if (surroundingPois.length === 0) {
surroundingPois.push({
title: result.addressComponents.city + result.addressComponents.district,
address: result.address,
point: result.point,
});
}
surroundingPois.some(poi => {
if (!poi.point) {
return false;
}
poi.distance = this.params.point ? this.map.getDistance(this.params.point, poi.point) : null;
poi.distance_current = this.map.getDistance(point, poi.point);
pois.push(poi);
})
}
this.updatePoiList(pois)
}, {
poiRadius: this.params.radius,
numPois: 20,
});
} }
/** /**
* 更新搜索结果列表 * 更新搜索结果列表
* @param results * @param pois
*/ */
updatePoiList(results) { updatePoiList(pois) {
const addressList = document.getElementById('address-list');
addressList.style.display = 'block';
const poiList = document.getElementById('poi-list'); const poiList = document.getElementById('poi-list');
poiList.innerHTML = ''; poiList.innerHTML = '';
// 如果没有搜索结果 // 如果没有搜索结果
if (results.length === 0 && this.params.noresult) { if (pois.length === 0) {
poiList.innerHTML = '<li>' + this.params.noresult + '</li>'; if (this.params.noresult) {
poiList.innerHTML = '<li><div class="address-noresult">' + this.params.noresult + '</div></li>';
}
return; return;
} }
// 筛选距离小于搜索半径的结果(+100
pois = pois.filter(poi => {
return poi.title && poi.point && poi.distance_current < this.params.radius + 100;
});
// 按距离排序(如果有距离信息) // 按距离排序(如果有距离信息)
results.sort((a, b) => { pois.sort((a, b) => {
if (a.distance && b.distance) { if (a.distance_current && b.distance_current) {
return a.distance - b.distance; return a.distance_current - b.distance_current;
} }
return 0; return 0;
}); });
results = results.slice(0, 20);
// 只显示前20个结果
pois = pois.slice(0, 20);
// 创建列表项 // 创建列表项
results.forEach(poi => { pois.forEach(poi => {
const li = document.createElement('li'); const li = document.createElement('li');
const distanceFormat = poi.distance ? `<div class="address-distance">${this.convertDistance(Math.round(poi.distance))}</div>` : ''; const distanceFormat = poi.distance ? `<div class="address-distance">${this.convertDistance(Math.round(poi.distance))}</div>` : '';
li.innerHTML = ` li.innerHTML = `

View File

@ -29,7 +29,6 @@ body {
.search-box { .search-box {
padding: 10px; padding: 10px;
background: #fff; background: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
position: relative; position: relative;
z-index: 100; z-index: 100;
} }
@ -121,6 +120,7 @@ body {
#poi-list { #poi-list {
list-style: none; list-style: none;
padding-bottom: 10px;
} }
#poi-list li { #poi-list li {
@ -147,8 +147,8 @@ body {
transform: scaleY(0.5); transform: scaleY(0.5);
} }
#poi-list li:hover { #poi-list li:last-child::before {
background: #f5f5f5; display: none;
} }
.address-name { .address-name {

View File

@ -76,7 +76,7 @@
</CheckboxGroup> </CheckboxGroup>
<div v-if="formData.modes.includes('face')" class="form-tip">{{$L('人脸签到')}}: {{$L('通过人脸识别机签到')}}</div> <div v-if="formData.modes.includes('face')" class="form-tip">{{$L('人脸签到')}}: {{$L('通过人脸识别机签到')}}</div>
<div v-if="formData.modes.includes('auto')" class="form-tip">{{$L('WiFi签到')}}: {{$L('详情看下文安装说明')}}</div> <div v-if="formData.modes.includes('auto')" class="form-tip">{{$L('WiFi签到')}}: {{$L('详情看下文安装说明')}}</div>
<div v-if="formData.modes.includes('locat')" class="form-tip">{{$L('定位签到')}}: {{$L('通过在签到打卡机器人发送位置签到')}}</div> <div v-if="formData.modes.includes('locat')" class="form-tip">{{$L('定位签到')}}: {{$L('通过在签到打卡机器人发送位置签到')}} ({{$L('仅支持移动端App')}})</div>
<div v-if="formData.modes.includes('manual')" class="form-tip">{{$L('手动签到')}}: {{$L('通过在签到打卡机器人发送指令签到')}}</div> <div v-if="formData.modes.includes('manual')" class="form-tip">{{$L('手动签到')}}: {{$L('通过在签到打卡机器人发送指令签到')}}</div>
</FormItem> </FormItem>
</template> </template>

View File

@ -978,7 +978,7 @@ export default {
openAppMapPage({dispatch}, objects) { openAppMapPage({dispatch}, objects) {
return new Promise(resolve => { return new Promise(resolve => {
const params = { const params = {
title: $A.L("签到地点"), title: $A.L("定位签到"),
label: $A.L("选择附近地点"), label: $A.L("选择附近地点"),
placeholder: $A.L("搜索地点"), placeholder: $A.L("搜索地点"),
noresult: $A.L("附近没有找到地点"), noresult: $A.L("附近没有找到地点"),
@ -986,6 +986,7 @@ export default {
selectclose: "true", selectclose: "true",
channel: $A.randomString(6) channel: $A.randomString(6)
} }
$A.eeuiAppSetVariate(`location::${params.channel}`, "");
const url = $A.urlAddParams($A.eeuiAppRewriteUrl('../public/tools/map/index.html'), Object.assign(params, objects || {})) const url = $A.urlAddParams($A.eeuiAppRewriteUrl('../public/tools/map/index.html'), Object.assign(params, objects || {}))
dispatch('openAppChildPage', { dispatch('openAppChildPage', {
pageType: 'app', pageType: 'app',
@ -997,9 +998,12 @@ export default {
url url
}, },
callback: ({status}) => { callback: ({status}) => {
if (status === 'destroy') { if (status === 'pause') {
const data = $A.jsonParse($A.eeuiAppGetVariate(`location::${params.channel}`)); const data = $A.jsonParse($A.eeuiAppGetVariate(`location::${params.channel}`));
resolve(data); if (data.point) {
$A.eeuiAppSetVariate(`location::${params.channel}`, "");
resolve(data);
}
} }
} }
}) })

View File

@ -290,7 +290,9 @@ class BaiduMapPicker {
*/ */
initMap() { initMap() {
// 初始化地图 // 初始化地图
this.map = new BMap.Map('map-container'); this.map = new BMap.Map('map-container', {
enableMapClick: false
});
// 初始化本地搜索,移除地图渲染 // 初始化本地搜索,移除地图渲染
this.localSearch = new BMap.LocalSearch(this.map, { this.localSearch = new BMap.LocalSearch(this.map, {
@ -320,9 +322,7 @@ class BaiduMapPicker {
this.bindEvents(); this.bindEvents();
// 初始化时自动定位 // 初始化时自动定位
Loader.show();
this.getCurrentLocation().then((point) => { this.getCurrentLocation().then((point) => {
Loader.hide();
if (point === null) { if (point === null) {
this.locationError(); this.locationError();
} }
@ -348,10 +348,7 @@ class BaiduMapPicker {
// 地图定位点击事件 // 地图定位点击事件
const mapLocation = document.getElementById('map-location'); const mapLocation = document.getElementById('map-location');
mapLocation.addEventListener('click', () => { mapLocation.addEventListener('click', () => {
Loader.show() this.getCurrentLocation();
this.getCurrentLocation().then(() => {
Loader.hide()
});
}); });
} }
@ -361,7 +358,9 @@ class BaiduMapPicker {
*/ */
getCurrentLocation() { getCurrentLocation() {
return new Promise(resolve => { return new Promise(resolve => {
Loader.show()
App.getLocation().then(res => { App.getLocation().then(res => {
Loader.hide()
if (App.isJson(res) && res.longitude && res.latitude) { if (App.isJson(res) && res.longitude && res.latitude) {
const bd09_coord = CoordTransform.wgs84toBd09(res.longitude, res.latitude); const bd09_coord = CoordTransform.wgs84toBd09(res.longitude, res.latitude);
const point = new BMap.Point(bd09_coord[0], bd09_coord[1]); const point = new BMap.Point(bd09_coord[0], bd09_coord[1]);
@ -381,9 +380,13 @@ class BaiduMapPicker {
*/ */
updateCurrentPoint(point) { updateCurrentPoint(point) {
this.currentPoint = point; this.currentPoint = point;
this.map.centerAndZoom(this.currentPoint, this.params.zoom); if (Math.abs(this.map.getZoom() - this.params.zoom) > 1) {
this.map.centerAndZoom(this.currentPoint, this.params.zoom);
} else {
this.map.setCenter(this.currentPoint);
}
this.updateMarker(this.currentPoint); this.updateMarker(this.currentPoint);
this.searchNearby(); this.searchAddress();
} }
/** /**
@ -403,95 +406,134 @@ class BaiduMapPicker {
* 搜索地址 * 搜索地址
*/ */
searchAddress() { searchAddress() {
const keyword = document.getElementById('search-input').value; const keyword = `${document.getElementById('search-input').value}`.trim();
this.searchNearby(keyword ? [keyword] : []); if (keyword) {
this.searchKeyword(this.currentPoint, keyword);
} else {
this.searchLocation(this.currentPoint);
}
} }
/** /**
* 搜索附近的地点 * 通过关键词搜索附近的地点
* @param keywords * @param centerPoint
* @param keyword
* @param retryCount * @param retryCount
*/ */
searchNearby(keywords = [], retryCount = 0) { searchKeyword(centerPoint, keyword, retryCount = 0) {
// 当前位置未获取
if (this.currentPoint === null) {
return;
}
// 清除之前的搜索结果 // 清除之前的搜索结果
this.localSearch.clearResults(); this.localSearch.clearResults();
// 搜索附近的关键词
if (keywords.length === 0) {
keywords = ["写字楼", "公司", "银行", "餐馆", "商场", "超市", "学校", "医院", "公交站", "地铁站"]
}
// 定义一个随机数,用于判断定时器是否过期 // 定义一个随机数,用于判断定时器是否过期
this.searchRandom = Math.random(); this.searchRandom = Math.random();
// 设置搜索完成回调 // 设置搜索完成回调
Loader.show(); Loader.show();
this.localSearch.setSearchCompleteCallback((results) => { this.localSearch.setSearchCompleteCallback(result => {
Loader.hide(); Loader.hide();
if (this.localSearch.getStatus() !== BMAP_STATUS_SUCCESS) { if (this.localSearch.getStatus() !== BMAP_STATUS_SUCCESS) {
// 搜索失败 // 搜索失败10次重试
if (retryCount < 60) { if (retryCount < 10) {
const tmpRand = this.searchRandom; const tmpRand = this.searchRandom;
Loader.show(); Loader.show();
setTimeout(() => { setTimeout(() => {
Loader.hide(); Loader.hide();
tmpRand === this.searchRandom && this.searchNearby(keywords, ++retryCount); tmpRand === this.searchRandom && this.searchKeyword(centerPoint, keyword, ++retryCount);
}, 1000) }, 300)
return; return;
} }
} }
// 搜索结果 // 搜索结果
document.getElementById('address-list').style.display = 'block'; const pois = [];
const array = []; for (let i = 0; i < result.getCurrentNumPois(); i++) {
if (results instanceof Array) { const poi = result.getPoi(i);
results.some(result => { if (!poi.point) {
if (!result) { continue;
return false; }
} poi.distance = this.params.point ? this.map.getDistance(this.params.point, poi.point) : null;
for (let i = 0; i < result.getCurrentNumPois(); i++) { poi.distance_current = this.map.getDistance(centerPoint, poi.point);
const poi = result.getPoi(i); pois.push(poi);
poi.distance = this.params.point ? this.map.getDistance(this.params.point, poi.point) : null;
array.push(poi);
}
});
} }
this.updatePoiList(array); this.updatePoiList(pois);
}); });
// 执行搜索 // 执行搜索
this.localSearch.searchNearby(keywords, this.currentPoint, this.params.radius); this.localSearch.searchNearby(keyword, centerPoint, this.params.radius);
}
/**
* 通过坐标搜索附近的地点
* @param point
*/
searchLocation(point) {
const geoc = new BMap.Geocoder();
Loader.show();
geoc.getLocation(point, (result) => {
Loader.hide();
const pois = [];
if (result) {
// 搜索结果
const surroundingPois = result.surroundingPois || [];
if (surroundingPois.length === 0) {
surroundingPois.push({
title: result.addressComponents.city + result.addressComponents.district,
address: result.address,
point: result.point,
});
}
surroundingPois.some(poi => {
if (!poi.point) {
return false;
}
poi.distance = this.params.point ? this.map.getDistance(this.params.point, poi.point) : null;
poi.distance_current = this.map.getDistance(point, poi.point);
pois.push(poi);
})
}
this.updatePoiList(pois)
}, {
poiRadius: this.params.radius,
numPois: 20,
});
} }
/** /**
* 更新搜索结果列表 * 更新搜索结果列表
* @param results * @param pois
*/ */
updatePoiList(results) { updatePoiList(pois) {
const addressList = document.getElementById('address-list');
addressList.style.display = 'block';
const poiList = document.getElementById('poi-list'); const poiList = document.getElementById('poi-list');
poiList.innerHTML = ''; poiList.innerHTML = '';
// 如果没有搜索结果 // 如果没有搜索结果
if (results.length === 0 && this.params.noresult) { if (pois.length === 0) {
poiList.innerHTML = '<li>' + this.params.noresult + '</li>'; if (this.params.noresult) {
poiList.innerHTML = '<li><div class="address-noresult">' + this.params.noresult + '</div></li>';
}
return; return;
} }
// 筛选距离小于搜索半径的结果(+100
pois = pois.filter(poi => {
return poi.title && poi.point && poi.distance_current < this.params.radius + 100;
});
// 按距离排序(如果有距离信息) // 按距离排序(如果有距离信息)
results.sort((a, b) => { pois.sort((a, b) => {
if (a.distance && b.distance) { if (a.distance_current && b.distance_current) {
return a.distance - b.distance; return a.distance_current - b.distance_current;
} }
return 0; return 0;
}); });
results = results.slice(0, 20);
// 只显示前20个结果
pois = pois.slice(0, 20);
// 创建列表项 // 创建列表项
results.forEach(poi => { pois.forEach(poi => {
const li = document.createElement('li'); const li = document.createElement('li');
const distanceFormat = poi.distance ? `<div class="address-distance">${this.convertDistance(Math.round(poi.distance))}</div>` : ''; const distanceFormat = poi.distance ? `<div class="address-distance">${this.convertDistance(Math.round(poi.distance))}</div>` : '';
li.innerHTML = ` li.innerHTML = `

View File

@ -29,7 +29,6 @@ body {
.search-box { .search-box {
padding: 10px; padding: 10px;
background: #fff; background: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
position: relative; position: relative;
z-index: 100; z-index: 100;
} }
@ -121,6 +120,7 @@ body {
#poi-list { #poi-list {
list-style: none; list-style: none;
padding-bottom: 10px;
} }
#poi-list li { #poi-list li {
@ -147,8 +147,8 @@ body {
transform: scaleY(0.5); transform: scaleY(0.5);
} }
#poi-list li:hover { #poi-list li:last-child::before {
background: #f5f5f5; display: none;
} }
.address-name { .address-name {