fix: 修复评论/资料/导航胶囊/宠物档案/定位等多处问题,补全相关云函数

- 新增 addComment/getComments/getFollowList/followUser/getUser/updateProfile/updatePet/deletePet 云函数并完成部署
- 统一通过 app.globalData.navBarInfo 避让系统胶囊按钮(编辑资料/编辑宠物等页面保存按钮被遮挡问题)
- 编辑资料页所在城市改为省份 picker 选择
- 修复"我的"页动态为空(getUserPosts 应传 openid 而非数据库 _id)
- 重构编辑宠物页:品种改用 picker 滚轮(替代有数量上限的 actionSheet),标签改用 selectedTagSet 映射 + 自定义标签输入(5字以内、仅中英文/数字、最多8个)
- 接通宠物保存/删除真实云函数调用并同步本地缓存
- 移除 feed 页对不存在的 getStories 云函数调用,修复模拟器卡死
- 移除 post 页对不存在的 wx.reverseGeocoder API 的调用
- 统一扩展 AppGlobalData 类型并修正所有 getApp 调用的泛型,解决 TS 报错
This commit is contained in:
2026-06-07 15:59:21 +08:00
parent 24891d9004
commit 3d21a9d297
49 changed files with 937 additions and 195 deletions

View File

@@ -0,0 +1,43 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { postId, content } = event
if (!postId || !content?.trim()) {
return { code: -1, message: '参数错误' }
}
try {
const postRes = await db.collection('posts').doc(postId).get().catch(() => null)
if (!postRes?.data) return { code: -1, message: '帖子不存在' }
const comment = {
postId,
authorId: OPENID,
content: content.trim(),
likeCount: 0,
createdAt: db.serverDate(),
}
const res = await db.collection('comments').add({ data: comment })
await db.collection('posts').doc(postId).update({
data: { commentCount: _.inc(1) },
})
const authorRes = await db.collection('users')
.where({ openid: OPENID })
.field({ nickName: true, avatarUrl: true, openid: true })
.get()
return {
code: 0,
data: { _id: res._id, ...comment, author: authorRes.data[0] || null },
}
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "addComment", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,30 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { petId } = event || {}
if (!petId) return { code: -1, message: '缺少宠物ID' }
try {
const userRes = await db.collection('users').where({ openid: OPENID }).get()
if (userRes.data.length === 0) {
return { code: -1, message: '用户不存在' }
}
const user = userRes.data[0]
const pets = (Array.isArray(user.pets) ? user.pets : []).filter(p => p._id !== petId)
await db.collection('users').doc(user._id).update({
data: {
pets,
updatedAt: db.serverDate(),
},
})
return { code: 0, data: null }
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "deletePet", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,40 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { targetId } = event
if (!targetId || targetId === OPENID) return { code: -1, message: '参数错误' }
try {
const existRes = await db.collection('follows')
.where({ followerId: OPENID, followeeId: targetId })
.count()
if (existRes.total > 0) {
// unfollow
await db.collection('follows')
.where({ followerId: OPENID, followeeId: targetId })
.remove()
await Promise.all([
db.collection('users').where({ openid: OPENID }).update({ data: { 'stats.friends': _.inc(-1) } }),
db.collection('users').where({ openid: targetId }).update({ data: { 'stats.friends': _.inc(-1) } }),
])
return { code: 0, data: { following: false } }
} else {
// follow
await db.collection('follows').add({
data: { followerId: OPENID, followeeId: targetId, createdAt: db.serverDate() },
})
await Promise.all([
db.collection('users').where({ openid: OPENID }).update({ data: { 'stats.friends': _.inc(1) } }),
db.collection('users').where({ openid: targetId }).update({ data: { 'stats.friends': _.inc(1) } }),
])
return { code: 0, data: { following: true } }
}
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "followUser", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,45 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
const _ = db.command
const PAGE_SIZE = 20
exports.main = async (event, context) => {
const { postId, page = 0 } = event
if (!postId) return { code: -1, message: '缺少 postId' }
try {
const skip = page * PAGE_SIZE
const [totalRes, commentsRes] = await Promise.all([
db.collection('comments').where({ postId }).count(),
db.collection('comments')
.where({ postId })
.orderBy('createdAt', 'asc')
.skip(skip)
.limit(PAGE_SIZE)
.get(),
])
const comments = commentsRes.data
const authorIds = [...new Set(comments.map(c => c.authorId))]
let authorMap = {}
if (authorIds.length > 0) {
const authorsRes = await db.collection('users')
.where({ openid: _.in(authorIds) })
.field({ nickName: true, avatarUrl: true, openid: true })
.get()
authorsRes.data.forEach(u => { authorMap[u.openid] = u })
}
return {
code: 0,
data: {
list: comments.map(c => ({ ...c, author: authorMap[c.authorId] || null })),
total: totalRes.total,
},
}
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "getComments", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,51 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { type = 'following', userId } = event
const targetId = userId || OPENID
try {
let followIds = []
if (type === 'following') {
const res = await db.collection('follows')
.where({ followerId: targetId })
.field({ followeeId: true })
.get()
followIds = res.data.map(f => f.followeeId)
} else {
const res = await db.collection('follows')
.where({ followeeId: targetId })
.field({ followerId: true })
.get()
followIds = res.data.map(f => f.followerId)
}
if (followIds.length === 0) {
return { code: 0, data: [] }
}
const usersRes = await db.collection('users')
.where({ openid: _.in(followIds) })
.field({ nickName: true, openid: true, avatarUrl: true, bio: true, location: true, isOnline: true, lastSeen: true, pets: true, stats: true })
.get()
// check if current user follows each
const myFollowsRes = await db.collection('follows')
.where({ followerId: OPENID, followeeId: _.in(followIds) })
.field({ followeeId: true })
.get()
const myFollowSet = new Set(myFollowsRes.data.map(f => f.followeeId))
return {
code: 0,
data: usersRes.data.map(u => ({ ...u, _id: u._id, isFollowing: myFollowSet.has(u.openid) })),
}
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "getFollowList", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,40 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { userId } = event
try {
let userRes
if (userId) {
// Look up by DB _id
userRes = await db.collection('users').doc(userId).get().catch(() => null)
if (!userRes?.data) {
// Fallback: look up by openid
const res = await db.collection('users').where({ openid: userId }).get()
userRes = res.data.length > 0 ? { data: res.data[0] } : null
}
} else {
const res = await db.collection('users').where({ openid: OPENID }).get()
userRes = res.data.length > 0 ? { data: res.data[0] } : null
}
if (!userRes?.data) return { code: -1, message: '用户不存在' }
const user = userRes.data
// Check follow status
const followRes = await db.collection('follows')
.where({ followerId: OPENID, followeeId: user.openid })
.count()
return {
code: 0,
data: { ...user, isFollowing: followRes.total > 0 },
}
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "getUser", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,72 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
// 根据生日计算年龄展示文案
function calcAge(birthday) {
if (!birthday) return ''
const dob = new Date(birthday).getTime()
if (isNaN(dob)) return ''
const diffMs = Date.now() - dob
if (diffMs < 0) return ''
const years = Math.floor(diffMs / (365.25 * 24 * 3600 * 1000))
const months = Math.floor((diffMs % (365.25 * 24 * 3600 * 1000)) / (30.44 * 24 * 3600 * 1000))
return years > 0 ? `${years}${months > 0 ? months + '个月' : ''}` : `${months}个月`
}
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { pet } = event || {}
if (!pet || !pet.name || !String(pet.name).trim()) {
return { code: -1, message: '宠物信息不完整' }
}
try {
const userRes = await db.collection('users').where({ openid: OPENID }).get()
if (userRes.data.length === 0) {
return { code: -1, message: '用户不存在' }
}
const user = userRes.data[0]
const pets = Array.isArray(user.pets) ? [...user.pets] : []
const petData = {
name: String(pet.name).trim(),
species: pet.species || 'dog',
breed: pet.breed || '',
gender: pet.gender || 'female',
birthday: pet.birthday || '',
age: calcAge(pet.birthday),
bio: (pet.bio || '').trim(),
tags: Array.isArray(pet.tags) ? pet.tags.slice(0, 8) : [],
emoji: pet.emoji || '🐾',
photos: pet.avatarUrl ? [pet.avatarUrl] : (Array.isArray(pet.photos) ? pet.photos : []),
ownerId: OPENID,
}
let resultPet
if (pet._id) {
const idx = pets.findIndex(p => p._id === pet._id)
if (idx === -1) {
return { code: -1, message: '宠物档案不存在' }
}
resultPet = { ...pets[idx], ...petData, _id: pet._id }
pets[idx] = resultPet
} else {
const newId = `pet_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
resultPet = { _id: newId, ...petData }
pets.push(resultPet)
}
await db.collection('users').doc(user._id).update({
data: {
pets,
updatedAt: db.serverDate(),
},
})
return { code: 0, data: resultPet }
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "updatePet", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }

View File

@@ -0,0 +1,27 @@
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
exports.main = async (event, context) => {
const { OPENID } = cloud.getWXContext()
const { nickName, bio, location } = event
if (!nickName?.trim()) return { code: -1, message: '昵称不能为空' }
try {
await db.collection('users')
.where({ openid: OPENID })
.update({
data: {
nickName: nickName.trim(),
bio: (bio || '').trim(),
location: (location || '').trim(),
updatedAt: db.serverDate(),
},
})
return { code: 0, data: null }
} catch (e) {
return { code: -1, message: e.message }
}
}

View File

@@ -0,0 +1 @@
{ "name": "updateProfile", "version": "1.0.0", "main": "index.js", "dependencies": { "wx-server-sdk": "~2.1.2" } }