|
|
@@ -18,14 +18,13 @@
|
|
|
<el-cascader
|
|
|
v-model="searchRegionValue"
|
|
|
:options="areaOptions"
|
|
|
- placeholder="所属城市"
|
|
|
- class="region-select"
|
|
|
+ :props="{ checkStrictly: true, value: 'id', label: 'name' }"
|
|
|
+ placeholder="所属站点"
|
|
|
+ class="station-select"
|
|
|
+ style="width: 350px"
|
|
|
clearable
|
|
|
@change="handleSearchAreaChange"
|
|
|
/>
|
|
|
- <el-select v-model="queryParams.station" placeholder="所属站点" class="station-select" clearable @change="handleQuery" :disabled="!queryParams.area">
|
|
|
- <el-option v-for="site in searchSiteOptions" :key="site.value" :label="site.label" :value="site.value" />
|
|
|
- </el-select>
|
|
|
<el-select v-model="queryParams.status" placeholder="状态" class="status-select" clearable @change="handleQuery">
|
|
|
<el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
@@ -210,20 +209,9 @@
|
|
|
<el-form-item label="有效期至" prop="validity">
|
|
|
<el-date-picker clearable v-model="form.validity" type="date" value-format="YYYY-MM-DD" placeholder="请选择有效期至" style="width: 100%" />
|
|
|
</el-form-item>
|
|
|
- <el-row :gutter="10">
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item label="所在区域" prop="regionId">
|
|
|
- <el-cascader v-model="regionValue" :options="areaOptions" placeholder="选择区域" style="width: 100%" @change="handleAreaChange" />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item label="归属站点" prop="site">
|
|
|
- <el-select v-model="form.site" placeholder="选择站点" :disabled="!form.regionId" style="width: 100%">
|
|
|
- <el-option v-for="site in siteOptions" :key="site.value" :label="site.label" :value="site.value" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
+ <el-form-item label="所属站点" prop="site">
|
|
|
+ <el-cascader v-model="regionValue" :options="areaOptions" :props="{ value: 'id', label: 'name' }" placeholder="选择站点" style="width: 100%" @change="handleAreaChange" />
|
|
|
+ </el-form-item>
|
|
|
<el-form-item label="详细地址">
|
|
|
<el-row :gutter="10" style="margin-bottom: 10px">
|
|
|
<el-col :span="24">
|
|
|
@@ -338,8 +326,8 @@ import { StoreVO, StoreForm, StoreQuery, StoreStatusVO, SysStorePageBo } from '@
|
|
|
import { listOnStore } from '@/api/system/tenant';
|
|
|
import { listOnStore as listTenantCategoriesOnStore } from '@/api/system/tenantCategories';
|
|
|
import { listAllService } from '@/api/service/list';
|
|
|
-import { listOnStore as listAreaStationOnStore } from '@/api/system/areaStation';
|
|
|
-import { SysAreaStationOnStoreVo } from '@/api/system/areaStation/types';
|
|
|
+import { listAreaStation } from '@/api/system/areaStation';
|
|
|
+import { AreaStationVO } from '@/api/system/areaStation/types';
|
|
|
import { regionData, codeToText, textToCode } from 'element-china-area-data';
|
|
|
import PageSelect from '@/components/PageSelect/index.vue';
|
|
|
import { checkPermi } from '@/utils/permission';
|
|
|
@@ -358,22 +346,21 @@ const searchSiteOptions = ref<any[]>([]); // 搜索的站点选项
|
|
|
|
|
|
/** 处理搜索区域选择变化 */
|
|
|
const handleSearchAreaChange = (value: any[]) => {
|
|
|
- queryParams.value.station = undefined;
|
|
|
-
|
|
|
if (value && value.length > 0) {
|
|
|
- const areaId = value[value.length - 1];
|
|
|
- queryParams.value.area = areaId;
|
|
|
- searchSiteOptions.value = areaStationList.value
|
|
|
- .filter((item: any) => item.type === 2 && String(item.parentId) === String(areaId))
|
|
|
- .map((item: any) => ({
|
|
|
- value: item.id,
|
|
|
- label: item.name
|
|
|
- }));
|
|
|
+ const lastId = value[value.length - 1];
|
|
|
+ const node = areaStationList.value.find(item => item.id === lastId);
|
|
|
+ if (node && node.type === 2) {
|
|
|
+ queryParams.value.station = lastId;
|
|
|
+ queryParams.value.area = node.parentId;
|
|
|
+ } else {
|
|
|
+ queryParams.value.area = lastId;
|
|
|
+ queryParams.value.station = undefined;
|
|
|
+ }
|
|
|
} else {
|
|
|
queryParams.value.area = undefined;
|
|
|
- searchSiteOptions.value = [];
|
|
|
+ queryParams.value.station = undefined;
|
|
|
}
|
|
|
- // 移除 handleQuery(); 只选城市不发送请求
|
|
|
+ handleQuery();
|
|
|
};
|
|
|
|
|
|
const regionValue = ref<any[]>([]);
|
|
|
@@ -391,7 +378,7 @@ const serviceList = ref<any[]>([]); // 服务项目列表
|
|
|
const statusList = ref<StoreStatusVO[]>([]); // 状态列表
|
|
|
const tenantCategoriesList = ref<any[]>([]); // 商户分类列表
|
|
|
const tenantCategoriesTotal = ref(0); // 商户分类总数
|
|
|
-const areaStationList = ref<SysAreaStationOnStoreVo[]>([]); // 区域站点列表
|
|
|
+const areaStationList = ref<AreaStationVO[]>([]); // 区域站点列表
|
|
|
const areaOptions = ref<any[]>([]); // 所在区域树形选项
|
|
|
const siteOptions = ref<any[]>([]); // 归属站点选项
|
|
|
|
|
|
@@ -617,8 +604,9 @@ const handleQuery = () => {
|
|
|
|
|
|
/** 新增按钮操作 */
|
|
|
const handleAdd = () => {
|
|
|
- if (areaStationList.value.length === 0) {
|
|
|
- proxy?.$modal.msgWarning("请先配置区域站点");
|
|
|
+ const hasStation = areaStationList.value.some(item => item.type === 2);
|
|
|
+ if (!hasStation) {
|
|
|
+ proxy?.$modal.msgWarning("请先配置站点");
|
|
|
return;
|
|
|
}
|
|
|
reset();
|
|
|
@@ -663,30 +651,22 @@ const handleUpdate = async (row: StoreVO) => {
|
|
|
}
|
|
|
|
|
|
if (res.data.site) {
|
|
|
- const siteData = areaStationList.value.find((item: any) => String(item.id) === String(res.data.site));
|
|
|
- if (siteData) {
|
|
|
- const regionId = siteData.parentId;
|
|
|
- form.value.regionId = regionId;
|
|
|
-
|
|
|
- const path: any[] = [];
|
|
|
- let currentId = regionId;
|
|
|
- while (currentId && String(currentId) !== '0') {
|
|
|
- path.unshift(currentId);
|
|
|
- const currentArea = areaStationList.value.find((item: any) => String(item.id) === String(currentId));
|
|
|
- if (currentArea) {
|
|
|
- currentId = currentArea.parentId;
|
|
|
- } else {
|
|
|
- break;
|
|
|
- }
|
|
|
+ const path: any[] = [];
|
|
|
+ let currentId = res.data.site;
|
|
|
+ while (currentId && String(currentId) !== '0') {
|
|
|
+ path.unshift(currentId);
|
|
|
+ const currentArea = areaStationList.value.find((item: any) => String(item.id) === String(currentId));
|
|
|
+ if (currentArea) {
|
|
|
+ currentId = currentArea.parentId;
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
}
|
|
|
- regionValue.value = path;
|
|
|
-
|
|
|
- siteOptions.value = areaStationList.value
|
|
|
- .filter((item: any) => item.type === 2 && String(item.parentId) === String(regionId))
|
|
|
- .map((item: any) => ({
|
|
|
- value: item.id,
|
|
|
- label: item.name
|
|
|
- }));
|
|
|
+ }
|
|
|
+ regionValue.value = path;
|
|
|
+ form.value.site = res.data.site;
|
|
|
+ const siteNode = areaStationList.value.find(n => n.id === res.data.site);
|
|
|
+ if (siteNode) {
|
|
|
+ form.value.regionId = siteNode.parentId;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -711,28 +691,76 @@ const submitForm = () => {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
-/** 获取经纬度 */
|
|
|
+/** 高德地图 Key 配置 */
|
|
|
+const amapKey = 'a30e76f457c14b6570925522be37565d';
|
|
|
+const securityJsCode = '531ae14ec1dff87e552e1ea51e848582';
|
|
|
+
|
|
|
+/** 动态加载高德地图脚本 */
|
|
|
+const loadAMapScript = (): Promise<any> => {
|
|
|
+ // 设置安全密钥
|
|
|
+ (window as any)._AMapSecurityConfig = {
|
|
|
+ securityJsCode: securityJsCode,
|
|
|
+ };
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ if ((window as any).AMap) {
|
|
|
+ resolve((window as any).AMap);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const script = document.createElement('script');
|
|
|
+ script.src = `https://webapi.amap.com/maps?v=2.0&key=${amapKey}`;
|
|
|
+ script.onload = () => resolve((window as any).AMap);
|
|
|
+ script.onerror = reject;
|
|
|
+ document.head.appendChild(script);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+/** 根据详细地址使用高德地图 Geocoder 获取经纬度 */
|
|
|
const getGeolocation = () => {
|
|
|
- if ('geolocation' in navigator) {
|
|
|
- navigator.geolocation.getCurrentPosition(
|
|
|
- (position) => {
|
|
|
- form.value.longitude = position.coords.longitude.toFixed(6);
|
|
|
- form.value.latitude = position.coords.latitude.toFixed(6);
|
|
|
- proxy?.$modal.msgSuccess('获取经纬度成功');
|
|
|
- },
|
|
|
- (error) => {
|
|
|
- let errorMessage = '获取位置失败';
|
|
|
- switch (error.code) {
|
|
|
- case error.PERMISSION_DENIED: errorMessage = '用户拒绝了地理定位请求'; break;
|
|
|
- case error.POSITION_UNAVAILABLE: errorMessage = '位置信息不可用'; break;
|
|
|
- case error.TIMEOUT: errorMessage = '获取位置超时'; break;
|
|
|
- case error.UNKNOWN_ERROR: errorMessage = '未知错误'; break;
|
|
|
+ // 拼接完整地址(省市区 + 详细地址)
|
|
|
+ let areaText = '';
|
|
|
+ if (addressCascaderValue.value && addressCascaderValue.value.length > 0) {
|
|
|
+ areaText = addressCascaderValue.value.map((code: string) => codeToText[code] || '').join('');
|
|
|
+ }
|
|
|
+ const detailAddr = form.value.detailAddress || '';
|
|
|
+ const fullAddress = (areaText + detailAddr).trim();
|
|
|
+
|
|
|
+ if (!fullAddress) {
|
|
|
+ proxy?.$modal.msgWarning('请先填写省市区和详细地址');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保高德地图脚本已加载
|
|
|
+ const doGeocode = () => {
|
|
|
+ const AMap = (window as any).AMap;
|
|
|
+ if (!AMap) {
|
|
|
+ proxy?.$modal.msgError('高德地图脚本未加载,请稍后重试');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ AMap.plugin('AMap.Geocoder', () => {
|
|
|
+ const geocoder = new AMap.Geocoder();
|
|
|
+ geocoder.getLocation(fullAddress, (status: string, result: any) => {
|
|
|
+ if (status === 'complete' && result.info === 'OK') {
|
|
|
+ const location = result.geocodes[0]?.location;
|
|
|
+ if (location) {
|
|
|
+ form.value.longitude = location.lng.toFixed(6);
|
|
|
+ form.value.latitude = location.lat.toFixed(6);
|
|
|
+ proxy?.$modal.msgSuccess('获取经纬度成功');
|
|
|
+ } else {
|
|
|
+ proxy?.$modal.msgError('未能解析到该地址的坐标,请检查地址是否准确');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ proxy?.$modal.msgError('地理编码失败:' + (result.info || status));
|
|
|
}
|
|
|
- proxy?.$modal.msgError(errorMessage);
|
|
|
- }
|
|
|
- );
|
|
|
+ });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ if ((window as any).AMap) {
|
|
|
+ doGeocode();
|
|
|
} else {
|
|
|
- proxy?.$modal.msgError('您的浏览器不支持地理定位');
|
|
|
+ loadAMapScript().then(() => doGeocode()).catch(() => {
|
|
|
+ proxy?.$modal.msgError('高德地图加载失败,请检查网络');
|
|
|
+ });
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -760,11 +788,10 @@ const getServiceList = async () => {
|
|
|
/** 获取区域站点列表 */
|
|
|
const getAreaStationList = async () => {
|
|
|
try {
|
|
|
- const res = await listAreaStationOnStore();
|
|
|
+ const res = await listAreaStation();
|
|
|
const data = res.data || res;
|
|
|
areaStationList.value = data;
|
|
|
- areaOptions.value = buildTree(data.filter((item: any) => item.type === 0 || item.type === 1), 0);
|
|
|
- siteOptions.value = [];
|
|
|
+ areaOptions.value = buildTree(data, 0);
|
|
|
} catch (error) {
|
|
|
console.error('获取区域站点列表失败:', error);
|
|
|
}
|
|
|
@@ -774,28 +801,31 @@ const getAreaStationList = async () => {
|
|
|
const buildTree = (data: any[], parentId: any): any[] => {
|
|
|
return data
|
|
|
.filter(item => String(item.parentId) === String(parentId))
|
|
|
- .map(item => ({
|
|
|
- value: item.id,
|
|
|
- label: item.name,
|
|
|
- children: buildTree(data, item.id)
|
|
|
- }));
|
|
|
+ .map(item => {
|
|
|
+ const children = buildTree(data, item.id);
|
|
|
+ const res: any = {
|
|
|
+ id: item.id,
|
|
|
+ name: item.name,
|
|
|
+ };
|
|
|
+ if (children && children.length > 0) {
|
|
|
+ res.children = children;
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
/** 处理所在区域选择变化 */
|
|
|
const handleAreaChange = (value: any[]) => {
|
|
|
- form.value.site = undefined;
|
|
|
if (value && value.length > 0) {
|
|
|
- const areaId = value[value.length - 1];
|
|
|
- form.value.regionId = areaId;
|
|
|
- siteOptions.value = areaStationList.value
|
|
|
- .filter((item: any) => item.type === 2 && String(item.parentId) === String(areaId))
|
|
|
- .map((item: any) => ({
|
|
|
- value: item.id,
|
|
|
- label: item.name
|
|
|
- }));
|
|
|
+ const lastId = value[value.length - 1];
|
|
|
+ form.value.site = lastId;
|
|
|
+ const node = areaStationList.value.find(item => item.id === lastId);
|
|
|
+ if (node) {
|
|
|
+ form.value.regionId = node.parentId;
|
|
|
+ }
|
|
|
} else {
|
|
|
+ form.value.site = undefined;
|
|
|
form.value.regionId = undefined;
|
|
|
- siteOptions.value = [];
|
|
|
}
|
|
|
};
|
|
|
|
|
|
@@ -889,6 +919,10 @@ onMounted(() => {
|
|
|
getServiceList();
|
|
|
getAreaStationList();
|
|
|
getStatusList();
|
|
|
+ // 提前加载高德地图脚本,加快首次地理编码速度
|
|
|
+ loadAMapScript().catch(() => {
|
|
|
+ console.warn('高德地图预加载失败,将在首次使用时重试');
|
|
|
+ });
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
@@ -928,7 +962,8 @@ onMounted(() => {
|
|
|
gap: 12px;
|
|
|
|
|
|
.search-input { width: 200px; }
|
|
|
- .region-select, .station-select, .status-select { width: 140px; }
|
|
|
+ .station-select { width: 420px; flex-shrink: 0; }
|
|
|
+ .status-select { width: 140px; }
|
|
|
|
|
|
:deep(.el-input__wrapper) {
|
|
|
background-color: #f4f5f7;
|