update
This commit is contained in:
parent
619d17f9a1
commit
018bc7c640
@ -8,10 +8,10 @@
|
|||||||
<title>蜂快 · 运营管理系统</title>
|
<title>蜂快 · 运营管理系统</title>
|
||||||
<script>
|
<script>
|
||||||
window._AMapSecurityConfig = {
|
window._AMapSecurityConfig = {
|
||||||
securityJsCode: '6c7f5a402a13bf2dee1a4bbe0d8023c7'
|
securityJsCode: '93527b49270ba2142f47f0407da7c0d6'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="https://webapi.amap.com/maps?v=2.0&key=fd47f3d4f54b675693c7d59dcd2a6c5f&plugin=AMap.Geocoder,AMap.AutoComplete,AMap.PlaceSearch"></script>
|
<script src="https://webapi.amap.com/maps?v=2.0&key=fd47f3d4f54b675693c7d59dcd2a6c5f&plugin=AMap.Geocoder,AMap.AutoComplete,AMap.PlaceSearch,AMap.DistrictSearch"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
|||||||
@ -1,16 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="map-picker-container">
|
<div class="map-picker-container">
|
||||||
<a-form-item :label="label">
|
<a-form-item :label="label">
|
||||||
<a-auto-complete
|
<div class="region-search-container">
|
||||||
v-model:value="searchAddress"
|
<!-- 省市选择器 -->
|
||||||
:options="searchOptions"
|
<div class="region-selector">
|
||||||
placeholder="输入地址搜索"
|
<a-select
|
||||||
@change="handleSearch"
|
v-model:value="selectedProvince"
|
||||||
@select="handleSelect"
|
placeholder="选择省份"
|
||||||
:loading="searchLoading"
|
style="width: 48%"
|
||||||
allow-clear
|
@change="handleProvinceChange"
|
||||||
class="map-picker-input"
|
:options="provinceOptions"
|
||||||
/>
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
/>
|
||||||
|
<a-select
|
||||||
|
v-model:value="selectedCity"
|
||||||
|
placeholder="选择城市"
|
||||||
|
style="width: 48%"
|
||||||
|
@change="handleCityChange"
|
||||||
|
:options="cityOptions"
|
||||||
|
:disabled="!selectedProvince"
|
||||||
|
show-search
|
||||||
|
:filter-option="filterOption"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 详细地址搜索 -->
|
||||||
|
<a-auto-complete
|
||||||
|
v-model:value="searchAddress"
|
||||||
|
:options="searchOptions"
|
||||||
|
placeholder="输入详细地址搜索"
|
||||||
|
@change="handleSearch"
|
||||||
|
@select="handleSelect"
|
||||||
|
:loading="searchLoading"
|
||||||
|
allow-clear
|
||||||
|
class="map-picker-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="地图选点" required>
|
<a-form-item label="地图选点" required>
|
||||||
@ -38,6 +64,110 @@ import { ref, onMounted, nextTick, watch } from 'vue'
|
|||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { loadAMap, createMap, createAutoComplete, createGeocoder } from '@/utils/amap.js'
|
import { loadAMap, createMap, createAutoComplete, createGeocoder } from '@/utils/amap.js'
|
||||||
|
|
||||||
|
// 备用省份数据
|
||||||
|
const fallbackProvinces = [
|
||||||
|
{ value: '北京市', label: '北京市' },
|
||||||
|
{ value: '天津市', label: '天津市' },
|
||||||
|
{ value: '河北省', label: '河北省' },
|
||||||
|
{ value: '山西省', label: '山西省' },
|
||||||
|
{ value: '内蒙古自治区', label: '内蒙古' },
|
||||||
|
{ value: '辽宁省', label: '辽宁省' },
|
||||||
|
{ value: '吉林省', label: '吉林省' },
|
||||||
|
{ value: '黑龙江省', label: '黑龙江省' },
|
||||||
|
{ value: '上海市', label: '上海市' },
|
||||||
|
{ value: '江苏省', label: '江苏省' },
|
||||||
|
{ value: '浙江省', label: '浙江省' },
|
||||||
|
{ value: '安徽省', label: '安徽省' },
|
||||||
|
{ value: '福建省', label: '福建省' },
|
||||||
|
{ value: '江西省', label: '江西省' },
|
||||||
|
{ value: '山东省', label: '山东省' },
|
||||||
|
{ value: '河南省', label: '河南省' },
|
||||||
|
{ value: '湖北省', label: '湖北省' },
|
||||||
|
{ value: '湖南省', label: '湖南省' },
|
||||||
|
{ value: '广东省', label: '广东省' },
|
||||||
|
{ value: '广西壮族自治区', label: '广西' },
|
||||||
|
{ value: '海南省', label: '海南省' },
|
||||||
|
{ value: '重庆市', label: '重庆市' },
|
||||||
|
{ value: '四川省', label: '四川省' },
|
||||||
|
{ value: '贵州省', label: '贵州省' },
|
||||||
|
{ value: '云南省', label: '云南省' },
|
||||||
|
{ value: '西藏自治区', label: '西藏' },
|
||||||
|
{ value: '陕西省', label: '陕西省' },
|
||||||
|
{ value: '甘肃省', label: '甘肃省' },
|
||||||
|
{ value: '青海省', label: '青海省' },
|
||||||
|
{ value: '宁夏回族自治区', label: '宁夏' },
|
||||||
|
{ value: '新疆维吾尔自治区', label: '新疆' },
|
||||||
|
{ value: '台湾省', label: '台湾省' },
|
||||||
|
{ value: '香港特别行政区', label: '香港' },
|
||||||
|
{ value: '澳门特别行政区', label: '澳门' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 备用城市数据
|
||||||
|
const fallbackCitiesMap = {
|
||||||
|
'北京市': [{ value: '北京市', label: '北京市' }],
|
||||||
|
'上海市': [{ value: '上海市', label: '上海市' }],
|
||||||
|
'天津市': [{ value: '天津市', label: '天津市' }],
|
||||||
|
'重庆市': [{ value: '重庆市', label: '重庆市' }],
|
||||||
|
'广东省': [
|
||||||
|
{ value: '广州市', label: '广州市' },
|
||||||
|
{ value: '深圳市', label: '深圳市' },
|
||||||
|
{ value: '珠海市', label: '珠海市' },
|
||||||
|
{ value: '汕头市', label: '汕头市' },
|
||||||
|
{ value: '佛山市', label: '佛山市' },
|
||||||
|
{ value: '韶关市', label: '韶关市' },
|
||||||
|
{ value: '湛江市', label: '湛江市' },
|
||||||
|
{ value: '肇庆市', label: '肇庆市' },
|
||||||
|
{ value: '江门市', label: '江门市' },
|
||||||
|
{ value: '茂名市', label: '茂名市' },
|
||||||
|
{ value: '惠州市', label: '惠州市' },
|
||||||
|
{ value: '梅州市', label: '梅州市' },
|
||||||
|
{ value: '汕尾市', label: '汕尾市' },
|
||||||
|
{ value: '河源市', label: '河源市' },
|
||||||
|
{ value: '阳江市', label: '阳江市' },
|
||||||
|
{ value: '清远市', label: '清远市' },
|
||||||
|
{ value: '东莞市', label: '东莞市' },
|
||||||
|
{ value: '中山市', label: '中山市' },
|
||||||
|
{ value: '潮州市', label: '潮州市' },
|
||||||
|
{ value: '揭阳市', label: '揭阳市' },
|
||||||
|
{ value: '云浮市', label: '云浮市' }
|
||||||
|
],
|
||||||
|
'浙江省': [
|
||||||
|
{ value: '杭州市', label: '杭州市' },
|
||||||
|
{ value: '宁波市', label: '宁波市' },
|
||||||
|
{ value: '温州市', label: '温州市' },
|
||||||
|
{ value: '嘉兴市', label: '嘉兴市' },
|
||||||
|
{ value: '湖州市', label: '湖州市' },
|
||||||
|
{ value: '绍兴市', label: '绍兴市' },
|
||||||
|
{ value: '金华市', label: '金华市' },
|
||||||
|
{ value: '衢州市', label: '衢州市' },
|
||||||
|
{ value: '舟山市', label: '舟山市' },
|
||||||
|
{ value: '台州市', label: '台州市' },
|
||||||
|
{ value: '丽水市', label: '丽水市' }
|
||||||
|
],
|
||||||
|
'江苏省': [
|
||||||
|
{ value: '南京市', label: '南京市' },
|
||||||
|
{ value: '无锡市', label: '无锡市' },
|
||||||
|
{ value: '徐州市', label: '徐州市' },
|
||||||
|
{ value: '常州市', label: '常州市' },
|
||||||
|
{ value: '苏州市', label: '苏州市' },
|
||||||
|
{ value: '南通市', label: '南通市' },
|
||||||
|
{ value: '连云港市', label: '连云港市' },
|
||||||
|
{ value: '淮安市', label: '淮安市' },
|
||||||
|
{ value: '盐城市', label: '盐城市' },
|
||||||
|
{ value: '扬州市', label: '扬州市' },
|
||||||
|
{ value: '镇江市', label: '镇江市' },
|
||||||
|
{ value: '泰州市', label: '泰州市' },
|
||||||
|
{ value: '宿迁市', label: '宿迁市' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为没有城市数据的省份添加一个默认城市
|
||||||
|
for (const province of fallbackProvinces) {
|
||||||
|
if (!fallbackCitiesMap[province.value]) {
|
||||||
|
fallbackCitiesMap[province.value] = [{ value: province.value, label: province.value }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MapPicker',
|
name: 'MapPicker',
|
||||||
props: {
|
props: {
|
||||||
@ -63,11 +193,73 @@ export default {
|
|||||||
const searchOptions = ref([])
|
const searchOptions = ref([])
|
||||||
const searchLoading = ref(false)
|
const searchLoading = ref(false)
|
||||||
|
|
||||||
|
// 省市选择
|
||||||
|
const provinceOptions = ref(fallbackProvinces)
|
||||||
|
const cityOptions = ref([])
|
||||||
|
const selectedProvince = ref('')
|
||||||
|
const selectedCity = ref('')
|
||||||
|
|
||||||
// 双向绑定的值
|
// 双向绑定的值
|
||||||
const address = ref(props.modelValue.address)
|
const address = ref(props.modelValue.address)
|
||||||
const longitude = ref(props.modelValue.longitude)
|
const longitude = ref(props.modelValue.longitude)
|
||||||
const latitude = ref(props.modelValue.latitude)
|
const latitude = ref(props.modelValue.latitude)
|
||||||
|
|
||||||
|
// 下拉框筛选函数
|
||||||
|
const filterOption = (input, option) => {
|
||||||
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理省份变化
|
||||||
|
const handleProvinceChange = (value) => {
|
||||||
|
selectedProvince.value = value
|
||||||
|
selectedCity.value = ''
|
||||||
|
|
||||||
|
// 获取城市数据
|
||||||
|
cityOptions.value = fallbackCitiesMap[value] || []
|
||||||
|
|
||||||
|
// 如果有地图实例,尝试定位到选择的省份
|
||||||
|
if (map.value) {
|
||||||
|
try {
|
||||||
|
// 使用地理编码获取省份中心点
|
||||||
|
const geocoder = createGeocoder()
|
||||||
|
geocoder.getLocation(value, (status, result) => {
|
||||||
|
if (status === 'complete' && result.info === 'OK' && result.geocodes.length > 0) {
|
||||||
|
const location = result.geocodes[0].location
|
||||||
|
map.value.setCenter([location.lng, location.lat])
|
||||||
|
map.value.setZoom(8) // 省级层面,缩放级别设置为8
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('设置地图中心点失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理城市变化
|
||||||
|
const handleCityChange = (value) => {
|
||||||
|
selectedCity.value = value
|
||||||
|
|
||||||
|
// 如果有地图实例,定位到选择的城市
|
||||||
|
if (map.value) {
|
||||||
|
try {
|
||||||
|
// 使用地理编码获取城市中心点
|
||||||
|
const geocoder = createGeocoder()
|
||||||
|
geocoder.getLocation(value, (status, result) => {
|
||||||
|
if (status === 'complete' && result.info === 'OK' && result.geocodes.length > 0) {
|
||||||
|
const location = result.geocodes[0].location
|
||||||
|
map.value.setCenter([location.lng, location.lat])
|
||||||
|
map.value.setZoom(12) // 城市级别,缩放级别设置为12
|
||||||
|
|
||||||
|
// 清空搜索框,准备输入详细地址
|
||||||
|
searchAddress.value = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('设置地图中心点失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 监听props变化
|
// 监听props变化
|
||||||
watch(() => props.modelValue, (newVal, oldVal) => {
|
watch(() => props.modelValue, (newVal, oldVal) => {
|
||||||
console.log('props变化:', newVal, oldVal)
|
console.log('props变化:', newVal, oldVal)
|
||||||
@ -97,6 +289,42 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
map.value.setCenter([newVal.longitude, newVal.latitude])
|
map.value.setCenter([newVal.longitude, newVal.latitude])
|
||||||
|
|
||||||
|
// 尝试从地址中提取省市信息
|
||||||
|
if (newVal.address) {
|
||||||
|
// 使用逆地理编码获取省市信息
|
||||||
|
const geocoder = createGeocoder()
|
||||||
|
geocoder.getAddress([newVal.longitude, newVal.latitude], (status, result) => {
|
||||||
|
if (status === 'complete' && result.info === 'OK') {
|
||||||
|
const addressComponent = result.regeocode.addressComponent
|
||||||
|
if (addressComponent) {
|
||||||
|
const province = addressComponent.province
|
||||||
|
const city = addressComponent.city
|
||||||
|
|
||||||
|
// 更新省份选择
|
||||||
|
const foundProvince = provinceOptions.value.find(p =>
|
||||||
|
province.includes(p.value) || p.value.includes(province)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (foundProvince) {
|
||||||
|
selectedProvince.value = foundProvince.value
|
||||||
|
|
||||||
|
// 更新城市选择
|
||||||
|
cityOptions.value = fallbackCitiesMap[foundProvince.value] || []
|
||||||
|
|
||||||
|
if (city) {
|
||||||
|
const foundCity = cityOptions.value.find(c =>
|
||||||
|
city.includes(c.value) || c.value.includes(city)
|
||||||
|
)
|
||||||
|
if (foundCity) {
|
||||||
|
selectedCity.value = foundCity.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新地图标记失败:', error)
|
console.error('更新地图标记失败:', error)
|
||||||
}
|
}
|
||||||
@ -174,9 +402,46 @@ export default {
|
|||||||
geocoder.getAddress([lng, lat], (status, result) => {
|
geocoder.getAddress([lng, lat], (status, result) => {
|
||||||
if (status === 'complete' && result.info === 'OK') {
|
if (status === 'complete' && result.info === 'OK') {
|
||||||
address.value = result.regeocode.formattedAddress
|
address.value = result.regeocode.formattedAddress
|
||||||
|
|
||||||
|
// 尝试从地址中提取省市信息
|
||||||
|
const addressComponent = result.regeocode.addressComponent
|
||||||
|
if (addressComponent) {
|
||||||
|
const province = addressComponent.province
|
||||||
|
const city = addressComponent.city
|
||||||
|
|
||||||
|
// 更新省份选择
|
||||||
|
const foundProvince = provinceOptions.value.find(p =>
|
||||||
|
province.includes(p.value) || p.value.includes(province)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (foundProvince) {
|
||||||
|
selectedProvince.value = foundProvince.value
|
||||||
|
|
||||||
|
// 更新城市选择
|
||||||
|
cityOptions.value = fallbackCitiesMap[foundProvince.value] || []
|
||||||
|
|
||||||
|
if (city) {
|
||||||
|
const foundCity = cityOptions.value.find(c =>
|
||||||
|
city.includes(c.value) || c.value.includes(city)
|
||||||
|
)
|
||||||
|
if (foundCity) {
|
||||||
|
selectedCity.value = foundCity.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateValue()
|
updateValue()
|
||||||
} else {
|
} else {
|
||||||
message.error('获取地址信息失败')
|
// 如果获取地址失败,使用经纬度作为地址
|
||||||
|
if (selectedCity.value) {
|
||||||
|
address.value = `${selectedProvince.value} ${selectedCity.value} (${lng.toFixed(6)},${lat.toFixed(6)})`
|
||||||
|
} else if (selectedProvince.value) {
|
||||||
|
address.value = `${selectedProvince.value} (${lng.toFixed(6)},${lat.toFixed(6)})`
|
||||||
|
} else {
|
||||||
|
address.value = `位置坐标: ${lng.toFixed(6)},${lat.toFixed(6)}`
|
||||||
|
}
|
||||||
|
updateValue()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -212,48 +477,140 @@ export default {
|
|||||||
searchLoading.value = true
|
searchLoading.value = true
|
||||||
await loadAMap()
|
await loadAMap()
|
||||||
|
|
||||||
const autoComplete = createAutoComplete()
|
// 检查是否是经纬度格式 (例如: 116.123456,39.123456)
|
||||||
await new Promise((resolve, reject) => {
|
const lngLatRegex = /^(\d+\.\d+),(\d+\.\d+)$/
|
||||||
autoComplete.search(value, (status, result) => {
|
const lngLatMatch = value.match(lngLatRegex)
|
||||||
if (status === 'complete') {
|
|
||||||
searchOptions.value = result.tips.map(tip => ({
|
if (lngLatMatch) {
|
||||||
value: tip.name,
|
const lng = parseFloat(lngLatMatch[1])
|
||||||
label: `${tip.name} (${tip.district})`,
|
const lat = parseFloat(lngLatMatch[2])
|
||||||
location: tip.location
|
|
||||||
}))
|
if (!isNaN(lng) && !isNaN(lat) && lng >= -180 && lng <= 180 && lat >= -90 && lat <= 90) {
|
||||||
resolve(result)
|
// 是有效的经纬度,直接使用
|
||||||
} else {
|
searchOptions.value = [{
|
||||||
reject(new Error(status))
|
value: `位置坐标: ${lng},${lat}`,
|
||||||
}
|
label: `位置坐标: ${lng},${lat}`,
|
||||||
|
location: { lng, lat }
|
||||||
|
}]
|
||||||
searchLoading.value = false
|
searchLoading.value = false
|
||||||
})
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoComplete = createAutoComplete({
|
||||||
|
city: selectedCity.value || selectedProvince.value || '全国',
|
||||||
|
citylimit: !!selectedCity.value
|
||||||
|
})
|
||||||
|
|
||||||
|
// 构建搜索关键词,包含省市信息
|
||||||
|
let keyword = value
|
||||||
|
if (selectedCity.value) {
|
||||||
|
keyword = `${selectedCity.value} ${value}`
|
||||||
|
} else if (selectedProvince.value) {
|
||||||
|
keyword = `${selectedProvince.value} ${value}`
|
||||||
|
}
|
||||||
|
|
||||||
|
autoComplete.search(keyword, (status, result) => {
|
||||||
|
if (status === 'complete' && result.tips && result.tips.length > 0) {
|
||||||
|
searchOptions.value = result.tips.map(tip => ({
|
||||||
|
value: tip.name,
|
||||||
|
label: `${tip.name} (${tip.district || ''})`,
|
||||||
|
location: tip.location
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
// 如果搜索失败,添加一个手动输入选项
|
||||||
|
searchOptions.value = [{
|
||||||
|
value: value,
|
||||||
|
label: `使用"${value}"作为地址(需手动在地图上选点)`,
|
||||||
|
manualInput: true
|
||||||
|
}]
|
||||||
|
message.info('未找到匹配的地址,您可以直接使用输入的文本或在地图上选点')
|
||||||
|
}
|
||||||
|
searchLoading.value = false
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('搜索地址失败:', error)
|
console.error('搜索地址失败:', error)
|
||||||
searchLoading.value = false
|
searchLoading.value = false
|
||||||
message.error('搜索地址失败')
|
|
||||||
|
// 如果搜索失败,添加一个手动输入选项
|
||||||
|
searchOptions.value = [{
|
||||||
|
value: value,
|
||||||
|
label: `使用"${value}"作为地址(需手动在地图上选点)`,
|
||||||
|
manualInput: true
|
||||||
|
}]
|
||||||
|
message.info('搜索地址失败,您可以直接使用输入的文本或在地图上选点')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择地址
|
// 选择地址
|
||||||
const handleSelect = (value, option) => {
|
const handleSelect = (value, option) => {
|
||||||
|
// 直接使用选中的值作为地址
|
||||||
|
address.value = value
|
||||||
|
|
||||||
|
// 查找选中的地址信息
|
||||||
const selected = searchOptions.value.find(opt => opt.value === value)
|
const selected = searchOptions.value.find(opt => opt.value === value)
|
||||||
if (selected && selected.location) {
|
|
||||||
const { lng, lat } = selected.location
|
// 如果是手动输入的地址,或者没有位置信息
|
||||||
updateMarkerPosition(lng, lat)
|
if (!selected || selected.manualInput || !selected.location) {
|
||||||
|
message.info('请在地图上选择具体位置')
|
||||||
|
updateValue()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { lng, lat } = selected.location
|
||||||
|
|
||||||
|
// 更新标记位置
|
||||||
|
updateMarkerPosition(lng, lat)
|
||||||
|
|
||||||
|
// 更新地图中心点
|
||||||
|
if (map.value) {
|
||||||
map.value.setCenter([lng, lat])
|
map.value.setCenter([lng, lat])
|
||||||
|
map.value.setZoom(15) // 放大到合适的级别
|
||||||
// 使用逆地理编码获取完整地址
|
}
|
||||||
|
|
||||||
|
// 尝试获取更详细的地址信息
|
||||||
|
try {
|
||||||
const geocoder = createGeocoder()
|
const geocoder = createGeocoder()
|
||||||
geocoder.getAddress([lng, lat], (status, result) => {
|
geocoder.getAddress([lng, lat], (status, result) => {
|
||||||
if (status === 'complete' && result.info === 'OK') {
|
if (status === 'complete' && result.info === 'OK') {
|
||||||
address.value = result.regeocode.formattedAddress
|
address.value = result.regeocode.formattedAddress
|
||||||
updateValue()
|
|
||||||
} else {
|
// 尝试从地址中提取省市信息
|
||||||
address.value = value
|
const addressComponent = result.regeocode.addressComponent
|
||||||
updateValue()
|
if (addressComponent) {
|
||||||
|
const province = addressComponent.province
|
||||||
|
const city = addressComponent.city
|
||||||
|
|
||||||
|
// 更新省份选择
|
||||||
|
const foundProvince = provinceOptions.value.find(p =>
|
||||||
|
province.includes(p.value) || p.value.includes(province)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (foundProvince) {
|
||||||
|
selectedProvince.value = foundProvince.value
|
||||||
|
|
||||||
|
// 更新城市选择
|
||||||
|
cityOptions.value = fallbackCitiesMap[foundProvince.value] || []
|
||||||
|
|
||||||
|
if (city) {
|
||||||
|
const foundCity = cityOptions.value.find(c =>
|
||||||
|
city.includes(c.value) || c.value.includes(city)
|
||||||
|
)
|
||||||
|
if (foundCity) {
|
||||||
|
selectedCity.value = foundCity.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 无论成功失败都更新值
|
||||||
|
updateValue()
|
||||||
})
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取详细地址失败:', error)
|
||||||
|
// 即使获取详细地址失败,也已经有了基本地址和经纬度,可以继续使用
|
||||||
|
updateValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +629,15 @@ export default {
|
|||||||
longitude,
|
longitude,
|
||||||
latitude,
|
latitude,
|
||||||
handleSearch,
|
handleSearch,
|
||||||
handleSelect
|
handleSelect,
|
||||||
|
// 省市选择相关
|
||||||
|
provinceOptions,
|
||||||
|
cityOptions,
|
||||||
|
selectedProvince,
|
||||||
|
selectedCity,
|
||||||
|
handleProvinceChange,
|
||||||
|
handleCityChange,
|
||||||
|
filterOption
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,6 +648,19 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.region-search-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.region-selector {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.map-picker-input {
|
.map-picker-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -301,4 +679,21 @@ export default {
|
|||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.ant-select-selector) {
|
||||||
|
border-radius: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-select-dropdown) {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-select-item) {
|
||||||
|
padding: 6px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input-affix-wrapper) {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -1,62 +1,244 @@
|
|||||||
// 高德地图配置
|
// 高德地图配置
|
||||||
const MAP_CONFIG = {
|
const MAP_CONFIG = {
|
||||||
key: 'fd47f3d4f54b675693c7d59dcd2a6c5f',
|
key: 'fd47f3d4f54b675693c7d59dcd2a6c5f', // Web端key
|
||||||
securityJsCode: '93527b49270ba2142f47f0407da7c0d6'
|
securityJsCode: '93527b49270ba2142f47f0407da7c0d6', // 安全密钥
|
||||||
|
webServiceKey: '4f017f9f211e76a8fc8093e29531f09c', // Web服务key
|
||||||
|
version: '2.0',
|
||||||
|
plugins: [
|
||||||
|
'AMap.ToolBar',
|
||||||
|
'AMap.Scale',
|
||||||
|
'AMap.HawkEye',
|
||||||
|
'AMap.MapType',
|
||||||
|
'AMap.Geolocation',
|
||||||
|
'AMap.Geocoder',
|
||||||
|
'AMap.AutoComplete',
|
||||||
|
'AMap.PlaceSearch',
|
||||||
|
'AMap.DistrictSearch'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置安全密钥
|
// 加载状态
|
||||||
window._AMapSecurityConfig = {
|
let loadingPromise = null
|
||||||
securityJsCode: MAP_CONFIG.securityJsCode
|
let AMap = null
|
||||||
}
|
|
||||||
|
|
||||||
let isMapLoaded = false
|
/**
|
||||||
|
* 加载高德地图API
|
||||||
// 加载高德地图及其插件
|
* @returns {Promise} 加载完成的Promise
|
||||||
|
*/
|
||||||
export const loadAMap = () => {
|
export const loadAMap = () => {
|
||||||
return new Promise((resolve, reject) => {
|
if (window.AMap) {
|
||||||
if (isMapLoaded && window.AMap) {
|
AMap = window.AMap
|
||||||
resolve(window.AMap)
|
return Promise.resolve(window.AMap)
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (loadingPromise) {
|
||||||
|
return loadingPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
loadingPromise = new Promise((resolve, reject) => {
|
||||||
|
// 创建script标签
|
||||||
const script = document.createElement('script')
|
const script = document.createElement('script')
|
||||||
script.type = 'text/javascript'
|
script.type = 'text/javascript'
|
||||||
script.async = true
|
script.async = true
|
||||||
script.src = `https://webapi.amap.com/maps?v=2.0&key=${MAP_CONFIG.key}&plugin=AMap.Geocoder,AMap.AutoComplete,AMap.PlaceSearch`
|
script.src = `https://webapi.amap.com/maps?v=${MAP_CONFIG.version}&key=${MAP_CONFIG.key}&plugin=${MAP_CONFIG.plugins.join(',')}&security=${MAP_CONFIG.securityJsCode}`
|
||||||
|
|
||||||
|
script.onerror = reject
|
||||||
script.onload = () => {
|
script.onload = () => {
|
||||||
isMapLoaded = true
|
// 设置安全密钥
|
||||||
|
if (window.AMap && window.AMap.SecurityConfig) {
|
||||||
|
window.AMap.SecurityConfig.securityJsCode = MAP_CONFIG.securityJsCode
|
||||||
|
}
|
||||||
|
|
||||||
|
AMap = window.AMap
|
||||||
resolve(window.AMap)
|
resolve(window.AMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
script.onerror = () => {
|
|
||||||
reject(new Error('加载高德地图失败'))
|
|
||||||
}
|
|
||||||
|
|
||||||
document.head.appendChild(script)
|
document.head.appendChild(script)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return loadingPromise
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建地图实例
|
/**
|
||||||
|
* 创建地图实例
|
||||||
|
* @param {string} container 容器ID
|
||||||
|
* @param {Object} options 地图选项
|
||||||
|
* @returns {Object} 地图实例
|
||||||
|
*/
|
||||||
export const createMap = (container, options = {}) => {
|
export const createMap = (container, options = {}) => {
|
||||||
const defaultOptions = {
|
if (!window.AMap) {
|
||||||
zoom: 15,
|
console.error('AMap未加载,请先调用loadAMap')
|
||||||
viewMode: '2D',
|
return null
|
||||||
center: [116.397428, 39.90923] // 默认中心点
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const defaultOptions = {
|
||||||
|
zoom: 11,
|
||||||
|
center: [116.397428, 39.90923], // 默认北京
|
||||||
|
viewMode: '2D'
|
||||||
|
}
|
||||||
|
|
||||||
|
return new window.AMap.Map(container, { ...defaultOptions, ...options })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('创建地图失败:', error)
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
return new window.AMap.Map(container, { ...defaultOptions, ...options })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建地址搜索服务
|
/**
|
||||||
|
* 创建自动完成实例
|
||||||
|
* @param {Object} options 选项
|
||||||
|
* @returns {Object} 自动完成实例
|
||||||
|
*/
|
||||||
export const createAutoComplete = (options = {}) => {
|
export const createAutoComplete = (options = {}) => {
|
||||||
return new window.AMap.AutoComplete({
|
if (!window.AMap) {
|
||||||
city: '全国',
|
console.error('AMap未加载,请先调用loadAMap')
|
||||||
citylimit: true,
|
return null
|
||||||
...options
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const defaultOptions = {
|
||||||
|
city: '全国', // 城市,默认全国
|
||||||
|
citylimit: false, // 是否限制城市内搜索
|
||||||
|
input: 'search-input' // 输入框ID,这里不使用
|
||||||
|
}
|
||||||
|
|
||||||
|
return new window.AMap.AutoComplete({ ...defaultOptions, ...options })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('创建自动完成实例失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建地理编码实例
|
||||||
|
* @param {Object} options 选项
|
||||||
|
* @returns {Object} 地理编码实例
|
||||||
|
*/
|
||||||
|
export const createGeocoder = (options = {}) => {
|
||||||
|
if (!window.AMap) {
|
||||||
|
console.error('AMap未加载,请先调用loadAMap')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const defaultOptions = {
|
||||||
|
city: '全国', // 城市,默认全国
|
||||||
|
radius: 1000 // 搜索半径
|
||||||
|
}
|
||||||
|
|
||||||
|
return new window.AMap.Geocoder({ ...defaultOptions, ...options })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('创建地理编码实例失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建地点搜索实例
|
||||||
|
* @param {Object} options 选项
|
||||||
|
* @returns {Object} 地点搜索实例
|
||||||
|
*/
|
||||||
|
export const createPlaceSearch = (options = {}) => {
|
||||||
|
if (!window.AMap) {
|
||||||
|
console.error('AMap未加载,请先调用loadAMap')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const defaultOptions = {
|
||||||
|
city: '全国', // 城市,默认全国
|
||||||
|
citylimit: false, // 是否限制城市内搜索
|
||||||
|
autoFitView: true // 是否自动调整地图视野
|
||||||
|
}
|
||||||
|
|
||||||
|
return new window.AMap.PlaceSearch({ ...defaultOptions, ...options })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('创建地点搜索实例失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建行政区查询实例
|
||||||
|
* @param {Object} options 选项
|
||||||
|
* @returns {Object} 行政区查询实例
|
||||||
|
*/
|
||||||
|
export const createDistrictSearch = (options = {}) => {
|
||||||
|
if (!window.AMap) {
|
||||||
|
console.error('AMap未加载,请先调用loadAMap')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const defaultOptions = {
|
||||||
|
level: 'district', // 级别
|
||||||
|
showbiz: false, // 是否显示商圈
|
||||||
|
extensions: 'all' // 返回行政区边界坐标点
|
||||||
|
}
|
||||||
|
|
||||||
|
return new window.AMap.DistrictSearch({ ...defaultOptions, ...options })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('创建行政区查询实例失败:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取行政区数据
|
||||||
|
* @param {string} keywords 关键字,如"中国"
|
||||||
|
* @param {number} subdistrict 子行政区级数
|
||||||
|
* @returns {Promise} 包含行政区数据的Promise
|
||||||
|
*/
|
||||||
|
export const fetchDistrictData = (keywords = '中国', subdistrict = 1) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// 尝试使用Web服务API直接获取
|
||||||
|
fetch(`https://restapi.amap.com/v3/config/district?keywords=${keywords}&subdistrict=${subdistrict}&key=${MAP_CONFIG.webServiceKey}&output=json`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status === '1') {
|
||||||
|
resolve(data)
|
||||||
|
} else {
|
||||||
|
// 如果Web服务API失败,尝试使用DistrictSearch
|
||||||
|
loadAMap().then(() => {
|
||||||
|
const districtSearch = createDistrictSearch()
|
||||||
|
districtSearch.search(keywords, (status, result) => {
|
||||||
|
if (status === 'complete') {
|
||||||
|
resolve(result)
|
||||||
|
} else {
|
||||||
|
reject(new Error('获取行政区数据失败'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(reject)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// 如果fetch失败,尝试使用DistrictSearch
|
||||||
|
loadAMap().then(() => {
|
||||||
|
const districtSearch = createDistrictSearch()
|
||||||
|
districtSearch.search(keywords, (status, result) => {
|
||||||
|
if (status === 'complete') {
|
||||||
|
resolve(result)
|
||||||
|
} else {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(reject)
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建地理编码服务
|
export default {
|
||||||
export const createGeocoder = () => {
|
MAP_CONFIG,
|
||||||
return new window.AMap.Geocoder()
|
loadAMap,
|
||||||
|
createMap,
|
||||||
|
createAutoComplete,
|
||||||
|
createGeocoder,
|
||||||
|
createPlaceSearch,
|
||||||
|
createDistrictSearch,
|
||||||
|
fetchDistrictData
|
||||||
}
|
}
|
||||||
@ -39,6 +39,27 @@
|
|||||||
<a v-if="record.qy_group_qrcode" @click="previewQRCode(record.qy_group_qrcode)">查看二维码</a>
|
<a v-if="record.qy_group_qrcode" @click="previewQRCode(record.qy_group_qrcode)">查看二维码</a>
|
||||||
<span v-else>-</span>
|
<span v-else>-</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.key === 'weekdays'">
|
||||||
|
<div class="weekdays-display">
|
||||||
|
<template v-if="record.weekdays && record.weekdays.length > 0">
|
||||||
|
<template v-if="isAllWeekdaysSelected(record.weekdays)">
|
||||||
|
<a-tag color="green">所有时间</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="weekdays-tags">
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 1)" color="blue">周一</a-tag>
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 2)" color="blue">周二</a-tag>
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 3)" color="blue">周三</a-tag>
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 4)" color="blue">周四</a-tag>
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 5)" color="blue">周五</a-tag>
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 6)" color="green">周六</a-tag>
|
||||||
|
<a-tag v-if="hasWeekday(record.weekdays, 7)" color="green">周日</a-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template v-if="column.key === 'delivery_price'">
|
<template v-if="column.key === 'delivery_price'">
|
||||||
<div class="delivery-price-info">
|
<div class="delivery-price-info">
|
||||||
<div>基础费:<span style="color: #1890ff; font-weight: bold;">{{ record.base_price }}</span> 元/单</div>
|
<div>基础费:<span style="color: #1890ff; font-weight: bold;">{{ record.base_price }}</span> 元/单</div>
|
||||||
@ -121,7 +142,7 @@
|
|||||||
@ok="handleSubmit"
|
@ok="handleSubmit"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
:confirmLoading="confirmLoading"
|
:confirmLoading="confirmLoading"
|
||||||
width="900px"
|
width="1000px"
|
||||||
>
|
>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-space>
|
<a-space>
|
||||||
@ -145,6 +166,36 @@
|
|||||||
<a-input v-model:value="formState.name" placeholder="请输入小区名称" />
|
<a-input v-model:value="formState.name" placeholder="请输入小区名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item required>
|
||||||
|
<template #label>
|
||||||
|
<div class="weekdays-label-container">
|
||||||
|
<span>服务时间</span>
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="toggleAllWeekdays"
|
||||||
|
class="select-all-btn"
|
||||||
|
>
|
||||||
|
{{ isAllSelected ? '取消全选' : '全选' }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="weekdays-checkbox-group">
|
||||||
|
<a-checkbox-group v-model:value="formState.weekdays">
|
||||||
|
<a-checkbox :value="1">周一</a-checkbox>
|
||||||
|
<a-checkbox :value="2">周二</a-checkbox>
|
||||||
|
<a-checkbox :value="3">周三</a-checkbox>
|
||||||
|
<a-checkbox :value="4">周四</a-checkbox>
|
||||||
|
<a-checkbox :value="5">周五</a-checkbox>
|
||||||
|
<a-checkbox :value="6">周六</a-checkbox>
|
||||||
|
<a-checkbox :value="7">周日</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div class="form-item-tip">
|
||||||
|
选择小区可提供配送服务的时间
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="企业微信Webhook"
|
label="企业微信Webhook"
|
||||||
name="webot_webhook"
|
name="webot_webhook"
|
||||||
@ -463,27 +514,42 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, ref, onMounted, nextTick } from 'vue'
|
import { defineComponent, ref, onMounted, nextTick, computed } from 'vue'
|
||||||
import { message, Tag, Menu, Dropdown, Image, Upload } from 'ant-design-vue'
|
import { message, Tag, Menu, Dropdown, Image, Upload, Checkbox, Table, Button, Input, Form, Modal, Space, InputNumber, Card } from 'ant-design-vue'
|
||||||
import { getCommunityList, createCommunity, updateCommunityStatus, updateCommunity, uploadImage } from '@/api/community'
|
import { getCommunityList, createCommunity, updateCommunityStatus, updateCommunity, uploadImage } from '@/api/community'
|
||||||
import { loadAMap, createMap } from '@/utils/amap.js'
|
import { loadAMap, createMap } from '@/utils/amap.js'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import PageContainer from '@/components/PageContainer.vue'
|
import PageContainer from '@/components/PageContainer.vue'
|
||||||
import { DownOutlined, PlusOutlined } from '@ant-design/icons-vue'
|
|
||||||
import MapPicker from '@/components/MapPicker/index.vue'
|
import MapPicker from '@/components/MapPicker/index.vue'
|
||||||
import request from '../../utils/request'
|
import {
|
||||||
|
DownOutlined,
|
||||||
|
PlusOutlined
|
||||||
|
} from '@ant-design/icons-vue'
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
PageContainer,
|
PageContainer,
|
||||||
|
ATable: Table,
|
||||||
ATag: Tag,
|
ATag: Tag,
|
||||||
|
AButton: Button,
|
||||||
|
AInput: Input,
|
||||||
|
AForm: Form,
|
||||||
|
AFormItem: Form.Item,
|
||||||
|
AModal: Modal,
|
||||||
ADropdown: Dropdown,
|
ADropdown: Dropdown,
|
||||||
AMenu: Menu,
|
AMenu: Menu,
|
||||||
AMenuItem: Menu.Item,
|
AMenuItem: Menu.Item,
|
||||||
DownOutlined,
|
DownOutlined,
|
||||||
MapPicker,
|
MapPicker,
|
||||||
|
ASpace: Space,
|
||||||
|
AInputNumber: InputNumber,
|
||||||
|
ACard: Card,
|
||||||
AImage: Image,
|
AImage: Image,
|
||||||
AUpload: Upload,
|
AUpload: Upload,
|
||||||
PlusOutlined
|
PlusOutlined,
|
||||||
|
ACheckbox: Checkbox,
|
||||||
|
ACheckboxGroup: Checkbox.Group
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@ -553,6 +619,12 @@ export default defineComponent({
|
|||||||
key: 'admin',
|
key: 'admin',
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '服务时间',
|
||||||
|
key: 'weekdays',
|
||||||
|
width: 150,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '位置',
|
title: '位置',
|
||||||
key: 'location',
|
key: 'location',
|
||||||
@ -668,8 +740,28 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
qy_group_qrcode: '',
|
qy_group_qrcode: '',
|
||||||
status: 'UNOPEN',
|
status: 'UNOPEN',
|
||||||
webot_webhook: ''
|
webot_webhook: '',
|
||||||
|
weekdays: [1, 2, 3, 4, 5, 6, 7] // 默认全选,周一到周日,使用数字
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 计算属性:是否全部选中
|
||||||
|
const isAllSelected = computed(() => {
|
||||||
|
const allDays = [1, 2, 3, 4, 5, 6, 7];
|
||||||
|
return formState.value.weekdays &&
|
||||||
|
formState.value.weekdays.length === 7 &&
|
||||||
|
allDays.every(day => formState.value.weekdays.includes(day));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 全选/取消全选方法
|
||||||
|
const toggleAllWeekdays = () => {
|
||||||
|
if (isAllSelected.value) {
|
||||||
|
// 如果已全选,则清空选择
|
||||||
|
formState.value.weekdays = [];
|
||||||
|
} else {
|
||||||
|
// 如果未全选,则全部选中
|
||||||
|
formState.value.weekdays = [1, 2, 3, 4, 5, 6, 7];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
name: [{ required: true, message: '请输入小区名称' }],
|
name: [{ required: true, message: '请输入小区名称' }],
|
||||||
@ -682,6 +774,9 @@ export default defineComponent({
|
|||||||
],
|
],
|
||||||
qy_group_qrcode: [
|
qy_group_qrcode: [
|
||||||
{ required: true, message: '请上传群二维码' }
|
{ required: true, message: '请上传群二维码' }
|
||||||
|
],
|
||||||
|
weekdays: [
|
||||||
|
{ required: false, type: 'array' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,13 +805,47 @@ export default defineComponent({
|
|||||||
|
|
||||||
console.log('编辑小区,处理后的地址信息:', locationData)
|
console.log('编辑小区,处理后的地址信息:', locationData)
|
||||||
|
|
||||||
|
// 处理 weekdays 数据,确保是数字数组格式
|
||||||
|
let weekdaysData = []; // 默认为空数组,表示没有选择
|
||||||
|
if (record.weekdays) {
|
||||||
|
try {
|
||||||
|
// 如果已经是数组,直接使用
|
||||||
|
if (Array.isArray(record.weekdays)) {
|
||||||
|
weekdaysData = record.weekdays.map(item => typeof item === 'string' ? parseInt(item, 10) : item);
|
||||||
|
}
|
||||||
|
// 尝试解析 JSON 字符串
|
||||||
|
else if (typeof record.weekdays === 'string') {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(record.weekdays);
|
||||||
|
if (Array.isArray(parsedData) && parsedData.length > 0) {
|
||||||
|
// 确保数组中的元素是数字
|
||||||
|
weekdaysData = parsedData.map(item => typeof item === 'string' ? parseInt(item, 10) : item);
|
||||||
|
} else if (typeof parsedData === 'string' && parsedData.trim() !== '') {
|
||||||
|
// 如果解析出来是字符串,可能是逗号分隔的
|
||||||
|
weekdaysData = parsedData.split(',').map(item => parseInt(item, 10));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 如果JSON解析失败,可能是逗号分隔的字符串,尝试转换
|
||||||
|
if (record.weekdays.trim() !== '') {
|
||||||
|
weekdaysData = record.weekdays.split(',').map(item => parseInt(item, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析 weekdays 失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('编辑小区,处理后的服务时间:', weekdaysData, '原始数据:', record.weekdays);
|
||||||
|
|
||||||
// 填充表单数据
|
// 填充表单数据
|
||||||
formState.value = {
|
formState.value = {
|
||||||
name: record.name || '',
|
name: record.name || '',
|
||||||
location: locationData,
|
location: locationData,
|
||||||
qy_group_qrcode: record.qy_group_qrcode || '',
|
qy_group_qrcode: record.qy_group_qrcode || '',
|
||||||
status: record.status || 'UNOPEN',
|
status: record.status || 'UNOPEN',
|
||||||
webot_webhook: record.webot_webhook || ''
|
webot_webhook: record.webot_webhook || '',
|
||||||
|
weekdays: weekdaysData
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有二维码,设置文件列表
|
// 如果有二维码,设置文件列表
|
||||||
@ -760,7 +889,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
qy_group_qrcode: '',
|
qy_group_qrcode: '',
|
||||||
status: 'UNOPEN',
|
status: 'UNOPEN',
|
||||||
webot_webhook: ''
|
webot_webhook: '',
|
||||||
|
weekdays: [1, 2, 3, 4, 5, 6, 7] // 默认全选,周一到周日,使用数字
|
||||||
}
|
}
|
||||||
|
|
||||||
fileList.value = []
|
fileList.value = []
|
||||||
@ -868,7 +998,8 @@ export default defineComponent({
|
|||||||
latitude: formState.value.location.latitude,
|
latitude: formState.value.location.latitude,
|
||||||
qy_group_qrcode: formState.value.qy_group_qrcode,
|
qy_group_qrcode: formState.value.qy_group_qrcode,
|
||||||
status: formState.value.status,
|
status: formState.value.status,
|
||||||
webot_webhook: formState.value.webot_webhook
|
webot_webhook: formState.value.webot_webhook,
|
||||||
|
weekdays: formState.value.weekdays // 直接传递数组,不转换为 JSON 字符串
|
||||||
}
|
}
|
||||||
|
|
||||||
let res
|
let res
|
||||||
@ -1268,6 +1399,64 @@ export default defineComponent({
|
|||||||
currentCommunity.value = null
|
currentCommunity.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否包含特定的工作日
|
||||||
|
const hasWeekday = (weekdays, day) => {
|
||||||
|
if (!weekdays) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 如果是字符串,尝试解析为数组
|
||||||
|
if (typeof weekdays === 'string') {
|
||||||
|
try {
|
||||||
|
const parsedWeekdays = JSON.parse(weekdays);
|
||||||
|
return Array.isArray(parsedWeekdays) && parsedWeekdays.includes(day);
|
||||||
|
} catch (e) {
|
||||||
|
// 如果解析失败,可能是逗号分隔的字符串
|
||||||
|
return weekdays.split(',').map(item => parseInt(item, 10)).includes(day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已经是数组
|
||||||
|
if (Array.isArray(weekdays)) {
|
||||||
|
return weekdays.includes(day);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析 weekdays 失败:', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 检查是否选择了所有时间(周一到周日)
|
||||||
|
const isAllWeekdaysSelected = (weekdays) => {
|
||||||
|
if (!weekdays) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let weekdaysArray = weekdays;
|
||||||
|
|
||||||
|
// 如果是字符串,尝试解析为数组
|
||||||
|
if (typeof weekdays === 'string') {
|
||||||
|
try {
|
||||||
|
weekdaysArray = JSON.parse(weekdays);
|
||||||
|
} catch (e) {
|
||||||
|
// 如果解析失败,可能是逗号分隔的字符串
|
||||||
|
weekdaysArray = weekdays.split(',').map(item => parseInt(item, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否包含所有天(1-7)
|
||||||
|
if (Array.isArray(weekdaysArray)) {
|
||||||
|
const allDays = [1, 2, 3, 4, 5, 6, 7];
|
||||||
|
return allDays.every(day => weekdaysArray.includes(day)) && weekdaysArray.length === 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('检查所有时间失败:', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchData()
|
fetchData()
|
||||||
})
|
})
|
||||||
@ -1331,7 +1520,11 @@ export default defineComponent({
|
|||||||
handleAdminSave,
|
handleAdminSave,
|
||||||
handleAdminCancel,
|
handleAdminCancel,
|
||||||
selectSearchResult,
|
selectSearchResult,
|
||||||
handleRemoveAdmin
|
handleRemoveAdmin,
|
||||||
|
hasWeekday,
|
||||||
|
isAllWeekdaysSelected,
|
||||||
|
isAllSelected,
|
||||||
|
toggleAllWeekdays
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -1653,56 +1846,6 @@ export default defineComponent({
|
|||||||
color: #ff4d4f;
|
color: #ff4d4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profit-sharing-form {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profit-rate-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profit-rate-label {
|
|
||||||
width: 150px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: rgba(0, 0, 0, 0.85);
|
|
||||||
}
|
|
||||||
|
|
||||||
.profit-rate-input {
|
|
||||||
width: 100px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profit-rate-tip {
|
|
||||||
flex: 1;
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgba(0, 0, 0, 0.45);
|
|
||||||
}
|
|
||||||
|
|
||||||
.total-rate-info {
|
|
||||||
margin-top: 16px;
|
|
||||||
padding: 8px 12px;
|
|
||||||
background-color: #f6ffed;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #b7eb8f;
|
|
||||||
color: #52c41a;
|
|
||||||
font-weight: 500;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rate-error {
|
|
||||||
background-color: #fff2f0;
|
|
||||||
border-color: #ffccc7;
|
|
||||||
color: #ff4d4f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rate-error-message {
|
|
||||||
margin-left: 8px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 表格中分润比例显示样式 */
|
|
||||||
.profit-sharing-info-table {
|
.profit-sharing-info-table {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -1927,7 +2070,7 @@ export default defineComponent({
|
|||||||
/* 左右布局样式 */
|
/* 左右布局样式 */
|
||||||
.form-content {
|
.form-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-left {
|
.form-left {
|
||||||
@ -1939,4 +2082,206 @@ export default defineComponent({
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 服务时间复选框组样式 */
|
||||||
|
.weekdays-checkbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border-bottom: 1px dashed #e8e8e8;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-label-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-all-btn {
|
||||||
|
padding: 0;
|
||||||
|
height: auto;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-checkbox-group :deep(.ant-checkbox-group) {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-checkbox-group :deep(.ant-checkbox-wrapper) {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
min-width: 80px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
transition: all 0.3s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-checkbox-group :deep(.ant-checkbox-wrapper:hover) {
|
||||||
|
border-color: #1890ff;
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-checkbox-group :deep(.ant-checkbox-wrapper-checked) {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-checkbox-group :deep(.ant-checkbox) {
|
||||||
|
top: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-checkbox-group :deep(.ant-checkbox-wrapper span:last-child) {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单项提示文字样式优化 */
|
||||||
|
.form-item-tip {
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 4px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单布局优化 */
|
||||||
|
.form-content {
|
||||||
|
display: flex;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-left {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-right {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单项间距优化 */
|
||||||
|
:deep(.ant-form-item) {
|
||||||
|
margin-bottom: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-form-item-label) {
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单项标签样式优化 */
|
||||||
|
.community-form :deep(.ant-form-item-label > label) {
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 必填星号样式优化 */
|
||||||
|
.community-form :deep(.ant-form-item-required::before) {
|
||||||
|
color: #ff4d4f !important;
|
||||||
|
margin-right: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 输入框样式优化 */
|
||||||
|
:deep(.ant-input),
|
||||||
|
:deep(.ant-input-number),
|
||||||
|
:deep(.ant-select) {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input:hover),
|
||||||
|
:deep(.ant-input-number:hover),
|
||||||
|
:deep(.ant-select:hover) {
|
||||||
|
border-color: #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input:focus),
|
||||||
|
:deep(.ant-input-number-focused),
|
||||||
|
:deep(.ant-select-focused .ant-select-selector) {
|
||||||
|
border-color: #40a9ff;
|
||||||
|
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 模态框样式优化 */
|
||||||
|
:deep(.ant-modal-header) {
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-modal-title) {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-modal-body) {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-modal-footer) {
|
||||||
|
padding: 16px 24px;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮样式优化 */
|
||||||
|
:deep(.ant-btn) {
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-btn-primary) {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-btn-primary:hover) {
|
||||||
|
background-color: #40a9ff;
|
||||||
|
border-color: #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 服务时间显示样式 */
|
||||||
|
.weekdays-display {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekdays-tags :deep(.ant-tag) {
|
||||||
|
margin-right: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 0 6px;
|
||||||
|
line-height: 20px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user