tmap
增加导航
This commit is contained in:
parent
779c2d32c4
commit
044e8371a4
@ -281,6 +281,16 @@ def amap_addr_input():
|
||||
amap_key, amap_key_2 = fleet.get_amap_key()
|
||||
return render_template("amap_addr_input.html", lon=lon, lat=lat, amap_key=amap_key, amap_key_2=amap_key_2)
|
||||
|
||||
@app.route("/tmap_addr_input", methods=['GET', 'POST'])
|
||||
def tmap_addr_input():
|
||||
if request.method == 'POST':
|
||||
postvars = request.form.to_dict()
|
||||
fleet.nav_confirmed(postvars)
|
||||
return redirect(url_for('tmap_addr_input'))
|
||||
else:
|
||||
lon, lat = fleet.get_last_lon_lat()
|
||||
return render_template("tmap_addr_input.html", lon=lon, lat=lat)
|
||||
|
||||
@app.route("/CurrentStep.json", methods=['GET'])
|
||||
def find_CurrentStep():
|
||||
directory = "/data/openpilot/selfdrive/manager/"
|
||||
@ -336,6 +346,34 @@ def store_toggle_values_route():
|
||||
except Exception as e:
|
||||
return jsonify({"error": "Failed to update values", "details": str(e)}), 400
|
||||
|
||||
@app.route("/get_nav_status", methods=['GET'])
|
||||
def get_nav_status():
|
||||
nav_active = fleet.get_nav_active()
|
||||
return jsonify({
|
||||
"active": nav_active
|
||||
})
|
||||
|
||||
@app.route("/get_system_status", methods=['GET'])
|
||||
def get_system_status():
|
||||
nav_active = fleet.get_nav_active()
|
||||
gps_status = fleet.get_gps_status()
|
||||
network_status = fleet.check_network_status()
|
||||
|
||||
return jsonify({
|
||||
"nav_status": {
|
||||
"active": nav_active,
|
||||
"state": "导航中" if nav_active else "待机"
|
||||
},
|
||||
"gps_status": {
|
||||
"active": gps_status["active"],
|
||||
"signal": gps_status["signal"]
|
||||
},
|
||||
"network_status": {
|
||||
"connected": network_status["connected"],
|
||||
"type": network_status["type"]
|
||||
}
|
||||
})
|
||||
|
||||
def main():
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
|
@ -221,9 +221,10 @@ def ffplay_mp4_wrap_process_builder(file_name):
|
||||
)
|
||||
|
||||
def get_nav_active():
|
||||
if params.get("NavDestination", encoding='utf8') is not None:
|
||||
return True
|
||||
else:
|
||||
try:
|
||||
with open('/data/params/d/NavDestination', 'r') as f:
|
||||
return f.read().strip() != ""
|
||||
except:
|
||||
return False
|
||||
|
||||
def get_public_token():
|
||||
@ -244,20 +245,29 @@ def get_amap_key():
|
||||
return (token.strip() if token is not None else None, token2.strip() if token2 is not None else None)
|
||||
|
||||
def get_SearchInput():
|
||||
SearchInput = params.get_int("SearchInput")
|
||||
return SearchInput
|
||||
try:
|
||||
with open('/data/params/d/SearchInput', 'r') as f:
|
||||
return int(f.read())
|
||||
except:
|
||||
return 0
|
||||
|
||||
def get_PrimeType():
|
||||
PrimeType = params.get_int("PrimeType")
|
||||
return PrimeType
|
||||
try:
|
||||
with open('/data/params/d/PrimeType', 'r') as f:
|
||||
return int(f.read())
|
||||
except:
|
||||
return 0
|
||||
|
||||
def get_last_lon_lat():
|
||||
last_pos = params.get("LastGPSPosition")
|
||||
if last_pos:
|
||||
l = json.loads(last_pos)
|
||||
else:
|
||||
return 0.0, 0.0
|
||||
return l["longitude"], l["latitude"]
|
||||
try:
|
||||
with open('/data/params/d/LastGPSPosition', 'r') as f:
|
||||
content = f.read().strip()
|
||||
if content:
|
||||
lat, lon = map(float, content.split(","))
|
||||
return lon, lat
|
||||
except:
|
||||
pass
|
||||
return 116.397128, 39.916527 # 默认北京天安门坐标
|
||||
|
||||
def get_locations():
|
||||
data = params.get("ApiCache_NavDestinations", encoding='utf-8')
|
||||
@ -463,3 +473,30 @@ def store_toggle_values(updated_values):
|
||||
params_memory.put_bool("FrogPilotTogglesUpdated", True)
|
||||
time.sleep(1)
|
||||
params_memory.put_bool("FrogPilotTogglesUpdated", False)
|
||||
|
||||
def get_gps_status():
|
||||
try:
|
||||
# 读取GPS状态
|
||||
with open('/data/params/d/LastGPSPosition', 'r') as f:
|
||||
content = f.read().strip()
|
||||
if not content:
|
||||
return {"active": False, "signal": "无信号"}
|
||||
return {
|
||||
"active": True,
|
||||
"signal": "正常"
|
||||
}
|
||||
except:
|
||||
return {"active": False, "signal": "未知"}
|
||||
|
||||
def check_network_status():
|
||||
try:
|
||||
# 检查网络连接
|
||||
result = subprocess.run(['ping', '-c', '1', '-W', '1', '8.8.8.8'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
return {
|
||||
"connected": result.returncode == 0,
|
||||
"type": "已连接" if result.returncode == 0 else "未连接"
|
||||
}
|
||||
except:
|
||||
return {"connected": False, "type": "未知"}
|
||||
|
@ -1,16 +1,146 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
Home
|
||||
Fleet Manager 主页
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<br>
|
||||
<h1>Fleet Manager</h1>
|
||||
<br>
|
||||
<a href='/footage'>View Dashcam Footage</a><br>
|
||||
<br><a href='/preserved'>Access Preserved Footage</a><br>
|
||||
<br><a href='/screenrecords'>View Screen Recordings</a><br>
|
||||
<br><a href='/error_logs'>Access Error Logs</a><br>
|
||||
<br><a href='/about'>About Fleet Manager</a><br>
|
||||
<!-- UIkit CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/css/uikit.min.css" />
|
||||
<!-- UIkit JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit-icons.min.js"></script>
|
||||
|
||||
<div class="uk-container uk-container-small">
|
||||
<h1 class="uk-heading-medium uk-text-center uk-margin-medium-top">Fleet Manager</h1>
|
||||
|
||||
<!-- 导航部分 -->
|
||||
<div class="uk-card uk-card-default uk-card-body uk-margin-medium">
|
||||
<h3 class="uk-card-title">导航服务</h3>
|
||||
<div class="uk-grid-small uk-child-width-1-2@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<a href="/addr_input" class="uk-button uk-button-primary uk-width-1-1">
|
||||
<span uk-icon="location"></span> 地址输入导航
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/amap_addr_input" class="uk-button uk-button-primary uk-width-1-1">
|
||||
<span uk-icon="location"></span> 高德地图导航
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/tmap_addr_input" class="uk-button uk-button-primary uk-width-1-1">
|
||||
<span uk-icon="location"></span> 腾讯地图导航
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/tools" class="uk-button uk-button-secondary uk-width-1-1">
|
||||
<span uk-icon="settings"></span> 系统设置
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视频和日志部分 -->
|
||||
<div class="uk-card uk-card-default uk-card-body uk-margin-medium">
|
||||
<h3 class="uk-card-title">视频和日志</h3>
|
||||
<div class="uk-grid-small uk-child-width-1-2@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<div class="uk-card uk-card-default uk-card-body uk-box-shadow-small">
|
||||
<h4>视频记录</h4>
|
||||
<a href="/footage" class="uk-button uk-button-default uk-width-1-1 uk-margin-small-bottom">
|
||||
<span uk-icon="video-camera"></span> 查看行车记录
|
||||
</a>
|
||||
<a href="/preserved" class="uk-button uk-button-default uk-width-1-1 uk-margin-small-bottom">
|
||||
<span uk-icon="album"></span> 已保存视频
|
||||
</a>
|
||||
<a href="/screenrecords" class="uk-button uk-button-default uk-width-1-1">
|
||||
<span uk-icon="desktop"></span> 屏幕录制
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="uk-card uk-card-default uk-card-body uk-box-shadow-small">
|
||||
<h4>系统日志</h4>
|
||||
<a href="/error_logs" class="uk-button uk-button-default uk-width-1-1 uk-margin-small-bottom">
|
||||
<span uk-icon="warning"></span> 错误日志
|
||||
</a>
|
||||
<a href="/about" class="uk-button uk-button-default uk-width-1-1">
|
||||
<span uk-icon="info"></span> 关于系统
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统状态部分 -->
|
||||
<div class="uk-card uk-card-default uk-card-body uk-margin-medium">
|
||||
<h3 class="uk-card-title">系统状态</h3>
|
||||
<div id="system-status" class="uk-grid-small uk-child-width-1-3@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<div class="uk-card uk-card-default uk-card-body uk-box-shadow-small">
|
||||
<h4>导航状态</h4>
|
||||
<div id="nav-status">
|
||||
<span class="uk-label uk-label-warning">待机</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="uk-card uk-card-default uk-card-body uk-box-shadow-small">
|
||||
<h4>GPS信号</h4>
|
||||
<div id="gps-status">
|
||||
<span class="uk-label uk-label-warning">检测中</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="uk-card uk-card-default uk-card-body uk-box-shadow-small">
|
||||
<h4>网络状态</h4>
|
||||
<div id="network-status">
|
||||
<span class="uk-label uk-label-warning">检测中</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 定期更新系统状态
|
||||
function updateSystemStatus() {
|
||||
fetch('/get_system_status')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// 更新导航状态
|
||||
document.getElementById('nav-status').innerHTML =
|
||||
`<span class="uk-label ${data.nav_status.active ? 'uk-label-success' : 'uk-label-warning'}">
|
||||
${data.nav_status.state}
|
||||
</span>`;
|
||||
|
||||
// 更新GPS状态
|
||||
document.getElementById('gps-status').innerHTML =
|
||||
`<span class="uk-label ${data.gps_status.active ? 'uk-label-success' : 'uk-label-warning'}">
|
||||
${data.gps_status.signal}
|
||||
</span>`;
|
||||
|
||||
// 更新网络状态
|
||||
document.getElementById('network-status').innerHTML =
|
||||
`<span class="uk-label ${data.network_status.connected ? 'uk-label-success' : 'uk-label-warning'}">
|
||||
${data.network_status.type}
|
||||
</span>`;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
// 发生错误时显示错误状态
|
||||
['nav-status', 'gps-status', 'network-status'].forEach(id => {
|
||||
document.getElementById(id).innerHTML =
|
||||
`<span class="uk-label uk-label-danger">错误</span>`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 每5秒更新一次状态
|
||||
setInterval(updateSystemStatus, 5000);
|
||||
updateSystemStatus(); // 初始更新
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
680
selfdrive/frogpilot/fleetmanager/templates/tmap_addr_input.html
Normal file
680
selfdrive/frogpilot/fleetmanager/templates/tmap_addr_input.html
Normal file
@ -0,0 +1,680 @@
|
||||
{% extends "layout.html" %}
|
||||
|
||||
{% block title %}
|
||||
腾讯地图导航
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<title>地点搜索与导航</title>
|
||||
<!-- UIkit CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/css/uikit.min.css" />
|
||||
<!-- UIkit JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit-icons.min.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#mapContainer {
|
||||
width: 100%;
|
||||
height: 80vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
background: white;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.search-results {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
z-index: 998;
|
||||
background: white;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.search-result-item {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-result-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="search-box">
|
||||
<div class="uk-grid-small" uk-grid>
|
||||
<div class="uk-width-1-4">
|
||||
<select id="save_type" class="uk-select">
|
||||
<option value="recent">最近</option>
|
||||
<option value="home">住家</option>
|
||||
<option value="work">工作</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="uk-width-expand">
|
||||
<div class="uk-inline uk-width-1-1">
|
||||
<span class="uk-form-icon" uk-icon="icon: search"></span>
|
||||
<input class="uk-input" type="text" id="keyword"
|
||||
placeholder="请输入关键字搜索地点"
|
||||
autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-width-auto">
|
||||
<button class="uk-button uk-button-primary" onclick="searchPlace(document.getElementById('keyword').value)">
|
||||
<span uk-icon="icon: search"></span> 搜索
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uk-margin-small-top">
|
||||
<button class="uk-button uk-button-default uk-button-small" onclick="locateUser()">
|
||||
<span uk-icon="icon: location"></span> 定位
|
||||
</button>
|
||||
<button class="uk-button uk-button-default uk-button-small" onclick="showSearchHistory()">
|
||||
<span uk-icon="icon: history"></span> 历史记录
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="search-results" class="search-results"></div>
|
||||
<div id="mapContainer"></div>
|
||||
|
||||
<!-- 更改腾讯地图API引入方式,增加passive参数,可能会减少一些警告 -->
|
||||
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&key=BDMBZ-LZQ63-GUG37-OCHES-2ESXV-Q5BVC&libraries=geometry"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var map, marker, infoWindow;
|
||||
var searchTimeout;
|
||||
var searchMarkers = [];
|
||||
var initialPosition;
|
||||
|
||||
// 修复标记图片URL问题 - 使用腾讯地图官方正确的图标URL
|
||||
var markerIconDefault = 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/marker.png';
|
||||
var markerIconSelected = 'https://mapapi.qq.com/web/lbs/javascriptV2/javascript/img/marker_red.png';
|
||||
var markerIconSearch = 'https://mapapi.qq.com/web/lbs/javascriptV2/javascript/img/marker_blue.png';
|
||||
|
||||
// 初始化地图
|
||||
function initMap() {
|
||||
// 修复Jinja变量语法,避免JavaScript解析错误
|
||||
initialPosition = new TMap.LatLng(Number("{{lat}}"), Number("{{lon}}"));
|
||||
|
||||
map = new TMap.Map('mapContainer', {
|
||||
center: initialPosition,
|
||||
zoom: 15,
|
||||
showControl: true,
|
||||
viewMode: '2D' // 明确指定2D模式,可能会减少一些警告
|
||||
});
|
||||
|
||||
// 添加当前位置标记 - 使用正确的图标URL
|
||||
marker = new TMap.MultiMarker({
|
||||
map: map,
|
||||
styles: {
|
||||
"marker": new TMap.MarkerStyle({
|
||||
width: 25,
|
||||
height: 35,
|
||||
anchor: { x: 12.5, y: 35 },
|
||||
src: markerIconDefault
|
||||
}),
|
||||
"selected": new TMap.MarkerStyle({
|
||||
width: 30,
|
||||
height: 42,
|
||||
anchor: { x: 15, y: 42 },
|
||||
src: markerIconSelected
|
||||
}),
|
||||
"searchResult": new TMap.MarkerStyle({
|
||||
width: 25,
|
||||
height: 35,
|
||||
anchor: { x: 12.5, y: 35 },
|
||||
src: markerIconSearch
|
||||
})
|
||||
},
|
||||
geometries: [{
|
||||
id: 'current',
|
||||
position: initialPosition,
|
||||
styleId: 'marker'
|
||||
}]
|
||||
});
|
||||
|
||||
// 添加点击事件
|
||||
map.on('click', handleMapClick);
|
||||
|
||||
// 初始化搜索服务
|
||||
initSearchService();
|
||||
}
|
||||
|
||||
// 初始化搜索服务和联想功能
|
||||
function initSearchService() {
|
||||
// 监听输入框,实现联想搜索
|
||||
var inputElement = document.getElementById('keyword');
|
||||
|
||||
inputElement.addEventListener('input', function() {
|
||||
var keyword = this.value.trim();
|
||||
if (keyword) {
|
||||
clearTimeout(searchTimeout);
|
||||
searchTimeout = setTimeout(function() {
|
||||
searchSuggestion(keyword);
|
||||
}, 300);
|
||||
} else {
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// 防止表单提交刷新页面
|
||||
inputElement.form && inputElement.form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
searchPlace(inputElement.value);
|
||||
});
|
||||
}
|
||||
|
||||
// 处理地图点击
|
||||
function handleMapClick(evt) {
|
||||
var position = evt.latLng;
|
||||
|
||||
// 清除搜索结果
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
|
||||
// 更新标记位置
|
||||
marker.updateGeometries([{
|
||||
id: 'current',
|
||||
position: position,
|
||||
styleId: 'marker'
|
||||
}]);
|
||||
|
||||
// 对于地图点击,设置一个默认地名 "选定位置"
|
||||
var coordsText = "(" + position.lat.toFixed(6) + ", " + position.lng.toFixed(6) + ")";
|
||||
showInfoWindow(position, "选定位置", coordsText);
|
||||
}
|
||||
|
||||
// 显示信息窗口 - 使用搜索框文本作为地名
|
||||
function showInfoWindow(position, name, addr) {
|
||||
if (infoWindow) {
|
||||
infoWindow.close();
|
||||
}
|
||||
|
||||
// 获取搜索框的值作为地名
|
||||
var searchText = document.getElementById('keyword').value.trim();
|
||||
var placeName = searchText || name || "选定位置";
|
||||
|
||||
// 调试输出
|
||||
console.log("显示信息窗口,搜索框文本:", searchText, "名称:", name, "地址:", addr, "使用地名:", placeName);
|
||||
|
||||
infoWindow = new TMap.InfoWindow({
|
||||
map: map,
|
||||
position: position,
|
||||
content: `
|
||||
<div class="uk-card uk-card-default uk-card-body" style="padding:10px; min-width:200px;">
|
||||
<a class="uk-card-badge uk-label" onClick="javascript:infoWindow.close()" uk-close></a>
|
||||
<h3 style="padding-top: 10px;" class="uk-card-title">${name || ""}</h3>
|
||||
<p>${addr || ""}</p>
|
||||
<div class="uk-card-footer" style="padding-top:10px;">
|
||||
<form name="navForm" method="post">
|
||||
<input type="hidden" name="lat" value="${position.lat}">
|
||||
<input type="hidden" name="lon" value="${position.lng}">
|
||||
<input type="hidden" name="save_type" value="${document.getElementById('save_type').value}">
|
||||
<input type="hidden" name="place_name" value="${placeName}">
|
||||
<input class="uk-button uk-button-primary" type="submit" value="导航" onclick="console.log('导航表单提交,地点名:', '${placeName}')">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
offset: { x: 0, y: -35 }
|
||||
});
|
||||
}
|
||||
|
||||
// 修改搜索联想函数,添加错误处理
|
||||
function searchSuggestion(keyword) {
|
||||
console.log("搜索联想:", keyword);
|
||||
|
||||
// 避免使用可能导致跨域问题的XMLHttpRequest
|
||||
// 直接使用JSONP方法,这是最可靠的
|
||||
var script = document.createElement('script');
|
||||
var callbackName = 'jsonp_suggestion_' + Math.round(100000 * Math.random());
|
||||
|
||||
window[callbackName] = function(res) {
|
||||
console.log("联想搜索结果:", res);
|
||||
if (script.parentNode) document.body.removeChild(script);
|
||||
delete window[callbackName];
|
||||
|
||||
if (res.status === 0 && res.data && res.data.length > 0) {
|
||||
showSuggestionResults(res.data);
|
||||
} else {
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
var suggestUrl = "https://apis.map.qq.com/ws/place/v1/suggestion?keyword=" +
|
||||
encodeURIComponent(keyword) +
|
||||
"&key=BDMBZ-LZQ63-GUG37-OCHES-2ESXV-Q5BVC&output=jsonp&callback=" + callbackName;
|
||||
|
||||
script.src = suggestUrl;
|
||||
document.body.appendChild(script);
|
||||
|
||||
// 添加超时处理
|
||||
setTimeout(function() {
|
||||
if (window[callbackName]) {
|
||||
console.error("联想搜索请求超时");
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
if (script.parentNode) document.body.removeChild(script);
|
||||
delete window[callbackName];
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// 显示搜索联想结果
|
||||
function showSuggestionResults(results) {
|
||||
var container = document.getElementById('search-results');
|
||||
container.innerHTML = '';
|
||||
|
||||
if (results && results.length > 0) {
|
||||
results.forEach(function(result) {
|
||||
var div = document.createElement('div');
|
||||
div.className = 'search-result-item';
|
||||
div.innerHTML = `
|
||||
<div class="uk-text-bold">${result.title}</div>
|
||||
<div class="uk-text-small uk-text-muted">${result.address || ''}</div>
|
||||
`;
|
||||
|
||||
div.onclick = function() {
|
||||
// 获取详细信息
|
||||
getPlaceDetail(result.id);
|
||||
};
|
||||
|
||||
container.appendChild(div);
|
||||
});
|
||||
|
||||
container.style.display = 'block';
|
||||
} else {
|
||||
container.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// 修改搜索函数,添加错误处理
|
||||
function searchPlace(keyword) {
|
||||
if (!keyword || keyword.trim() === '') {
|
||||
UIkit.notification({
|
||||
message: '请输入搜索关键词',
|
||||
status: 'warning',
|
||||
pos: 'top-center',
|
||||
timeout: 3000
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示加载提示和调试信息
|
||||
console.log("开始搜索:", keyword);
|
||||
UIkit.notification({
|
||||
message: '正在搜索...',
|
||||
status: 'primary',
|
||||
pos: 'top-center',
|
||||
timeout: 2000
|
||||
});
|
||||
|
||||
// 使用唯一的回调函数名称避免冲突
|
||||
var callbackName = 'jsonp_search_' + Math.round(100000 * Math.random());
|
||||
var script = document.createElement('script');
|
||||
|
||||
window[callbackName] = function(res) {
|
||||
console.log("搜索结果:", res);
|
||||
if (script.parentNode) document.body.removeChild(script);
|
||||
delete window[callbackName];
|
||||
|
||||
if (res.status === 0 && res.data && res.data.length > 0) {
|
||||
// 转换返回的数据格式
|
||||
var places = res.data.map(function(item) {
|
||||
return {
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
address: item.address,
|
||||
location: {
|
||||
lat: item.location.lat,
|
||||
lng: item.location.lng
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// 显示搜索结果列表
|
||||
showSearchResults(places);
|
||||
|
||||
// 在地图上显示多个标记点
|
||||
showMultipleMarkers(places);
|
||||
|
||||
// 调整地图视野以包含所有结果
|
||||
fitMapToBounds(places);
|
||||
} else {
|
||||
UIkit.notification({
|
||||
message: '未找到相关结果',
|
||||
status: 'warning',
|
||||
pos: 'top-center',
|
||||
timeout: 3000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var searchUrl = "https://apis.map.qq.com/ws/place/v1/search?keyword=" +
|
||||
encodeURIComponent(keyword) +
|
||||
"&boundary=region(全国,0)" +
|
||||
"&page_size=10" +
|
||||
"&page_index=1" +
|
||||
"&key=BDMBZ-LZQ63-GUG37-OCHES-2ESXV-Q5BVC&output=jsonp&callback=" + callbackName;
|
||||
|
||||
script.src = searchUrl;
|
||||
document.body.appendChild(script);
|
||||
|
||||
// 添加超时处理
|
||||
setTimeout(function() {
|
||||
if (window[callbackName]) {
|
||||
console.error("搜索请求超时");
|
||||
UIkit.notification({
|
||||
message: '搜索超时,请重试',
|
||||
status: 'danger',
|
||||
pos: 'top-center',
|
||||
timeout: 3000
|
||||
});
|
||||
if (script.parentNode) document.body.removeChild(script);
|
||||
delete window[callbackName];
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// 修改获取地点详情函数
|
||||
function getPlaceDetail(id) {
|
||||
var detailUrl = "https://apis.map.qq.com/ws/place/v1/detail?id=" +
|
||||
encodeURIComponent(id) +
|
||||
"&key=BDMBZ-LZQ63-GUG37-OCHES-2ESXV-Q5BVC&output=jsonp&callback=detailCallback";
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = detailUrl;
|
||||
document.body.appendChild(script);
|
||||
|
||||
// 定义全局回调函数
|
||||
window.detailCallback = function(res) {
|
||||
console.log("地点详情:", res);
|
||||
document.body.removeChild(script);
|
||||
|
||||
if (res.status === 0 && res.data) {
|
||||
// 转换数据格式
|
||||
var place = {
|
||||
id: res.data.id,
|
||||
title: res.data.title,
|
||||
address: res.data.address,
|
||||
location: {
|
||||
lat: res.data.location.lat,
|
||||
lng: res.data.location.lng
|
||||
}
|
||||
};
|
||||
|
||||
selectPlace(place);
|
||||
} else {
|
||||
UIkit.notification({
|
||||
message: '获取地点详情失败',
|
||||
status: 'danger',
|
||||
pos: 'top-center',
|
||||
timeout: 3000
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 选择地点
|
||||
function selectPlace(place) {
|
||||
var position = new TMap.LatLng(place.location.lat, place.location.lng);
|
||||
|
||||
// 更新地图视图
|
||||
map.setCenter(position);
|
||||
map.setZoom(16);
|
||||
|
||||
// 更新标记
|
||||
marker.updateGeometries([{
|
||||
id: 'current',
|
||||
position: position,
|
||||
styleId: 'selected'
|
||||
}]);
|
||||
|
||||
// 显示信息窗口
|
||||
showInfoWindow(position, place.title, place.address);
|
||||
|
||||
// 保存到历史记录
|
||||
saveSearchHistory(place);
|
||||
|
||||
// 隐藏搜索结果
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
}
|
||||
|
||||
// 在地图上显示多个标记点 - 修复图标URL
|
||||
function showMultipleMarkers(places) {
|
||||
// 清除之前的搜索结果标记
|
||||
clearSearchMarkers();
|
||||
console.log("显示多个标记点:", places.length);
|
||||
|
||||
// 准备新的标记点数据
|
||||
var geometries = [];
|
||||
|
||||
places.forEach(function(place, index) {
|
||||
// 确保所有必要属性存在
|
||||
if (!place.location || !place.location.lat || !place.location.lng) {
|
||||
console.error("地点数据不完整:", place);
|
||||
return;
|
||||
}
|
||||
|
||||
var position = new TMap.LatLng(place.location.lat, place.location.lng);
|
||||
|
||||
geometries.push({
|
||||
id: 'search_' + index,
|
||||
position: position,
|
||||
styleId: 'searchResult',
|
||||
properties: {
|
||||
title: place.title || "",
|
||||
address: place.address || ""
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log("创建几何标记:", geometries.length);
|
||||
|
||||
// 创建新的标记点图层 - 使用正确的图标URL
|
||||
if (geometries.length > 0) {
|
||||
try {
|
||||
var searchResultMarker = new TMap.MultiMarker({
|
||||
map: map,
|
||||
styles: {
|
||||
"searchResult": new TMap.MarkerStyle({
|
||||
width: 25,
|
||||
height: 35,
|
||||
anchor: { x: 12.5, y: 35 },
|
||||
src: markerIconSearch
|
||||
})
|
||||
},
|
||||
geometries: geometries
|
||||
});
|
||||
|
||||
// 添加点击事件
|
||||
searchResultMarker.on('click', function(evt) {
|
||||
var properties = evt.geometry.properties;
|
||||
var position = evt.geometry.position;
|
||||
|
||||
// 显示信息窗口
|
||||
showInfoWindow(position, properties.title, properties.address);
|
||||
|
||||
// 更新当前选中标记
|
||||
marker.updateGeometries([{
|
||||
id: 'current',
|
||||
position: position,
|
||||
styleId: 'selected'
|
||||
}]);
|
||||
});
|
||||
|
||||
// 保存到搜索标记数组
|
||||
searchMarkers.push(searchResultMarker);
|
||||
console.log("标记创建成功");
|
||||
} catch (error) {
|
||||
console.error("创建标记时出错:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清除搜索结果标记
|
||||
function clearSearchMarkers() {
|
||||
searchMarkers.forEach(function(markerLayer) {
|
||||
markerLayer.setMap(null);
|
||||
});
|
||||
searchMarkers = [];
|
||||
}
|
||||
|
||||
// 调整地图视野以包含所有结果
|
||||
function fitMapToBounds(places) {
|
||||
if (!places || places.length === 0) return;
|
||||
|
||||
// 如果只有一个结果,直接定位到该位置
|
||||
if (places.length === 1) {
|
||||
var position = new TMap.LatLng(places[0].location.lat, places[0].location.lng);
|
||||
map.setCenter(position);
|
||||
map.setZoom(16);
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算包含所有结果的视野范围
|
||||
var bounds = new TMap.LatLngBounds();
|
||||
places.forEach(function(place) {
|
||||
bounds.extend(new TMap.LatLng(place.location.lat, place.location.lng));
|
||||
});
|
||||
|
||||
// 设置地图视野
|
||||
map.fitBounds(bounds, {
|
||||
padding: 100 // 设置边距,避免标记点太靠近边缘
|
||||
});
|
||||
}
|
||||
|
||||
// 显示搜索结果 - 修复版本
|
||||
function showSearchResults(results) {
|
||||
console.log("显示搜索结果列表:", results.length);
|
||||
|
||||
var container = document.getElementById('search-results');
|
||||
container.innerHTML = '';
|
||||
|
||||
if (results && results.length > 0) {
|
||||
results.forEach(function(result) {
|
||||
var div = document.createElement('div');
|
||||
div.className = 'search-result-item';
|
||||
div.innerHTML = `
|
||||
<div class="uk-text-bold">${result.title || ""}</div>
|
||||
<div class="uk-text-small uk-text-muted">${result.address || ""}</div>
|
||||
`;
|
||||
|
||||
div.onclick = function() {
|
||||
selectSearchResult(result);
|
||||
};
|
||||
|
||||
container.appendChild(div);
|
||||
});
|
||||
|
||||
container.style.display = 'block';
|
||||
} else {
|
||||
container.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// 添加用户定位功能
|
||||
function locateUser() {
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
const userPosition = new TMap.LatLng(position.coords.latitude, position.coords.longitude);
|
||||
map.setCenter(userPosition);
|
||||
marker.updateGeometries([{
|
||||
id: 'current',
|
||||
position: userPosition,
|
||||
styleId: 'selected'
|
||||
}]);
|
||||
},
|
||||
(error) => {
|
||||
UIkit.notification({
|
||||
message: '无法获取您的位置,请检查位置权限',
|
||||
status: 'warning',
|
||||
pos: 'top-center',
|
||||
timeout: 3000
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
UIkit.notification({
|
||||
message: '您的浏览器不支持地理定位',
|
||||
status: 'danger',
|
||||
pos: 'top-center',
|
||||
timeout: 3000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 添加历史记录功能
|
||||
function saveSearchHistory(item) {
|
||||
let history = JSON.parse(localStorage.getItem('searchHistory') || '[]');
|
||||
// 避免重复添加
|
||||
history = history.filter(h => h.title !== item.title);
|
||||
history.unshift(item);
|
||||
// 最多保存10条记录
|
||||
if (history.length > 10) history.pop();
|
||||
localStorage.setItem('searchHistory', JSON.stringify(history));
|
||||
}
|
||||
|
||||
function showSearchHistory() {
|
||||
const history = JSON.parse(localStorage.getItem('searchHistory') || '[]');
|
||||
if (history.length > 0) {
|
||||
showSearchResults(history);
|
||||
}
|
||||
}
|
||||
|
||||
// 选择搜索结果 - 确保title正确传递
|
||||
function selectSearchResult(result) {
|
||||
// 调试输出
|
||||
console.log("选择搜索结果:", result);
|
||||
|
||||
const position = new TMap.LatLng(result.location.lat, result.location.lng);
|
||||
|
||||
// 更新地图视图
|
||||
map.setCenter(position);
|
||||
map.setZoom(16);
|
||||
|
||||
// 更新标记
|
||||
marker.updateGeometries([{
|
||||
id: 'current',
|
||||
position: position,
|
||||
styleId: 'selected'
|
||||
}]);
|
||||
|
||||
// 确保传递完整的title和address
|
||||
showInfoWindow(position, result.title || "", result.address || "");
|
||||
|
||||
// 保存到历史记录
|
||||
saveSearchHistory(result);
|
||||
|
||||
// 隐藏搜索结果
|
||||
document.getElementById('search-results').style.display = 'none';
|
||||
}
|
||||
|
||||
// 初始化地图
|
||||
initMap();
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user