113 lines
3.9 KiB
JavaScript
113 lines
3.9 KiB
JavaScript
const cloud = require('wx-server-sdk')
|
|
|
|
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
|
|
const db = cloud.database()
|
|
const _ = db.command
|
|
|
|
// Query a collection that may not exist yet (created lazily on first write).
|
|
async function safeGet(collection, where, limit = 200, orderBy) {
|
|
try {
|
|
let query = db.collection(collection).where(where)
|
|
if (orderBy) query = query.orderBy(orderBy.field, orderBy.direction)
|
|
return await query.limit(limit).get()
|
|
} catch (e) {
|
|
return { data: [] }
|
|
}
|
|
}
|
|
|
|
function formatTimeText(ts) {
|
|
const diff = Date.now() - ts
|
|
const mins = Math.floor(diff / 60000)
|
|
if (mins < 1) return '刚刚'
|
|
if (mins < 60) return `${mins} 分钟前`
|
|
const hours = Math.floor(mins / 60)
|
|
if (hours < 24) return `${hours} 小时前`
|
|
const days = Math.floor(hours / 24)
|
|
if (days === 1) return '昨天'
|
|
if (days < 7) return `${days} 天前`
|
|
const d = new Date(ts)
|
|
return `${d.getMonth() + 1}月${d.getDate()}日`
|
|
}
|
|
|
|
exports.main = async event => {
|
|
const { OPENID } = cloud.getWXContext()
|
|
const postId = String(event.postId || '').trim()
|
|
if (!postId) throw new Error('postId is required')
|
|
|
|
const postRes = await db.collection('posts').doc(postId).get().catch(() => null)
|
|
if (!postRes || !postRes.data) return { post: null, comments: [] }
|
|
const post = postRes.data
|
|
|
|
// Resolve the author's current profile (fresh avatar), liked/favorited state.
|
|
let author = null
|
|
if (post.authorId) {
|
|
const authorRes = await safeGet('users', { _id: post.authorId }, 1)
|
|
author = authorRes.data[0] || null
|
|
}
|
|
|
|
let likedByMe = false
|
|
let favoritedByMe = false
|
|
if (OPENID) {
|
|
const [likedRes, favRes] = await Promise.all([
|
|
safeGet('postLikes', { openid: OPENID, postId }, 1),
|
|
safeGet('postFavorites', { openid: OPENID, postId }, 1)
|
|
])
|
|
likedByMe = likedRes.data.length > 0
|
|
favoritedByMe = favRes.data.length > 0
|
|
}
|
|
|
|
const mappedPost = {
|
|
_id: post._id,
|
|
author: {
|
|
id: post.authorId || '',
|
|
name: (author && author.nickname) || post.authorSnapshot?.name || '用户',
|
|
avatarKey: (author && author.avatarKey) || post.authorSnapshot?.avatarKey || 'gradient-avatar-1',
|
|
avatarUrl: (author && author.avatarUrl) || post.authorSnapshot?.avatarUrl || ''
|
|
},
|
|
pet: post.petSnapshot || { name: '', breed: '' },
|
|
body: post.content || '',
|
|
topics: post.topics || [],
|
|
media: Array.isArray(post.media)
|
|
? post.media.map(m => (typeof m === 'string' ? m : m && (m.url || m.fileId))).filter(Boolean)
|
|
: [],
|
|
mediaTone: post.mediaTone || 'pet-1',
|
|
sticker: post.sticker || undefined,
|
|
locationText: post.locationText || '',
|
|
timeText: formatTimeText(post.createdAt || Date.now()),
|
|
counts: {
|
|
likes: post.counts?.likes || 0,
|
|
comments: post.counts?.comments || 0,
|
|
favorites: post.counts?.favorites || 0
|
|
},
|
|
likedByMe,
|
|
favoritedByMe
|
|
}
|
|
|
|
// Comments, oldest first. Resolve each author's current profile for avatars.
|
|
const commentsRes = await safeGet('comments', { postId }, 200, { field: 'createdAt', direction: 'asc' })
|
|
const commentAuthorIds = [...new Set(commentsRes.data.map(c => c.authorId).filter(Boolean))]
|
|
const authorMap = new Map()
|
|
for (let i = 0; i < commentAuthorIds.length; i += 100) {
|
|
const chunk = commentAuthorIds.slice(i, i + 100)
|
|
const usersRes = await safeGet('users', { _id: _.in(chunk) }, 100)
|
|
usersRes.data.forEach(u => authorMap.set(u._id, u))
|
|
}
|
|
|
|
const comments = commentsRes.data.map(c => {
|
|
const u = authorMap.get(c.authorId)
|
|
return {
|
|
_id: c._id,
|
|
author: {
|
|
id: c.authorId || '',
|
|
name: (u && u.nickname) || c.authorSnapshot?.name || '用户',
|
|
avatarKey: (u && u.avatarKey) || c.authorSnapshot?.avatarKey || 'gradient-avatar-1',
|
|
avatarUrl: (u && u.avatarUrl) || c.authorSnapshot?.avatarUrl || ''
|
|
},
|
|
content: c.content || '',
|
|
timeText: formatTimeText(c.createdAt || Date.now())
|
|
}
|
|
})
|
|
|
|
return { post: mappedPost, comments }
|
|
}
|