增加导航
This commit is contained in:
机械小鸽 2025-03-28 23:54:06 +08:00 committed by GitHub
parent 779c2d32c4
commit 044e8371a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 907 additions and 22 deletions

View File

@ -281,6 +281,16 @@ def amap_addr_input():
amap_key, amap_key_2 = fleet.get_amap_key() 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) 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']) @app.route("/CurrentStep.json", methods=['GET'])
def find_CurrentStep(): def find_CurrentStep():
directory = "/data/openpilot/selfdrive/manager/" directory = "/data/openpilot/selfdrive/manager/"
@ -336,6 +346,34 @@ def store_toggle_values_route():
except Exception as e: except Exception as e:
return jsonify({"error": "Failed to update values", "details": str(e)}), 400 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(): def main():
try: try:
set_core_affinity([0, 1, 2, 3]) set_core_affinity([0, 1, 2, 3])

View File

@ -221,9 +221,10 @@ def ffplay_mp4_wrap_process_builder(file_name):
) )
def get_nav_active(): def get_nav_active():
if params.get("NavDestination", encoding='utf8') is not None: try:
return True with open('/data/params/d/NavDestination', 'r') as f:
else: return f.read().strip() != ""
except:
return False return False
def get_public_token(): 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) return (token.strip() if token is not None else None, token2.strip() if token2 is not None else None)
def get_SearchInput(): def get_SearchInput():
SearchInput = params.get_int("SearchInput") try:
return SearchInput with open('/data/params/d/SearchInput', 'r') as f:
return int(f.read())
except:
return 0
def get_PrimeType(): def get_PrimeType():
PrimeType = params.get_int("PrimeType") try:
return PrimeType with open('/data/params/d/PrimeType', 'r') as f:
return int(f.read())
except:
return 0
def get_last_lon_lat(): def get_last_lon_lat():
last_pos = params.get("LastGPSPosition") try:
if last_pos: with open('/data/params/d/LastGPSPosition', 'r') as f:
l = json.loads(last_pos) content = f.read().strip()
else: if content:
return 0.0, 0.0 lat, lon = map(float, content.split(","))
return l["longitude"], l["latitude"] return lon, lat
except:
pass
return 116.397128, 39.916527 # 默认北京天安门坐标
def get_locations(): def get_locations():
data = params.get("ApiCache_NavDestinations", encoding='utf-8') data = params.get("ApiCache_NavDestinations", encoding='utf-8')
@ -463,3 +473,30 @@ def store_toggle_values(updated_values):
params_memory.put_bool("FrogPilotTogglesUpdated", True) params_memory.put_bool("FrogPilotTogglesUpdated", True)
time.sleep(1) time.sleep(1)
params_memory.put_bool("FrogPilotTogglesUpdated", False) 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": "未知"}

View File

@ -1,16 +1,146 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %} {% block title %}
Home Fleet Manager 主页
{% endblock %} {% endblock %}
{% block main %} {% block main %}
<br> <!-- UIkit CSS -->
<h1>Fleet Manager</h1> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/css/uikit.min.css" />
<br> <!-- UIkit JS -->
<a href='/footage'>View Dashcam Footage</a><br> <script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit.min.js"></script>
<br><a href='/preserved'>Access Preserved Footage</a><br> <script src="https://cdn.jsdelivr.net/npm/uikit@3.9.2/dist/js/uikit-icons.min.js"></script>
<br><a href='/screenrecords'>View Screen Recordings</a><br>
<br><a href='/error_logs'>Access Error Logs</a><br> <div class="uk-container uk-container-small">
<br><a href='/about'>About Fleet Manager</a><br> <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 %} {% endblock %}

View 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 %}