📸 完整产品截图和真实运营数据,见落地案例:战斗吧我的爱人
前言
2026年2月,一个叫"战斗吧我的爱人"的微信小程序悄悄上线。没有大厂背书,没有融资推广,开发者摸鱼博士用一台学生服务器和AI编程工具,7天做出了这款产品。上线3个月后,数据表现让摸鱼博士自己都愣住了:访问人数2,806(同比增长27,900%)、打开次数8,129(同比增长26,350%)、访问页面数9,661(同比增长262,100%)。
这不是什么互联网大厂的内部创新项目,这是一个普通开发者用AI从零开始做出来的产品。
我采访了他,把完整的技术实现路径、商业逻辑、踩坑经验整理成这篇文章。如果你也想用AI开发小程序,或者正在寻找一个"小而美"的创业方向,这篇文章值得你认真读完。
第一章 为什么这个赛道值得做
1.1 一个被大厂忽视的蓝海市场
打开应用商店,搜索"情侣"二字,出来的结果要么是社交软件(探探、Soul),要么是工具类产品(情侣日历、纪念日提醒)。但真正解决"情侣间私密互动"需求的产品,几乎找不到。
不是没有需求,而是需求太敏感,大厂不敢做。
两性/情感赛道有三个特点:
需求极强,付费意愿高。 情趣用品市场2024年规模超过1800亿元,年增速15%以上。这个市场里的用户,付费意愿远超普通消费者。但"软件"部分几乎是空白——用户买了跳蛋、买了飞机杯,却没有对应的App来完成整个体验闭环。
公开讨论少,搜索流量高。 "情侣互动"相关关键词的微信指数常年居高不下,但内容供给严重不足。用户找不到好用的产品,只能去知乎、去小红书问"有没有什么情侣之间的小游戏"。
大厂不敢做,小团队做不好。 大厂有合规压力,两性内容稍有不慎就上热搜,所以干脆不做。小团队想做,但技术能力、内容能力、运营能力都跟不上,做出来的产品要么太粗糙,要么审核被拒。
这就形成了一个独特的真空地带:谁做出来,谁吃独食。
1.2 微信小程序的天然优势
微信小程序月活9亿+,情侣类应用的渗透率不到0.5%。这意味着99.5%的情侣还没有被触达。
更重要的是,情侣类应用有天然的双端裂变属性。一个人注册后,想要完整使用功能,必须邀请伴侣也注册。这意味着:
- 一个人注册 → 绑定伴侣 → 伴侣也得注册 → 传播系数 > 1
- 用户绑定数据后,迁移成本极高,竞品很难抢人
- 先发优势明显,早期用户就是壁垒
1.3 真实数据验证
摸鱼博士的"战斗吧我的爱人"就是最好的证明。
他不是技术大牛,没有运营团队,甚至没有推广预算。凭什么能做到27900%的增长?
核心就三点:
- 高度封闭的数据隐私保护 + 全国战友比拼并存。 既保护私密,又有社交张力。
- 海王标签机制。 频繁换绑伴侣会被打上"海王"标签,而且是永久标记、不可消除。这个设计成了最强的传播钩子——用户截图分享,引发讨论,带来新用户。
- 丰富的趣味互动游戏。 让记录过程本身变成一种游戏体验。
这就是我要在这篇文章里拆解的方法论。
第二章 产品长什么样
2.1 用户旅程:10秒注册,3步绑定,永久留存
"战斗吧我的爱人"的产品设计极其简洁,整个用户旅程不超过5个页面:
第一步:注册(10秒) 打开小程序 → 微信授权 → 选择性别(男/女)→ 填写昵称 → 完成注册
没有任何多余的表单,不需要手机号,不需要邮箱。微信授权是唯一的注册方式。
第二步:绑定伴侣(裂变起点) 点击"绑定伴侣" → 生成分享卡片 → 分享给微信好友 → 伴侣打开链接,授权注册 → 双向确认绑定
这里有一个关键设计:绑定必须是双向的。你想绑定对方,对方也必须完成注册并同意绑定。这意味着每一个新用户,都会带来一个新的潜在用户。
绑定时还需要设定每月"对战目标"——这是游戏化的核心锚点。
第三步:亲密时刻记录(核心功能) 进入"战斗"页面 → 选择"发起挑战"或"接受挑战" → 设定时间 → 战斗结束后填写战绩评分和备注
记录过程被包装成"递战书→决高下→记战果"的完整游戏化流程。用户不是在填表,而是在玩游戏。
第四步:数据面板与成就系统 查看累计数据、日历热力图、本月完成率、场均时长、战斗评级(五颗星)。7项成就徽章挂在个人主页:持久战神、清晨刺客、一招制敌、最佳拍档等。
第五步:广场(可选功能) 匿名社区,实时战况地图(无具体位置),话题讨论区。这是留存和促活的辅助功能,不是核心。
2.2 海王标签:最强传播钩子
"战斗吧我的爱人"最出圈的设计,是那个永久不可消除的"海王"标签。
逻辑很简单:如果你在短时间内频繁更换伴侣绑定,系统会给你打上一个"海王"标签。而且这个标签一旦打上,永远无法消除。
这个设计的巧妙之处在于:
- 话题性。 用户发现被标记后,第一反应是截图发朋友圈/微博吐槽。"我用这个小程序被标记成海王了"——这是天然的社交货币。
- 筛选机制。 真正有稳定伴侣的用户不会触发这个标签,被标记的确实是"高频换人"的用户,标签本身是准确的。
- 传播链条。 吐槽帖引发讨论 → 好奇的用户来体验 → 发现自己的数据被保护得很好 → 口碑传播。
摸鱼博士在520当天发了一条抖音视频,标题是:"不是吧你们都不用上班的么?大白天啊拜托",直接引爆了传播。
第三章 云数据库表设计(详细到字段级别)
3.1 技术选型:微信云开发
"战斗吧我的爱人"选择的是微信云开发(CloudBase),原因很简单:0服务器成本,0运维成本,微信官方托管,已认证小程序可直接调用内容安全API。
根据微信官方2025-2026年的最新计费政策:
| 资源类型 | 免费体验版配额 | 个人版配额 | 足够支撑 |
|---|---|---|---|
| 云函数调用 | 3000点/月 | 40,000点/月 | 日活3000以下 |
| 云存储 | 共享实例 | 共享实例 | 普通用户量级 |
| 云数据库 | 共享实例 | 共享实例 | 10万条数据以下 |
对于初创项目来说,免费体验版完全够用。摸鱼博士用学生服务器做了部分数据备份,但核心业务完全跑在云开发上,成本几乎为零。
3.2 集合设计:6个集合,支撑完整业务
3.2.1 users 集合(用户表)
存储用户基本信息:
{
"_id": "user_abc123",
"openid": "oXXXX_xxxxxxxxxxxxx",
"nickName": "摸鱼博士",
"gender": "male",
"avatar": "https://mmbiz.qpic.cn/...",
"inviteCode": "MF2026",
"tags": ["海王", "清晨刺客"],
"bindHistory": [
{
"coupleId": "couple_xxx",
"bindTime": "2026-02-06T10:00:00+08:00",
"unbindTime": null,
"reason": "主动解绑"
}
],
"currentCoupleId": "couple_xxx",
"stats": {
"totalBattles": 23,
"totalDuration": 1840,
"avgRating": 4.2,
"longestStreak": 7
},
"achievements": ["持久战神", "清晨刺客"],
"createTime": "2026-02-06T09:30:00+08:00",
"lastActiveTime": "2026-05-06T15:20:00+08:00"
}
字段说明:
openid:微信用户唯一标识,用于登录认证inviteCode:邀请码,用于绑定伴侣时的分享链接参数tags:用户标签数组,"海王"标签会永久保留bindHistory:绑定历史,支持解绑后查看历史伴侣currentCoupleId:当前绑定伴侣ID,为空则表示未绑定stats:用户统计数据,用于面板展示achievements:已解锁成就列表
3.2.2 couples 集合(伴侣关系表)
存储一对伴侣的绑定关系:
{
"_id": "couple_xxx",
"user1": "user_abc123",
"user2": "user_def456",
"monthlyGoal": 8,
"status": "active",
"bindTime": "2026-02-06T10:00:00+08:00",
"unbindTime": null,
"monthlyStats": [
{
"month": "2026-02",
"battles": 5,
"completed": 3,
"completionRate": 0.6
}
],
"createTime": "2026-02-06T10:00:00+08:00"
}
字段说明:
user1/user2:双方用户ID,建议约定user1<user2保持一致性monthlyGoal:每月对战目标次数status:关系状态,active(活跃)、inactive(已解绑)monthlyStats:按月统计的战绩,用于年度回顾和成就计算
3.2.3 battles 集合(战斗记录表)
存储每次亲密时刻的记录:
{
"_id": "battle_789",
"coupleId": "couple_xxx",
"initiator": "user_abc123",
"date": "2026-05-06",
"duration": 45,
"rounds": 3,
"rating1": 5,
"rating2": 4,
"note": "周末下午,窗外下着小雨",
"mood": "温馨",
"images": ["cloud://xxx1.jpg", "cloud://xxx2.jpg"],
"status": "completed",
"createTime": "2026-05-06T15:00:00+08:00",
"updateTime": "2026-05-06T15:45:00+08:00"
}
字段说明:
duration:时长(分钟)rounds:回合数(可选字段)rating1/rating2:双方评分(1-5分)note:私密备注,仅伴侣双方可见mood:心情标签,提供预设选项供选择images:云存储的图片路径status:pending(进行中)、completed(已完成)、cancelled(已取消)
3.2.4 achievements 集合(成就表)
存储用户的成就解锁记录:
{
"_id": "ach_001",
"userId": "user_abc123",
"type": "early_bird",
"name": "清晨刺客",
"description": "在早上6点前完成一次战斗",
"unlockedAt": "2026-03-15T05:45:00+08:00",
"evidence": {
"battleId": "battle_456",
"battleDate": "2026-03-15"
}
}
预设成就类型:
| type | name | description | 解锁条件 |
|---|---|---|---|
marathon | 持久战神 | 单次战斗超过60分钟 | duration >= 60 |
early_bird | 清晨刺客 | 早上6点前完成战斗 | hour < 6 |
quick_shot | 一招制敌 | 15分钟内结束战斗 | duration <= 15 |
consistent | 坚持不懈 | 连续7天每天至少1次 | streak >= 7 |
anniversary | 纪念日战士 | 绑定纪念日当天战斗 | date == bindAnniversary |
perfect_match | 天作之合 | 双方都给出5星评分 | rating1 == 5 && rating2 == 5 |
total_warrior | 战神之路 | 累计完成50次战斗 | totalBattles >= 50 |
3.2.5 memos 集合(私密备忘录表)
{
"_id": "memo_111",
"coupleId": "couple_xxx",
"authorId": "user_abc123",
"content": "下周二是我们的100天纪念日,要准备惊喜!",
"isRead": false,
"createTime": "2026-05-01T20:00:00+08:00",
"readTime": null
}
3.2.6 posts 集合(广场帖子表)
{
"_id": "post_222",
"authorId": "user_abc123",
"authorNick": "用户7***3",
"content": "5月的战斗目标是20次,目前完成12次,加油!",
"type": "progress",
"likes": 42,
"comments": 8,
"anonymous": true,
"status": "published",
"createTime": "2026-05-06T10:00:00+08:00"
}
字段说明:
authorNick:脱敏后的昵称,显示格式为"用户X***Y"anonymous:是否匿名发布type:帖子类型,progress(进度分享)、question(提问)、discuss(讨论)
3.3 权限设计:数据隔离原则
云开发数据库支持记录级权限控制(ACL)。核心原则是:
{
"_id": {
"read": true,
"write": true
},
"openid": {
"read": true,
"write": false
},
"note": {
"read": "doc._openid == auth.openid || doc.coupleId in couples.bindings[auth.openid]",
"write": "doc._openid == auth.openid"
}
}
简单来说:
- 用户只能读写自己的基础信息
- 战斗记录的
note(私密备注)只有伴侣双方可以读写 - 广场帖子匿名发布,不暴露真实用户信息
第四章 AI开发实战:从PRD到代码的完整流程
4.1 核心心法:不要一次生成整个项目
很多新手用AI编程时会犯一个错误:把完整需求丢给AI,期待它一次性输出整个项目。
结果往往是:AI生成的代码bug一堆,逻辑混乱,根本跑不起来。
正确的做法是:逐页面、逐功能生成。每次给AI线框图 + 已有代码 + 具体功能需求。
摸鱼博士的开发方式叫"半vibe coding + 半手搓":AI负责生成框架和大部分代码,他负责审核、修正、补充细节。
4.2 Step 1:AI生成PRD
用AI生成PRD时,建议使用CRTC框架(Customer-Context-Requirements-Technical):
## PRD模板
# 产品名称
战斗吧我的爱人 - 情侣私密互动记录小程序
# 目标用户
- 有稳定伴侣关系的成年情侣
- 年龄段:20-35岁
- 核心诉求:私密记录、情感升温、有趣互动
# 用户场景
1. 用户A和用户B是情侣,想要记录他们的亲密时刻
2. 用户想要设定每月"战斗目标",保持一定频率
3. 用户想要查看历年数据,找到纪念日规律
4. 用户想要在广场匿名分享进度,获得社区支持
# 核心功能(P0)
1. 微信授权注册登录
2. 伴侣双向绑定(分享邀请制)
3. 亲密时刻记录(时间、内容、评分、备注)
4. 数据统计面板(累计、每月、每日热力图)
5. 成就徽章系统
6. 海王标签检测
# 次要功能(P1)
1. 私密备忘录
2. 匿名广场
3. 纪念日提醒
# 约束条件
- 所有用户数据仅伴侣双方可见
- 内容安全必须通过微信msgSecCheck审核
- 界面风格:温馨、暧昧但不色情
- 文案措辞:含蓄、隐喻,避免直白描述
# 技术要求
- 平台:微信小程序
- 后端:微信云开发
- AI编程工具:Cursor + Claude
4.3 Step 2:逐页面生成代码框架
不要一次性生成所有页面。按以下顺序逐个开发:
开发顺序(优先级排序):
pages/index- 启动页/加载页pages/login- 注册页pages/home- 首页(未绑定/已绑定状态)pages/bind- 绑定伴侣页pages/battle- 战斗记录页pages/stats- 数据统计页pages/achievement- 成就页pages/square- 广场页pages/memo- 备忘录页
给AI的prompt模板:
## 任务
生成微信小程序页面:[页面名称]
## 已有代码
// 粘贴页面目录下已有的文件内容(第一次为空)
## 线框图描述
[用文字描述页面布局,例如:
顶部:用户头像 + 昵称 + 标签
中间:月度目标进度条(圆形进度)
下方:本周数据统计卡片
底部:导航栏(首页/战斗/统计/我的)]
## 功能需求
1. [具体功能1]
2. [具体功能2]
## 注意事项
- 所有文案使用含蓄表达
- 禁止出现直白描述性词汇
- 符合微信小程序设计规范
4.4 Step 3:核心功能关键代码
以下是4个最核心的云函数完整代码,复制即可使用。
4.4.1 绑定伴侣云函数
// cloudfunctions/bindCouple/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
const { type, inviteCode, partnerOpenid } = event
const wxContext = cloud.getWXContext()
const openid = wxContext.OPENID
try {
// 查询当前用户信息
const userRes = await db.collection('users').where({
openid: openid
}).get()
if (!userRes.data || userRes.data.length === 0) {
return { success: false, message: '用户不存在' }
}
const currentUser = userRes.data[0]
// 检查是否已有伴侣
if (currentUser.currentCoupleId) {
return { success: false, message: '您已绑定伴侣,请先解绑' }
}
if (type === 'create') {
// 方式一:创建新的绑定请求
// 生成唯一的coupleId
const coupleId = 'couple_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)
// 创建伴侣关系记录
await db.collection('couples').add({
data: {
_id: coupleId,
user1: openid,
user2: '',
monthlyGoal: 8,
status: 'pending',
user1BindTime: new Date(),
createTime: new Date()
}
})
// 更新用户表的绑定邀请码
await db.collection('users').where({
openid: openid
}).update({
data: {
pendingCoupleId: coupleId,
inviteCode: currentUser.inviteCode || 'CP' + Date.now().toString(36).toUpperCase()
}
})
return {
success: true,
coupleId: coupleId,
inviteCode: currentUser.inviteCode,
message: '绑定请求已创建,请分享给伴侣'
}
} else if (type === 'accept') {
// 方式二:接受绑定邀请(通过inviteCode)
if (!inviteCode) {
return { success: false, message: '邀请码不能为空' }
}
// 查找邀请码对应的用户
const inviterRes = await db.collection('users').where({
inviteCode: inviteCode
}).get()
if (!inviterRes.data || inviterRes.data.length === 0) {
return { success: false, message: '邀请码无效' }
}
const inviter = inviterRes.data[0]
if (!inviter.pendingCoupleId) {
return { success: false, message: '该用户暂无待处理的绑定请求' }
}
// 检查是否是自己邀请自己
if (inviter.openid === openid) {
return { success: false, message: '不能绑定自己' }
}
// 获取伴侣关系记录
const coupleRes = await db.collection('couples').doc(inviter.pendingCoupleId).get()
if (!coupleRes.data) {
return { success: false, message: '绑定关系已失效' }
}
const couple = coupleRes.data
// 更新伴侣关系:填写user2
await db.collection('couples').doc(couple._id).update({
data: {
user2: openid,
status: 'active',
user2BindTime: new Date(),
bindTime: new Date()
}
})
// 更新双方用户信息
await db.collection('users').where({
openid: openid
}).update({
data: {
currentCoupleId: couple._id,
bindTime: new Date(),
pendingCoupleId: null
}
})
await db.collection('users').where({
openid: inviter.openid
}).update({
data: {
currentCoupleId: couple._id,
bindTime: new Date(),
pendingCoupleId: null
}
})
return {
success: true,
coupleId: couple._id,
partnerNick: inviter.nickName,
message: '绑定成功!'
}
}
} catch (err) {
console.error('绑定伴侣失败:', err)
return { success: false, message: '系统错误:' + err.message }
}
}
云函数配置文件 config.json:
{
"permissions": {
"openapi": []
}
}
4.4.2 亲密记录云函数(含内容安全校验)
// cloudfunctions/createBattle/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
const { coupleId, duration, rating, note, mood } = event
const wxContext = cloud.getWXContext()
const openid = wxContext.OPENID
try {
// 1. 验证用户是否属于该伴侣关系
const userRes = await db.collection('users').where({
openid: openid
}).get()
if (!userRes.data || userRes.data.length === 0) {
return { success: false, message: '用户不存在' }
}
const user = userRes.data[0]
if (user.currentCoupleId !== coupleId) {
return { success: false, message: '您不属于该伴侣关系' }
}
// 2. 内容安全校验(msgSecCheck)
if (note && note.trim()) {
try {
const checkRes = await cloud.openapi.security.msgSecCheck({
content: note
})
if (checkRes.errCode && checkRes.errCode !== 0) {
return {
success: false,
message: '内容可能含有不当信息,请修改后重试',
code: 'CONTENT_RISKY'
}
}
} catch (checkErr) {
console.error('内容安全校验失败:', checkErr)
// 内容安全校验失败时,不阻止提交,但记录日志
}
}
// 3. 创建战斗记录
const today = new Date()
const todayStr = today.toISOString().split('T')[0]
const battleData = {
_id: 'battle_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9),
coupleId: coupleId,
initiator: openid,
date: todayStr,
duration: parseInt(duration) || 0,
rounds: 1,
rating: parseInt(rating) || 3,
note: note || '',
mood: mood || '平常',
status: 'completed',
createTime: new Date(),
updateTime: new Date()
}
await db.collection('battles').add({
data: battleData
})
// 4. 更新用户统计数据
const monthStr = today.toISOString().slice(0, 7) // 格式:2026-05
await db.collection('users').where({
openid: openid
}).update({
data: {
'stats.totalBattles': db.command.inc(1),
'stats.totalDuration': db.command.inc(parseInt(duration) || 0),
'stats.avgRating': db.command.aggregate.avgf('stats.avgRating'),
lastActiveTime: new Date()
}
})
// 5. 更新伴侣月统计
const coupleRes = await db.collection('couples').doc(coupleId).get()
if (coupleRes.data) {
const monthlyStats = coupleRes.data.monthlyStats || []
const monthIndex = monthlyStats.findIndex(s => s.month === monthStr)
if (monthIndex >= 0) {
monthlyStats[monthIndex].battles += 1
monthlyStats[monthIndex].completed = Math.min(
monthlyStats[monthIndex].battles,
coupleRes.data.monthlyGoal
)
} else {
monthlyStats.push({
month: monthStr,
battles: 1,
completed: 1,
completionRate: 1 / coupleRes.data.monthlyGoal
})
}
await db.collection('couples').doc(coupleId).update({
data: {
monthlyStats: monthlyStats
}
})
}
// 6. 检查成就解锁
await checkAndUnlockAchievements(openid, coupleId, battleData)
return {
success: true,
battleId: battleData._id,
message: '记录已保存'
}
} catch (err) {
console.error('创建战斗记录失败:', err)
return { success: false, message: '系统错误:' + err.message }
}
}
// 成就检测函数
async function checkAndUnlockAchievements(openid, coupleId, battle) {
const db = cloud.database()
// 获取用户当前成就
const userRes = await db.collection('users').where({ openid: openid }).get()
if (!userRes.data || userRes.data.length === 0) return
const user = userRes.data[0]
const currentAchievements = user.achievements || []
const newAchievements = []
// 检查1:清晨刺客 - 早上6点前
if (!currentAchievements.includes('清晨刺客') && battle.date) {
const hour = new Date().getHours()
if (hour < 6) {
newAchievements.push('清晨刺客')
}
}
// 检查2:持久战神 - 单次超过60分钟
if (!currentAchievements.includes('持久战神') && battle.duration >= 60) {
newAchievements.push('持久战神')
}
// 检查3:一招制敌 - 15分钟内
if (!currentAchievements.includes('一招制敌') && battle.duration <= 15) {
newAchievements.push('一招制敌')
}
// 检查4:战神之路 - 累计50次
if (!currentAchievements.includes('战神之路') && user.stats.totalBattles >= 50) {
newAchievements.push('战神之路')
}
// 更新用户成就
if (newAchievements.length > 0) {
await db.collection('users').where({ openid: openid }).update({
data: {
achievements: db.command.push(newAchievements)
}
})
// 记录成就解锁日志
for (const ach of newAchievements) {
await db.collection('achievements').add({
data: {
userId: openid,
type: ach,
name: ach,
description: getAchievementDesc(ach),
unlockedAt: new Date(),
evidence: {
battleId: battle._id,
battleDate: battle.date
}
}
})
}
}
}
function getAchievementDesc(type) {
const descMap = {
'清晨刺客': '在早上6点前完成一次战斗',
'持久战神': '单次战斗超过60分钟',
'一招制敌': '15分钟内结束战斗',
'坚持不懈': '连续7天每天至少1次',
'纪念日战士': '绑定纪念日当天战斗',
'天作之合': '双方都给出5星评分',
'战神之路': '累计完成50次战斗'
}
return descMap[type] || type
}
云函数配置文件:
{
"permissions": {
"openapi": ["security.msgSecCheck"]
}
}
4.4.3 海王标签检测逻辑
// cloudfunctions/checkWhaleTag/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
// 海王标签检测阈值
const WHALE_TAG_THRESHOLD = {
unbindCount: 3, // 解绑次数超过3次
unbindPeriodDays: 90, // 90天内的解绑次数
unbindFrequency: 2 // 30天内解绑超过2次
}
// 云函数入口函数
exports.main = async (event, context) => {
const { userId, action } = event
const wxContext = cloud.getWXContext()
const openid = userId || wxContext.OPENID
try {
// 获取用户绑定历史
const userRes = await db.collection('users').where({
openid: openid
}).get()
if (!userRes.data || userRes.data.length === 0) {
return { success: false, message: '用户不存在' }
}
const user = userRes.data[0]
const bindHistory = user.bindHistory || []
const currentTags = user.tags || []
// 检查是否已有海王标签
if (currentTags.includes('海王')) {
return {
success: true,
hasWhaleTag: true,
message: '您已被标记为海王,此标签不可消除'
}
}
// 分析绑定历史
const now = new Date()
const ninetyDaysAgo = new Date(now - 90 * 24 * 60 * 60 * 1000)
const thirtyDaysAgo = new Date(now - 30 * 24 * 60 * 60 * 1000)
// 统计90天内的解绑次数
const recentUnbinds = bindHistory.filter(h => {
if (!h.unbindTime) return false
const unbindDate = new Date(h.unbindTime)
return unbindDate >= ninetyDaysAgo
})
// 统计30天内的解绑次数
const recent30DaysUnbinds = bindHistory.filter(h => {
if (!h.unbindTime) return false
const unbindDate = new Date(h.unbindTime)
return unbindDate >= thirtyDaysAgo
})
// 计算是否应该打上海王标签
let shouldTag = false
let tagReason = ''
if (recentUnbinds.length >= WHALE_TAG_THRESHOLD.unbindCount) {
shouldTag = true
tagReason = `90天内解绑${recentUnbinds.length}次`
}
if (recent30DaysUnbinds.length >= WHALE_TAG_THRESHOLD.unbindFrequency) {
shouldTag = true
tagReason = `30天内解绑${recent30DaysUnbinds.length}次`
}
// 如果应该打标签
if (shouldTag) {
await db.collection('users').where({
openid: openid
}).update({
data: {
tags: db.command.push('海王'),
whaleTagReason: tagReason,
whaleTagTime: new Date()
}
})
return {
success: true,
hasWhaleTag: true,
tagged: true,
reason: tagReason,
message: '检测到频繁更换伴侣,已被标记为海王'
}
}
return {
success: true,
hasWhaleTag: false,
tagged: false,
recentUnbindCount: recentUnbinds.length,
message: '未检测到异常'
}
} catch (err) {
console.error('海王标签检测失败:', err)
return { success: false, message: '系统错误:' + err.message }
}
}
4.4.4 数据聚合统计云函数
// cloudfunctions/getStats/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
const { coupleId, period } = event
const wxContext = cloud.getWXContext()
const openid = wxContext.OPENID
try {
// 获取用户信息
const userRes = await db.collection('users').where({
openid: openid
}).get()
if (!userRes.data || userRes.data.length === 0) {
return { success: false, message: '用户不存在' }
}
const user = userRes.data[0]
const effectiveCoupleId = coupleId || user.currentCoupleId
if (!effectiveCoupleId) {
return { success: false, message: '未绑定伴侣' }
}
// 获取伴侣关系信息
const coupleRes = await db.collection('couples').doc(effectiveCoupleId).get()
if (!coupleRes.data) {
return { success: false, message: '伴侣关系不存在' }
}
const couple = coupleRes.data
// 确定查询时间范围
let startDate, endDate
const now = new Date()
endDate = now.toISOString().split('T')[0]
if (period === 'week') {
const weekAgo = new Date(now - 7 * 24 * 60 * 60 * 1000)
startDate = weekAgo.toISOString().split('T')[0]
} else if (period === 'month') {
const monthAgo = new Date(now.getFullYear(), now.getMonth(), 1)
startDate = monthAgo.toISOString().split('T')[0]
} else if (period === 'year') {
const yearAgo = new Date(now.getFullYear(), 0, 1)
startDate = yearAgo.toISOString().split('T')[0]
} else {
// all time
startDate = '2000-01-01'
}
// 查询战斗记录
const battlesRes = await db.collection('battles')
.where({
coupleId: effectiveCoupleId,
date: db.command.gte(startDate).and(db.command.lte(endDate))
})
.orderBy('date', 'desc')
.get()
const battles = battlesRes.data || []
// 计算统计数据
const totalBattles = battles.length
const totalDuration = battles.reduce((sum, b) => sum + (b.duration || 0), 0)
const avgDuration = totalBattles > 0 ? Math.round(totalDuration / totalBattles) : 0
// 计算评分统计
const ratings = battles.map(b => b.rating || 0).filter(r => r > 0)
const avgRating = ratings.length > 0
? (ratings.reduce((a, b) => a + b, 0) / ratings.length).toFixed(1)
: 0
// 计算本月完成率
const currentMonth = now.toISOString().slice(0, 7)
const monthStats = couple.monthlyStats?.find(s => s.month === currentMonth)
const monthlyGoal = couple.monthlyGoal || 8
const monthBattles = monthStats?.battles || 0
const completionRate = Math.min(monthBattles / monthlyGoal, 1)
// 生成日历热力图数据(最近365天)
const heatmapData = []
const oneYearAgo = new Date(now - 365 * 24 * 60 * 60 * 1000)
// 获取一年内所有战斗
const yearBattlesRes = await db.collection('battles')
.where({
coupleId: effectiveCoupleId,
date: db.command.gte(oneYearAgo.toISOString().split('T')[0])
})
.get()
const yearBattles = yearBattlesRes.data || []
const battleDates = new Set(yearBattles.map(b => b.date))
for (let d = new Date(oneYearAgo); d <= now; d.setDate(d.getDate() + 1)) {
const dateStr = d.toISOString().split('T')[0]
const dayBattles = yearBattles.filter(b => b.date === dateStr)
heatmapData.push({
date: dateStr,
count: dayBattles.length,
level: dayBattles.length === 0 ? 0 : dayBattles.length === 1 ? 1 : dayBattles.length === 2 ? 2 : 3
})
}
// 计算战斗评级(五星制)
let rating = 0
if (totalBattles >= 30 && completionRate >= 0.8) rating = 5
else if (totalBattles >= 20 && completionRate >= 0.6) rating = 4
else if (totalBattles >= 10 && completionRate >= 0.4) rating = 3
else if (totalBattles >= 5) rating = 2
else if (totalBattles >= 1) rating = 1
return {
success: true,
data: {
totalBattles,
totalDuration,
avgDuration,
avgRating: parseFloat(avgRating),
monthBattles,
monthlyGoal,
completionRate: Math.round(completionRate * 100),
rating,
heatmapData,
bindDays: Math.floor((now - new Date(couple.bindTime)) / (24 * 60 * 60 * 1000)),
achievements: user.achievements || [],
tags: user.tags || []
}
}
} catch (err) {
console.error('获取统计数据失败:', err)
return { success: false, message: '系统错误:' + err.message }
}
}
4.5 Step 4:前端页面开发要点
4.5.1 WXML结构示例(战斗记录页)
<!-- pages/battle/battle.wxml -->
<view class="container">
<!-- 月度目标进度 -->
<view class="goal-card">
<view class="goal-header">
<text class="goal-title">{{currentMonth}}月目标</text>
<text class="goal-progress">{{monthBattles}}/{{monthlyGoal}}</text>
</view>
<view class="progress-bar">
<view class="progress-fill" style="width: {{completionRate}}%"></view>
</view>
</view>
<!-- 发起战斗按钮 -->
<button class="battle-btn" bindtap="startBattle" disabled="{{!hasPartner}}">
<text class="battle-icon">⚔️</text>
<text class="battle-text">{{hasPartner ? '发起挑战' : '先绑定伴侣'}}</text>
</button>
<!-- 历史记录列表 -->
<view class="history-section">
<text class="section-title">战斗记录</text>
<view class="history-list">
<block wx:for="{{battles}}" wx:key="_id">
<view class="history-item">
<view class="history-date">{{item.date}}</view>
<view class="history-info">
<text class="history-duration">{{item.duration}}分钟</text>
<text class="history-rating">评分: {{item.rating}}星</text>
</view>
<view class="history-note">{{item.note}}</view>
</view>
</block>
</view>
</view>
</view>
4.5.2 WXSS样式示例
/* pages/battle/battle.wxss */
.container {
padding: 32rpx;
background: linear-gradient(180deg, #FFF5F5 0%, #FFFFFF 100%);
min-height: 100vh;
}
.goal-card {
background: #FFFFFF;
border-radius: 24rpx;
padding: 32rpx;
margin-bottom: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(255, 100, 100, 0.1);
}
.goal-header {
display: flex;
justify-content: space-between;
margin-bottom: 16rpx;
}
.goal-title {
font-size: 28rpx;
color: #666;
}
.goal-progress {
font-size: 32rpx;
font-weight: bold;
color: #FF6B6B;
}
.progress-bar {
height: 12rpx;
background: #F0F0F0;
border-radius: 6rpx;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #FF6B6B, #FF8E8E);
border-radius: 6rpx;
transition: width 0.3s ease;
}
.battle-btn {
width: 100%;
height: 120rpx;
background: linear-gradient(135deg, #FF6B6B, #FF8E8E);
border-radius: 60rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 48rpx;
border: none;
}
.battle-btn[disabled] {
background: #CCCCCC;
}
.battle-icon {
font-size: 48rpx;
margin-right: 16rpx;
}
.battle-text {
font-size: 36rpx;
color: #FFFFFF;
font-weight: bold;
}
.history-section {
background: #FFFFFF;
border-radius: 24rpx;
padding: 32rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 24rpx;
display: block;
}
.history-item {
padding: 24rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
.history-item:last-child {
border-bottom: none;
}
.history-date {
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.history-info {
display: flex;
justify-content: space-between;
margin-bottom: 8rpx;
}
.history-duration {
font-size: 28rpx;
color: #333;
}
.history-rating {
font-size: 24rpx;
color: #FF6B6B;
}
.history-note {
font-size: 26rpx;
color: #666;
line-height: 1.5;
}
4.5.3 JS逻辑示例
// pages/battle/battle.js
const app = getApp()
Page({
data: {
monthBattles: 0,
monthlyGoal: 8,
completionRate: 0,
hasPartner: false,
battles: [],
currentMonth: ''
},
onLoad() {
const now = new Date()
this.setData({
currentMonth: (now.getMonth() + 1) + '月'
})
this.checkPartnerStatus()
},
onShow() {
this.loadStats()
},
async checkPartnerStatus() {
const userInfo = app.globalData.userInfo
this.setData({
hasPartner: !!userInfo?.currentCoupleId
})
},
async loadStats() {
wx.showLoading({ title: '加载中...' })
try {
const res = await wx.cloud.callFunction({
name: 'getStats',
data: {
period: 'month'
}
})
if (res.result.success) {
const data = res.result.data
this.setData({
monthBattles: data.monthBattles,
monthlyGoal: data.monthlyGoal,
completionRate: data.completionRate
})
this.loadBattleHistory()
}
} catch (err) {
console.error('加载统计失败:', err)
wx.showToast({ title: '加载失败', icon: 'none' })
} finally {
wx.hideLoading()
}
},
async loadBattleHistory() {
try {
const res = await wx.cloud.callFunction({
name: 'getBattleHistory',
data: {
limit: 20
}
})
if (res.result.success) {
this.setData({
battles: res.result.data
})
}
} catch (err) {
console.error('加载历史记录失败:', err)
}
},
startBattle() {
wx.navigateTo({
url: '/pages/battle-form/battle-form'
})
}
})
4.6 Step 5:AI填充内容
用AI生成互动内容、成就描述、话术,可以大幅提升产品趣味性:
生成成就描述的prompt:
## 任务
为情侣亲密记录小程序生成7个成就的名称和描述。
## 要求
1. 成就名称要有趣味性,使用隐喻而非直白描述
2. 描述要简短有趣,激发用户解锁欲望
3. 难度从易到难,覆盖不同使用场景
4. 避免色情暗示,保持温馨暧昧风格
## 成就类型参考
- 时长类(长/短)
- 时间类(早晚/节假日)
- 频率类(连续/累计)
- 评分类(双方满意)
- 特殊日期类(纪念日)
## 输出格式
JSON数组,每个成就包含:
- type: 英文标识
- name: 中文名称
- description: 描述文字
- condition: 解锁条件
生成广场话题的prompt:
## 任务
为情侣互动广场生成20个讨论话题。
## 要求
1. 话题要引发情侣共鸣,促进互动
2. 避免敏感内容,保持积极健康
3. 覆盖不同阶段的情侣(热恋期/稳定期/老夫老妻)
4. 有的话题要有争议性,激发讨论
## 输出格式
JSON数组,每个话题包含:
- type: progress/question/discuss
- content: 话题内容
- tips: 补充说明(可选)
第五章 微信审核:两性类小程序怎么过审
5.1 5条审核红线
情侣类小程序最常见的被拒原因,是触碰了微信的审核红线。以下是5条最关键的红线:
红线一:功能涉及性行为描述
- 禁止:直接描述性行为过程、频率、细节
- 允许:游戏化包装、情感化表达、数据记录
红线二:内容含有暗示性词汇
- 禁止:"做爱"、"上床"、"上床时间"等直白词汇
- 允许:"亲密时刻"、"战斗"、"约会"、"相处时间"等含蓄表达
红线三:社区/广场内容失控
- 禁止:UGC内容未接入内容安全审核
- 要求:必须接入msgSecCheck API,所有用户生成内容需审核
红线四:隐私协议不规范
- 禁止:没有隐私协议、隐私协议不完整
- 要求:必须提供完整的隐私政策,说明数据收集和使用方式
红线五:截图/分享内容含敏感信息
- 禁止:分享卡片、战报截图包含露骨内容
- 要求:所有对外展示的内容必须是脱敏后的
5.2 措辞含蓄化:替换词对照表
| 禁止使用 | 建议替换 |
|---|---|
| 做爱/性爱/性生活 | 亲密时刻、相处时光、战斗 |
| 做一次/几次 | 对战一场、完成任务 |
| 持久/时间长 | 马拉松、耐力赛 |
| 频率/次数 | 完成率、目标达成 |
| 姿势/体位 | 模式、玩法 |
| 伴侣/男女朋友 | 战友、搭档 |
| 出轨/海王 | 频繁更换搭档 |
5.3 msgSecCheck接入:完整代码示例
已在第四章4.4.2节提供了完整的云函数代码。
关键点回顾:
- 在云函数
config.json中配置权限:
{
"permissions": {
"openapi": ["security.msgSecCheck"]
}
}
- 调用方式(云调用):
const result = await cloud.openapi.security.msgSecCheck({
content: '需要检测的文本'
})
if (result.errCode === 87014) {
return { risky: true }
}
- 重要提示:已认证的小程序可直接调用内容安全API,无需额外申请。
5.4 隐私协议要点
小程序必须提供隐私协议,且协议需要包含以下内容:
必填内容:
- 信息收集范围
- 微信授权信息(昵称、头像、性别)
- 用户主动填写的信息
- 战斗记录数据(仅伴侣双方可见)
- 信息存储方式
- 存储地点(腾讯云服务器)
- 存储期限(账户有效期内,注销后删除)
- 信息共享范围
- 不向第三方共享用户数据
- 伴侣数据仅对双方可见
- 用户权利
- 注销账户
- 导出个人数据
- 删除历史记录
协议示例结构:
隐私保护指引
1. 信息收集
我们收集您主动提供的信息,用于为您提供服务...
2. 信息使用
您的数据仅用于为您提供情侣互动记录功能...
3. 信息保护
我们采用加密技术保护您的数据安全...
4. 您的权利
您可以随时注销账户,我们将删除您的数据...
5. 联系我们
如有疑问,请联系:[邮箱]
5.5 过审Checklist(7项)
提交审核前,逐一检查以下7项:
- 所有页面文案已替换为含蓄表达
- 搜索关键词:做爱、性、啪啪、持久、频率
- 替换为:亲密、战斗、挑战、目标、进度
- 所有云函数已接入msgSecCheck
- 检查点:用户输入的内容(备注、帖子、昵称)是否都经过审核
- 隐私协议已完整提供
- 检查点:用户首次进入时是否弹窗提示
- 广场功能已关闭或内容已审核
- 建议:初期不开放广场,上线后再逐步开放
- 截图分享功能已脱敏
- 检查点:分享卡片是否包含敏感信息
- 用户数据隔离已验证
- 检查点:用小号登录,无法看到主号数据
- 所有图片资源已自检
- 检查点:无裸露、无暗示性图片
第六章 7天实操路径
Day 1:产品定义
上午:AI生成PRD
- 用第四章的PRD模板,让AI生成完整的产品需求文档
- 与AI讨论功能优先级,确定MVP范围
- 输出:完整的PRD文档
下午:线框图设计
- 用Figma/Excalidraw绘制关键页面线框图
- 确定页面跳转逻辑
- 输出:5-8个页面的线框图
预期产出: PRD文档 + 线框图
Day 2:环境搭建
上午:账号与工具准备
- 注册微信小程序账号(已有可跳过)
- 下载微信开发者工具
- 开通云开发(微信开发者工具 → 云开发 → 开通)
- 安装AI编程工具(Cursor或Trae)
下午:项目初始化
- 在微信开发者工具中创建项目,选择云开发模板
- 在AI工具中打开项目目录
- 创建数据库集合(users、couples、battles、achievements)
- 配置集合权限
预期产出: 可运行的小程序项目框架
Day 3-4:核心开发
Day 3:认证与绑定
- 页面:登录页、首页、绑定页
- 云函数:微信登录、绑定伴侣
- 测试:完整走通注册→绑定流程
Day 4:记录与统计
- 页面:战斗记录页、数据统计页
- 云函数:创建战斗记录、获取统计数据
- 测试:创建记录→查看统计完整流程
预期产出: 可用的MVP版本
Day 5:合规处理
上午:内容安全
- 为所有用户输入场景接入msgSecCheck
- 测试审核接口是否正常工作
下午:文案与协议
- 全量检查所有页面文案
- 编写隐私协议并嵌入小程序
- 制作合规的Logo和启动图
预期产出: 符合审核标准的小程序
Day 6:测试与提审
上午:功能测试
- 完整测试所有功能流程
- 修复发现的bug
- 测试数据隔离是否有效
下午:提交审核
- 填写小程序信息(名称、简介、标签)
- 上传代码包
- 提交审核
预期产出: 已提交审核
Day 7:推广准备
上午:素材制作
- 制作分享海报
- 准备抖音/小红书素材
- 撰写推广文案
下午:预告发布
- 在朋友圈/社群发布预告
- 收集种子用户反馈
预期产出: 推广素材 + 种子用户名单
第七章 推广:从0到1000用户
7.1 抖音(主力渠道)
为什么选抖音?
摸鱼博士的数据证明,抖音是情侣类小程序最有效的推广渠道。原因:
- 25-35岁用户是主力,与目标人群高度重合
- 算法推荐机制对"猎奇内容"友好
- 情侣互动话题有天然热度
3种内容类型:
类型一:猎奇展示型
- 核心钩子:展示产品最独特的机制(海王标签)
- 模板:"我用这个小程序被标记成海王了"
- 形式:屏幕录制 + 表情反应
- 时长:15-30秒
类型二:痛点共鸣型
- 核心钩子:引发情侣间的讨论
- 模板:"你们情侣之间有没有什么专属的小秘密?"
- 形式:口播 + 互动话术
- 时长:30-60秒
类型三:蹭热点型
- 核心钩子:520、七夕、情人节等节点
- 摸鱼博士520视频标题:"不是吧你们都不用上班的么?大白天啊拜托"
- 形式:热点话题 + 产品植入
- 时长:15-45秒
标题A/B测试模板:
| 类型 | 标题1 | 标题2 |
|---|---|---|
| 疑问句 | 你们情侣间有这个吗? | 男朋友给我下了战书... |
| 感叹句 | 居然还有这种小程序! | 太上头了这个APP |
| 数字句 | 7天用了30次,根本停不下来 | 记录我们第100次约会 |
7.2 小红书(辅助渠道)
图文笔记策略:
- 测评类:截图+文字描述,适合展示产品功能
- 情侣日常类:以故事形式植入产品,不生硬
- 攻略类:"情侣必做的100件事"系列
注意事项:
- 小红书禁止外链,不要放小程序码或链接
- 用"同名搜索"引导用户主动搜索
- AI生成的图片需标注"AI生成"
7.3 微信私域(冷启动)
种子用户获取:
- 朋友圈发布产品预告,收集种子用户
- 加入情侣社群/豆瓣小组,精准触达
- 提供"内测资格"激励早期参与
战报分享机制:
- 用户完成战斗后,生成精美的战绩分享卡
- 分享卡带有小程序码,但不含敏感信息
- 好友扫码后可看到"有人完成了挑战",激发好奇
7.4 关键数据节点
| 阶段 | 用户数 | 核心指标 | 重点动作 |
|---|---|---|---|
| 冷启动 | 0-50 | 种子用户验证 | 收集反馈,优化体验 |
| 早期 | 50-500 | 留存率 > 30% | 完善功能,增加成就 |
| 增长期 | 500-2000 | 传播系数 > 1 | 加大推广,激励分享 |
| 规模化 | 2000-5000 | 日活 > 20% | 商业化探索 |
7.5 摸鱼博士的实际推广策略
摸鱼博士没有预算,完全靠内容自然传播。他的关键动作:
- 520蹭热点:提前2周准备,在520当天发布视频
- 海王标签话题性:"被标记成海王"的吐槽帖引发二次传播
- 持续更新:保持每周1-2条抖音/小红书内容
第八章 变现模型
8.1 三阶段变现路径
阶段一:0收入积累(0-1000用户)
- 目标:打磨产品,积累用户
- 收入:0
- 重点:产品迭代,用户反馈
阶段二:流量主变现(1000-3000日活)
- 目标:接入广告,开始有收入
- 收入预估:Banner广告 3-5元/千次曝光,激励视频 15-30元/千次
- 开通条件:累计用户 > 1000
阶段三:会员+广告双轮驱动(3000+日活)
- 目标:建立付费会员体系
- 收入预估:会员转化5%,ARPU 10元/月,月收入 3000-15000
8.2 流量主开通条件与CPM估算
| 流量主类型 | 开通条件 | CPM估算 | 适合场景 |
|---|---|---|---|
| Banner广告 | 1000累计用户 | 3-5元 | 数据面板底部 |
| 激励视频 | 1000累计用户 | 15-30元 | 解锁高级成就 |
| 插屏广告 | 5000日活 | 8-12元 | 功能完成后 |
建议: 初期只放Banner广告,用户体验优先。
8.3 会员定价建议
定价策略:
| 等级 | 月费 | 年费 | 核心权益 |
|---|---|---|---|
| 免费版 | 0 | 0 | 基础记录、基础统计 |
| 高级版 | 19.9 | 169 | 高级成就、私密相册、年度回顾 |
权益设计原则:
- 付费功能不能影响核心体验
- 免费用户也能正常使用主要功能
- 付费功能是"锦上添花"
8.4 长期变现:情侣小程序矩阵
当用户量超过1万后,可以考虑:
- 横向扩展:推出纪念日管理、情侣游戏等小程序
- 纵向深耕:B端SaaS,为婚庆公司、情侣酒店提供服务
- 品牌合作:情侣品牌联名,定制内容
第九章 风险与应对
9.1 微信审核被拒(高概率)
风险描述: 两性类小程序审核较严格,首次提交可能被拒。
应对策略:
- 严格按照第五章的Checklist自查
- 准备2-3个替代方案(不同文案、不同功能组合)
- 被拒后仔细阅读拒绝原因,针对性修改
9.2 用户留存低(中概率)
风险描述: 用户新鲜感过后,流失率高。
应对策略:
- 游戏化设计:成就系统、等级系统、连续打卡
- 内容更新:定期推出新成就、新话题
- 纪念日提醒:在重要日期前推送提醒
9.3 竞品抄袭(中概率)
风险描述: 产品爆火后,被大厂或竞品模仿。
应对策略:
- 快速迭代:保持功能领先
- 内容深度:积累用户数据,形成壁垒
- 社区建设:建立用户情感连接
9.4 政策收紧(低概率)
风险描述: 两性内容监管政策收紧。
应对策略:
- 合规底线:不踩政策红线
- 定位调整:强调"双人私密工具"而非"社交平台"
- 多元化:适时拓展到其他赛道
结语
"战斗吧我的爱人"的成功,证明了几个事实:
第一,AI真的可以降低开发门槛。 摸鱼博士不是技术大牛,但他用AI工具7天做出了一个能跑的产品。
第二,小而美的赛道有机会。 大厂不屑于做的,恰恰是创业者的机会。
第三,传播靠的是产品设计,而不是预算。 "海王标签"这个设计没有花一分钱推广,却带来了最大的传播效应。
如果你也想做类似的项目,现在是最好的时机。AI工具越来越好用,微信云开发免费额度足够支撑早期产品,内容审核API已默认开放。
剩下的,就是你的执行力了。
本文案例来自开发者摸鱼博士(已获授权发布),数据来自微信小程序后台。
如果你想了解更多AI创业案例和实操技巧,欢迎访问 TouchAI(https://www.touchai.tech/),一人公司的灵感库,用AI放大你的能力。
想看更多产品细节和数据验证,查看落地案例:战斗吧我的爱人。