Files
gaoYuJournal/miniprogram/pages/main/travel-location-detail/index.ts
2025-12-17 16:56:33 +08:00

276 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// pages/main/travel-location-detail/index.ts
import config from "../../../config/index";
import { TravelLocationApi } from "../../../api/TravelLocationApi";
import { TravelLocation, TravelLocationTypeIcon, TravelLocationTypeLabel } from "../../../types/Travel";
import { MediaAttachExt, MediaAttachType } from "../../../types/Attachment";
import { MapMarker, MediaItem, MediaItemType } from "../../../types/UI";
import Toolkit from "../../../utils/Toolkit";
interface TravelLocationView extends TravelLocation {
/** 媒体列表 */
mediaItems?: MediaItem[];
}
interface TravelLocationDetailData {
/** 地点详情 */
location: TravelLocationView | null;
/** 地点 ID */
locationId: string;
/** 出行 ID */
travelId: string;
/** 是否正在加载 */
isLoading: boolean;
/** 错误信息 */
errorMessage: string;
/** 地点类型标签映射 */
locationTypeLabels: typeof TravelLocationTypeLabel;
/** 地点类型图标映射 */
locationTypeIcons: typeof TravelLocationTypeIcon;
/** 媒体类型枚举 */
mediaItemTypeEnum: typeof MediaItemType;
/** 地图标记 */
mapMarkers: MapMarker[];
/** 删除对话框可见性 */
deleteDialogVisible: boolean;
/** 删除确认文本 */
deleteConfirmText: string;
}
Page({
data: <TravelLocationDetailData>{
location: null,
locationId: "",
travelId: "",
isLoading: true,
errorMessage: "",
locationTypeLabels: TravelLocationTypeLabel,
locationTypeIcons: TravelLocationTypeIcon,
mediaItemTypeEnum: {
...MediaItemType
},
mapMarkers: [],
deleteDialogVisible: false,
deleteConfirmText: ""
},
onLoad(options: any) {
const { id, travelId } = options;
if (id) {
this.setData({
locationId: id,
travelId: travelId || ""
});
this.fetchDetail(id);
} else {
wx.showToast({
title: "参数错误",
icon: "error"
});
setTimeout(() => {
wx.navigateBack();
}, 1500);
}
},
onShow() {
// 页面显示时刷新数据(从编辑页返回时)
if (this.data.locationId && !this.data.isLoading && this.data.location) {
this.fetchDetail(this.data.locationId);
}
},
/** 获取地点详情 */
async fetchDetail(id: string) {
this.setData({
isLoading: true,
errorMessage: ""
});
try {
const location = await TravelLocationApi.getDetail(id);
const thumbItems = (location.items || []).filter((item) => item.attachType === MediaAttachType.THUMB);
const mediaItems: MediaItem[] = [];
thumbItems.forEach((thumbItem) => {
try {
const ext = JSON.parse(thumbItem.ext!.toString()) as MediaAttachExt;
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
mediaItems.push({
type: ext.isVideo ? MediaItemType.VIDEO : MediaItemType.IMAGE,
thumbURL,
sourceURL,
size: thumbItem.size || 0,
attachmentId: thumbItem.id!
});
} catch (parseError) {
console.warn("解析附件扩展信息失败", parseError);
}
});
// 构建地图标记
const mapMarkers: MapMarker[] = [];
if (location.lat !== undefined && location.lng !== undefined) {
mapMarkers.push({
id: 0,
latitude: location.lat,
longitude: location.lng,
width: 24,
height: 30,
customCallout: {
anchorY: 0,
anchorX: 0,
display: "ALWAYS"
}
});
}
console.log(mediaItems);
this.setData({
location: {
...location,
mediaItems
},
travelId: location.travelId ? String(location.travelId) : this.data.travelId,
mapMarkers
});
} catch (error) {
console.error("获取地点详情失败:", error);
this.setData({
errorMessage: "加载失败,请稍后重试"
});
wx.showToast({
title: "加载失败",
icon: "error"
});
} finally {
this.setData({ isLoading: false });
}
},
/** 重新加载 */
retryFetch() {
if (this.data.locationId) {
this.fetchDetail(this.data.locationId);
}
},
/** 编辑地点 */
toEdit() {
const { location, travelId } = this.data;
if (location && location.id) {
wx.navigateTo({
url: `/pages/main/travel-location-editor/index?id=${location.id}&travelId=${travelId || location.travelId || ""}`
});
}
},
/** 出发(打开地图导航) */
navigate() {
const { location } = this.data;
if (location && location.lat !== undefined && location.lng !== undefined) {
wx.openLocation({
latitude: location.lat,
longitude: location.lng,
name: location.title || "目的地",
address: location.location || "",
scale: 15
});
} else {
wx.showToast({
title: "位置信息不完整",
icon: "error"
});
}
},
/** 预览媒体 */
preview(e: WechatMiniprogram.BaseEvent) {
const index = e.currentTarget.dataset.index;
const { location } = this.data;
if (!location || !location.mediaItems) {
return;
}
const sources = location.mediaItems.map(item => ({
url: item.sourceURL,
type: item.type
}));
const total = sources.length;
const startIndex = Math.max(0, index - 25);
const endIndex = Math.min(total, startIndex + 50);
const newCurrentIndex = index - startIndex;
wx.previewMedia({
current: newCurrentIndex,
sources: sources.slice(startIndex, endIndex) as WechatMiniprogram.MediaSource[]
});
},
/** 删除地点 */
deleteLocation() {
this.setData({
deleteDialogVisible: true,
deleteConfirmText: ""
});
},
/** 取消删除 */
cancelDelete() {
this.setData({
deleteDialogVisible: false,
deleteConfirmText: ""
});
},
/** 确认删除 */
confirmDelete() {
const inputText = this.data.deleteConfirmText.trim();
if (inputText !== "确认删除") {
wx.showToast({
title: "输入不匹配",
icon: "error"
});
return;
}
this.setData({
deleteDialogVisible: false
});
this.executeDelete();
},
/** 执行删除 */
async executeDelete() {
if (!this.data.location || !this.data.location.id) {
return;
}
wx.showLoading({ title: "删除中...", mask: true });
try {
await TravelLocationApi.delete(this.data.location.id);
wx.showToast({
title: "删除成功",
icon: "success"
});
setTimeout(() => {
wx.navigateBack();
}, 1500);
} catch (error) {
// 错误已由 Network 类处理
} finally {
wx.hideLoading();
}
},
/** 返回 */
async goBack() {
Toolkit.async(() => wx.navigateBack()); // 微信 BUG需要延时
}
});