修复动态发布与互动问题
This commit is contained in:
@@ -26,11 +26,44 @@ function formatTimeText(ts) {
|
||||
return `${d.getMonth() + 1}月${d.getDate()}日`
|
||||
}
|
||||
|
||||
function isCloudFileId(value) {
|
||||
return typeof value === 'string' && value.startsWith('cloud://')
|
||||
}
|
||||
|
||||
function extractMediaUrl(media) {
|
||||
if (!media) return ''
|
||||
if (typeof media === 'string') return media
|
||||
return media.url || media.fileId || media.fileID || ''
|
||||
}
|
||||
|
||||
async function resolveTempUrlMap(urls) {
|
||||
const fileIds = [...new Set(urls.filter(isCloudFileId))]
|
||||
if (!fileIds.length) return new Map()
|
||||
|
||||
try {
|
||||
const result = await cloud.getTempFileURL({ fileList: fileIds })
|
||||
const fileList = Array.isArray(result.fileList) ? result.fileList : []
|
||||
return new Map(fileList.map(file => [
|
||||
file.fileID || file.fileId,
|
||||
file.tempFileURL || file.tempFileUrl || ''
|
||||
]).filter(([fileId, tempUrl]) => fileId && tempUrl))
|
||||
} catch (e) {
|
||||
return new Map()
|
||||
}
|
||||
}
|
||||
|
||||
function readableUrl(url, tempUrlMap) {
|
||||
if (!url) return ''
|
||||
if (!isCloudFileId(url)) return url
|
||||
return tempUrlMap.get(url) || ''
|
||||
}
|
||||
|
||||
// List a user's own posts. Defaults to the caller; pass authorId to view
|
||||
// another user (only public posts are returned for others).
|
||||
exports.main = async event => {
|
||||
const { OPENID } = cloud.getWXContext()
|
||||
if (!OPENID) throw new Error('no openid in wx context')
|
||||
const pageSize = Math.max(1, Math.min(Number(event.pageSize || 20), 50))
|
||||
|
||||
let authorOpenid = OPENID
|
||||
let viewingSelf = true
|
||||
@@ -43,35 +76,59 @@ exports.main = async event => {
|
||||
|
||||
const where = { authorOpenid }
|
||||
if (!viewingSelf) where.visibility = 'public'
|
||||
const cursor = Number(event.cursor || 0)
|
||||
if (Number.isFinite(cursor) && cursor > 0) where.createdAt = _.lt(cursor)
|
||||
|
||||
const res = await db.collection('posts')
|
||||
.where(where)
|
||||
.orderBy('createdAt', 'desc')
|
||||
.limit(50)
|
||||
.limit(pageSize + 1)
|
||||
.get()
|
||||
|
||||
if (!res.data.length) return { list: [] }
|
||||
if (!res.data.length) return { list: [], nextCursor: '' }
|
||||
|
||||
const postIds = res.data.map(p => p._id)
|
||||
const [likedRes, favRes] = await Promise.all([
|
||||
safeGet('postLikes', { openid: OPENID, postId: _.in(postIds) }),
|
||||
safeGet('postFavorites', { openid: OPENID, postId: _.in(postIds) })
|
||||
])
|
||||
const page = res.data.slice(0, pageSize)
|
||||
const nextCursor = res.data.length > pageSize && page[page.length - 1]
|
||||
? String(page[page.length - 1].createdAt || '')
|
||||
: ''
|
||||
|
||||
const authorRes = await db.collection('users').where({ openid: authorOpenid }).limit(1).get().catch(() => null)
|
||||
const authorUser = authorRes && authorRes.data ? authorRes.data[0] : null
|
||||
|
||||
// Real presence: author has a recent, visible location (same signal as 附近).
|
||||
const ONLINE_WINDOW_MS = 5 * 60 * 1000
|
||||
const locRes = await safeGet('locations', { openid: authorOpenid }, 1)
|
||||
const authorLoc = locRes.data[0]
|
||||
const authorOnline = Boolean(
|
||||
authorLoc && authorLoc.visible && authorLoc.updatedAt && Date.now() - authorLoc.updatedAt < ONLINE_WINDOW_MS
|
||||
)
|
||||
const postIds = page.map(p => p._id)
|
||||
const likedRes = await safeGet('postLikes', { openid: OPENID, postId: _.in(postIds) })
|
||||
const likedSet = new Set(likedRes.data.map(l => l.postId))
|
||||
const favSet = new Set(favRes.data.map(f => f.postId))
|
||||
const assetUrls = [
|
||||
authorUser?.avatarUrl || '',
|
||||
...page.flatMap(post => Array.isArray(post.media) ? post.media.map(extractMediaUrl) : [])
|
||||
]
|
||||
const tempUrlMap = await resolveTempUrlMap(assetUrls)
|
||||
|
||||
const list = res.data.map(post => ({
|
||||
const list = page.map(post => ({
|
||||
_id: post._id,
|
||||
author: {
|
||||
id: post.authorId || '',
|
||||
name: post.authorSnapshot?.name || '用户',
|
||||
avatarKey: post.authorSnapshot?.avatarKey || 'gradient-avatar-1'
|
||||
avatarKey: authorUser?.avatarKey || post.authorSnapshot?.avatarKey || 'gradient-avatar-1',
|
||||
avatarUrl: readableUrl(authorUser?.avatarUrl || post.authorSnapshot?.avatarUrl || '', tempUrlMap),
|
||||
online: authorOnline
|
||||
},
|
||||
pet: post.petSnapshot || { name: '', breed: '' },
|
||||
body: post.content || '',
|
||||
topics: post.topics || [],
|
||||
visibility: post.visibility || 'public',
|
||||
media: Array.isArray(post.media)
|
||||
? post.media.map(m => (typeof m === 'string' ? m : m && (m.url || m.fileId))).filter(Boolean)
|
||||
? post.media
|
||||
.map(extractMediaUrl)
|
||||
.map(url => readableUrl(url, tempUrlMap))
|
||||
.filter(Boolean)
|
||||
: [],
|
||||
mediaTone: post.mediaTone || 'pet-1',
|
||||
sticker: post.sticker || undefined,
|
||||
@@ -79,12 +136,10 @@ exports.main = async event => {
|
||||
timeText: formatTimeText(post.createdAt || Date.now()),
|
||||
counts: {
|
||||
likes: post.counts?.likes || 0,
|
||||
comments: post.counts?.comments || 0,
|
||||
favorites: post.counts?.favorites || 0
|
||||
comments: post.counts?.comments || 0
|
||||
},
|
||||
likedByMe: likedSet.has(post._id),
|
||||
favoritedByMe: favSet.has(post._id)
|
||||
likedByMe: likedSet.has(post._id)
|
||||
}))
|
||||
|
||||
return { list }
|
||||
return { list, nextCursor }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user