Files
gaoYuJournal/miniprogram/pages/main/travel-detail/index.ts
2025-12-23 14:45:15 +08:00

272 lines
6.6 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-detail/index.ts
import Time from "../../../utils/Time";
import { TravelApi } from "../../../api/TravelApi";
import { TravelLocationApi } from "../../../api/TravelLocationApi";
import config from "../../../config/index";
import { Travel, TravelStatusLabel, TravelStatusIcon, TransportationTypeLabel, TravelLocation, TravelLocationTypeLabel, TravelLocationTypeIcon, TransportationTypeIcon, TravelLocationType } from "../../../types/Travel";
interface TravelLocationView extends TravelLocation {
/** 预览图 */
previewThumb?: string;
}
interface TravelDetailData {
/** 出行详情 */
travel: Travel | null;
/** 出行 ID */
travelId: string;
/** 是否正在加载 */
isLoading: boolean;
/** 地点列表 */
locations: TravelLocationView[];
/** 是否正在加载地点 */
isLoadingLocations: boolean;
/** 状态标签映射 */
statusLabels: typeof TravelStatusLabel;
/** 状态图标映射 */
statusIcons: typeof TravelStatusIcon;
/** 交通类型标签映射 */
transportLabels: typeof TransportationTypeLabel;
/** 交通类型图标映射 */
transportIcons: typeof TransportationTypeIcon;
/** 地点类型标签映射 */
locationTypeLabels: typeof TravelLocationTypeLabel;
/** 地点类型图标映射 */
locationTypeIcons: typeof TravelLocationTypeIcon;
/** 地点类型选项 */
locationTypes: string[];
/** 选中的地点类型索引 */
selectedLocationTypeIndex: number;
/** 删除对话框可见性 */
deleteDialogVisible: boolean;
/** 删除确认文本 */
deleteConfirmText: string;
}
Page({
data: <TravelDetailData>{
travel: null,
travelId: "",
isLoading: true,
locations: [],
isLoadingLocations: false,
statusLabels: TravelStatusLabel,
statusIcons: TravelStatusIcon,
transportLabels: TransportationTypeLabel,
transportIcons: TransportationTypeIcon,
locationTypeLabels: TravelLocationTypeLabel,
locationTypeIcons: TravelLocationTypeIcon,
locationTypes: ["全部", ...Object.values(TravelLocationTypeLabel)],
selectedLocationTypeIndex: 0,
deleteDialogVisible: false,
deleteConfirmText: ""
},
onLoad(options: any) {
const { id } = options;
if (id) {
this.setData({ travelId: id });
this.fetchDetail(id);
} else {
wx.showToast({
title: "参数错误",
icon: "error"
});
setTimeout(() => {
wx.navigateBack();
}, 1500);
}
},
onShow() {
// 页面显示时刷新地点列表(从编辑页返回时)
if (this.data.travelId && !this.data.isLoading) {
this.fetchLocations(this.data.travelId);
}
},
/** 获取出行详情 */
async fetchDetail(id: string) {
this.setData({ isLoading: true });
try {
const travel = await TravelApi.getDetail(id);
// 格式化数据
if (travel.travelAt) {
travel.travelDate = Time.toDate(travel.travelAt);
travel.travelTime = Time.toTime(travel.travelAt);
}
this.setData({ travel });
// 获取地点列表
this.fetchLocations(id);
} catch (error) {
console.error("获取出行详情失败:", error);
wx.showToast({
title: "加载失败",
icon: "error"
});
setTimeout(() => {
wx.navigateBack();
}, 1500);
} finally {
this.setData({ isLoading: false });
}
},
/** 获取地点列表 */
async fetchLocations(travelId: string) {
this.setData({ isLoadingLocations: true });
try {
const { selectedLocationTypeIndex, locationTypes } = this.data;
// 构建查询条件
const equalsExample: { [key: string]: number | string } = {
travelId: Number(travelId)
};
// 添加类型过滤(索引 0 表示"全部"
if (0 < selectedLocationTypeIndex) {
const selectedTypeLabel = locationTypes[selectedLocationTypeIndex];
const selectedType = Object.keys(TravelLocationTypeLabel).find(
key => TravelLocationTypeLabel[key as TravelLocationType] === selectedTypeLabel
) as TravelLocationType | undefined;
if (selectedType) {
equalsExample.type = selectedType;
}
}
const result = await TravelLocationApi.getList({
index: 0,
size: 999,
equalsExample
});
const locations = result.list.map((location) => {
const previewItem = location.items && 0 < location.items.length ? location.items[0] : undefined;
return {
...location,
previewThumb: previewItem ? `${config.url}/attachment/read/${previewItem.mongoId}` : undefined
};
});
this.setData({ locations });
} catch (error) {
console.error("获取地点列表失败:", error);
} finally {
this.setData({ isLoadingLocations: false });
}
},
/** 地点类型改变 */
onLocationTypeChange(e: WechatMiniprogram.PickerChange) {
const index = Number(e.detail.value);
this.setData({ selectedLocationTypeIndex: index });
// 重新从接口获取过滤后的数据
this.fetchLocations(this.data.travelId);
},
/** 编辑出行 */
toEdit() {
const { travel } = this.data;
if (travel && travel.id) {
wx.navigateTo({
url: `/pages/main/travel-editor/index?id=${travel.id}`
});
}
},
/** 新增地点 */
toAddLocation() {
const { travel } = this.data;
if (travel && travel.id) {
wx.navigateTo({
url: `/pages/main/travel-location-editor/index?travelId=${travel.id}`
});
}
},
/** 查看地点详情 */
toLocationDetail(e: WechatMiniprogram.BaseEvent) {
const { id } = e.currentTarget.dataset;
const { travel } = this.data;
if (id && travel && travel.id) {
wx.navigateTo({
url: `/pages/main/travel-location-detail/index?id=${id}&travelId=${travel.id}`
});
}
},
/** 跳转地图 */
toMap() {
const { travel } = this.data;
if (travel && travel.id) {
wx.navigateTo({
url: `/pages/main/travel-location-map/index?travelId=${travel.id}`
});
}
},
/** 删除出行 */
deleteTravel() {
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.travel || !this.data.travel.id) return;
wx.showLoading({ title: "删除中...", mask: true });
try {
await TravelApi.delete(this.data.travel.id);
wx.showToast({
title: "删除成功",
icon: "success"
});
setTimeout(() => {
wx.navigateBack();
}, 1500);
} catch (error) {
// 错误已由 Network 类处理
} finally {
wx.hideLoading();
}
},
/** 返回 */
goBack() {
wx.navigateBack();
}
});