feat: 完善高德地图地点搜索功能
This commit is contained in:
@@ -32,9 +32,12 @@ public class HrmTravelReqController extends BaseController {
|
|||||||
private final IHrmTravelReqService service;
|
private final IHrmTravelReqService service;
|
||||||
private final IHrmTravelReqService hrmTravelReqService;
|
private final IHrmTravelReqService hrmTravelReqService;
|
||||||
|
|
||||||
@Value("${fad.amap.key}")
|
@Value("${fad.amap.webkey}")
|
||||||
private String amapKey;
|
private String amapKey;
|
||||||
|
|
||||||
|
@Value("${fad.amap.securitykey}")
|
||||||
|
private String amapSecurityKey;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo<HrmTravelReqVo> list(HrmTravelReqBo bo, PageQuery pageQuery) {
|
public TableDataInfo<HrmTravelReqVo> list(HrmTravelReqBo bo, PageQuery pageQuery) {
|
||||||
return service.queryPageList(bo, pageQuery);
|
return service.queryPageList(bo, pageQuery);
|
||||||
@@ -66,10 +69,17 @@ public class HrmTravelReqController extends BaseController {
|
|||||||
public R<Void> earlyEnd(@PathVariable Long bizId) {
|
public R<Void> earlyEnd(@PathVariable Long bizId) {
|
||||||
return toAjax(hrmTravelReqService.earlyEnd(bizId));
|
return toAjax(hrmTravelReqService.earlyEnd(bizId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/amapKey")
|
@GetMapping("/amapKey")
|
||||||
public R<String> getAmapKey() {
|
public R<String> getAmapKey() {
|
||||||
return R.ok(amapKey);
|
return R.ok(amapKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/amapSecurityKey")
|
||||||
|
public R<String> getAmapSecurityKey() {
|
||||||
|
return R.ok(amapSecurityKey);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/all")
|
@GetMapping("/all")
|
||||||
public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) {
|
public R<List<HrmTravelReqVo>> all(HrmTravelReqBo bo) {
|
||||||
return R.ok(service.queryList(bo));
|
return R.ok(service.queryList(bo));
|
||||||
|
|||||||
@@ -318,7 +318,11 @@ flowable:
|
|||||||
# 关闭历史任务定时任务job
|
# 关闭历史任务定时任务job
|
||||||
async-history-executor-activate: false
|
async-history-executor-activate: false
|
||||||
|
|
||||||
|
|
||||||
fad:
|
fad:
|
||||||
amap:
|
amap:
|
||||||
|
# 留作后端接口调用(服务 API)的 Key
|
||||||
key: 978ae5bc551f57d172d3e397af5a6f67
|
key: 978ae5bc551f57d172d3e397af5a6f67
|
||||||
|
# 新增的前端 Web 端使用的 Key 和安全密钥
|
||||||
|
webKey: 34bf20d1db5b183558b9bb85d6eed783
|
||||||
|
securityKey: 6f9171724396deb5f8c42ef256b3cbc5
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
<%= webpackConfig.name %>
|
<%= webpackConfig.name %>
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
|
|
||||||
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
||||||
<style>
|
<style>
|
||||||
html,
|
html,
|
||||||
|
|||||||
@@ -59,3 +59,9 @@ export function getAmapKey() {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function getAmapSecurityKey() {
|
||||||
|
return request({
|
||||||
|
url: '/hrm/travel/amapSecurityKey',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="选择出差城市"
|
title="选择出差城市 / 地点"
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
width="900px"
|
width="900px"
|
||||||
:append-to-body="true"
|
:append-to-body="true"
|
||||||
@@ -22,44 +22,47 @@
|
|||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="searchKeyword"
|
v-model="searchKeyword"
|
||||||
placeholder="输入城市名搜索"
|
placeholder="输入城市或具体地点搜索"
|
||||||
size="small"
|
size="small"
|
||||||
prefix-icon="el-icon-search"
|
prefix-icon="el-icon-search"
|
||||||
@keyup.enter="searchCity"
|
@keyup.enter.native="searchLocation"
|
||||||
clearable
|
clearable
|
||||||
|
@clear="searchKeyword = ''"
|
||||||
>
|
>
|
||||||
<el-button slot="append" @click="searchCity">搜索</el-button>
|
<el-button slot="append" @click="searchLocation">搜索</el-button>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hot-cities" v-if="!searchKeyword">
|
<!-- 热门城市模块 -->
|
||||||
|
<div class="hot-cities" v-if="!searchKeyword || searchResults.length === 0">
|
||||||
<div class="section-title">热门城市</div>
|
<div class="section-title">热门城市</div>
|
||||||
<div class="city-list">
|
<div class="city-list">
|
||||||
<span
|
<span
|
||||||
v-for="city in hotCities"
|
v-for="city in hotCities"
|
||||||
:key="city"
|
:key="city"
|
||||||
class="city-item"
|
class="city-item"
|
||||||
@click="selectCityFromList(city)"
|
@click="selectHotCity(city)"
|
||||||
>
|
>
|
||||||
{{ city }}
|
{{ city }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-results" v-else>
|
<!-- 搜索结果模块 -->
|
||||||
|
<div class="search-results" v-if="searchResults.length > 0">
|
||||||
<div class="section-title">搜索结果</div>
|
<div class="section-title">搜索结果</div>
|
||||||
<div class="result-list">
|
<div class="result-list">
|
||||||
<div
|
<div
|
||||||
v-for="result in searchResults"
|
v-for="(result, index) in searchResults"
|
||||||
:key="result.id"
|
:key="index"
|
||||||
class="result-item"
|
class="result-item"
|
||||||
@click="selectCityFromList(result.name)"
|
@click="selectLocation(result)"
|
||||||
>
|
>
|
||||||
<i class="el-icon-location-outline"></i>
|
<i class="el-icon-location-outline"></i>
|
||||||
<span>{{ result.name }}</span>
|
<div class="result-info">
|
||||||
</div>
|
<div class="poi-name">{{ result.name }}</div>
|
||||||
<div v-if="searchResults.length === 0" class="no-result">
|
<div class="poi-address">{{ result.address }}</div>
|
||||||
未找到相关城市
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,15 +71,19 @@
|
|||||||
<div class="map-container">
|
<div class="map-container">
|
||||||
<div id="amapContainer" class="amap-wrapper"></div>
|
<div id="amapContainer" class="amap-wrapper"></div>
|
||||||
<div class="map-tip">
|
<div class="map-tip">
|
||||||
<i class="el-icon-info"></i> 点击地图上的位置,自动识别城市
|
<i class="el-icon-info"></i> 点击地图上的位置或搜索地点,自动识别归属城市
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<div class="selected-info" v-if="selectedCity">
|
<div class="selected-info" v-if="selectedCity">
|
||||||
已选择:<span class="selected-city">{{ selectedCity }}</span>
|
识别城市:<span class="selected-city">{{ selectedCity }}</span>
|
||||||
|
<span v-if="selectedPoi" style="margin-left: 10px; color: #909399; font-size: 12px;">
|
||||||
|
( {{ selectedPoi }} )
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else></div>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="closeDialog">取消</el-button>
|
<el-button @click="closeDialog">取消</el-button>
|
||||||
<el-button type="primary" @click="confirmCity" :disabled="!selectedCity">确定</el-button>
|
<el-button type="primary" @click="confirmCity" :disabled="!selectedCity">确定</el-button>
|
||||||
@@ -88,13 +95,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AMapLoader from '@amap/amap-jsapi-loader'
|
import AMapLoader from '@amap/amap-jsapi-loader'
|
||||||
import { getAmapKey } from '@/api/hrm/travel'
|
import { getAmapKey, getAmapSecurityKey } from '@/api/hrm/travel'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AmapCitySelect',
|
name: 'AmapCitySelect',
|
||||||
props: {
|
props: {
|
||||||
value: { type: String, default: '' },
|
value: { type: String, default: '' },
|
||||||
placeholder: { type: String, default: '请选择出差城市' }
|
placeholder: { type: String, default: '请选择出差地点' }
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -102,16 +109,17 @@ export default {
|
|||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
searchKeyword: '',
|
searchKeyword: '',
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
selectedCity: '',
|
selectedCity: '', // 最终表单需要的城市名
|
||||||
|
selectedPoi: '', // 具体的地点名(仅用于展示)
|
||||||
map: null,
|
map: null,
|
||||||
geocoder: null,
|
geocoder: null,
|
||||||
|
placeSearch: null, // 新增地点搜索对象
|
||||||
marker: null,
|
marker: null,
|
||||||
AMap: null,
|
AMap: null,
|
||||||
hotCities: [
|
hotCities: [
|
||||||
'北京市', '上海市', '广州市', '深圳市',
|
'北京市', '上海市', '广州市', '深圳市',
|
||||||
'杭州市', '南京市', '成都市', '武汉市',
|
'杭州市', '南京市', '成都市', '武汉市',
|
||||||
'重庆市', '天津市', '苏州市', '西安市',
|
'重庆市', '天津市', '苏州市', '西安市'
|
||||||
'石家庄市', '唐山市', '保定市', '邯郸市'
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -122,45 +130,43 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 弹窗打开时调用
|
|
||||||
async onDialogOpened() {
|
async onDialogOpened() {
|
||||||
await this.loadAMap()
|
const AMap = await this.loadAMap()
|
||||||
|
if (!AMap) return
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.initMap()
|
this.initMap()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载高德地图
|
|
||||||
async loadAMap() {
|
async loadAMap() {
|
||||||
if (this.AMap) return this.AMap
|
if (this.AMap && window._AMapSecurityConfig) return this.AMap
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await getAmapKey()
|
const [keyRes, securityRes] = await Promise.all([getAmapKey(), getAmapSecurityKey()])
|
||||||
console.log("接口完整返回:", JSON.stringify(res))
|
const amapkey = keyRes.data || keyRes.msg
|
||||||
|
const securityKey = securityRes.data || securityRes.msg
|
||||||
|
|
||||||
const amapkey = res.msg
|
if (!amapkey) throw new Error('未获取到高德地图 Key')
|
||||||
console.log('获取到的Key:', amapkey)
|
|
||||||
|
|
||||||
if (!amapkey) {
|
window._AMapSecurityConfig = { securityJsCode: securityKey }
|
||||||
throw new Error('获取高德地图Key失败')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.AMap = await AMapLoader.load({
|
this.AMap = await AMapLoader.load({
|
||||||
key: amapkey,
|
key: amapkey,
|
||||||
version: '2.0',
|
version: '2.0',
|
||||||
|
// 加入 PlaceSearch 插件
|
||||||
plugins: ['AMap.Geocoder', 'AMap.PlaceSearch']
|
plugins: ['AMap.Geocoder', 'AMap.PlaceSearch']
|
||||||
})
|
})
|
||||||
return this.AMap
|
return this.AMap
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('高德地图加载失败:', error)
|
console.error('地图加载失败:', error)
|
||||||
this.$message.error('地图加载失败,请刷新重试')
|
this.$message.error('地图加载失败,请重试')
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
initMap() {
|
initMap() {
|
||||||
const container = document.getElementById('amapContainer')
|
const container = document.getElementById('amapContainer')
|
||||||
if (!container) {
|
if (!container) {
|
||||||
console.error('地图容器不存在')
|
setTimeout(() => this.initMap(), 100)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,92 +177,127 @@ export default {
|
|||||||
|
|
||||||
this.map = new this.AMap.Map('amapContainer', {
|
this.map = new this.AMap.Map('amapContainer', {
|
||||||
zoom: 12,
|
zoom: 12,
|
||||||
center: [116.397428, 39.90923],
|
center: [116.397428, 39.90923], // 默认北京
|
||||||
resizeEnable: true
|
resizeEnable: true
|
||||||
})
|
})
|
||||||
|
|
||||||
this.geocoder = new this.AMap.Geocoder()
|
this.geocoder = new this.AMap.Geocoder()
|
||||||
|
|
||||||
|
// 初始化地点搜索插件
|
||||||
|
this.placeSearch = new this.AMap.PlaceSearch({
|
||||||
|
pageSize: 15, // 单页显示结果条数
|
||||||
|
pageIndex: 1, // 页码
|
||||||
|
autoFitView: false // 禁用自动调整视图,我们自己控制
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听地图点击
|
||||||
this.map.on('click', (e) => {
|
this.map.on('click', (e) => {
|
||||||
const lng = e.lnglat.getLng()
|
const lng = e.lnglat.getLng()
|
||||||
const lat = e.lnglat.getLat()
|
const lat = e.lnglat.getLat()
|
||||||
this.getCityByLngLat(lng, lat)
|
this.selectedPoi = '地图选点'
|
||||||
|
this.getCityByLngLat(lng, lat, true)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getCityByLngLat(lng, lat) {
|
// 通过经纬度逆解析城市
|
||||||
|
getCityByLngLat(lng, lat, setCenter = false) {
|
||||||
this.geocoder.getAddress([lng, lat], (status, result) => {
|
this.geocoder.getAddress([lng, lat], (status, result) => {
|
||||||
if (status === 'complete' && result.regeocode) {
|
if (status === 'complete' && result.regeocode) {
|
||||||
const addrComp = result.regeocode.addressComponent
|
const addrComp = result.regeocode.addressComponent
|
||||||
let city = addrComp.city
|
let city = addrComp.city
|
||||||
if (!city || city === '[]') {
|
// 直辖市的 city 可能是空的,取 province
|
||||||
|
if (!city || city === '[]' || city.length === 0) {
|
||||||
city = addrComp.province
|
city = addrComp.province
|
||||||
}
|
}
|
||||||
this.selectedCity = city
|
this.selectedCity = city
|
||||||
this.addMarker(lng, lat)
|
this.addMarker(lng, lat)
|
||||||
this.$message.success(`识别到城市:${city}`)
|
if(setCenter) {
|
||||||
} else {
|
this.map.setCenter([lng, lat])
|
||||||
this.$message.warning('无法识别该位置的城市')
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 在地图上打点
|
||||||
addMarker(lng, lat) {
|
addMarker(lng, lat) {
|
||||||
if (this.marker) {
|
if (this.marker) {
|
||||||
this.marker.setMap(null)
|
this.marker.setMap(null)
|
||||||
}
|
}
|
||||||
this.marker = new this.AMap.Marker({
|
this.marker = new this.AMap.Marker({
|
||||||
position: [lng, lat],
|
position: [lng, lat],
|
||||||
map: this.map
|
map: this.map,
|
||||||
|
animation: 'AMAP_ANIMATION_DROP' // 加上掉落动画
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
openMapDialog() {
|
openMapDialog() {
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
this.selectedCity = ''
|
this.selectedCity = this.value || ''
|
||||||
|
this.selectedPoi = ''
|
||||||
this.searchKeyword = ''
|
this.searchKeyword = ''
|
||||||
this.searchResults = []
|
this.searchResults = []
|
||||||
},
|
},
|
||||||
|
|
||||||
async searchCity() {
|
// 搜索地点核心方法
|
||||||
|
async searchLocation() {
|
||||||
if (!this.searchKeyword.trim()) {
|
if (!this.searchKeyword.trim()) {
|
||||||
this.$message.warning('请输入城市名称')
|
this.searchResults = []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.loadAMap()
|
await this.loadAMap()
|
||||||
|
|
||||||
this.geocoder.getLocation(this.searchKeyword, (status, result) => {
|
// 使用 PlaceSearch 搜索具体地点
|
||||||
if (status === 'complete' && result.geocodes && result.geocodes.length) {
|
this.placeSearch.search(this.searchKeyword, (status, result) => {
|
||||||
const cities = []
|
if (status === 'complete' && result.info === 'OK') {
|
||||||
result.geocodes.forEach(item => {
|
// 提取返回的 POI 列表
|
||||||
const cityName = item.city || item.province
|
const pois = result.poiList.pois
|
||||||
if (cityName && !cities.find(c => c.name === cityName)) {
|
this.searchResults = pois.map(poi => ({
|
||||||
cities.push({ id: item.adcode, name: cityName })
|
id: poi.id,
|
||||||
}
|
name: poi.name,
|
||||||
})
|
address: poi.address && typeof poi.address === 'string' ? poi.address : poi.adname,
|
||||||
this.searchResults = cities
|
location: poi.location, // 包含 lng/lat 的对象
|
||||||
if (this.searchResults.length === 0) {
|
city: poi.cityname || poi.pname // 城市名
|
||||||
this.$message.info('未找到相关城市')
|
}))
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.searchResults = []
|
this.searchResults = []
|
||||||
this.$message.info('未找到相关城市')
|
this.$message.info('未找到相关地点,请尝试更换关键词')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
async selectCityFromList(city) {
|
// 选中左侧搜索结果列表的具体地点
|
||||||
this.selectedCity = city
|
selectLocation(poi) {
|
||||||
await this.loadAMap()
|
if (!poi.location) {
|
||||||
|
this.$message.warning('该地点缺少坐标信息')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const lng = poi.location.lng
|
||||||
|
const lat = poi.location.lat
|
||||||
|
|
||||||
|
// 设置地图中心点并放大(层级15看街道)
|
||||||
|
this.map.setZoomAndCenter(15, [lng, lat])
|
||||||
|
this.addMarker(lng, lat)
|
||||||
|
|
||||||
|
// 更新选择数据
|
||||||
|
this.selectedCity = poi.city
|
||||||
|
this.selectedPoi = poi.name
|
||||||
|
this.$message.success(`已定位到:${poi.name}`)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 选中热门城市
|
||||||
|
async selectHotCity(city) {
|
||||||
|
await this.loadAMap()
|
||||||
|
this.selectedCity = city
|
||||||
|
this.selectedPoi = city
|
||||||
|
|
||||||
|
// 获取城市中心点坐标
|
||||||
this.geocoder.getLocation(city, (status, result) => {
|
this.geocoder.getLocation(city, (status, result) => {
|
||||||
if (status === 'complete' && result.geocodes.length) {
|
if (status === 'complete' && result.geocodes.length) {
|
||||||
const loc = result.geocodes[0].location
|
const loc = result.geocodes[0].location
|
||||||
this.map.setCenter([loc.lng, loc.lat])
|
this.map.setZoomAndCenter(11, [loc.lng, loc.lat])
|
||||||
this.map.setZoom(12)
|
|
||||||
this.addMarker(loc.lng, loc.lat)
|
this.addMarker(loc.lng, loc.lat)
|
||||||
this.$message.success(`已定位到:${city}`)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -264,21 +305,16 @@ export default {
|
|||||||
confirmCity() {
|
confirmCity() {
|
||||||
if (this.selectedCity) {
|
if (this.selectedCity) {
|
||||||
this.cityName = this.selectedCity
|
this.cityName = this.selectedCity
|
||||||
|
// 组件 v-model 抛出城市名
|
||||||
this.$emit('input', this.selectedCity)
|
this.$emit('input', this.selectedCity)
|
||||||
|
// 如果你需要具体的地点名,可以额外抛出一个事件
|
||||||
|
this.$emit('poi-change', { city: this.selectedCity, poi: this.selectedPoi })
|
||||||
this.closeDialog()
|
this.closeDialog()
|
||||||
this.$message.success(`已选择:${this.selectedCity}`)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
this.selectedCity = ''
|
|
||||||
this.searchKeyword = ''
|
|
||||||
this.searchResults = []
|
|
||||||
if (this.marker) {
|
|
||||||
this.marker.setMap(null)
|
|
||||||
this.marker = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,28 +323,49 @@ export default {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.amap-city-select { width: 100%; }
|
.amap-city-select { width: 100%; }
|
||||||
.map-selector { display: flex; gap: 20px; min-height: 450px;
|
.map-selector { display: flex; gap: 20px; min-height: 450px;
|
||||||
.city-sidebar { width: 280px; flex-shrink: 0;
|
.city-sidebar { width: 300px; flex-shrink: 0; display: flex; flex-direction: column;
|
||||||
.search-box { margin-bottom: 16px; }
|
.search-box { margin-bottom: 16px; }
|
||||||
.section-title { font-size: 14px; font-weight: 500; color: #303133; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #e4e7ed; }
|
.section-title { font-size: 14px; font-weight: bold; color: #303133; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #ebeef5; }
|
||||||
|
|
||||||
.hot-cities .city-list { display: flex; flex-wrap: wrap; gap: 10px;
|
.hot-cities .city-list { display: flex; flex-wrap: wrap; gap: 10px;
|
||||||
.city-item { padding: 4px 12px; background: #f5f7fa; border-radius: 4px; font-size: 13px; cursor: pointer;
|
.city-item { padding: 6px 14px; background: #f4f4f5; color: #606266; border-radius: 4px; font-size: 13px; cursor: pointer; transition: all 0.2s;
|
||||||
&:hover { background: #409eff; color: white; }
|
&:hover { background: #409eff; color: white; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.search-results .result-list { max-height: 380px; overflow-y: auto;
|
|
||||||
.result-item { padding: 10px 12px; cursor: pointer; display: flex; align-items: center; gap: 8px; border-bottom: 1px solid #f0f0f0;
|
/* 搜索结果列表样式升级 */
|
||||||
&:hover { background: #ecf5ff; }
|
.search-results {
|
||||||
i { color: #409eff; }
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.result-list {
|
||||||
|
flex: 1; overflow-y: auto; padding-right: 5px;
|
||||||
|
|
||||||
|
/* 自定义滚动条 */
|
||||||
|
&::-webkit-scrollbar { width: 4px; }
|
||||||
|
&::-webkit-scrollbar-thumb { background: #dcdfe6; border-radius: 4px; }
|
||||||
|
|
||||||
|
.result-item {
|
||||||
|
padding: 12px 10px; cursor: pointer; display: flex; align-items: flex-start; gap: 10px; border-bottom: 1px solid #ebeef5; transition: background 0.2s;
|
||||||
|
&:hover { background: #f0f7ff; }
|
||||||
|
i { color: #409eff; margin-top: 3px; font-size: 16px; }
|
||||||
|
.result-info {
|
||||||
|
flex: 1; overflow: hidden;
|
||||||
|
.poi-name { font-size: 14px; color: #303133; font-weight: 500; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
|
.poi-address { font-size: 12px; color: #909399; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.no-result { padding: 40px 0; text-align: center; color: #909399; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map-container { flex: 1;
|
|
||||||
.amap-wrapper { width: 100%; height: 400px; border: 1px solid #e4e7ed; border-radius: 8px; overflow: hidden; }
|
.map-container { flex: 1; display: flex; flex-direction: column;
|
||||||
.map-tip { margin-top: 8px; font-size: 12px; color: #909399; text-align: center; i { margin-right: 4px; } }
|
.amap-wrapper { flex: 1; width: 100%; border: 1px solid #dcdfe6; border-radius: 6px; overflow: hidden; }
|
||||||
|
.map-tip { margin-top: 10px; font-size: 12px; color: #909399; text-align: center; i { margin-right: 4px; color: #e6a23c; } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dialog-footer { display: flex; justify-content: space-between; align-items: center;
|
.dialog-footer { display: flex; justify-content: space-between; align-items: center;
|
||||||
.selected-info { font-size: 13px; color: #606266; .selected-city { color: #409eff; font-weight: 500; } }
|
.selected-info { font-size: 14px; color: #606266; .selected-city { color: #409eff; font-weight: bold; font-size: 15px; } }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in New Issue
Block a user