145 lines
4.2 KiB
TypeScript
145 lines
4.2 KiB
TypeScript
// components/journal-detail-panel/index.ts
|
|
import { Journal } from "../../types/Journal";
|
|
import config from "../../config/index";
|
|
import Toolkit from "../../utils/Toolkit";
|
|
import { ImageMetadata, MediaAttachExt, MediaAttachType } from "../../types/Attachment";
|
|
import { MediaItem, MediaItemType } from "../../types/UI";
|
|
import Time from "../../utils/Time";
|
|
import { JournalApi } from "../../api/JournalApi";
|
|
|
|
interface JournalDetailPanelData {
|
|
journals: Journal[];
|
|
currentJournalIndex: number;
|
|
}
|
|
|
|
Component({
|
|
properties: {
|
|
visible: {
|
|
type: Boolean,
|
|
value: false
|
|
},
|
|
ids: {
|
|
type: Array,
|
|
value: []
|
|
},
|
|
mode: {
|
|
type: String,
|
|
value: "DATE"
|
|
}
|
|
},
|
|
data: <JournalDetailPanelData>{
|
|
journals: [],
|
|
currentJournalIndex: 0,
|
|
},
|
|
observers: {
|
|
async 'ids, visible'(ids: number[], visible: boolean) {
|
|
if (visible && ids && 0 < ids.length) {
|
|
wx.showLoading({ title: "加载中...", mask: true });
|
|
try {
|
|
const journals = await JournalApi.getListByIds(ids);
|
|
journals.forEach(journal => {
|
|
journal.date = Time.toPassedDate(journal.createdAt);
|
|
journal.time = Time.toTime(journal.createdAt);
|
|
journal.datetime = Time.toPassedDateTime(journal.createdAt);
|
|
|
|
const thumbItems = journal.items?.filter((item) => item.attachType === MediaAttachType.THUMB);
|
|
if (!thumbItems) {
|
|
return;
|
|
}
|
|
const mediaItems: MediaItem[] = thumbItems.map((thumbItem, index) => {
|
|
const metadata = thumbItem.metadata as ImageMetadata;
|
|
const ext = thumbItem.ext = JSON.parse(thumbItem.ext!.toString()) as MediaAttachExt;
|
|
const thumbURL = `${config.url}/attachment/read/${thumbItem.mongoId}`;
|
|
const sourceURL = `${config.url}/attachment/read/${ext.sourceMongoId}`;
|
|
return {
|
|
type: ext.isVideo ? MediaItemType.VIDEO : MediaItemType.IMAGE,
|
|
thumbURL,
|
|
sourceURL,
|
|
size: thumbItem.size || 0,
|
|
attachmentId: thumbItem.id,
|
|
width: metadata.width,
|
|
height: metadata.height,
|
|
originalIndex: index
|
|
} as MediaItem;
|
|
});
|
|
journal.mediaItems = mediaItems;
|
|
// 为每个 journal 添加分列后的 mediaItems
|
|
(journal as any).columnedMediaItems = Toolkit.splitItemsIntoColumns(mediaItems, 3, (item) => {
|
|
// 计算相对高度:如果有宽高信息,使用宽高比;否则假设为正方形
|
|
if (item.width && item.height && 0 < item.width) {
|
|
return item.height / item.width;
|
|
}
|
|
return 1; // 默认正方形
|
|
});
|
|
})
|
|
this.setData({
|
|
journals,
|
|
currentJournalIndex: 0,
|
|
});
|
|
wx.hideLoading();
|
|
} catch (err: any) {
|
|
wx.hideLoading();
|
|
wx.showToast({
|
|
title: err.message || "加载失败",
|
|
icon: "error"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
/** 关闭详情 */
|
|
closeDetail() {
|
|
this.triggerEvent("close");
|
|
},
|
|
/** swiper 切换事件 */
|
|
onSwiperChange(e: WechatMiniprogram.SwiperChange) {
|
|
this.setData({
|
|
currentJournalIndex: e.detail.current
|
|
});
|
|
},
|
|
/** 打开位置 */
|
|
openLocation(e: WechatMiniprogram.BaseEvent) {
|
|
const { journalIndex } = e.currentTarget.dataset;
|
|
if (!journalIndex && this.properties.mode !== "LOCATION") {
|
|
return;
|
|
}
|
|
const journals = this.properties.journals as Journal[];
|
|
const journal = journals[journalIndex || 0];
|
|
if (journal.lat && journal.lng) {
|
|
wx.openLocation({
|
|
latitude: journal.lat,
|
|
longitude: journal.lng,
|
|
});
|
|
}
|
|
},
|
|
/** 预览媒体 */
|
|
previewMedia(e: WechatMiniprogram.BaseEvent) {
|
|
const journals = this.data.journals;
|
|
if (!journals || journals.length === 0) {
|
|
return;
|
|
}
|
|
const { itemIndex } = e.currentTarget.dataset;
|
|
const journal = journals[this.data.currentJournalIndex];
|
|
const items = journal.mediaItems!;
|
|
const total = items.length;
|
|
|
|
const startIndex = Math.max(0, itemIndex - 25);
|
|
const endIndex = Math.min(total, startIndex + 50);
|
|
const newCurrentIndex = itemIndex - startIndex;
|
|
|
|
const sources = items.slice(startIndex, endIndex).map((item) => {
|
|
return {
|
|
url: item.sourceURL,
|
|
type: item.type === MediaItemType.IMAGE ? "image" : "video"
|
|
}
|
|
}) as any;
|
|
wx.previewMedia({
|
|
current: newCurrentIndex,
|
|
sources
|
|
})
|
|
}
|
|
}
|
|
});
|