Files
Pawer/cloudfunctions/feedList/index.js
2026-06-18 14:33:50 +08:00

106 lines
3.5 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).
// Returns an empty result instead of throwing "collection not exists".
async function safeGet(collection, where, limit = 200) {
try {
return await db.collection(collection).where(where).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 pageSize = Math.min(event.pageSize || 20, 50)
const query = { visibility: 'public' }
if (event.topic) query.topics = event.topic
// Follow channel: only posts from users I follow (plus my own).
if (event.channel === 'follow') {
if (!OPENID) return { list: [], nextCursor: '' }
const meRes = await db.collection('users').where({ openid: OPENID }).limit(1).get()
if (!meRes.data.length) return { list: [], nextCursor: '' }
const meId = meRes.data[0]._id
const followRes = await safeGet('follows', { followerId: meId }, 500)
const authorOpenids = followRes.data.map(f => f.followeeOpenid).filter(Boolean)
authorOpenids.push(OPENID)
query.authorOpenid = _.in(authorOpenids)
query.visibility = _.in(['public', 'friends'])
}
if (event.cursor) {
query.createdAt = _.lt(Number(event.cursor))
}
const res = await db.collection('posts')
.where(query)
.orderBy('createdAt', 'desc')
.limit(pageSize)
.get()
if (!res.data.length) return { list: [], nextCursor: '' }
const postIds = res.data.map(p => p._id)
// Batch-check liked/favorited status — skip if no valid OPENID (non-WeChat context)
let likedSet = new Set()
let favSet = new Set()
if (OPENID) {
const [likedRes, favRes] = await Promise.all([
safeGet('postLikes', { openid: OPENID, postId: _.in(postIds) }),
safeGet('postFavorites', { openid: OPENID, postId: _.in(postIds) })
])
likedSet = new Set(likedRes.data.map(l => l.postId))
favSet = new Set(favRes.data.map(f => f.postId))
}
const list = res.data.map(post => ({
_id: post._id,
author: {
id: post.authorId || '',
name: post.authorSnapshot?.name || '用户',
avatarKey: post.authorSnapshot?.avatarKey || 'gradient-avatar-1'
},
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: likedSet.has(post._id),
favoritedByMe: favSet.has(post._id)
}))
const last = res.data[res.data.length - 1]
return { list, nextCursor: last ? String(last.createdAt) : '' }
}