From 1e547826006810d5fa8d1a2df60b74b4fd37ed41 Mon Sep 17 00:00:00 2001 From: Timi Date: Wed, 10 Dec 2025 16:45:29 +0800 Subject: [PATCH] add journal-detail-panel --- .../journal-detail-panel/index.json | 7 + .../journal-detail-panel/index.less | 160 ++++++++++++++ .../components/journal-detail-panel/index.ts | 102 +++++++++ .../journal-detail-panel/index.wxml | 54 +++++ .../pages/main/journal-date/index.json | 5 +- .../pages/main/journal-date/index.less | 150 ------------- miniprogram/pages/main/journal-date/index.ts | 63 +----- .../pages/main/journal-date/index.wxml | 64 +----- miniprogram/pages/main/journal-map/index.json | 7 +- miniprogram/pages/main/journal-map/index.less | 152 ++----------- miniprogram/pages/main/journal-map/index.ts | 203 ++++++++++-------- miniprogram/pages/main/journal-map/index.wxml | 56 ++--- 12 files changed, 496 insertions(+), 527 deletions(-) create mode 100644 miniprogram/components/journal-detail-panel/index.json create mode 100644 miniprogram/components/journal-detail-panel/index.less create mode 100644 miniprogram/components/journal-detail-panel/index.ts create mode 100644 miniprogram/components/journal-detail-panel/index.wxml diff --git a/miniprogram/components/journal-detail-panel/index.json b/miniprogram/components/journal-detail-panel/index.json new file mode 100644 index 0000000..55c9bde --- /dev/null +++ b/miniprogram/components/journal-detail-panel/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-popup": "tdesign-miniprogram/popup/popup" + } +} diff --git a/miniprogram/components/journal-detail-panel/index.less b/miniprogram/components/journal-detail-panel/index.less new file mode 100644 index 0000000..d6848ea --- /dev/null +++ b/miniprogram/components/journal-detail-panel/index.less @@ -0,0 +1,160 @@ +/* components/journal-detail-panel/index.less */ +.detail-panel { + width: 100%; + height: 70vh; + display: flex; + background: var(--theme-bg-card); + border-radius: 16rpx 16rpx 0 0; + flex-direction: column; + + .detail-content { + flex: 1; + display: flex; + overflow: hidden; + flex-direction: column; + + .header { + display: flex; + padding: 32rpx 32rpx 0 32rpx; + flex-shrink: 0; + margin-bottom: 24rpx; + align-items: flex-start; + justify-content: space-between; + + .info { + flex: 1; + display: flex; + flex-direction: column; + + .title { + color: #333; + display: flex; + font-size: 32rpx; + font-weight: 600; + align-items: center; + margin-bottom: 8rpx; + + .icon { + width: 32rpx; + height: 32rpx; + margin-right: 8rpx; + } + } + } + + .actions { + gap: 16rpx; + display: flex; + flex-shrink: 0; + align-items: center; + + .indicator { + color: var(--theme-wx); + padding: 4rpx 12rpx; + font-size: 24rpx; + font-weight: 600; + border-radius: 12rpx; + background: var(--theme-bg-journal); + } + } + } + + .journals-swiper { + flex: 1; + height: 100%; + + .swiper-item-wrapper { + height: 100%; + + .journal-item { + height: 100%; + display: flex; + flex-direction: column; + + .journal-header { + gap: 16rpx; + display: flex; + padding: 0 32rpx; + flex-wrap: wrap; + flex-shrink: 0; + margin-bottom: 16rpx; + align-items: baseline; + + .location { + color: #666; + flex-basis: 100%; + font-size: 24rpx; + } + + .date { + flex: 1; + color: #333; + font-size: 28rpx; + font-weight: 600; + } + + .time { + color: #999; + font-size: 24rpx; + } + } + + .idea { + color: #333; + display: block; + padding: 0 32rpx; + font-size: 28rpx; + line-height: 1.6; + flex-shrink: 0; + margin-bottom: 16rpx; + } + + .items-scroll { + flex: 1; + height: 100%; + + .items { + padding: 0 32rpx 128rpx 32rpx; + + .wrapper { + column-gap: 8rpx; + column-count: 3; + padding-bottom: 128rpx; + + .item { + overflow: hidden; + background: var(--theme-bg-card); + break-inside: avoid; + margin-bottom: 8rpx; + + &.thumbnail { + width: 100%; + display: block; + } + + &.video { + position: relative; + + &::after { + content: ""; + top: 50%; + left: 53%; + width: 0; + height: 0; + position: absolute; + transform: translate(-50%, -50%); + border-top: 16px solid transparent; + border-left: 24px solid var(--theme-video-play); + border-bottom: 16px solid transparent; + pointer-events: none; + } + } + } + } + } + } + } + } + } + } +} diff --git a/miniprogram/components/journal-detail-panel/index.ts b/miniprogram/components/journal-detail-panel/index.ts new file mode 100644 index 0000000..a410862 --- /dev/null +++ b/miniprogram/components/journal-detail-panel/index.ts @@ -0,0 +1,102 @@ +// components/journal-detail-panel/index.ts + +interface JournalInfo { + id: number; + date: string; + time: string; + location?: string; + idea?: string; + items: Array<{ + type: number; + thumbURL: string; + sourceURL: string; + mongoId: string; + }>; +} + +interface JournalDetailPanelData { + currentJournalIndex: number; +} + +Component({ + properties: { + // 是否显示 + visible: { + type: Boolean, + value: false + }, + // 标题(如 "2024 年 1 月 1 日" 或位置名称) + title: { + type: String, + value: "" + }, + // 日记列表 + journals: { + type: Array, + value: [] + }, + // 是否显示标题位置图标 + showLocationIcon: { + type: Boolean, + value: false + }, + // 是否显示每条日记的日期 + showJournalDate: { + type: Boolean, + value: true + }, + // 是否显示每条日记的位置 + showJournalLocation: { + type: Boolean, + value: true + } + }, + + data: { + currentJournalIndex: 0, + }, + + observers: { + 'journals, visible'(journals: JournalInfo[], visible: boolean) { + if (visible && journals && journals.length > 0) { + // 显示时重置索引和 margin + this.setData({ + currentJournalIndex: 0, + }); + } + } + }, + + methods: { + /** 关闭详情 */ + closeDetail() { + this.triggerEvent('close'); + }, + + /** swiper 切换事件 */ + onSwiperChange(e: WechatMiniprogram.SwiperChange) { + this.setData({ + currentJournalIndex: e.detail.current + }); + }, + + /** 预览媒体 */ + previewMedia(e: WechatMiniprogram.BaseEvent) { + const { mediaIndex } = e.currentTarget.dataset; + const journals = this.properties.journals as JournalInfo[]; + if (!journals || journals.length === 0) return; + + // 使用当前 swiper 的索引 + const journal = journals[this.data.currentJournalIndex]; + const sources = journal.items.map((item: any) => ({ + url: item.sourceURL, + type: item.type === 0 ? "image" : "video" + })); + + wx.previewMedia({ + current: mediaIndex, + sources: sources as WechatMiniprogram.MediaSource[] + }); + } + } +}); diff --git a/miniprogram/components/journal-detail-panel/index.wxml b/miniprogram/components/journal-detail-panel/index.wxml new file mode 100644 index 0000000..9129119 --- /dev/null +++ b/miniprogram/components/journal-detail-panel/index.wxml @@ -0,0 +1,54 @@ + + + + + + + + + {{title}} + + + + + {{currentJournalIndex + 1}}/{{journals.length}} + + + + + + + + + + 📍 {{item.location}} + {{item.date}} + + {{item.idea}} + + + + + + + + + + + + + + + + diff --git a/miniprogram/pages/main/journal-date/index.json b/miniprogram/pages/main/journal-date/index.json index f494faf..a2c4d4e 100644 --- a/miniprogram/pages/main/journal-date/index.json +++ b/miniprogram/pages/main/journal-date/index.json @@ -1,9 +1,8 @@ { "usingComponents": { - "t-icon": "tdesign-miniprogram/icon/icon", - "t-popup": "tdesign-miniprogram/popup/popup", "t-navbar": "tdesign-miniprogram/navbar/navbar", - "calendar": "/components/calendar/index" + "calendar": "/components/calendar/index", + "journal-detail-panel": "/components/journal-detail-panel/index" }, "navigationStyle": "custom" } diff --git a/miniprogram/pages/main/journal-date/index.less b/miniprogram/pages/main/journal-date/index.less index a4c5d1e..5a3a6ef 100644 --- a/miniprogram/pages/main/journal-date/index.less +++ b/miniprogram/pages/main/journal-date/index.less @@ -22,153 +22,3 @@ } } } - -.date-detail { - height: 61.8vh; - display: flex; - border-radius: 24rpx 24rpx 0 0; - flex-direction: column; - - .detail-content { - flex: 1; - display: flex; - overflow: hidden; - flex-direction: column; - - .header { - display: flex; - padding: 24rpx 24rpx 4rpx; - flex-shrink: 0; - align-items: flex-start; - justify-content: space-between; - - .info { - flex: 1; - display: flex; - flex-direction: column; - - .date { - color: var(--theme-text); - font-size: 32rpx; - font-weight: 600; - margin-bottom: 8rpx; - } - - .count { - color: var(--theme-text-secondary); - font-size: 26rpx; - } - } - - .actions { - gap: 16rpx; - display: flex; - flex-shrink: 0; - align-items: center; - - .indicator { - color: var(--theme-text-secondary); - padding: 8rpx 16rpx; - font-size: 24rpx; - border-radius: 24rpx; - background: var(--theme-bg); - } - } - } - - .journals-swiper { - flex: 1; - - .swiper-item-wrapper { - height: 100%; - display: flex; - padding: 0 24rpx; - box-sizing: border-box; - - .journal-item { - flex: 1; - display: flex; - background: var(--theme-bg); - flex-direction: column; - - .journal-header { - display: flex; - margin-top: 16rpx; - flex-shrink: 0; - align-items: center; - justify-content: space-between; - - .location { - flex: 1; - color: var(--theme-text); - overflow: hidden; - font-size: 28rpx; - white-space: nowrap; - text-overflow: ellipsis; - } - - .time { - color: var(--theme-text-secondary); - font-size: 24rpx; - margin-left: 16rpx; - flex-shrink: 0; - } - } - - .idea { - color: var(--theme-text); - display: block; - font-size: 28rpx; - line-height: 1.6; - flex-shrink: 0; - } - - .items-scroll { - flex: 1; - height: 0; - margin-top: 16rpx; - - .items { - - .wrapper { - position: relative; - column-gap: 8rpx; - column-count: 3; - - .item { - overflow: hidden; - break-inside: avoid; - margin-bottom: 8rpx; - background: var(--theme-bg-card); - - &.thumbnail { - width: 100%; - display: block; - } - - &.video { - position: relative; - - &::after { - top: 50%; - left: 53%; - width: 0; - height: 0; - content: ""; - position: absolute; - transform: translate(-50%, -50%); - border-top: 16rpx solid transparent; - border-left: 24rpx solid rgba(255, 255, 255, .9); - border-bottom: 16rpx solid transparent; - pointer-events: none; - } - } - } - } - } - } - } - } - } - } -} diff --git a/miniprogram/pages/main/journal-date/index.ts b/miniprogram/pages/main/journal-date/index.ts index 921a5db..b9f130a 100644 --- a/miniprogram/pages/main/journal-date/index.ts +++ b/miniprogram/pages/main/journal-date/index.ts @@ -27,9 +27,7 @@ interface JournalDateData { journalMap: Record; // 存储每个日期的日记 id 列表 selectedDate: SelectedDateInfo | null; isLoading: boolean; - currentJournalIndex: number; // 当前日记索引 popupVisible: boolean; // popup 显示状态 - swiperNextMargin: string; // swiper 的 next-margin 值 } Page({ @@ -37,9 +35,7 @@ Page({ journalMap: {}, selectedDate: null, isLoading: true, - currentJournalIndex: 0, - popupVisible: false, - swiperNextMargin: "0" + popupVisible: false }, async onLoad() { @@ -170,9 +166,7 @@ Page({ displayDate, journals }, - currentJournalIndex: 0, // 重置索引 - popupVisible: true, // 显示 popup - swiperNextMargin: journals.length > 1 ? "128rpx" : "0" // 设置初始 margin + popupVisible: true // 显示 popup }); wx.hideLoading(); @@ -188,57 +182,8 @@ Page({ /** 关闭详情 */ closeDetail() { this.setData({ - popupVisible: false - }); - }, - /** popup 显示状态变化 */ - onPopupVisibleChange(e: WechatMiniprogram.CustomEvent) { - const { visible } = e.detail; - this.setData({ - popupVisible: visible - }); - // 关闭时清空数据 - if (!visible) { - this.setData({ - selectedDate: null, - currentJournalIndex: 0 - }); - } - }, - /** swiper 切换事件 */ - onSwiperChange(e: WechatMiniprogram.SwiperChange) { - this.setData({ - currentJournalIndex: e.detail.current - }); - }, - /** swiper 动画完成事件 */ - onSwiperAnimationFinish(e: WechatMiniprogram.SwiperAnimationFinish) { - if (!this.data.selectedDate) return; - - const current = e.detail.current; - const total = this.data.selectedDate.journals.length; - - // 动画完成后更新 margin,确保过渡流畅 - const nextMargin = total > 1 && current < total - 1 ? "128rpx" : "0"; - this.setData({ - swiperNextMargin: nextMargin - }); - }, - /** 预览媒体 */ - previewMedia(e: WechatMiniprogram.BaseEvent) { - const { mediaIndex } = e.currentTarget.dataset; - if (!this.data.selectedDate) return; - - // 使用当前 swiper 的索引 - const journal = this.data.selectedDate.journals[this.data.currentJournalIndex]; - const sources = journal.items.map((item: any) => ({ - url: item.sourceURL, - type: item.type === 0 ? "image" : "video" - })); - - wx.previewMedia({ - current: mediaIndex, - sources: sources as WechatMiniprogram.MediaSource[] + popupVisible: false, + selectedDate: null }); } }); diff --git a/miniprogram/pages/main/journal-date/index.wxml b/miniprogram/pages/main/journal-date/index.wxml index 2cff1b7..fbfcbe7 100644 --- a/miniprogram/pages/main/journal-date/index.wxml +++ b/miniprogram/pages/main/journal-date/index.wxml @@ -9,61 +9,11 @@ - - - - - - {{selectedDate.displayDate}} - {{selectedDate.journals.length}} 条日记 - - - - {{currentJournalIndex + 1}}/{{selectedDate.journals.length}} - - - - - - - - - - 📍 {{item.location}} - {{item.time}} - - {{item.idea}} - - - - - - - - - - - - - - - - + title="{{selectedDate.displayDate}}" + journals="{{selectedDate.journals}}" + show-journal-date="{{false}}" + show-journal-location="{{true}}" + bind:close="closeDetail" +/> diff --git a/miniprogram/pages/main/journal-map/index.json b/miniprogram/pages/main/journal-map/index.json index 7f9dcef..b7014d1 100644 --- a/miniprogram/pages/main/journal-map/index.json +++ b/miniprogram/pages/main/journal-map/index.json @@ -1,6 +1,7 @@ { - "component": true, "usingComponents": { - "t-navbar": "tdesign-miniprogram/navbar/navbar" - } + "t-navbar": "tdesign-miniprogram/navbar/navbar", + "journal-detail-panel": "/components/journal-detail-panel/index" + }, + "navigationStyle": "custom" } diff --git a/miniprogram/pages/main/journal-map/index.less b/miniprogram/pages/main/journal-map/index.less index 3b9c7f3..e1ae02d 100644 --- a/miniprogram/pages/main/journal-map/index.less +++ b/miniprogram/pages/main/journal-map/index.less @@ -25,6 +25,7 @@ .thumb-container { width: 72rpx; height: 72rpx; + position: relative; flex-shrink: 0; margin-right: 12rpx; overflow: hidden; @@ -34,6 +35,17 @@ width: 100%; height: 100%; } + + .count-badge { + top: 4rpx; + right: 4rpx; + color: #fff; + padding: 2rpx 6rpx; + position: absolute; + font-size: 20rpx; + background: rgba(0, 0, 0, .7); + border-radius: 8rpx; + } } .text-container { @@ -43,24 +55,18 @@ flex-direction: column; .location { - flex: 1; color: #999; overflow: hidden; font-size: 24rpx; white-space: nowrap; text-overflow: ellipsis; - margin-bottom: 8rpx; + margin-bottom: 4rpx; } - .idea { - color: #333; - display: -webkit-box; - font-size: 26rpx; - line-height: 1.4; - overflow: hidden; - -webkit-line-clamp: 3; - text-overflow: ellipsis; - -webkit-box-orient: vertical; + .count-text { + color: var(--theme-wx); + font-size: 24rpx; + font-weight: 600; } } } @@ -81,128 +87,4 @@ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, .15); } } - - .marker-detail { - left: 0; - right: 0; - bottom: 0; - height: 61.8vh; - z-index: 999; - display: flex; - position: fixed; - transition: transform 350ms cubic-bezier(.19, .1, .22, 1); - transform: translateY(100%); - background: var(--theme-bg-card); - box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, .15); - border-radius: 24rpx 24rpx 0 0; - flex-direction: column; - - &.visible { - transform: translateY(0); - } - - .detail-content { - flex: 1; - display: flex; - padding: 32rpx; - flex-direction: column; - - .header { - display: flex; - flex-shrink: 0; - margin-bottom: 16rpx; - align-items: flex-start; - justify-content: space-between; - - .info { - flex: 1; - display: flex; - flex-direction: column; - - .date { - color: #333; - font-size: 32rpx; - font-weight: 600; - margin-bottom: 8rpx; - } - - .location { - color: #666; - display: flex; - font-size: 26rpx; - align-items: center; - - .icon { - width: 32rpx; - height: 32rpx; - } - } - } - - .close { - width: 48rpx; - height: 48rpx; - color: #999; - display: flex; - font-size: 48rpx; - line-height: 1; - flex-shrink: 0; - align-items: center; - justify-content: center; - } - } - - .idea { - color: #333; - display: block; - font-size: 28rpx; - line-height: 1.6; - flex-shrink: 0; - margin-bottom: 16rpx; - } - - .items { - flex: 1; - overflow: scroll; - - .wrapper { - position: relative; - column-gap: .25rem; - column-count: 3; - padding-bottom: 2rem; - - .item { - overflow: hidden; - background: var(--theme-bg-card); - break-inside: avoid; - margin-bottom: .25rem; - - &.thumbnail { - width: 100%; - display: block; - } - - &.video { - height: auto; - position: relative; - - &::after { - content: ""; - top: 50%; - left: 53%; - width: 0; - height: 0; - position: absolute; - transform: translate(-50%, -50%); - border-top: 16px solid transparent; - border-left: 24px solid var(--theme-video-play); - border-bottom: 16px solid transparent; - pointer-events: none; - } - } - } - } - } - } - } } diff --git a/miniprogram/pages/main/journal-map/index.ts b/miniprogram/pages/main/journal-map/index.ts index c3b7990..5bd6115 100644 --- a/miniprogram/pages/main/journal-map/index.ts +++ b/miniprogram/pages/main/journal-map/index.ts @@ -18,12 +18,11 @@ interface MapMarker { }; } -interface JournalMarker { +interface JournalInfo { id: number; date: string; + time: string; location?: string; - lat: number; - lng: number; idea?: string; items: Array<{ type: number; @@ -33,15 +32,30 @@ interface JournalMarker { }>; } +interface LocationMarker { + locationKey: string; // 位置键 "lat,lng" + lat: number; + lng: number; + location?: string; + journalIds: number[]; // 该位置的所有日记 ID + count: number; // 日记数量 + previewThumb?: string; // 预览缩略图 +} + +interface SelectedLocationInfo { + location?: string; + journals: JournalInfo[]; +} + interface JournalMapData { centerLat: number; centerLng: number; scale: number; markers: MapMarker[]; - journals: JournalMarker[]; - customCalloutMarkerIds: number[]; + locations: LocationMarker[]; // 位置标记列表 + customCalloutMarkerIds: string[]; // 改为 string[] 以支持 locationKey includePoints: Array<{ latitude: number; longitude: number }>; // 缩放视野以包含所有点 - selectedMarker: JournalMarker | null; + selectedLocation: SelectedLocationInfo | null; // 选中的位置信息 showDetail: boolean; // 是否显示详情(控制 DOM 存在) detailVisible: boolean; // 详情是否可见(控制动画) isLoading: boolean; @@ -53,10 +67,10 @@ Page({ centerLng: 116.397470, scale: 13, markers: [], - journals: [], + locations: [], customCalloutMarkerIds: [], includePoints: [], - selectedMarker: null, + selectedLocation: null, showDetail: false, detailVisible: false, isLoading: true, @@ -90,28 +104,45 @@ Page({ fail: reject }); }) || []; - // 过滤有位置信息的记录 - const journals: JournalMarker[] = list - .filter((journal: any) => journal.lat && journal.lng) - .map((journal: any) => ({ - id: journal.id, - date: Time.toPassedDateTime(journal.createdAt), - location: journal.location, - lat: journal.lat, - lng: journal.lng, - idea: journal.idea, - items: journal.items.filter((item: any) => item.attachType === "THUMB") - .map((item: any) => { - const ext = JSON.parse(item.ext); - return { - type: ext.isVideo ? 1 : 0, - thumbURL: `${config.url}/attachment/read/${item.mongoId}`, - mongoId: item.mongoId, - source: journal.items.find((source: any) => source.id === ext.sourceId) - }; - }) - })); - if (journals.length === 0) { + + // 过滤有位置信息的记录,并按位置分组 + const locationMap = new Map(); + + list.filter((journal: any) => journal.lat && journal.lng).forEach((journal: any) => { + // 保留 6 位小数作为位置键,约等于 0.1 米精度 + const lat = Number(journal.lat.toFixed(6)); + const lng = Number(journal.lng.toFixed(6)); + const locationKey = `${lat},${lng}`; + + if (!locationMap.has(locationKey)) { + // 获取第一个有缩略图的日记 + const thumbItem = journal.items.find((item: any) => item.attachType === "THUMB"); + locationMap.set(locationKey, { + locationKey, + lat, + lng, + location: journal.location, + journalIds: [], + count: 0, + previewThumb: thumbItem ? `${config.url}/attachment/read/${thumbItem.mongoId}` : undefined + }); + } + + const marker = locationMap.get(locationKey)!; + marker.journalIds.push(journal.id); + marker.count++; + // 如果还没有预览图,尝试从当前日记获取 + if (!marker.previewThumb) { + const thumbItem = journal.items.find((item: any) => item.attachType === "THUMB"); + if (thumbItem) { + marker.previewThumb = `${config.url}/attachment/read/${thumbItem.mongoId}`; + } + } + }); + + const locations = Array.from(locationMap.values()); + + if (locations.length === 0) { wx.showToast({ title: "暂无位置记录", icon: "none" @@ -119,11 +150,12 @@ Page({ this.setData({ isLoading: false }); return; } + // 生成地图标记 - const markers: MapMarker[] = journals.map((journal) => ({ - id: journal.id, - latitude: journal.lat, - longitude: journal.lng, + const markers: MapMarker[] = locations.map((location, index) => ({ + id: index, + latitude: location.lat, + longitude: location.lng, width: 24, height: 30, customCallout: { @@ -133,19 +165,19 @@ Page({ } })); - // 所有标记的 ID 列表 - const customCalloutMarkerIds = journals.map((j) => j.id); + // 所有标记的 locationKey 列表 + const customCalloutMarkerIds = locations.map(l => l.locationKey); // 计算中心点(所有标记的平均位置) - const centerLat = journals.reduce((sum, j) => sum + j.lat, 0) / journals.length; - const centerLng = journals.reduce((sum, j) => sum + j.lng, 0) / journals.length; + 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 = journals.map((j) => ({ - latitude: j.lat, - longitude: j.lng + const includePoints = locations.map((l) => ({ + latitude: l.lat, + longitude: l.lng })); this.setData({ - journals, + locations, markers, customCalloutMarkerIds, centerLat, @@ -164,58 +196,71 @@ Page({ /** 标记点击事件 */ onMarkerTap(e: any) { const markerId = e.detail.markerId || e.markerId; - this.loadMarkerDetail(markerId); + this.loadLocationDetail(markerId); }, /** 气泡点击事件 */ onCalloutTap(e: any) { const markerId = e.detail.markerId || e.markerId; - this.loadMarkerDetail(markerId); + this.loadLocationDetail(markerId); }, - /** 加载标记详情 */ - async loadMarkerDetail(markerId: number) { + /** 加载位置详情(该位置的所有日记) */ + async loadLocationDetail(markerId: number) { + const location = this.data.locations[markerId]; + if (!location) return; + wx.showLoading({ title: "加载中...", mask: true }); try { - const journal: any = await new Promise((resolve, reject) => { + // 根据 journalIds 加载日记详情 + const list: Journal[] = await new Promise((resolve, reject) => { wx.request({ - url: `${config.url}/journal/${markerId}`, + url: `${config.url}/journal/list/ids`, method: "POST", header: { Key: wx.getStorageSync("key") }, - success: (res: any) => { - if (res.data.code === 20000) { - resolve(res.data.data); + data: location.journalIds, + success: (resp: any) => { + if (resp.data.code === 20000) { + resolve(resp.data.data); } else { - reject(new Error(res.data.message || "加载失败")); + reject(new Error(resp.data.message || "加载失败")); } }, fail: reject }); - }); + }) || []; - const items = journal.items || []; - const thumbItems = items.filter((item: any) => item.attachType === MediaAttachType.THUMB); - const mediaItems = thumbItems.map((thumbItem: any) => { - const ext = JSON.parse(thumbItem.ext) as MediaAttachExt; + // 转换为 JournalInfo 格式 + const journals: JournalInfo[] = list.map((journal: any) => { + const date = new Date(journal.createdAt); return { - type: ext.isVideo ? 1 : 0, - thumbURL: `${config.url}/attachment/read/${thumbItem.mongoId}`, - sourceURL: `${config.url}/attachment/read/${ext.sourceMongoId}`, - mongoId: thumbItem.mongoId, + id: journal.id, + date: Time.toPassedDateTime(journal.createdAt), + time: `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`, + location: journal.location, + idea: journal.idea, + items: journal.items + .filter((item: any) => item.attachType === MediaAttachType.THUMB) + .map((item: any) => { + const ext = JSON.parse(item.ext); + return { + type: ext.isVideo ? 1 : 0, + thumbURL: `${config.url}/attachment/read/${item.mongoId}`, + sourceURL: `${config.url}/attachment/read/${ext.sourceMongoId}`, + mongoId: item.mongoId, + }; + }) }; }); - const selectedMarker = { - id: journal.id, - date: Time.toPassedDateTime(journal.createdAt), - location: journal.location, - lat: journal.lat, - lng: journal.lng, - idea: journal.idea, - items: mediaItems - }; // 先显示元素,再触发动画 - this.setData({ selectedMarker, showDetail: true }); + this.setData({ + selectedLocation: { + location: location.location, + journals + }, + showDetail: true + }); wx.nextTick(() => { this.setData({ detailVisible: true }); }); @@ -232,19 +277,9 @@ Page({ async closeDetail() { this.setData({ detailVisible: false }); await Toolkit.sleep(350); - this.setData({ showDetail: false, selectedMarker: null }); - }, - /** 预览媒体 */ - previewMedia(e: WechatMiniprogram.BaseEvent) { - const index = e.currentTarget.dataset.index; - if (!this.data.selectedMarker) return; - const sources = this.data.selectedMarker.items.map((item: any) => ({ - url: item.sourceURL, - type: item.type === 0 ? "image" : "video" - })); - wx.previewMedia({ - current: index, - sources: sources as WechatMiniprogram.MediaSource[] + this.setData({ + showDetail: false, + selectedLocation: null }); }, }); diff --git a/miniprogram/pages/main/journal-map/index.wxml b/miniprogram/pages/main/journal-map/index.wxml index 8b07c18..8ae82b5 100644 --- a/miniprogram/pages/main/journal-map/index.wxml +++ b/miniprogram/pages/main/journal-map/index.wxml @@ -13,49 +13,33 @@ bindcallouttap="onCalloutTap" > - - + + - - + + + {{item.count}} - {{journals[index].location}} - {{journals[index].idea}} + {{item.location}} + {{item.count}} 条日记 - - 加载中... - - - - - - {{selectedMarker.date}} - - - {{selectedMarker.location}} - - - × - - {{selectedMarker.idea}} - - - - - - - - - + + 加载中... + + +