# approvebuddy **Repository Path**: fakerlove/approvebuddy ## Basic Information - **Project Name**: approvebuddy - **Description**: No description available - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-30 - **Last Updated**: 2026-09-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 买前问问(buy-before-ask) 好友投票帮你控制冲动消费。发起购买申请,审批通过再下单;买后打卡分享真实体验,种草避雷。 | 项 | 内容 | | --- | --- | | 小程序名称 | 买前问问 | | 项目代号 | `buy-before-ask` | | Slogan | 发起审批,让朋友帮你踩刹车。 | --- ## 目录 1. [背景与痛点](#背景与痛点) 2. [需求设计](#需求设计) 3. [数据库设计](#数据库设计) 4. [数据流向](#数据流向) 5. [仓库结构](#仓库结构) 6. [部署说明](#部署说明) 7. [快速开始](#快速开始) 8. [技术栈](#技术栈) 9. [安全与注意事项](#安全与注意事项) --- ## 背景与痛点 | 痛点 | 描述 | | --- | --- | | 冲动消费 | 用户常因一时冲动加购,买后即后悔,缺乏冷静机制 | | 社交审批低效 | 依靠聊天框或共享文档发商品链接,信息碎片化、难以统计 | | 决策模糊 | 朋友口头说「还行」难以量化,最终购买决策依然模糊 | | 缺乏数据反馈 | 不知道自己冲动消费了多少、被朋友拦下了多少 | **产品目标**:打造一款轻量、私密、有趣的消费决策工具——通过好友投票审批机制,减少非理性消费、量化社交反馈、沉淀真实买家体验,并用数据看板洞察消费习惯。 **目标用户**:18~35 岁,有网购习惯、乐于分享的年轻人。 --- ## 需求设计 ### 角色 | 角色 | 定义 | 核心行为 | | --- | --- | --- | | 申请人 | 有购买欲望、需要外部参考的用户 | 发起审批、查看结果、购买打卡 | | 审批人 | 被信任的 1~5 位好友 | 接收通知、投票审批、留言建议 | | 旁观者 | 未参与审批的其他用户 | 查看已购打卡(公开部分) | ### 核心功能 | 模块 | 说明 | | --- | --- | | 发起审批 | 填写商品名、价格、理由、图片、链接;选择 1~5 位审批人、截止时间、可见范围 | | 好友投票 | 同意 / 拒绝 + 留言;每人每单仅可投一票 | | 结果裁决 | 全部投完按票数;超时自动拒绝;平票默认拒绝 | | 购买打卡 | 通过后上传实物图 + 体验,标记种草 / 避雷 | | 已购清单 | 公开展示已打卡商品(好物广场) | | 数据看板 | 总申请数、通过率、总花费、拦截金额、好友决策榜、7 日趋势 | | 商品链接导入 | 支持京东、淘宝、抖音、小红书链接 / 分享文案自动解析 | ### 审批状态流转 ``` pending(待审批) ├── 全部投完 / 超时 → passed(已通过)或 rejected(未通过) └── passed → bought(已打卡) ``` | 状态 | 含义 | | --- | --- | | `pending` | 待审批 | | `passed` | 已通过(同意 > 拒绝) | | `rejected` | 未通过(含超时、平票) | | `bought` | 已购买并打卡 | ### 完整用户旅程 ``` 看中商品 → 填写信息 / 粘贴链接自动导入 → 选择审批人 → 发起申请(pending) → 好友投票 → 系统统计票数 ├── 通过 → 购买 → 打卡(bought)→ 进入已购清单 └── 不通过 → 可重新发起 ``` 详细 PRD 见 [`buy-before-ask/README.md`](./buy-before-ask/README.md)。 --- ## 数据库设计 业务数据存储在**微信云开发数据库**(MongoDB 风格集合),Schema 定义位于 `buy-before-ask/cloud/database/`。无传统 SQL / ORM / migrations。 ### ER 关系概览 ``` users (1) ──< approvals (N) 申请人 approvals (1) ──< votes (N) 投票明细 approvals (1) ─── checkins (1) 打卡(一对一) users (1) ──< user_invites (N) 邀请关系 ``` ### 集合一览 #### `users` — 用户表 | 字段 | 类型 | 说明 | | --- | --- | --- | | `_id` / `openId` | String | 微信 OpenID(唯一) | | `nickName` | String | 昵称 | | `avatarUrl` | String | 头像 | | `createTime` / `updateTime` | Date | 注册 / 更新时间 | 索引:`openId` 唯一。 #### `approvals` — 审批单(核心表) | 字段 | 类型 | 说明 | | --- | --- | --- | | `applicantId` | String | 申请人 OpenID | | `productName` | String | 商品名(≤30 字) | | `price` | Number | 价格(元) | | `reason` | String | 购买理由(≤200 字) | | `productDesc` | String | 商品描述 | | `productLink` | String | 商品链接 | | `images` | Array | 商品图 FileID,最多 3 张 | | `approvers` | Array | 审批人 OpenID 列表(1~5 人) | | `visibility` | Enum | `approvers` / `all` / `applicant` | | `status` | Enum | `pending` / `passed` / `rejected` / `bought` | | `expireTime` | Date | 审批截止时间 | | `checkinId` | String | 关联打卡记录 ID | 索引:`applicantId + createTime`、`status + createTime`、`approvers + status`。 #### `votes` — 投票明细 | 字段 | 类型 | 说明 | | --- | --- | --- | | `approvalId` | String | 关联审批单 | | `openId` | String | 投票人 OpenID | | `vote` | Enum | `agree` / `reject` | | `comment` | String | 留言(≤200 字) | | `voteTime` | Date | 投票时间 | 索引:`approvalId + openId` 唯一(防重复投票)。 #### `checkins` — 购买打卡 | 字段 | 类型 | 说明 | | --- | --- | --- | | `approvalId` | String | 关联审批单(一对一) | | `applicantId` | String | 打卡人 OpenID | | `images` | Array | 实物图 FileID,最多 9 张 | | `text` | String | 使用体验(≤500 字) | | `type` | Enum | `recommend`(种草)/ `avoid`(避雷) | | `buyTime` | Date | 实际购买时间 | | `visibility` | Enum | `friends` / `all` / `private` | 索引:`approvalId` 唯一。 #### `user_invites` — 邀请关系 | 字段 | 类型 | 说明 | | --- | --- | --- | | `inviterOpenId` | String | 邀请人 | | `inviteeOpenId` | String | 被邀请人 | | `createTime` | Date | 接受邀请时间 | 索引:`inviterOpenId + inviteeOpenId` 唯一。 Schema 源文件:[`buy-before-ask/cloud/database/`](./buy-before-ask/cloud/database/)。 初始化:云函数 `approvalBuddy` 的 `initDatabase` action 自动创建集合。 --- ## 数据流向 ### 系统架构 ``` ┌──────────────────────────────────────────────────────────────┐ │ 微信小程序 (miniprogram) │ │ 首页 / 发起 / 详情 / 打卡 / 看板 / 已购清单 / 个人中心 │ │ │ │ │ ▼ cloudApi.js │ │ wx.cloud.callFunction │ └──────────────────────────┼───────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ 云函数 approvalBuddy (Node.js) │ │ loginUser · createApproval · voteApproval · checkinApproval │ │ getMyApprovals · getDashboard · importProductLink · ... │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ 云数据库 云存储 Chromium │ │ users/approvals 商品图/打卡图 商品链接解析 │ │ votes/checkins │ └──────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────┐ │ Python FastAPI (backend/) — 独立部署 │ │ POST /api/parse-goods ← Playwright 解析小红书商品 │ │ │ │ │ ▼ Docker :8000 │ │ ▼ nginx → https://web.xiaowang.link/approve/api/* │ └──────────────────────────────────────────────────────────────┘ ``` > 小程序主业务走微信云开发;Python 后端为独立的小红书解析服务,供 API 测试与 nginx 对外暴露,小程序内小红书解析优先走云函数 `importProductLink`。 ### 典型业务流程 **发起审批** 1. 用户填写表单,可选调用 `importProductLink` 解析商品链接 2. 图片上传云存储,获得 FileID 3. `createApproval` 写入 `approvals`(status = `pending`) **投票** 1. 审批人打开详情 → `getApprovalDetail` 2. `voteApproval` 写入 `votes`,更新 `approvals.status` 3. 全部投完按票数裁决;超时由定时任务置为 `rejected` **打卡** 1. 状态为 `passed` → `checkinApproval` 2. 写入 `checkins`,更新 `approvals.status = bought` **定时任务** - 每日凌晨 2 点,`updateExpiredApprovals` 将超时 `pending` 审批自动拒绝 --- ## 仓库结构 ``` approve/ ├── Dockerfile # Python 后端镜像(构建上下文为仓库根目录) ├── build.sh # 本地 / CI 构建镜像 ├── start.sh # 服务器拉取镜像并启动容器 ├── backend/ # Python FastAPI:小红书商品链接解析 │ ├── main.py # API 入口 │ ├── xhs_parser.py # Playwright 解析逻辑 │ └── requirements.txt ├── buy-before-ask/ # 微信小程序 + 云开发 │ ├── miniprogram/ # 小程序前端(WXML / WXSS / JS) │ ├── cloudfunctions/ │ │ └── approvalBuddy/ # 统一业务云函数 │ ├── cloud/database/ # 数据库 Schema + 安全规则 │ ├── docs/CLOUD_SETUP.md # 云开发部署指南 │ └── README.md # 完整 PRD └── sh/ # 运维脚本(nginx HTTPS、基础镜像构建等) ``` ### 小程序页面 | 页面 | 路径 | 功能 | | --- | --- | --- | | 首页 | `pages/index/` | 审批列表、待办计数 | | 发起审批 | `pages/create/` | 填写商品、选审批人、链接导入 | | 审批详情 | `pages/detail/` | 查看详情、投票 | | 打卡 | `pages/checkin/` | 上传实物图 + 体验 | | 已购清单 | `pages/bought/` | 好物广场 | | 数据看板 | `pages/dashboard/` | 统计图表 | | 个人中心 | `pages/profile/` | 用户资料 | ### Python 后端 API | 方法 | 路径 | 说明 | | --- | --- | --- | | GET | `/api/health` | 健康检查 | | POST | `/api/parse-goods` | 解析小红书商品(body: `{ "url": "..." }`) | | GET | `/docs` | Swagger 文档 | --- ## 部署说明 项目分为**前端(微信小程序 + 云开发)**和**后端(Python 解析服务)**两套独立部署链路。 ### 前端:微信小程序 + 云开发 前端业务全部运行在微信生态内,无需自建服务器。 | 组件 | 部署方式 | | --- | --- | | 小程序页面 | 微信开发者工具 → 上传代码 → 提交审核 / 发布 | | 云函数 `approvalBuddy` | 开发者工具右键 → **上传并部署:云端安装依赖** | | 云数据库 | 云函数 `initDatabase` 初始化,或控制台手动建表 | | 云存储 | 随小程序上传图片自动使用 | | 定时触发器 | 随云函数 `config.json` 部署(每日 2 点处理超时审批) | **部署步骤** 1. 用微信开发者工具打开 `buy-before-ask/` 2. 确认 `project.config.json` 中的 AppID,配置云环境 ID(见 `miniprogram/app.js`) 3. 右键 `cloudfunctions/approvalBuddy` → 上传并部署(云端安装依赖) 4. 小程序端上传代码并发布 详细指南:[`buy-before-ask/docs/CLOUD_SETUP.md`](./buy-before-ask/docs/CLOUD_SETUP.md) ### 后端:代码上传 → 构建镜像 → 阿里云自动部署 Python 解析服务通过 Docker 容器化,推送至阿里云容器镜像服务(ACR),由阿里云侧配置**镜像推送 webhook** 自动触发服务器拉取并重启。 ``` 开发机 / CI │ │ git push 代码 ▼ 构建镜像 (build.sh) │ │ docker build → docker push ▼ 阿里云 ACR registry.cn-shanghai.aliyuncs.com/jokerak/buy-before-ask:latest │ │ 镜像推送 webhook 触发 ▼ 生产服务器 (start.sh) │ │ docker pull → docker run :8000 ▼ nginx 反向代理 https://web.xiaowang.link/approve/api/* ``` **构建镜像** ```bash # 仓库根目录 sh build.sh # 默认 buy-before-ask:latest sh build.sh registry.cn-shanghai.aliyuncs.com/jokerak/buy-before-ask:latest # 构建并本地试运行 RUN_AFTER=1 sh build.sh ``` **推送到阿里云 ACR** ```bash docker login --username=<账号> registry.cn-shanghai.aliyuncs.com docker push registry.cn-shanghai.aliyuncs.com/jokerak/buy-before-ask:latest ``` 推送完成后,阿里云 webhook 通知生产服务器执行 `start.sh`(或等价的 pull + restart 脚本),自动拉取最新镜像并重启容器。 **服务器启动** ```bash ./start.sh # 容器名: buy-before-ask # 端口映射: 8000:8000 # 健康检查: http://127.0.0.1:8000/api/health ``` **nginx 反向代理**(首次配置) ```bash # Ubuntu 服务器,以 root 执行 bash sh/setup-nginx-https.sh ``` | 对外地址 | 转发目标 | | --- | --- | | `https://web.xiaowang.link/approve/api/*` | `http://127.0.0.1:8000/api/*` | --- ## 快速开始 ### 1. 小程序 1. 微信开发者工具打开 `buy-before-ask/` 2. 按 [`CLOUD_SETUP.md`](./buy-before-ask/docs/CLOUD_SETUP.md) 配置云环境 3. 上传并部署云函数 `approvalBuddy` ### 2. Python 解析服务(本地开发) ```bash cd backend python -m venv .venv # Windows PowerShell .\.venv\Scripts\Activate.ps1 # macOS / Linux # source .venv/bin/activate pip install -r requirements.txt # Windows:国内镜像安装 Chromium $env:PLAYWRIGHT_DOWNLOAD_HOST = "https://npmmirror.com/mirrors/playwright" playwright install chromium uvicorn main:app --host 0.0.0.0 --port 8000 ``` 或使用 Docker(仓库根目录): ```bash docker build -t buy-before-ask-backend . docker run --rm -p 8000:8000 buy-before-ask-backend ``` 健康检查:`http://127.0.0.1:8000/api/health` --- ## 技术栈 | 层级 | 技术 | | --- | --- | | 小程序前端 | 微信小程序原生框架(WXML / WXSS / JS) | | 业务后端 | 微信云开发(云函数 / 云数据库 / 云存储) | | 商品解析(云) | Node.js + Puppeteer + Chromium | | 商品解析(独立) | Python 3.12、FastAPI、Playwright | | 数据库 | 微信云数据库(MongoDB 风格) | | 容器化 | Docker(Debian Bookworm + Chromium) | | 部署 | 阿里云 ACR + nginx 反向代理 | --- ## 安全与注意事项 - 不要将 AppSecret、`.env`、私钥、`.xhs_storage_state.json` 提交到仓库(已写入 `.gitignore`) - 小程序私有配置 `project.private.config.json` 仅本地使用 - 云函数 `importProductLink` 使用 Chromium,内存 1024 MB,冷启动可能较慢 - Python 后端需 Debian/glibc 基础镜像(Alpine 不支持 Playwright) --- ## 相关文档 | 文档 | 说明 | | --- | --- | | [`buy-before-ask/README.md`](./buy-before-ask/README.md) | 完整 PRD 产品需求文档 | | [`buy-before-ask/docs/CLOUD_SETUP.md`](./buy-before-ask/docs/CLOUD_SETUP.md) | 微信云开发部署指南 |