13 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
"点线得面" - A WeChat Mini Program for collaborative meeting point selection. Users create rooms, share with friends, each member adds their location, and the system calculates the optimal meeting venue based on everyone's coordinates. Maximum 8 members per room, and rooms expire after 30 days.
Architecture: WeChat Mini Program frontend + WeChat Cloud Functions backend + MeetSpot Python API (external service)
Repository Structure
WoMenQuNaJu/
├── miniprogram/ # WeChat Mini Program frontend
│ ├── pages/ # Page components (index, create-room, room, result)
│ ├── app.js/json/wxss # Application entry
│ └── images/ # Static assets
├── cloudfunctions/ # WeChat Cloud Functions (Node.js)
│ ├── calculateMeetSpot/ # Core: calls MeetSpot API to calculate venues
│ ├── createRoom/ # Create a new room
│ ├── joinRoom/ # Add member to room (max 8 people)
│ ├── updateLocation/ # Update current user's location
│ ├── updateMemberLocation/ # Update test member's location (dev only)
│ ├── updateRoomInfo/ # Update room metadata
│ ├── removeMember/ # Remove member from room
│ ├── deleteRoom/ # Delete entire room
│ ├── cleanExpiredRooms/ # Scheduled: delete rooms older than 30 days
│ ├── addTestMember/ # Add test member (dev only)
│ └── getOpenId/ # Get user's WeChat OpenID
└── MeetSpot/ # Python FastAPI backend (has its own CLAUDE.md)
Key Insight: The WeChat Mini Program is a lightweight frontend/coordinator. The heavy lifting (geocoding, POI search, venue ranking) is delegated to the MeetSpot FastAPI service via the calculateMeetSpot cloud function.
WeChat Mini Program Development
Setup
# Install WeChat Developer Tools
# Download from: https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
# Open project in WeChat Developer Tools
# Project directory: d:\download\WoMenQuNaJu
# AppID: wxb7e6344198f6526f (from project.config.json)
Cloud Functions: Each function in cloudfunctions/ needs dependencies installed separately:
# For cloud functions that use axios (like calculateMeetSpot)
cd cloudfunctions/calculateMeetSpot
npm install
# Repeat for other functions with package.json
cd ../createRoom
npm install
Deploy Cloud Functions: Use WeChat Developer Tools GUI to upload cloud functions, or use CLI:
# Upload a single cloud function
miniprogram-ci cloud uploadFunction --functionName calculateMeetSpot
Testing
Local Testing: Use WeChat Developer Tools simulator. The simulator supports:
- Cloud function calls
- Cloud database operations
- Location services (mocked)
Backend URL Configuration:
calculateMeetSpot/index.js:78containsBACKEND_URLenvironment variable- Default:
https://meetspot.onrender.com(production MeetSpot API) - For local testing: Set cloud function env var to
http://localhost:8000(requires ngrok or similar for Mini Program to reach local machine)
Data Model
Cloud Database Collection: rooms
Data Retention: Rooms are automatically deleted 30 days after creation. A scheduled cloud function cleanExpiredRooms runs periodically to clean up expired data.
{
_id: "auto-generated",
_openid: "creator's openid",
createdAt: ServerDate,
expireTime: Date, // Auto-delete 30 days after creation
status: "active" | "calculating" | "calculated",
name: "聚会名称",
meetTime: "2026-02-10 18:00",
keywords: "咖啡馆",
requirements: "parking, quiet",
members: [
{
openid: "wx-openid",
avatarUrl: "https://...",
nickName: "用户昵称",
location: {
lng: 116.32,
lat: 39.99,
address: "北京大学",
name: "北京大学"
},
joinedAt: Date,
isTestMember: false // true for dev test members
}
],
result: {
success: true,
venues: [...],
center: { lat: 39.99, lng: 116.32 },
html_url: "/workspace/js_src/recommendation_xxx.html"
},
lastCalculateTime: ServerDate,
lastCalculatedMembers: "openid1_lat_lng,openid2_lat_lng,..." // Snapshot for duplicate detection
}
Member Limit: Maximum 8 members per room. Enforced in joinRoom cloud function.
Architecture Patterns
Status Locking Pattern
Problem: Multiple users clicking "Calculate" simultaneously could trigger duplicate API calls.
Solution: calculateMeetSpot uses database-level status locking:
// 1. Check if status is "calculating" (early return if locked)
if (data.status === 'calculating') return { msg: '正在计算中' }
// 2. Acquire lock
await db.collection('rooms').doc(roomId).update({ status: 'calculating' })
// 3. Call backend API
const result = await axios.post(BACKEND_URL, ...)
// 4. Release lock and save result
await db.collection('rooms').doc(roomId).update({
status: 'calculated',
result: result.data
})
Exception Handling: If API call fails, the catch block releases the lock by setting status: 'active'.
Duplicate Calculation Prevention
Problem: Users might click "Calculate" multiple times without changing member locations.
Solution: calculateMeetSpot/index.js:43-61 compares current member positions against lastCalculatedMembers snapshot:
const currentSnapshot = validMembers
.map(m => `${m.openid}_${m.location.lat}_${m.location.lng}`)
.sort()
.join(',')
if (currentSnapshot === data.lastCalculatedMembers) {
return { isDuplicate: true, existingResult: data.result }
}
Real-time Synchronization
Pattern: Database Watch API for live updates
Implementation: miniprogram/pages/room/room.js:125-179
db.collection('rooms').doc(roomId).watch({
onChange: snapshot => {
// Sync room state, member list, calculation status
// Auto-navigate to result page when status changes from 'calculating' to 'calculated'
}
})
Critical Detail: Uses previousStatus tracking to only auto-navigate when calculation just finished, preventing navigation loops when users return to the room page.
Test Member System
Purpose: Allow room creators to add mock members for testing without needing multiple WeChat accounts.
Identification: Test members have isTestMember: true and openid format test_<timestamp>_<random>
Special Handling:
addTestMember: Creates member with random location (Beijing area)updateMemberLocation: Allows creator to update test member locationsremoveMember: Can delete test members- UI shows "测试" badge and allows creator to edit their locations
Cloud Functions
Core Function: calculateMeetSpot
Responsibility: Bridge between Mini Program and MeetSpot API
Flow:
- Validate: At least 2 members with locations
- Check: Duplicate calculation detection
- Lock: Set status to
calculating - Transform: Extract
{ lng, lat, address, name }from members - Call: POST to
BACKEND_URL/api/miniprogram/calculate - Store: Save result to database, update status to
calculated
Environment Variables: Set in WeChat Cloud Console
BACKEND_URL: MeetSpot API endpoint (default:https://meetspot.onrender.com)
Timeout: 30 seconds (axios timeout). MeetSpot API typically responds in 3-15 seconds.
Database Mutating Functions
| Function | Mutation | Permission Check |
|---|---|---|
createRoom |
Add document to rooms |
Anyone (creator = caller's openid) |
joinRoom |
Push to members array |
Anyone (duplicate check by openid) |
updateLocation |
Update member's location in array | Own openid only |
updateMemberLocation |
Update test member location | Creator only |
updateRoomInfo |
Update room metadata | Creator only (checked via _openid) |
removeMember |
Remove from members array |
Self-exit OR creator removing others |
deleteRoom |
Delete entire document | Creator only |
Security Note: Cloud Functions automatically add _openid field (caller's WeChat ID) to database writes. Permission checks compare wxContext.OPENID against stored _openid.
MeetSpot Backend Integration
The MeetSpot/ subdirectory is a separate Python/FastAPI project. See MeetSpot/CLAUDE.md for details.
Key Integration Point: calculateMeetSpot cloud function calls POST /api/miniprogram/calculate endpoint.
Expected Request:
{
"locations": [
{ "lng": 116.32, "lat": 39.99, "address": "北京大学", "name": "北京大学" }
],
"keywords": "咖啡馆",
"requirements": "parking, quiet"
}
Expected Response:
{
"success": true,
"venues": [ /* Array of ranked venues */ ],
"center": { "lat": 39.99, "lng": 116.32 },
"html_url": "/workspace/js_src/recommendation_xxx.html"
}
To run MeetSpot locally:
cd MeetSpot
python web_server.py
# Backend will be at http://localhost:8000
Common Development Tasks
Adding a New Cloud Function
- Create directory:
cloudfunctions/myFunction/ - Add
index.js:
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
// Your logic here
return { success: true }
}
- Add
package.jsonif using npm dependencies - Install dependencies:
npm install(in function directory) - Upload via WeChat Developer Tools
Modifying Room Schema
Important: WeChat Cloud Database is schemaless, but for consistency:
- Update
createRoom/index.jsfor new fields in initial data - Add migration logic in
calculateMeetSpotor other functions if transforming existing data - Update TypeScript interfaces if using typed Mini Program (this project uses plain JS)
Changing Keywords/Requirements Options
Keywords Picker: miniprogram/pages/room/room.js:10
keywordOptions: ['咖啡馆', '餐厅', '公园', ...]
Requirements: Free-text input, no predefined options. MeetSpot API parses natural language.
Debugging Cloud Functions
Method 1: WeChat Developer Tools Console
- Right-click function → "Upload and Debug"
- Use
console.log()- logs appear in Cloud Development Console
Method 2: Local Cloud Function Emulation
- Install
miniprogram-ci - Use
npx miniprogram-ci cloud emulator
Performance Considerations
Cold Start: Cloud functions have ~500ms-2s cold start. First calculation in a room may feel slow.
Database Watch: Each page maintains one watch connection. WeChat limits 5 concurrent watches per user. Close watches in onUnload().
Calculation Time: Typical flow takes 5-15 seconds:
- Cloud function startup: 0.5-2s
- MeetSpot API call: 3-12s (includes geocoding, POI search, ranking)
- Database write: 0.1-0.5s
Optimization: Duplicate calculation prevention saves ~90% of redundant API calls.
Deployment
Mini Program
- Update version in WeChat Developer Tools
- Click "Upload" → Enter version number and description
- Submit for review in WeChat Public Platform
- After approval, release to production
Cloud Functions
Individual Upload: Right-click function → "Upload and Deploy: Cloud Installation Dependencies"
Batch Upload: Cloud Development Console → Cloud Functions → Batch upload
CI/CD: Use miniprogram-ci for automated deployment:
miniprogram-ci upload --project /path/to/project \
--appid wxb7e6344198f6526f \
--version 1.0.0 \
--desc "Update description"
Debugging Common Issues
| Issue | Cause | Solution |
|---|---|---|
| "未找到云函数" | Function not uploaded | Upload via Developer Tools |
| "正在计算中" stuck | Lock not released after error | Manually set status: 'active' in database |
| Empty result page | BACKEND_URL unreachable | Check cloud function logs, verify MeetSpot API is running |
| Location picker fails | Missing permission | Check app.json → permission → scope.userLocation |
| Watch connection lost | Network interruption | Page will auto-reconnect on next data change |
| "至少需要2人" error | Only 1 member has location | Add more member locations or use test members |
Logs: Cloud Development Console → Cloud Functions → Function logs (search by requestId)
Code Style
- JavaScript: 4-space indent, ES6+ syntax, no semicolons (Mini Program convention)
- Cloud Functions: Use
async/await, avoid callbacks - Naming:
camelCasefor variables/functions,PascalCasefor pages/components - Comments: Chinese for user-facing strings, English for technical comments acceptable
Related Documentation
- WeChat Mini Program Docs: https://developers.weixin.qq.com/miniprogram/dev/framework/
- Cloud Functions Guide: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/capabilities.html
- MeetSpot Backend: See
MeetSpot/CLAUDE.mdfor Python/FastAPI development guide