官方不提供现金交易,线下交易风险自担,请仔细鉴别!
体验地址(有需要资源的欢迎注册):云盘资源库 - 资源集合地
yaoys_vip — VIP 会员插件
适配 XIUNOX(Xiuno BBS 4.0.4 重构版)的 VIP 会员系统:充值/续费、成长等级、红名徽标、每日成长值、隐藏内容特权。 当前版本 1.5.1 · 作者 yaoys · 只修改本插件目录,不动系统源码与其它插件。
1. 插件简介
面向会员运营的完整 VIP 体系,包含:
购买:前台「我的VIP」页自助购买/续费,支持月付/季付/半年付/年付 4 种套餐、按份数叠加,扣费走系统
CreditsService(事务 + 行锁原子扣费)。等级:按累计成长值分 Lv1–Lv6 六级,等级决定徽标颜色与特权门槛。
展示:全站多处用户名旁渲染 VIP 徽标(等级图标优先、文字胶囊回退),可自行替换图标图片。
特权:VIP 可免除 xnx_hidden 隐藏内容解锁条件(开关控制)。
管理:后台三 Tab(套餐设置 / 会员管理 / 会员历史),可搜索、手动改到期/成长值、一键取消会员。
依赖:
购买扣费依赖系统
lib/CreditsService.php(内置)。特权「免除隐藏内容解锁」依赖 xnx_hidden 插件(未安装则该特权不生效,功能仍可用)。
其余功能无外部依赖。
2. 功能总览
2.1 前台功能
功能 | 入口 | 说明 |
|---|---|---|
我的VIP页 |
| 四 Tab:VIP状态 / 充值套餐 / 成长规则 / 开通历史 |
自助购买/续费 | 我的VIP → 充值套餐 | htmx 提交, |
余额不足引导 | 购买流程 | 前端即时弹 Bootstrap Modal 引导「去充值 / 联系管理员」(链接后台可配);服务端 htmx 响应兜底返回同名 Modal |
VIP 徽标 | 全站多处 | 楼层、帖子列表、用户主页、个人中心、主题详情楼主观/作者卡、首页侧边栏用户名旁 |
开通历史 | 我的VIP → 开通历史 | 分页展示本人开通/取消记录 |
积分记录页优化 |
| 历史 |
2.2 后台功能(插件设置 → yaoys_vip,仅 gid=1/2)
Tab | 功能 |
|---|---|
套餐设置 | 总开关、充值货币、4 套餐价格/赠送成长值、每日成长值规则、等级阈值、等级徽标颜色、余额不足引导链接、隐藏内容特权开关 |
会员管理 | 搜索(用户名/UID)、VIP 用户列表(到期/成长值/等级/状态)、手动改到期与成长值、一键取消会员 |
会员历史 | 全站 VIP 开通/取消流水(分页) |
2.3 会员特权
特权 | 后台开关 | 说明 |
|---|---|---|
会员红名徽标 + 等级图标 | 固定 | Lv1–Lv6,颜色/图标按等级 |
每日登录 +成长值 |
| 仅 VIP 生效,非 VIP 每日 -成长值 |
免除隐藏内容解锁 |
| 达标等级 VIP 直接查看 xnx_hidden 锁块内容 |
⚠️ 预留功能:后台设置页保留「特权:VIP 附件免费下载」卡片,但标注为「预留功能、无效」,红色提示。该功能曾实现后被取消,代码已整体回退,详见 第 10 节。
3. 数据表
由 install.php 创建(前缀遵循 $db->tablepre,默认 bbs_),卸载时删除。
yaoys_vip — VIP 会员主表
字段 | 类型 | 说明 |
|---|---|---|
| int unsigned PK | 用户 ID |
| int unsigned | 累计成长值 |
| int unsigned | VIP 到期时间戳(0=非 VIP) |
| tinyint | 当前等级(1–6), |
end不写核心bbs_user表,统一存本表;is_vip = end > time()。
yaoys_vip_log — 开通/取消日志
字段 | 类型 | 说明 |
|---|---|---|
| int PK 自增 | |
| int | 用户 |
| varchar(16) |
|
| varchar(16) |
|
| int | 本次获得的天数/成长值 |
| int | 到期时间戳 |
| int | 时间 |
4. 后台配置项(setting_get('yaoys_vip'))
键 | 默认 | 说明 |
|---|---|---|
| 1 | VIP 功能总开关 |
|
| 充值货币: |
| 1000/3000/6000/12000 | 套餐价格 |
| 10/50/100/300 | 套餐赠送成长值 |
| 10 | VIP 每日登录 +成长值 |
| 10 | 非 VIP 每日登录 -成长值 |
| 3000…100000 | 等级成长值阈值 |
| 1→ | 各等级徽标颜色(hex,可后台改) |
| 0 | 免除 xnx_hidden 解锁开关 |
| 1 | 所需最低等级(0=任意 VIP) |
| ‘’ | 余额不足弹窗「去充值 / 联系管理员」链接(白名单校验,防 |
套餐映射(YaoysVipService::$_yaoys_vip_plans):month=31 天、season=93、half_year=186、year=372。
5. 前台路由
注册于 hook/model_route_table_end.php + 分发于 hook/index_route_case_end.php。
路由 | 文件 | 说明 |
|---|---|---|
|
| 我的VIP页(GET 渲染 / POST 购买),含频率限制(IP+uid 60 秒 5 次) |
|
| VIP 等级图标输出( |
6. 代码结构
plugin/yaoys_vip/
├── conf.json # 插件清单:版本 1.5.1、hooks_rank、overwrites_rank
├── install.php # 建表 + 默认配置(幂等)
├── uninstall.php # 删表 + 清理设置/缓存
├── upgrade.php # 迁移:清理废弃表 + 重跑 install.php
├── setting.php # 后台三 Tab 入口(套餐设置/会员管理/会员历史)
├── icon.png # 插件图标
├── model/
│ └── YaoysVipService.php # ★ 核心服务(所有业务逻辑)
├── route/
│ ├── vip.php # 我的VIP页路由
│ └── icon.php # 等级图标输出路由
├── hook/ # 15 个 hook 点(详见下节)
├── overwrite/view/htm/ # 覆盖系统模板(仅补 hook 注释标记)
│ ├── thread_list.inc.htm # + <!--{hook thread_list_inc_username_after.htm}-->
│ └── sidebar_right.inc.htm # + <!--{hook sidebar_user_username_after.htm}-->
├── view/htm/
│ ├── my_vip.htm # 前台我的VIP页(四 Tab + 内联 JS)
│ ├── setting.htm # 后台套餐设置
│ ├── vip_admin.htm # 后台会员管理
│ └── vip_history.htm # 后台会员历史
└── img/vip/ # 等级图标 vip1.png ~ vip6.png(可选,缺则文字回退)
6.1 核心服务 model/YaoysVipService.php
方法 | 作用 |
|---|---|
| 读/写设置(合并默认值;saveSettings 白名单 + intval;引导链接协议白名单) |
| 充值货币 → |
| 读本表返回状态数组(含 |
| 是否 VIP(后者走 60s 缓存 map) |
| 活跃 VIP map( |
| 等级徽标颜色(hex 校验) |
| 等级图标 URL/HTML(进程内缓存;走 |
| VIP 徽标 HTML(图标优先,无图文字胶囊回退,盒子高度=文字高度) |
| 购买/续费:套餐校验 → 前置余额检查 → |
| 写/查开通日志 |
| 一键取消(end=0 + 日志) |
| 按成长值重算等级并写库 |
| 下一级阈值(进度条) |
| 每日成长值(VIP +,非 VIP -,下限 0) |
| 等级豁免判断( |
| 作者/管理员/版主放行(遗留,配合隐藏内容) |
| 按 |
| 内部:查询活跃 VIP / 清缓存 |
6.2 Hook 清单(conf.json hooks_rank,rank 同值按插件目录字母序)
Hook 点 | rank | 作用 |
|---|---|---|
| 10 | 全局加载 |
| 10 | 注册 |
| 10 | 分发 |
| 10 | 个人中心侧边栏加「我的VIP」入口 |
| 10 | 积分记录页: |
| 10 | 登录密码校验后捕获旧 |
| 10 | 登录后每日成长值(跨天幂等) |
| 10 | 楼层用户名后 VIP 徽标 |
| 10 | 首页帖子列表用户名后 VIP 徽标 |
| 10 | 帖子详情楼主名旁 VIP 徽标 |
| 10 | 详情右侧作者卡 VIP 徽标 |
| 10 | 首页侧边栏用户名后 VIP 徽标 |
| 10 | 用户主页卡 VIP 徽标 |
| 10 | 个人中心 VIP 徽标 |
| 0 | VIP 免除 xnx_hidden 解锁:rank 0 低于 xnx_hidden 的 rank 1,在其渲染锁块后把锁块换为内容 |
6.3 Overwrite 文件(系统模板覆盖)
两个 overwrite 各只加了一行 hook 注释标记,用于暴露系统模板中不存在的 hook 点(不改其它任何内容):
overwrite/view/htm/thread_list.inc.htm:在帖子列表用户名后加<!--{hook thread_list_inc_username_after.htm}-->overwrite/view/htm/sidebar_right.inc.htm:在首页侧边栏用户名后加<!--{hook sidebar_user_username_after.htm}-->
view/htm/不在 protected_paths 内,允许覆盖;系统升级若改这两个模板需人工同步。
7. 核心机制详解
7.1 VIP 状态判定与缓存
状态以
yaoys_vip.end > time()判定,不落bbs_user表。活跃 VIP 用
activeVipMap()一次查出uid=>level后经 CacheHelper 缓存 60s,徽标渲染、接口放行均走该 map,避免 N+1 查询。写操作(购买/取消/成长值)后
_clearCache()失效进程内缓存并CacheHelper::pluginDeletePrefix('yaoys_vip')。
7.2 等级成长体系
成长值来源:购买套餐赠送 + 每日登录(VIP)。阈值
level2..level6,Lv1=0。updateLevel()按成长值区间定级,降级也生效(非 VIP 每日扣减会导致降级)。等级用于:徽标颜色/图标、
vipLevelExempt()特权门槛。
7.3 每日成长值(跨天幂等)
user_login_post_password_check_after.php先捕获旧login_date;user_login_post_end.php判断login_date早于今天才执行dailyGrow(),避免同日多次登录重复累加。
7.4 购买/续费流程与余额不足弹窗
route/vip.phpPOST → 频率限制(IP+uid,60s/5 次)→buy()。buy():套餐/开关校验 →checkNegative()前置余额检查(不足返回code=insufficient_balance+ 余额/需扣)→CreditsService::sub()事务+行锁原子扣费。续费:有效期内
end+叠加;过期:重置到期 + 成长值累计;新用户:插入。服务端 htmx 响应在余额不足时返回 Bootstrap Modal(引导「去充值/联系管理员」,链接来自
recharge_url/contact_url)。前端 my_vip.htm 内联 JS:套餐 Tab 即时算应付/赠成长值、余额不足即时弹窗(不发请求)、
XN.confirm二次确认、htmx:afterRequest失败恢复按钮。
7.5 徽标渲染(图标优先 / 文字回退)
levelIconUrl()检测img/vip/vip{N}.{png|svg|gif|jpg|jpeg|webp}(每级进程内缓存),有图返回<img>(经vip_icon路由输出,规避 Web 服务器拦截plugin/静态目录的 404)。无图回退文字胶囊
Lv{N},样式保证整个 span 盒子高度 = 一个文字高度(padding:0 .35em+line-height:1),与用户名同大。颜色取
level_colors[level],Lv1 即普通 VIP 色。
7.6 VIP 免除隐藏内容解锁(依赖 xnx_hidden)
model_post_format_end.php(rank 0):hidden_enable开启且等级达标时,对每个未解锁的隐藏块调用HiddenService::renderHiddenContent()生成内容,再用replaceLockedBlock()平衡替换锁块。只调用 xnx_hidden 的公开方法,不改 xnx_hidden 代码。
7.7 积分记录页优化
my_credits_page_start.htm在credits.htm渲染前重写展示数据:历史vip_purchase/raw:vip_purchase→ 「开通VIP会员」;changes中的 积分/金币/RMB →$conf['credits_name']/['golds_name']/['rmbs_name']自定义名。
7.8 等级图标路由
route/icon.php:按lv找img/vip/vip{lv}.*,输出对应 MIME + 1 天缓存头;找不到http_404()。
8. 前台路由 URL 一览
场景 | URL(取决于 url_rewrite 配置) |
|---|---|
我的VIP |
|
等级图标 |
|
购买提交 |
|
9. 安装 / 升级 / 卸载
安装:后台「插件 → 上传/启用」yaoys_vip,
install.php自动建表 + 写默认配置。升级:上传新 zip 覆盖 → 后台重新启用(触发
plugin_clear_tmp_dir()清编译缓存);upgrade.php清理废弃表并重跑install.php(幂等)。卸载:
uninstall.php删yaoys_vip、yaoys_vip_log表 + 配置 + 缓存。
注意:改插件源码后
_include()只在 tmp 编译产物缺失时重编译,需删除tmp/下对应文件(或重启用插件)才会生效。
10. 预留功能(v1.5.1 取消)
「特权:VIP 附件免费下载 / 免回复下载」(原计划对接 xnx_attach_access 附件权限插件)——已取消,代码整体回退:
曾实现并评审的路径:overwrite
route/attach.php显式接管下载权限 + 前台按钮替换 + 购买接口防御,均已删除。原因:方案(无论「临时伪装管理员 gid=1」还是 overwrite 整文件副本)均不被接受,且有维护与边界风险。
现状:后台设置页保留该卡片,标注红色「预留功能 / 无效 / 无实际作用」,开关与输入
disabled,不参与表单提交、不读任何设置键。后续如需接入:在设置卡片处实现即可,当前为预留开发位。
11. 开发与部署注意事项
不改系统源码:一切扩展走 hook + 非保护路径 overwrite(
view/htm/等),禁止动model/route/xiunophp/lib/。积分名自定义:前台支付/余额显示优先用
$conf['credits_name']/['golds_name']/['rmbs_name'],勿硬编码 人民币/金币/积分。扣费安全:一律走
CreditsService(事务+行锁);saveSettings白名单 + intval;引导链接协议白名单防javascript:注入。缓存:活跃 VIP map 60s;等级图标 URL 进程内缓存;改代码后清 tmp。
打包:
plugin/yaoys_vip/→plugin/yaoys_vip.zip(zip 根目录含内层yaoys_vip/),conf.json版本号随变更递增驱动后台「需升级」徽章。