2025-11-03 12:30:37 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view>
|
2025-11-04 15:16:22 +08:00
|
|
|
|
<uni-popup ref="visible">
|
|
|
|
|
|
<view style="position: relative;height: 100vh;width: 100vw;">
|
|
|
|
|
|
<!-- 搜索容器 -->
|
|
|
|
|
|
<view class="search-container">
|
|
|
|
|
|
<!-- 搜索区域 -->
|
|
|
|
|
|
<view class="search-area">
|
|
|
|
|
|
<!-- 搜索框带图标 -->
|
|
|
|
|
|
<view class="search-input-wrapper">
|
|
|
|
|
|
<!-- <u-icon name="search" class="search-icon" size="28rpx" color="#999999"></u-icon> -->
|
|
|
|
|
|
<input
|
|
|
|
|
|
v-model="placeInput"
|
|
|
|
|
|
@focus="onInputFocus"
|
|
|
|
|
|
@blur="onInputBlur"
|
|
|
|
|
|
@input="onInputChange"
|
|
|
|
|
|
placeholder="请输入并选择相应地点"
|
|
|
|
|
|
placeholder-style="color: #CCCCCC"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
@clear="onInputClear"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<!-- 搜索加载动画 -->
|
|
|
|
|
|
<!-- <u-loading v-if="isSearching" size="24rpx" class="search-loading"></u-loading> -->
|
2025-11-03 12:30:37 +08:00
|
|
|
|
</view>
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 搜索历史记录 -->
|
|
|
|
|
|
<!-- <view v-if="showHistory && placeInput === ''" class="search-history">
|
|
|
|
|
|
<view class="history-title">搜索历史</view>
|
|
|
|
|
|
<view class="history-list">
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in searchHistory"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
class="history-item"
|
|
|
|
|
|
@tap="searchHistoryItem(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<u-icon name="clock" size="24rpx" color="#999999" class="history-icon"></u-icon>
|
|
|
|
|
|
<text>{{ item }}</text>
|
|
|
|
|
|
添加单个删除按钮
|
|
|
|
|
|
<u-icon
|
|
|
|
|
|
name="close"
|
|
|
|
|
|
size="24rpx"
|
|
|
|
|
|
color="#CCCCCC"
|
|
|
|
|
|
class="delete-icon"
|
|
|
|
|
|
@tap.stop="deleteHistoryItem(index)"
|
|
|
|
|
|
></u-icon>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-if="searchHistory.length === 0" class="empty-history">暂无搜索记录</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view> -->
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 热门搜索 -->
|
|
|
|
|
|
<view v-if="showHotSearch && placeInput === '' && !showHistory" class="hot-search">
|
|
|
|
|
|
<view class="hot-title">热门搜索</view>
|
|
|
|
|
|
<view class="hot-tags">
|
|
|
|
|
|
<view v-for="(tag, index) in hotSearchTags" :key="index" class="hot-tag" @tap="searchHotTag(tag)">
|
|
|
|
|
|
{{ tag }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 已选择的地点 -->
|
|
|
|
|
|
<view v-if="checkedMarker && checkedMarker.name" class="selected">
|
|
|
|
|
|
<view class="selected-content">
|
|
|
|
|
|
|
|
|
|
|
|
<text class="selected-text">您已选择:{{ checkedMarker.name }}</text>
|
|
|
|
|
|
<text v-if="checkedMarker.address" class="selected-address">({{ checkedMarker.address }})</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="clear-btn" @tap="resetSelection">清除</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 搜索结果列表 -->
|
|
|
|
|
|
<view v-if="placeList.length > 0" class="search-results">
|
|
|
|
|
|
<view class="results-title">找到 {{ placeList.length }} 个相关地点</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in placeList"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
class="place-item"
|
|
|
|
|
|
@tap="addIcon(item.name)"
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="item-content">
|
|
|
|
|
|
<view class="item-name">{{ item.name }}</view>
|
|
|
|
|
|
<view class="item-address">{{ item.address }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<!-- <u-icon name="arrow-right" size="24rpx" color="#CCCCCC" class="item-arrow"></u-icon> -->
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 无结果提示 -->
|
|
|
|
|
|
|
2025-11-03 12:30:37 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 地图组件 -->
|
|
|
|
|
|
<map
|
|
|
|
|
|
id="map"
|
|
|
|
|
|
class="map"
|
|
|
|
|
|
:latitude="mapCenter.latitude"
|
|
|
|
|
|
:longitude="mapCenter.longitude"
|
|
|
|
|
|
:markers="markers"
|
|
|
|
|
|
:scale="15"
|
|
|
|
|
|
show-location
|
|
|
|
|
|
@markertap="onMarkerTap"
|
|
|
|
|
|
@regionchange="onRegionChange"
|
|
|
|
|
|
@tap="onMapTap"
|
|
|
|
|
|
></map>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部按钮 -->
|
2025-11-03 12:30:37 +08:00
|
|
|
|
<view class="button-area">
|
2025-11-04 15:16:22 +08:00
|
|
|
|
<view class="btn" @tap="cancel">取 消</view>
|
|
|
|
|
|
<view class="btn save" @tap="submitForm">确 定</view>
|
2025-11-03 12:30:37 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-11-04 15:16:22 +08:00
|
|
|
|
</uni-popup>
|
2025-11-03 12:30:37 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-11-04 15:16:22 +08:00
|
|
|
|
// 请修改saveToSearchHistory和loadSearchHistory方法,添加异常处理
|
2025-11-03 12:30:37 +08:00
|
|
|
|
export default {
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
placeList: [],
|
|
|
|
|
|
placeInput: '',
|
|
|
|
|
|
checkedMarker: '',
|
|
|
|
|
|
visible: false,
|
2025-11-04 15:16:22 +08:00
|
|
|
|
// 地图中心点(济南市)
|
|
|
|
|
|
mapCenter: {
|
|
|
|
|
|
latitude: 36.657017,
|
|
|
|
|
|
longitude: 117.123237
|
|
|
|
|
|
},
|
|
|
|
|
|
// 地图标记点
|
|
|
|
|
|
markers: [],
|
|
|
|
|
|
// 当前选中的标记点
|
|
|
|
|
|
currentMarker: null,
|
|
|
|
|
|
// 搜索状态
|
|
|
|
|
|
isSearching: false,
|
|
|
|
|
|
showHistory: true,
|
|
|
|
|
|
showHotSearch: true,
|
|
|
|
|
|
// 搜索历史
|
|
|
|
|
|
searchHistory: [],
|
|
|
|
|
|
// 热门搜索标签
|
|
|
|
|
|
hotSearchTags: ['济南西站', '泉城广场', '大明湖', '千佛山', '济南东站', '融创文旅城']
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
mounted() {
|
2025-11-04 15:16:22 +08:00
|
|
|
|
// 获取用户位置权限
|
|
|
|
|
|
this.getUserLocation();
|
|
|
|
|
|
// 加载搜索历史
|
|
|
|
|
|
this.loadSearchHistory();
|
2025-11-03 12:30:37 +08:00
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
2025-11-04 15:16:22 +08:00
|
|
|
|
deleteHistoryItem(index) {
|
|
|
|
|
|
// 删除指定索引的历史记录
|
|
|
|
|
|
this.searchHistory.splice(index, 1);
|
|
|
|
|
|
// 更新本地存储
|
|
|
|
|
|
uni.setStorageSync('placeSearchHistory', this.searchHistory);
|
|
|
|
|
|
},
|
|
|
|
|
|
// 获取用户位置
|
|
|
|
|
|
getUserLocation() {
|
|
|
|
|
|
uni.getLocation({
|
|
|
|
|
|
type: 'gcj02',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
this.mapCenter = {
|
|
|
|
|
|
latitude: res.latitude,
|
|
|
|
|
|
longitude: res.longitude
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.log('获取位置失败:', err);
|
|
|
|
|
|
// 使用默认位置(济南市)
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-03 12:30:37 +08:00
|
|
|
|
submitForm() {
|
2025-11-04 15:16:22 +08:00
|
|
|
|
if(this.checkedMarker && this.checkedMarker.name){
|
2025-11-03 12:30:37 +08:00
|
|
|
|
this.$emit('selected', this.checkedMarker)
|
2025-11-04 15:16:22 +08:00
|
|
|
|
// this.visible = false;
|
|
|
|
|
|
this.$refs.visible.close();
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}else{
|
2025-11-04 15:16:22 +08:00
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '您尚未选择地点!',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
2025-11-03 12:30:37 +08:00
|
|
|
|
cancel() {
|
2025-11-04 15:16:22 +08:00
|
|
|
|
this.$refs.visible.close();
|
|
|
|
|
|
// this.visible = false;
|
2025-11-03 12:30:37 +08:00
|
|
|
|
},
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
2025-11-03 12:30:37 +08:00
|
|
|
|
openDialog() {
|
2025-11-04 15:16:22 +08:00
|
|
|
|
this.$refs.visible.open();
|
|
|
|
|
|
// this.visible = true;
|
|
|
|
|
|
this.placeInput = '';
|
|
|
|
|
|
this.placeList = [];
|
|
|
|
|
|
this.checkedMarker = '';
|
|
|
|
|
|
this.markers = [];
|
|
|
|
|
|
this.isSearching = false;
|
|
|
|
|
|
// this.showHistory = true;
|
|
|
|
|
|
this.showHotSearch = true;
|
2025-11-03 12:30:37 +08:00
|
|
|
|
},
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 重置选择
|
|
|
|
|
|
resetSelection() {
|
|
|
|
|
|
this.checkedMarker = '';
|
|
|
|
|
|
this.markers = [];
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '已清除选择',
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 1500
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索框聚焦
|
|
|
|
|
|
onInputFocus() {
|
|
|
|
|
|
// this.showHistory = true;
|
|
|
|
|
|
this.showHotSearch = true;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索框失焦
|
|
|
|
|
|
onInputBlur(e) {
|
|
|
|
|
|
// 失焦时保持搜索结果显示
|
|
|
|
|
|
console.log("e",e); // 保留调试信息
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 输入变化
|
|
|
|
|
|
onInputChange(e) {
|
|
|
|
|
|
// 安全地获取输入值,处理各种可能的情况
|
|
|
|
|
|
let value = '';
|
|
|
|
|
|
if (!e) {
|
|
|
|
|
|
value = '';
|
|
|
|
|
|
} else if (e.detail && e.detail.value !== undefined) {
|
|
|
|
|
|
value = e.detail.value;
|
|
|
|
|
|
} else if (e.target && e.target.value !== undefined) {
|
|
|
|
|
|
value = e.target.value;
|
|
|
|
|
|
} else if (typeof e === 'string') {
|
|
|
|
|
|
value = e;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.placeInput = value;
|
|
|
|
|
|
|
|
|
|
|
|
if (value.trim() === '') {
|
|
|
|
|
|
this.placeList = [];
|
|
|
|
|
|
// this.showHistory = true;
|
|
|
|
|
|
this.showHotSearch = true;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 延迟搜索,避免频繁请求
|
|
|
|
|
|
if (this.searchTimer) {
|
|
|
|
|
|
clearTimeout(this.searchTimer);
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
this.searchTimer = setTimeout(() => {
|
|
|
|
|
|
this.getLocations(value);
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 清除输入框
|
|
|
|
|
|
onInputClear() {
|
|
|
|
|
|
this.placeInput = '';
|
|
|
|
|
|
this.placeList = [];
|
|
|
|
|
|
// this.showHistory = true;
|
|
|
|
|
|
this.showHotSearch = true;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索历史项点击
|
|
|
|
|
|
searchHistoryItem(keyword) {
|
|
|
|
|
|
this.placeInput = keyword;
|
|
|
|
|
|
this.getLocations(keyword);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 热门标签点击
|
|
|
|
|
|
searchHotTag(tag) {
|
|
|
|
|
|
this.placeInput = tag;
|
|
|
|
|
|
this.getLocations(tag);
|
|
|
|
|
|
this.saveToSearchHistory(tag);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到搜索历史
|
|
|
|
|
|
saveToSearchHistory(keyword) {
|
|
|
|
|
|
if (!keyword || keyword.trim() === '') return;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 去重
|
|
|
|
|
|
const index = this.searchHistory.indexOf(keyword);
|
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
|
this.searchHistory.splice(index, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加到开头
|
|
|
|
|
|
this.searchHistory.unshift(keyword);
|
|
|
|
|
|
|
|
|
|
|
|
// 限制历史记录数量
|
|
|
|
|
|
if (this.searchHistory.length > 10) {
|
|
|
|
|
|
this.searchHistory.pop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到本地存储
|
|
|
|
|
|
uni.setStorageSync('placeSearchHistory', this.searchHistory);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('保存搜索历史失败:', e);
|
|
|
|
|
|
// 即使保存失败也不影响功能使用
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 加载搜索历史
|
|
|
|
|
|
loadSearchHistory() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const history = uni.getStorageSync('placeSearchHistory');
|
|
|
|
|
|
if (history && Array.isArray(history)) {
|
|
|
|
|
|
this.searchHistory = history;
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
2025-11-04 15:16:22 +08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('加载搜索历史失败:', e);
|
|
|
|
|
|
// 即使加载失败也不影响功能使用
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索地点
|
|
|
|
|
|
getLocations(place) {
|
|
|
|
|
|
if (!place || place.trim() === '') {
|
|
|
|
|
|
this.placeList = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 显示搜索中状态
|
|
|
|
|
|
this.isSearching = true;
|
|
|
|
|
|
// this.showHistory = false;
|
|
|
|
|
|
this.showHotSearch = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟搜索请求(实际项目中使用真实API)
|
|
|
|
|
|
// 这里添加了模拟数据,确保在无网络或API限制时也能看到搜索效果
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
// 模拟搜索结果数据
|
|
|
|
|
|
const mockResults = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: `${place}购物中心`,
|
|
|
|
|
|
address: `山东省济南市历下区${place}路123号`,
|
|
|
|
|
|
location: { lat: 36.657017, lng: 117.123237 }
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: `${place}公园`,
|
|
|
|
|
|
address: `山东省济南市槐荫区${place}路456号`,
|
|
|
|
|
|
location: { lat: 36.667017, lng: 117.133237 }
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: `${place}小区`,
|
|
|
|
|
|
address: `山东省济南市历城区${place}路789号`,
|
|
|
|
|
|
location: { lat: 36.677017, lng: 117.143237 }
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
this.placeList = mockResults;
|
|
|
|
|
|
this.isSearching = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到搜索历史
|
|
|
|
|
|
this.saveToSearchHistory(place);
|
|
|
|
|
|
|
|
|
|
|
|
// 实际项目中使用的真实API请求
|
|
|
|
|
|
/*
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: 'https://api.map.baidu.com/place/v2/suggestion',
|
|
|
|
|
|
data: {
|
|
|
|
|
|
q: place,
|
|
|
|
|
|
ak: "qr93Dm5Ph6Vb4n1aTfvHG9KZkvG8S4YU",
|
|
|
|
|
|
region: '济南市',
|
|
|
|
|
|
output: "json",
|
|
|
|
|
|
},
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log('地点搜索结果:', res.data);
|
|
|
|
|
|
if (res.data && res.data.result) {
|
|
|
|
|
|
this.placeList = res.data.result;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.log('搜索地点失败:', err);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '搜索失败,请重试',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
complete: () => {
|
|
|
|
|
|
this.isSearching = false;
|
|
|
|
|
|
// 保存到搜索历史
|
|
|
|
|
|
this.saveToSearchHistory(place);
|
|
|
|
|
|
}
|
2025-11-03 12:30:37 +08:00
|
|
|
|
});
|
2025-11-04 15:16:22 +08:00
|
|
|
|
*/
|
|
|
|
|
|
}, 800); // 模拟网络延迟
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 选择地点
|
|
|
|
|
|
addIcon(placeName) {
|
|
|
|
|
|
const selectedPlace = this.placeList.find(item => item.name === placeName);
|
|
|
|
|
|
if (selectedPlace) {
|
|
|
|
|
|
this.checkedMarker = selectedPlace;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新地图中心点和标记
|
|
|
|
|
|
this.mapCenter = {
|
|
|
|
|
|
latitude: selectedPlace.location.lat,
|
|
|
|
|
|
longitude: selectedPlace.location.lng
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 添加标记点
|
|
|
|
|
|
this.markers = [{
|
|
|
|
|
|
id: 1,
|
|
|
|
|
|
latitude: selectedPlace.location.lat,
|
|
|
|
|
|
longitude: selectedPlace.location.lng,
|
|
|
|
|
|
title: selectedPlace.name,
|
|
|
|
|
|
width: 32,
|
|
|
|
|
|
height: 32
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 显示选择结果
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `已选择: ${selectedPlace.name}`,
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.placeList = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 标记点点击事件
|
|
|
|
|
|
onMarkerTap(e) {
|
|
|
|
|
|
const markerId = e.markerId;
|
|
|
|
|
|
const marker = this.markers.find(m => m.id === markerId);
|
|
|
|
|
|
if (marker) {
|
|
|
|
|
|
this.checkedMarker = {
|
|
|
|
|
|
name: marker.title,
|
|
|
|
|
|
location: {
|
|
|
|
|
|
lat: marker.latitude,
|
|
|
|
|
|
lng: marker.longitude
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 地图区域变化事件
|
|
|
|
|
|
onRegionChange(e) {
|
|
|
|
|
|
if (e.type === 'end' && e.detail.centerLocation) {
|
|
|
|
|
|
// 可以在这里处理地图拖动后的逻辑
|
|
|
|
|
|
console.log('地图中心变化:', e.detail.centerLocation);
|
|
|
|
|
|
}
|
2025-11-03 12:30:37 +08:00
|
|
|
|
},
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
// 点击地图事件
|
|
|
|
|
|
onMapTap(e) {
|
|
|
|
|
|
console.log('点击地图:', e);
|
|
|
|
|
|
const { latitude, longitude } = e.detail;
|
|
|
|
|
|
|
|
|
|
|
|
// 通过坐标获取地点信息
|
|
|
|
|
|
this.getLocationInfo(latitude, longitude);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 根据坐标获取地点信息
|
|
|
|
|
|
getLocationInfo(latitude, longitude) {
|
|
|
|
|
|
// 模拟请求
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
const locationInfo = {
|
|
|
|
|
|
formatted_address: `点击位置(${latitude.toFixed(6)},${longitude.toFixed(6)})`,
|
|
|
|
|
|
addressComponent: {
|
|
|
|
|
|
district: '历下区',
|
|
|
|
|
|
street: '经十路',
|
|
|
|
|
|
street_number: '123号'
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 更新选中的地点信息
|
|
|
|
|
|
this.checkedMarker = {
|
|
|
|
|
|
name: locationInfo.formatted_address,
|
|
|
|
|
|
address: `${locationInfo.addressComponent.district}${locationInfo.addressComponent.street}${locationInfo.addressComponent.street_number}`,
|
|
|
|
|
|
location: {
|
|
|
|
|
|
lat: latitude,
|
|
|
|
|
|
lng: longitude
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 更新地图标记
|
|
|
|
|
|
this.markers = [{
|
|
|
|
|
|
id: 1,
|
|
|
|
|
|
latitude: latitude,
|
|
|
|
|
|
longitude: longitude,
|
|
|
|
|
|
title: this.checkedMarker.name,
|
|
|
|
|
|
width: 32,
|
|
|
|
|
|
height: 32
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 显示选择结果
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `已选择: ${this.checkedMarker.name}`,
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
|
|
/* 实际项目中使用的真实API请求
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: 'https://api.map.baidu.com/reverse_geocoding/v3',
|
|
|
|
|
|
data: {
|
|
|
|
|
|
ak: "qr93Dm5Ph6Vb4n1aTfvHG9KZkvG8S4YU",
|
|
|
|
|
|
output: "json",
|
|
|
|
|
|
coordtype: "gcj02ll",
|
|
|
|
|
|
location: `${latitude},${longitude}`
|
|
|
|
|
|
},
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log('逆地理编码结果:', res.data);
|
|
|
|
|
|
if (res.data && res.data.result) {
|
|
|
|
|
|
const locationInfo = res.data.result;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新选中的地点信息
|
|
|
|
|
|
this.checkedMarker = {
|
|
|
|
|
|
name: locationInfo.formatted_address || '未知地点',
|
|
|
|
|
|
address: locationInfo.formatted_address,
|
|
|
|
|
|
location: {
|
|
|
|
|
|
lat: latitude,
|
|
|
|
|
|
lng: longitude
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 更新地图标记
|
|
|
|
|
|
this.markers = [{
|
|
|
|
|
|
id: 1,
|
|
|
|
|
|
latitude: latitude,
|
|
|
|
|
|
longitude: longitude,
|
|
|
|
|
|
title: this.checkedMarker.name,
|
|
|
|
|
|
width: 32,
|
|
|
|
|
|
height: 32
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 显示选择结果
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `已选择: ${this.checkedMarker.name}`,
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.log('获取地点信息失败:', err);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '获取地点信息失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
*/
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
|
2025-11-04 15:16:22 +08:00
|
|
|
|
.search-container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
padding: 24rpx 32rpx;
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
border-radius: 0 0 16rpx 16rpx;
|
|
|
|
|
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
max-height: 50vh;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索区域样式 */
|
|
|
|
|
|
.search-area {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索输入框包装 */
|
|
|
|
|
|
.search-input-wrapper {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
border: 2rpx solid #E5E5E5;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
background: #F5F7FA;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:focus-within {
|
|
|
|
|
|
border-color: #1D64CF;
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
box-shadow: 0 0 0 4rpx rgba(29, 100, 207, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索图标 */
|
|
|
|
|
|
.search-icon {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 24rpx;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 输入框样式 */
|
|
|
|
|
|
.search-input-wrapper .u-input {
|
|
|
|
|
|
padding-left: 72rpx !important;
|
|
|
|
|
|
padding-right: 80rpx !important;
|
|
|
|
|
|
background: transparent !important;
|
|
|
|
|
|
border: none !important;
|
|
|
|
|
|
border-radius: 8rpx !important;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索加载动画 */
|
|
|
|
|
|
.search-loading {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 24rpx;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索历史样式 */
|
|
|
|
|
|
.search-history {
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
padding: 16rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-title {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-list {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 16rpx 20rpx;
|
|
|
|
|
|
background: #F5F7FA;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background: #E5E9F2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.history-icon {
|
|
|
|
|
|
margin-right: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-history {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
padding: 40rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 热门搜索样式 */
|
|
|
|
|
|
.hot-search {
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
padding: 16rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hot-title {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hot-tags {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hot-tag {
|
|
|
|
|
|
padding: 12rpx 24rpx;
|
|
|
|
|
|
background: #F5F7FA;
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background: #1D64CF;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 选中项样式优化 */
|
2025-11-03 12:30:37 +08:00
|
|
|
|
.selected {
|
2025-11-04 15:16:22 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 16rpx 24rpx;
|
2025-11-03 12:30:37 +08:00
|
|
|
|
background: #DCE2E9;
|
|
|
|
|
|
border-radius: 8rpx;
|
2025-11-04 15:16:22 +08:00
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
animation: fadeIn 0.3s ease;
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
.selected-content {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selected-text {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
margin-left: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.selected-address {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #666666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.clear-btn {
|
|
|
|
|
|
color: #ff4757;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
padding: 8rpx 16rpx;
|
|
|
|
|
|
background: rgba(255, 71, 87, 0.1);
|
|
|
|
|
|
border-radius: 4rpx;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background: rgba(255, 71, 87, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 搜索结果样式 */
|
|
|
|
|
|
.search-results {
|
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.results-title {
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.place-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
margin-bottom: 12rpx;
|
|
|
|
|
|
border: 2rpx solid #F5F7FA;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background: #F5F7FA;
|
|
|
|
|
|
border-color: #1D64CF;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-icon {
|
|
|
|
|
|
margin-right: 20rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-name {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
margin-bottom: 4rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-address {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-arrow {
|
|
|
|
|
|
margin-left: 16rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 无结果样式 */
|
|
|
|
|
|
.no-results {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
padding: 60rpx 20rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.no-results-tip {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
margin-top: 12rpx;
|
|
|
|
|
|
color: #CCCCCC;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 地图样式 */
|
|
|
|
|
|
.map {
|
2025-11-03 12:30:37 +08:00
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-04 15:16:22 +08:00
|
|
|
|
/* 底部按钮区域样式 */
|
|
|
|
|
|
.button-area {
|
2025-11-03 12:30:37 +08:00
|
|
|
|
position: absolute;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
bottom: 0;
|
2025-11-04 15:16:22 +08:00
|
|
|
|
right:0;
|
|
|
|
|
|
padding: 24rpx 32rpx;
|
2025-11-03 12:30:37 +08:00
|
|
|
|
width: 100%;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
margin-top: 40rpx;
|
|
|
|
|
|
border-radius: 16px 16px 0px 0px;
|
2025-11-04 15:16:22 +08:00
|
|
|
|
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
|
|
|
|
|
|
.btn {
|
2025-11-03 12:30:37 +08:00
|
|
|
|
line-height: 72rpx;
|
|
|
|
|
|
width: 176rpx;
|
|
|
|
|
|
margin-right: 16rpx;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
border: 1px solid #B8C5D4;
|
|
|
|
|
|
color: #282828;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
border-radius: 8rpx;
|
2025-11-04 15:16:22 +08:00
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
opacity: 0.8;
|
|
|
|
|
|
}
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
.reset {
|
2025-11-03 12:30:37 +08:00
|
|
|
|
background: #DCE2E9;
|
|
|
|
|
|
}
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
.save {
|
2025-11-03 12:30:37 +08:00
|
|
|
|
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
border: 0;
|
|
|
|
|
|
flex-grow: 1;
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
|
transform: translateY(1rpx);
|
|
|
|
|
|
}
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-04 15:16:22 +08:00
|
|
|
|
|
|
|
|
|
|
/* 动画 */
|
|
|
|
|
|
@keyframes fadeIn {
|
|
|
|
|
|
from {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transform: translateY(-10rpx);
|
|
|
|
|
|
}
|
|
|
|
|
|
to {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
}
|
2025-11-03 12:30:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|