xnx_lottery 抽奖插件
功能
两套抽奖系统:帖子回复抽奖 + 首页侧边栏抽奖,可分别开关
帖子抽奖:发帖时在发布页配置奖品/中奖人数/开奖模式/允许用户组/排除作者;发起人按「奖品积分 × 中奖人数」预扣积分
回帖自动参与帖子抽奖(含用户组限制、作者排除、重复参与校验)
帖子手动开奖(发帖人或管理员),CAS 并发防护防止重复开奖;支持强制结束(不发奖)
侧边栏抽奖:每个奖品为独立抽奖,配置概率(0-100)/库存(-1 不限)/消耗积分;htmx 抽奖返回 HTML 片段
奖品类型:积分(credits)/ 自定义实物(custom)/ 勋章(medal,依赖 xnx_medal 插件)
中奖通知(notify_create)、中奖榜滚动展示(最近中奖记录,5 分钟缓存)
后台管理:基本设置、侧边栏奖品管理、帖子抽奖活动管理(按状态筛选)、中奖记录(按 uid/来源/奖品类型筛选,支持手动补发)、侧边栏抽奖记录
接入发现页(DiscoverService)配置
文件结构
plugin/xnx_lottery/
├── conf.json
├── install.php / uninstall.php / upgrade.php
├── setting.php + view/htm/setting.htm
├── model/LotteryService.php
├── route/lottery.php
├── api/lottery.php + api_register.php
├── hook/
│ ├── model_inc_file.php
│ ├── model_route_table_end.php
│ ├── index_route_case_end.php
│ ├── post_ref_thread_after.htm
│ ├── post_js.htm
│ ├── post_post_end.php
│ ├── thread_message_after.htm
│ ├── thread_create_thread_end.php
│ ├── model_thread_delete_end.php
│ ├── index_site_brief_after.htm
│ ├── footer_js_after.htm
│ ├── lang_zh_cn_bbs.php
│ ├── lang_zh_tw_bbs.php
│ └── lang_en_us_bbs.php
├── view/htm/
│ ├── setting.htm
│ ├── lottery_card.htm
│ └── lottery_sidebar.htm
├── static/js/
│ ├── lottery.js
│ └── lottery_post.js
└── lang/
├── zh-cn.php
├── zh-tw.php
└── en-us.php
配置流程
后台启用插件
进入「插件设置」→「基本设置」→ 开启帖子抽奖/侧边栏抽奖,配置允许发起的用户组、奖品积分类型与范围、中奖人数范围、中奖榜显示来源
切换到「侧边栏奖品」→ 添加奖品(类型/名称/概率/库存/消耗积分)
测试帖子抽奖:在允许用户组内发帖,发布页配置奖品并发布 → 其他用户回帖自动参与 → 发帖人或管理员在帖子详情页点「开奖」
测试侧边栏抽奖:前台首页侧边栏点抽奖按钮,htmx 返回中奖/未中奖结果
扩展说明
本插件提供事件型 hook,供其他插件监听中奖发奖事件:
hook 标记名:
xnx_lottery_grant_end.php(源码标记// hook xnx_lottery_grant_end.php)触发时机:在
LotteryService::grantPrizes()(帖子抽奖发奖)和LotteryService::grantSidebarPrize()(侧边栏抽奖发奖)中,发送中奖通知之后触发。每个中奖者触发一次可用上下文变量:
$uid:中奖者 uid$prize:奖品数据数组(含type= credits/custom/medal,及 credits_type/amount/medal_id/name 等)$tid:帖子抽奖时为帖子 id,侧边栏抽奖时为 0$activity:帖子抽奖活动记录(侧边栏场景无此变量)
监听示例:其他插件(如 xnx_feeds)在
plugin/<dir>/hook/xnx_lottery_grant_end.php创建文件即可监听,编译时拼入发奖流程LotteryService 关键公开方法:
createActivity($data):创建帖子抽奖活动drawThreadLottery($activity_id, $operator_uid):帖子开奖(CAS 并发防护)drawSidebar($uid, $prize_id):侧边栏抽奖grantPrizes($activity, $winners)/grantSidebarPrize($uid, $prize, $creditsService):发奖(触发上述 hook)regrantPrize($winner_id):手动补发奖品getRecentWinners($limit, $sources):最近中奖记录(缓存)