# toupiao
**Repository Path**: kk_coder/toupiao
## Basic Information
- **Project Name**: toupiao
- **Description**: toupiao:一个专注于投票系统的开源项目,提供简单易用的接口和灵活的配置选项,支持多种投票场景,旨在为开发者和组织者提供高效便捷的投票解决方案。
- **Primary Language**: NodeJS
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2026-05-31
- **Last Updated**: 2026-05-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Toupiao
Gitee
一款开箱即用的全栈投票系统,支持 H5 扫码投票、微信小程序投票、PC 后台管理与实时数据看板。
适用于歌唱比赛、才艺展示、优秀员工评选、摄影大赛等各类大众投票场景。
---
## ✨ 功能特性
- **多端投票入口**
- H5 页面:扫码即投,无需任何资质,基于浏览器指纹识别
- 微信小程序:支持 `wx.login` 获取 openid,防刷能力更强
- 支持平滑切换两种身份识别方案
- **实时排行榜**
- 实时票数统计与排名展示
- 大屏展示模式,适合活动现场投影
- **PC 管理后台**
- 比赛 / 选手的增删改查
- 数据看板:总票数、参与人数、UV、小时趋势图
- 风控管理:用户封禁 / 解封、异常投票审计
- 数据导出:投票记录 Excel 导出
- **防刷与风控**
- 基于 openid 或浏览器指纹的投票频次限制(每人每天每选手 1 票)
- Redis 限流:单用户每秒最多 1 次投票请求
- 投票日志记录 IP / UA / 时间戳,便于事后追溯
- 后台一键封禁异常账号
- **部署友好**
- 提供 PM2 / Docker 两种后端部署方案
- 提供完整的 Nginx / OpenResty 配置示例
- 提供 SQL 初始化脚本与一键构建脚本
---
## 🛠️ 技术架构
### 后端架构
| 层级 | 技术 / 组件 | 说明 |
|------|-------------|------|
| 运行环境 | **Node.js 18+** | 服务端 JavaScript 运行时 |
| Web 框架 | **Express 4** | 轻量级 HTTP 服务框架,RESTful API 路由管理 |
| 开发语言 | **TypeScript 5** | 静态类型检查,提升可维护性 |
| 数据库 | **MySQL 8** | 关系型数据库,存储比赛、选手、用户、投票日志等核心数据 |
| 数据库驱动 | **mysql2** | 支持 Promise 的 MySQL 驱动,原生 SQL 查询 |
| 缓存 / 限流 | **Redis 7** + **ioredis** | 投票频次计数、请求限流、排行榜缓存 |
| 身份认证 | **JWT** + **bcryptjs** | 管理员 Token 认证 + 密码哈希 |
| 文件上传 | **multer** | 选手头像等文件上传处理 |
| 工具库 | dayjs、axios、dotenv | 日期处理、微信服务端接口调用、环境变量管理 |
| 启动脚本 | ts-node-dev(开发)/ PM2(生产) | 开发热更新,生产进程守护 |
后端采用**模块化路由分层**设计:
- `routes/` 按业务域拆分为 `wx`(小程序)、`h5`(浏览器端)、`admin`(后台)、`contest`(比赛)、`player`(选手)、`vote`(投票)、`rank`(排行榜)
- `middleware/` 统一处理认证拦截(`auth.ts`)和全局异常(`error.ts`)
- 数据库初始化脚本 `scripts/init-db.js` 可一键建表
### 前端架构
| 项目 | 框架 / 库 | 说明 |
|------|-----------|------|
| H5 投票端 | **Vue 3** + **Vite** | Composition API,工程化构建 |
| | **Vant 4** | 有赞移动端组件库(Toast、Dialog、List 等) |
| | **vue-router 4** | 页面路由管理(hash 模式,兼容微信浏览器) |
| | **axios** | HTTP 客户端,统一拦截请求/响应 |
| | **@fingerprintjs/fingerprintjs** | 浏览器指纹识别,用于 H5 投票身份标识 |
| | **qrcode** | 二维码生成(分享、大屏展示) |
| PC 管理后台 | **Vue 3** + **Vite** | 与 H5 同构的技术栈,降低维护成本 |
| | **Element Plus** | 桌面端 UI 组件库(表格、表单、弹窗、分页等) |
| | **Pinia** | Vue 3 官方推荐的状态管理(管理员登录态、全局配置) |
| | **ECharts 5** | 数据可视化:投票趋势图、排行榜图表 |
| | **vue-router 4** + **axios** | 路由 + API 通信 |
| 微信小程序 | **原生小程序** | WXML + WXSS + JS,调用 `wx.login` 获取 openid,防刷能力更强 |
### 部署架构
| 组件 | 方案 | 说明 |
|------|------|------|
| 反向代理 / 静态托管 | **Nginx / OpenResty** | `/api` 转发至 Node 后端,`/admin/` 和 `/` 分别托管两个前端 SPA |
| 后端进程守护 | **PM2**(推荐)或 **Docker** | 崩溃自动重启、日志切割、开机自启 |
| 域名与 HTTPS | Let's Encrypt / 商业证书 | 微信生态强制要求 HTTPS |
| 文件存储 | 本地磁盘 + Nginx 暴露 | 选手头像上传至 `uploads/` 目录 |
### 一键部署
项目根目录提供 `deploy.sh` 脚本,支持在本地一键构建并推送至远程服务器:
```bash
# 修改 deploy.sh 内的 SSH_HOST、REMOTE_DIR 为你的服务器地址后执行:
./deploy.sh all # 构建并部署全部(admin + h5 + server)
./deploy.sh api # 仅部署后端 API
./deploy.sh admin # 仅部署管理后台
./deploy.sh h5 # 仅部署 H5 投票端
```
脚本内部自动完成:
- 本地 `npm install && npm run build`
- 通过 `rsync` 增量上传构建产物到服务器
- 远端执行 `npm install --omit=dev` 并自动 `pm2 restart` 或 `pm2 start`
> 首次部署前,请先在服务器上完成数据库初始化与 PM2 环境安装,详见 [`docs/DEPLOY.md`](./docs/DEPLOY.md)。
---
## 📸 界面预览











- H5 投票页:选手列表 → 投票 → 实时排行榜
- 管理后台:比赛管理 / 选手管理 / 数据看板 / 风控管理
- 微信小程序:与 H5 一致的投票体验
---
## 🚀 快速开始
### 环境要求
- Node.js >= 18
- MySQL >= 8.0
- Redis >= 7.0
### 1. 克隆项目
```bash
# Gitee(国内访问更快)
git clone https://gitee.com/kk_coder/toupiao.git
cd toupiao
```
### 2. 启动后端
```bash
cd server
cp .env.example .env # 根据本地环境修改数据库与 Redis 配置
npm install
npm run db:init # 初始化数据表(docs/schema.sql)
npm run dev # http://localhost:3000
```
### 3. 启动 H5 投票端
```bash
cd ../h5
npm install
npm run dev # http://localhost:5174
```
### 4. 启动 PC 管理后台
```bash
cd ../admin
npm install
npm run dev # http://localhost:5173
# 默认账号:admin / admin123(生产环境请务必修改)
```
### 5. 微信小程序(可选)
使用微信开发者工具打开 `miniprogram` 目录即可预览。如需上线,需配置合法域名并提交审核。
---
## 📁 项目结构
```
toupiao/
├── server/ # 后端 API(Node.js + Express + TypeScript)
│ ├── src/
│ │ ├── index.ts # 入口
│ │ ├── routes/ # 路由(h5 / admin / wx)
│ │ ├── middleware/ # 中间件(认证、限流、错误处理)
│ │ ├── db.ts # MySQL 连接
│ │ └── redis.ts # Redis 连接
│ └── scripts/
│ └── init-db.js # 数据库初始化脚本
├── h5/ # H5 投票前端(Vue 3 + Vant)
├── admin/ # PC 管理后台(Vue 3 + Element Plus)
├── miniprogram/ # 微信小程序(原生)
└── docs/ # 文档与 SQL 脚本
├── schema.sql # 数据库初始化脚本
├── API.md # 接口文档
└── DEPLOY.md # 生产环境部署指南
```
---
## 📖 相关文档
- [接口文档 (API.md)](./docs/API.md)
- [生产部署指南 (DEPLOY.md)](./docs/DEPLOY.md)
---
## 🔒 安全与风控说明
本项目提供了多层防刷机制,但安全与场景对抗强度直接相关:
| 方案 | 识别方式 | 防刷强度 | 适用场景 |
|------|----------|----------|----------|
| H5(浏览器指纹) | FingerprintJS + IP | 中等 | 内部活动、低对抗场景 |
| 微信小程序 | wx.login openid | 较高 | 需要微信生态的活动 |
**重要提醒**:
- H5 方案中,用户清除浏览器缓存、使用隐身模式或更换设备可绕过指纹限制,**请勿用于高对抗或高价值评选场景**。
- 生产环境务必将 `JWT_SECRET` 替换为不少于 32 位的强随机字符串。
- 上线后请立即修改默认管理员密码。
- 建议关闭数据库与 Redis 的公网端口,仅开放 80/443。
---
## 🤝 贡献指南
欢迎提交 Issue 和 Pull Request!
1. Fork 本仓库
2. 创建你的特性分支:`git checkout -b feature/my-feature`
3. 提交你的改动:`git commit -m 'feat: add some feature'`
4. 推送到分支:`git push origin feature/my-feature`
5. 提交一个 Pull Request
---
## 📄 License
本项目基于 [MIT License](LICENSE) 开源。