Files
gaoYuJournal/miniprogram/pages/main/travel-location-map/index.ts
2025-12-13 18:44:37 +08:00

182 lines
4.0 KiB
TypeScript

// pages/main/travel-location-map/index.ts
import { TravelLocationApi } from "../../../api/TravelLocationApi";
import { TravelLocation, TravelLocationTypeLabel } from "../../../types/Travel";
interface MapMarker {
id: number;
latitude: number;
longitude: number;
width: number;
height: number;
customCallout: {
anchorY: number;
anchorX: number;
display: string;
};
/** 该位置的所有地点 */
locations: TravelLocation[];
}
interface TravelMapData {
travelId: number;
centerLat: number;
centerLng: number;
scale: number;
markers: MapMarker[];
locations: TravelLocation[];
includePoints: Array<{ latitude: number; longitude: number }>;
isLoading: boolean;
detailVisible: boolean;
detailIds: number[];
}
Page({
data: <TravelMapData>{
travelId: 0,
centerLat: 39.908823,
centerLng: 116.397470,
scale: 13,
markers: [],
locations: [],
includePoints: [],
isLoading: true,
detailVisible: false,
detailIds: []
},
onLoad(options: any) {
const travelId = options.travelId ? parseInt(options.travelId) : 0;
if (travelId) {
this.setData({ travelId });
this.loadLocations(travelId);
} else {
wx.showToast({
title: "参数错误",
icon: "error"
});
setTimeout(() => {
wx.navigateBack();
}, 1500);
}
},
/** 加载所有地点 */
async loadLocations(travelId: number) {
this.setData({ isLoading: true });
try {
const result = await TravelLocationApi.getList({
index: 0,
size: 100,
equalsExample: {
travelId
}
});
// 过滤有位置信息的地点
const locations = result.list.filter(loc => loc.lat && loc.lng);
if (locations.length === 0) {
wx.showToast({
title: "暂无位置记录",
icon: "none"
});
this.setData({ isLoading: false });
return;
}
// 为每个地点添加类型标签
locations.forEach(location => {
(location as any).typeLabel = location.type ? TravelLocationTypeLabel[location.type] : "";
});
// 按位置分组,处理重叠地点
const locationMap = new Map<string, TravelLocation[]>();
locations.forEach(location => {
const key = `${location.lat},${location.lng}`;
if (!locationMap.has(key)) {
locationMap.set(key, []);
}
locationMap.get(key)!.push(location);
});
// 生成地图标记(每个唯一位置一个标记)
const markers: MapMarker[] = Array.from(locationMap.values()).map((locs, index) => ({
id: index,
latitude: locs[0].lat!,
longitude: locs[0].lng!,
width: 24,
height: 30,
customCallout: {
anchorY: -2,
anchorX: 0,
display: "ALWAYS"
},
locations: locs
}));
// 计算中心点(所有标记的平均位置)
const centerLat = locations.reduce((sum, l) => sum + l.lat!, 0) / locations.length;
const centerLng = locations.reduce((sum, l) => sum + l.lng!, 0) / locations.length;
// 缩放视野以包含所有标记点
const includePoints = locations.map((l) => ({
latitude: l.lat!,
longitude: l.lng!
}));
this.setData({
locations,
markers,
centerLat,
centerLng,
includePoints,
isLoading: false
});
} catch (err: any) {
wx.showToast({
title: "加载失败",
icon: "error"
});
this.setData({ isLoading: false });
}
},
/** 标记点击事件 */
onMarkerTap(e: any) {
const markerId = e.detail.markerId || e.markerId;
this.loadLocationDetail(markerId);
},
/** 气泡点击事件 */
onCalloutTap(e: any) {
const markerId = e.detail.markerId || e.markerId;
this.loadLocationDetail(markerId);
},
/** 加载位置详情 */
loadLocationDetail(markerId: number) {
const marker = this.data.markers[markerId];
if (!marker || !marker.locations || marker.locations.length === 0) {
return;
}
// 获取该标记点的所有地点 ID
const locationIds = marker.locations.map(loc => loc.id!).filter(id => id);
if (locationIds.length === 0) {
return;
}
this.setData({
detailVisible: true,
detailIds: locationIds
});
},
/** 关闭详情 */
closeDetail() {
this.setData({
detailVisible: false
});
}
});