简介
本开发文档面向活动策划人员与开发者,系统性说明 DouPHP 投票系统的功能与实现。内容覆盖:
- 投票活动创建、选项设置、规则配置(时间窗口、最大票数等)
- 防刷机制与安全策略(IP 限制、单 IP 投票上限、时间状态校验)
- 结果统计、实时数据更新、图表展示建议
- 管理后台的投票管理、参与者分析、结果导出
- 小程序与移动端界面、分享与二维码、投票提醒接入思路
项目结构
投票能力由“前台控制器 + API 控制器 + 后台控制器 + 服务层”共同构成,核心业务逻辑集中在服务层,便于多端复用。
graph TB
subgraph "前端"
FVC["front/controller/vote/VoteController"]
FVS["front/service/vote/VoteService"]
end
subgraph "API"
AVC["api/controller/vote/VoteController"]
end
subgraph "后台"
AVCtrl["admin/controller/vote/VoteController"]
AVS["admin/service/vote/VoteService"]
AOS["admin/service/vote/OptionService"]
end
subgraph "核心服务"
CVS["_'/module/vote/core/service/vote/VoteService"]
end
FVC --> FVS
AVC --> FVS
AVCtrl --> AVS
AVS --> AOS
FVS --> CVS
AVC --> FVS
图示来源
- front/controller/vote/VoteController.php:72-295
- api/controller/vote/VoteController.php:47-199
- admin/controller/vote/VoteController.php:63-233
- front/service/vote/VoteService.php
- admin/service/vote/VoteService.php
- admin/service/vote/OptionService.php
- _'/module/vote/core/service/vote/VoteService.php:37-289
核心组件
- 前台投票控制器:负责页面渲染、SEO、面包屑、点击量记录、提交投票(Ajax)。
- API 投票控制器:为小程序/第三方提供统一 JSON 接口,复用前台 VoteService。
- 后台投票控制器:提供投票列表、新增/编辑/删除、候选项排行等管理能力。
- 核心投票服务:提供通用工具方法(时间状态判断、IP 投票限制、二维码生成、统计快照等)。
- 前台/后台服务:封装具体业务编排,调用核心服务完成数据组装与操作。
架构总览
投票系统采用分层架构:控制器仅做请求解析与响应封装,业务规则下沉至服务层,核心能力通过共享服务跨端复用。
sequenceDiagram
participant U as "用户/小程序"
participant F as "前台控制器"
participant A as "API 控制器"
participant S as "前台 VoteService"
participant C as "核心 VoteService"
participant DB as "数据库"
U->>F : 访问投票详情/选项页
F->>S : buildVoteShowData / buildVoteOptionsData
S->>C : checkVoteNostart/checkVoteEnded
C-->>S : 时间状态
S->>DB : 读取 vote/vote_option/vote_log
DB-->>S : 数据
S-->>F : 视图数据
F-->>U : HTML 页面
U->>A : 提交投票 poll(option_id, ip)
A->>S : submitVote(option_id, ip)
S->>C : checkIpVoted / checkOutMaxVoteNumber
C->>DB : 查询 vote_log 计数
DB-->>C : 计数
C-->>S : 是否允许投票
S->>DB : 写入 vote_log
S-->>A : count
A-->>U : {code,message,data}
图示来源
- front/controller/vote/VoteController.php:107-179
- api/controller/vote/VoteController.php:180-199
- _'/module/vote/core/service/vote/VoteService.php:101-182
详细组件分析
前台投票控制器(Web)
职责
- 列表、详情、选项页、排行、选项详情页面渲染
- 记录投票点击量
- 接收 Ajax 提交并返回统一信封
关键流程
- 详情页/选项页:加载数据 → 记录点击 → 渲染模板
- 提交投票:参数校验 → 调用服务 → 返回成功信封
API 投票控制器(小程序/第三方)
职责
- 提供投票列表、详情、选项、排行、选项详情、提交投票等 JSON 接口
- 复用前台 VoteService,保证行为一致
关键点
- 错误码统一:非法参数、未找到等
- 小程序场景下,详情页会注入二维码字段到 image,便于直接展示
后台投票控制器(管理端)
职责
- 投票 CRUD:列表、新增、编辑、删除
- 候选项票数排行(只读)
- 表单校验委托 Request,业务异常通过 DomainException 抛出
要点
- 新增时清理草稿并生成草稿令牌
- 编辑/删除前进行合法性校验
- 排行页聚合候选项票数与排序
核心投票服务(跨端复用)
能力
- 时间状态判断:未到开始时间、已结束
- IP 限制:同一 IP 对同一选项是否已投票;同一 IP 对同一活动的累计票数是否达到上限
- 二维码:按 web/mini 区分缓存路径,失败回退空串
- 统计快照:候选项数、日志数、点击量
- 辅助工具:数组列提取、换行转 <br/>
复杂度与影响
- 多数为 O(1)~O(n) 的简单聚合,适合高并发读取
- 二维码生成存在 I/O 开销,已做本地缓存
前台 VoteService(业务编排)
职责
- 组装列表、详情、选项、排行、选项详情的数据
- 记录投票点击量
- 提交投票:整合核心服务的限制检查与持久化
注意
- 对外暴露的方法被前台与 API 控制器共同调用,确保一致性
后台 VoteService 与 OptionService
职责
- 后台 VoteService:构建列表数据、默认值、新增/更新/删除、获取名称等
- OptionService:构建候选项票数排行数据
依赖关系分析
- 控制器与服务解耦:控制器不直接写库,全部通过 Service 调用
- 核心服务被前台/后台/API 复用,避免重复实现
- 外部依赖:数据库表 vote、vote_option、vote_log;二维码生成器;附件 URL 工具
classDiagram
class Front_VoteController {
+index()
+show()
+options()
+rank()
+option()
+submit()
}
class Api_VoteController {
+index()
+show()
+options()
+rank()
+option()
+poll()
}
class Admin_VoteController {
+index()
+create()
+store()
+edit()
+update()
+destroy()
+rank()
}
class Front_VoteService {
+buildVoteListData()
+buildVoteShowData()
+buildVoteOptionsData()
+buildVoteRankData()
+buildVoteOptionData()
+recordVoteView()
+submitVote()
}
class Core_VoteService {
+checkVoteNostart()
+checkVoteEnded()
+checkIpVoted()
+checkOutMaxVoteNumber()
+qrcode()
+countVote()
}
class Admin_VoteService
class Admin_OptionService
Front_VoteController --> Front_VoteService : "调用"
Api_VoteController --> Front_VoteService : "调用"
Admin_VoteController --> Admin_VoteService : "调用"
Admin_VoteController --> Admin_OptionService : "调用"
Front_VoteService --> Core_VoteService : "调用"
图示来源
- front/controller/vote/VoteController.php:72-295
- api/controller/vote/VoteController.php:47-199
- admin/controller/vote/VoteController.php:63-233
- [front/service/vote/VoteService.php]
- [admin/service/vote/VoteService.php]
- [admin/service/vote/OptionService.php]
- _'/module/vote/core/service/vote/VoteService.php:37-289
性能与扩展性
- 读取优化
- 列表/详情/选项/排行均为轻量查询,建议在热点场景引入缓存(如 Redis),键可按 vote_id/page/ip 维度设计
- 二维码已本地缓存,可考虑 CDN 加速
- 写入优化
- 提交投票涉及 vote_log 写入,在高并发时可考虑队列异步落库或批量写入
- 单 IP 上限与是否已投过票的查询应加索引(vote_log.ip、vote_log.option_id、vote_log.vote_id)
- 可扩展点
- 在核心服务中增加“用户身份校验”钩子,支持登录用户去重与更细粒度限制
- 增加“选项级上限”“时间段限流”“验证码/风控”等策略开关
故障排查指南
常见问题与定位
- 无法投票
- 检查是否未到开始时间或已结束:调用核心服务的“时间状态判断”
- 检查是否已达单 IP 上限:调用“单 IP 最大票数检查”
- 检查是否已为该选项投过票:调用“IP 已投票检查”
- 二维码不显示
- 确认图片目录是否存在且可写
- 确认二维码生成库可用,查看返回是否为空
- 排行榜为空
- 确认是否有 vote_log 记录
- 确认后台排行服务是否正确聚合 vote_option 与 vote_log
结论
该投票系统以清晰的分层与共享核心服务实现了跨端一致的业务能力,具备完善的防刷与统计基础。结合缓存、索引与可选的风控策略,可满足从中小型到中高流量的投票场景。管理端提供了完整的活动生命周期管理与数据分析入口,便于运营与策划人员高效使用。
附录:管理与使用指南
活动创建与选项设置
- 后台新建投票:填写标题、描述、关键词、封面等,保存后进入编辑页
- 添加选项:为每个选项设置名称、图片、内容、排序
- 规则配置:设置开始/结束时间、单 IP 最大票数、是否允许匿名等(通过后台表单与核心服务配合)
投票规则与防刷机制
- 时间控制:未到开始时间与已结束均不可投票
- IP 限制:同一 IP 对同一选项只能投一次;同一 IP 对同一活动累计票数不超过上限
- 二维码:按 web/mini 分别缓存,便于分享传播
结果统计与可视化
- 统计快照:候选项数量、日志总数、点击量
- 排行:后台与前台均可查看按票数排序的候选项
- 可视化建议:在前台或管理端集成柱状图/饼图,基于 option_list 与 vote_log 聚合数据绘制
管理功能
- 列表与搜索:支持关键字过滤与分页
- 编辑与删除:编辑表单、安全删除
- 参与分析:通过 vote_log 统计参与人数、地域/IP 分布(可在后台扩展)
- 结果导出:可将 vote_option 与 vote_log 导出为 CSV/Excel(建议在后端服务中新增导出接口)
小程序与移动端
- 小程序接口:通过 API 控制器提供的列表、详情、选项、排行、选项详情、提交投票等接口
- 分享与二维码:详情页返回二维码地址,小程序可直接展示;支持长按保存或跳转 H5
- 投票提醒:可通过消息中心/订阅消息在服务层触发(需结合业务通知模块)
自定义开发建议
- 新增限制策略:在核心服务中增加“用户 ID 去重”“选项级上限”“时间段限流”等开关
- 增强统计:增加“时段统计”“来源渠道统计”“设备类型统计”
- 前端扩展:在模板中接入图表库,将 option_list 与 vote_log 聚合结果可视化