- 新增 .gitignore(排除 node_modules、私有配置、编译产物) - 新增 cloudbaserc.json,绑定云环境 cloud1-d4g697lte499543d8 - project.config.json:补 miniprogramRoot、开启 useCompilerPlugins typescript,修复预览报 app.json 找不到的问题 - tsconfig.json:移除无效 typeRoots,解除 TypeScript 编译阻断 - miniprogram/app.json:移除 glass-easel(需基础库 3.x,兼容性差) - miniprogram/utils/constants.ts:填入真实云环境 ID - cloudfunctions/updateLocation:位置字段改用 GeoPoint 以支持地理索引 - cloudfunctions/getNearbyPets:改用 geoNear 聚合管道,支持真实距离排序 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
67 lines
1.9 KiB
JavaScript
67 lines
1.9 KiB
JavaScript
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 {
|
||
latitude,
|
||
longitude,
|
||
maxDistance = 5000, // 默认 5km,单位:米
|
||
page = 0,
|
||
pageSize = 20,
|
||
} = event
|
||
|
||
if (!latitude || !longitude) return { code: -1, message: '缺少位置' }
|
||
|
||
try {
|
||
// ✅ geoNear 聚合管道:依赖 users.lastLocation 字段上的 2dsphere 地理位置索引
|
||
const { list } = await db.collection('users')
|
||
.aggregate()
|
||
.geoNear({
|
||
near: db.Geo.Point(longitude, latitude), // 注意:CloudBase GeoPoint 是 (lng, lat) 顺序
|
||
spherical: true,
|
||
distanceField: 'dist', // 在每条记录上附加实际距离(米)
|
||
maxDistance,
|
||
query: {
|
||
openid: _.neq(OPENID), // 排除自己
|
||
'pets.0': _.exists(true), // 至少有一只宠物
|
||
},
|
||
})
|
||
.skip(page * pageSize)
|
||
.limit(pageSize)
|
||
.project({
|
||
openid: false,
|
||
})
|
||
.end()
|
||
|
||
// 在线状态:5 分钟内活跃
|
||
const fiveMin = 5 * 60 * 1000
|
||
const now = Date.now()
|
||
|
||
const result = list.map(u => ({
|
||
userId: u._id,
|
||
user: u,
|
||
pet: u.pets?.[0] || null,
|
||
distance: Math.round(u.dist),
|
||
distanceText: formatDist(u.dist),
|
||
isOnline: u.lastSeen && (now - new Date(u.lastSeen).getTime()) < fiveMin,
|
||
location: {
|
||
latitude: u.lastLocation?.coordinates?.[1],
|
||
longitude: u.lastLocation?.coordinates?.[0],
|
||
},
|
||
}))
|
||
|
||
return { code: 0, data: result }
|
||
} catch (e) {
|
||
return { code: -1, message: e.message }
|
||
}
|
||
}
|
||
|
||
function formatDist(meters) {
|
||
if (!meters && meters !== 0) return '未知'
|
||
if (meters < 1000) return Math.round(meters) + 'm'
|
||
return (meters / 1000).toFixed(1) + 'km'
|
||
}
|