放一个PHP源码 | 星海抽卡:Deepseek写的网页抽卡模拟器
牢糯的前言
这是本人第一次策划有很多文件的项目。花了8个小时,让Deepseek给我写了个抽卡模拟器。给我忙得晕头转向的,但是真的搞出来了一个可用的系统,非常值得纪念!
我以前用纯Html做过一个,但纯编辑js还是太烦了。所以后来就没有更新内容了。体验:https://card.050601.xyz/
而今天的主角是用PHP编写的,使用效果会更好,而且有后台,可以编辑卡池和角色。体验:https://www.1103.wang/tools/gacha/index.php
以下内容也是Deepseek亲自写的文档,有一点我的人工修改。星海抽卡这个名字也是Deepseek自己起的,如果让我起那我包叫牢糯抽卡的(?)。
分享名称: Deepseek-gacha-1.0.zip
分享链接: https://file.chbnuohuang.com/#s/EEWm_zMV
提取密码: gacha

星海抽卡 · 抽卡模拟器
一个自包含的抽卡模拟系统,包含前台抽卡页面、角色图鉴、后台管理、数据备份、模拟千抽。
纯 PHP + SQLite,不需要额外的数据库服务,上传即用。
目录
功能总览
前台
- 多卡池切换,单抽 / 十连抽
- 十连过场:点击切过每张立绘,展示立绘大图 + Q 版小人 + 星级配色
- 抽卡结果卡片,星级配色分级
- 概率公示 + 池内角色弹窗
- 刷新后回显上一次抽卡结果(1 小时内)
- 角色图鉴独立页(all-characters.php):搜索、按星级筛选、按入池状态筛选、查看角色详情
后台
- 管理员登录(单账号)
- 仪表盘:角色数、卡池数、各星级角色分布、系统信息
- 角色管理:三张图字段(立绘大图 / 半身立绘 / Q 版),支持本地上传 / 素材库选择 / 外部 URL
- 卡池管理:新建卡池,关联角色,设置权重与 UP 标记
- 素材库:本地上传、URL 导入、搜索、分类筛选、引用检查,可以当成图床使用
- 数据备份:导出 zip(可选包含设置和图片)、导入 zip(合并模式)
- 站点设置:标题、副标题、页脚、背景图、favicon、自定义 HTML / CSS、抽卡概率、保底参数
- 模拟千抽:按卡池或全部角色模式跑指定次数,验证概率配置
- 深色 / 浅色主题切换
数据
- 全 SQLite,单文件数据库,无外部依赖
- 图片自动压缩转 WebP
- 文件引用检查,删除前确认无其他引用
运行环境
必须
| 项目 | 要求 |
|---|---|
| PHP | 7.4 ~ 8.5 均可,推荐 8.0 以上 |
| pdo_sqlite | 数据库驱动 |
| sqlite3 | SQLite 底层支持 |
| mbstring | UTF-8 中文处理 |
| data/ 目录 | 可写 |
| uploads/ 目录 | 可写 |
⚠️ > 如果你的 PHP 镜像没有提供 gd / zip 预编译扩展,说明该版本刚出、生态还在跟进。此时换 PHP 8.2 / 8.3 更省事——代码本身不受影响。
可选
| 扩展 | 缺了会怎样 |
|---|---|
| gd | 上传的图片不压缩,原图直接存(占用空间大) |
| zip | 数据备份页提示未安装,导入导出不可用 |
| fileinfo | favicon 上传时 MIME 检测失效(安全性略降) |
| openssl | URL 导入功能无法访问 https 图片 |
目录结构
gacha/
├── index.php 前台抽卡页
├── all-characters.php 角色图鉴
├── api.php 前台接口
├── install.php 安装向导
├── check.php 环境自检(可选)
│
├── admin/
│ ├── index.php 登录
│ ├── logout.php
│ ├── _header.php
│ ├── _footer.php
│ ├── dashboard.php 仪表盘
│ ├── characters.php 角色列表
│ ├── character_edit.php 角色编辑
│ ├── pools.php 卡池列表
│ ├── pool_edit.php 卡池编辑
│ ├── uploads.php 素材库
│ ├── library_api.php 素材库数据接口
│ ├── backup.php 数据备份
│ ├── simulate.php 模拟千抽
│ └── settings.php 站点设置
│
├── lib/
│ ├── db.php 数据库连接 + 建表
│ ├── auth.php 鉴权 + CSRF
│ ├── helpers.php 公共函数
│ ├── settings.php 设置读写
│ └── upload.php 上传 + 压缩 + URL 导入
│
├── assets/
│ ├── admin.css 后台样式
│ ├── front.css 前台样式
│ ├── front.js 前台逻辑
│ └── pool_edit.js 卡池编辑页脚本
│
├── data/ 数据库文件目录(禁止外部访问)
│ └── gacha.sqlite 自动生成
│
└── uploads/ 图片目录
├── library/ 素材库
├── full/ 立绘大图
├── half/ 半身立绘
├── chibi/ Q 版
├── icon/ favicon
└── bg/ 背景图
安装步骤
1. 上传文件
把 gacha/ 整个目录放到网站根目录下(或任意子目录)。
2. 创建必需目录
data/ 和 uploads/ 及其子目录必须提前创建,因为空目录在上传时可能被跳过:
cd /path/to/gacha
mkdir -p data
mkdir -p uploads/library uploads/full uploads/half \
uploads/chibi uploads/icon uploads/bg
chmod 755 data uploads uploads/library uploads/full \
uploads/half uploads/chibi uploads/icon uploads/bg
每个目录下建议放一个占位文件(.gitkeep 或 index.html),避免被打包工具跳过。
牢糯本人已经把这些做好了,如果没有的话自己做一下也没有多麻烦2333。
3. 配置 Nginx
把下面两条加到网站的 Nginx 配置里。把 /gacha/ 换成你实际的部署路径:
location ^~ /gacha/data/ {
deny all;
return 404;
}
location ~ ^/gacha/uploads/.*\.php$ {
deny all;
}
第一条防止数据库被下载,第二条防止有人上传伪装成图片的 PHP 文件。
4. 访问安装向导
打开浏览器访问:
https://你的域名/gacha/
如果目录权限正确,会自动跳转到安装向导(install.php)。
如果显示 500,先看常见问题里的"访问 500"。
安装向导会:
- 检查环境(PHP 版本、扩展、目录权限)
- 创建
data/gacha.sqlite - 让你设置管理员用户名和密码
5. 登录后台
安装完成后访问:
https://你的域名/gacha/admin/
用刚才设置的账号登录。
6. 首次配置
进入后台后建议顺序:
- 站点设置 → 填站点标题、副标题、页脚、背景图
- 站点设置 → 抽卡概率 → 按需调整三档概率、星级权重、保底参数
- 角色管理 → 创建角色(至少建几个低星角色,避免只抽到高星)
- 卡池管理 → 新建卡池,关联角色,设权重和 UP
- 素材库 → 上传或导入图片(可选,也可以在角色编辑页直接上传)
前台说明
主页 /index.php
- 顶部:站点标题、副标题
- 右上角浮动按钮:📖 进入角色图鉴
- 卡池切换 tab:切换不同卡池
- 横幅:显示当前卡池名称、副标题、介绍语、配色
- 保底栏:显示距离 6★ 硬保底还剩几抽
- 概率 & 池内角色按钮:打开弹窗
- 单抽 / 十连按钮
- 结果区:显示最近一次抽卡结果
十连过场
- 全屏 overlay
- 显示角色立绘大图 + 右下角 Q 版小人 + 名字 / 称号 / 星级
- 点击屏幕任意处切下一张
- 第 10 张点击后回到结果网格
角色图鉴 /all-characters.php
- 显示所有角色(不管是否入池)
- Q 版小人缩略图 + 名字
- 搜索:按名字 / 称号 / code 过滤
- 星级筛选:显示指定星级
- 状态筛选:全部 / 已入池 / 未入池 / UP 中
- 点击卡片:弹出详情(半身立绘、Q 版小图、名字、称号、星级、code、所属卡池、主题色)
后台教程
仪表盘
显示:
- 角色总数、卡池总数、已上架卡池数
- 各星级角色数量分布
- 系统信息:PHP 版本、SQLite 版本、GD 是否启用、数据库大小、上传目录可写性
角色管理
创建 / 编辑角色:
code(唯一标识,手填,只允许字母数字_-)- 名字、称号
- 稀有度:1★ ~ 9★
- 三张图片:
- 立绘大图:抽卡过场用,建议竖图或大场景横图
- 半身立绘:结果卡片、图鉴详情用
- Q 版小人:过场右下角、图鉴缩略图用
- 每张图支持三种方式:上传本地 / 从素材库选择 / 填外部 URL
- 渐变色 A / B:无图时作为兜底色
- 无图首字:没有图时显示这个字
换图不删旧文件。旧图会保留在素材库,可以给其他角色用。
清除图片:
- 如果该图还被其他角色或站点使用 → 只解除本角色关联,文件保留
- 如果没有任何其他引用 → 删除文件
卡池管理
创建 / 编辑卡池:
code(唯一标识)- 名称、副标题、介绍语
- 横幅配色 A / B
- 上架状态:控制是否在前台显示
- 排序:数字越小越靠前
关联角色:
- 展示为卡片网格,支持搜索、按星级筛选、按状态筛选
- 点击卡片选中 / 取消
- 每个关联可以设置权重(越大越容易出)和 UP 标记
删除卡池:池内关联记录一起删除,角色本身保留。
素材库
- 本地上传:拖进 / 选择图片,自动压缩转 WebP
- URL 导入:粘贴图片链接,服务器下载到本地
- 支持搜索文件名
- 支持按分类筛选(素材库 / 立绘大图 / 半身 / Q 版 / 图标 / 背景图)
- 支持按引用状态筛选(全部 / 已引用 / 未引用)
- 未被引用的文件可以删除
- 被引用的文件删除按钮为灰色不可点
数据备份
导出:
- 勾"包含站点设置" → zip 里会带上
settings - 勾"包含图片" → zip 里会打包
uploads/目录 - 文件名:
gacha-backup-YYYYMMDD-HHMMSS.zip
导入:
- 上传之前导出的 zip
- 会显示预览:新增 / 更新多少角色、多少卡池、多少图片
- 点击"确认导入"执行
- 合并模式:按
code匹配- 同 code 的角色 / 卡池 → 更新
- 新 code → 新增
- 图片 → 同名跳过,不重复复制
站点设置
分五个 tab:
站点信息
- 站点标题、副标题、页脚文字
- 默认卡池:前台打开时默认选中哪个
- 时区:影响备份文件名和时间显示
- 背景图片:上传或填 URL
- favicon:上传或填 URL
自定义代码
- 自定义
<head>内容:可插入 meta、统计脚本 - 自定义页脚 HTML:可插入回到顶部按钮、备案号
- 自定义 CSS:会以
<style>插入前台
抽卡概率
- 三档基础概率(普通 / 稀有 / 传说),总和不必等于 100,系统自动归一化
- 九级内部权重,按比例分配档内概率
- 6★ 及以上软保底:起始抽数 / 每抽累加 / 硬保底抽数
界面参数
- 十连过场每张停留时间(毫秒)
管理员账号
- 修改用户名
- 修改密码(需验证当前密码)
模拟千抽
验证概率配置是否符合预期。
- 按卡池抽:读该池的关联角色和权重
- 全部角色模式:读全部角色,等权重
- 抽取次数 100 ~ 10000
- 结果表格显示:星级、次数、实际出率、预期出率、偏差
- 各角色出现次数列表
不写数据库,不影响真实保底,不影响前台。
抽卡机制
两层概率
这些是默认设置。管理员可以自己修改。
第一层:档位
抽卡先决定落在哪一档:
| 档位 | 包含星级 | 默认概率 |
|---|---|---|
| 普通 | 1★ ~ 3★ | 78% |
| 稀有 | 4★ ~ 5★ | 20% |
| 传说 | 6★ ~ 9★ | 2% |
第二层:档内星级权重
落到某档后,按后台设置的权重在档内分配:
| 星级 | 默认权重 | 换算后概率 |
|---|---|---|
| 1★ | 30 | 23.40% |
| 2★ | 40 | 31.20% |
| 3★ | 30 | 23.40% |
| 4★ | 70 | 14.00% |
| 5★ | 30 | 6.00% |
| 6★ | 75 | 1.50% |
| 7★ | 18 | 0.36% |
| 8★ | 5.5 | 0.11% |
| 9★ | 1.5 | 0.03% |
第三层:角色权重
确定星级后,在该池该星级的角色中按 weight 加权随机。
保底
只对 6★ 及以上生效。
- 从第 N 抽开始,每抽未出 6★ 就累加概率
- 到硬保底抽数时必出 6★
默认:50 抽开始 +2% / 抽,80 抽硬保底。
星级回退
如果某个池没有配置目标星级的角色,会自动回退到距离最近的可用星级。
例如一个只关联了 5★ 和 6★ 的池子:
- 抽到 1~4★ → 回退给 5★
- 抽到 5★ → 给 5★
- 抽到 6★+ → 给对应 6★+
这样"联合寻访"式的限定池也能正常运行。
常见问题
访问 500
按顺序排查:
- PHP 版本低于 7.4 → 升级
- 缺 pdo_sqlite / mbstring → 在 PHP 里装扩展
- data/ 或 uploads/ 不存在或不可写 → 手动创建 +
chmod 755 - Nginx / PHP-FPM 挂了 → 在面板里重启
- 文件被编辑器加了 BOM 头 → 用 VS Code 或 Notepad++ 存成"UTF-8 无 BOM"
最快定位方法:在 index.php 最顶部临时加:
ini_set('display_errors', '1');
error_reporting(E_ALL);
访问一次,PHP 会把具体错误打在页面上。看完后记得删掉这两行。
访问首页没有自动跳转到 install
在 index.php 顶部确认有以下代码,且在 require settings.php 之前:
require_once __DIR__ . '/lib/db.php';
if (!gacha_is_installed()) {
require __DIR__ . '/install.php';
exit;
}
require_once __DIR__ . '/lib/settings.php';
图片不显示
- 检查
uploads/目录权限 - 检查 Nginx 是否配了拒绝访问
uploads/*.php(不影响图片) - 检查图片路径:后台复制的是完整 URL,角色编辑页填的是相对路径
- F12 → Network → 看图片请求返回的状态码
背景图上传了但前台看不到
前台 assets/front.css 里有两层遮罩:
body::before显示背景图(默认 55% 不透明)body::after是深色遮罩(不透明度.55 / .65)
如果背景图偏暗或偏亮,调整这两处的 opacity 和渐变透明度。建议背景图选偏暗的图。
备份文件名时间少 8 小时
lib/settings.php 里会自动应用 settings.timezone。如果不对:
- 检查数据库
settings表里timezone是否为Asia/Shanghai - 在
lib/settings.php的settings_all()里确认有:
if (!empty($cache['timezone'])) {
@date_default_timezone_set($cache['timezone']);
}
上传大图失败
改 Nginx 和 PHP 配置:
client_max_body_size 10m;
upload_max_filesize = 10M
post_max_size = 10M
换图后旧图还在
这是设计如此。旧图会保留在素材库,避免误删被其他角色共用的图。
如果想清理未引用的图片:
- 后台 → 素材库
- 筛选"未引用"
- 逐个删除
删除角色 / 卡池时提示"正在被引用"
- 删角色:如果角色还在某个卡池里,需要先解除关联,或勾选"强制删除"
- 删素材:如果文件还被角色或站点设置引用,需要先解绑
后台样式在浅色模式下有死黑块
某个页面的内联 <style> 里可能还有硬编码颜色。F12 → Elements → 看那个元素的 style 属性里有没有 #1...、#2... 开头的色值。把 background 换成 var(--panel) 或 var(--input-bg) 即可。
自检清单
上传到新服务器后,按以下顺序验证(其中环境可以通过访问check.php来验证):
环境
- [ ] PHP 版本 ≥ 7.4
- [ ] pdo_sqlite 已安装
- [ ] sqlite3 已安装
- [ ] mbstring 已安装
- [ ] gd 已安装(推荐)
- [ ] zip 已安装(推荐)
- [ ] data/ 目录存在且可写
- [ ] uploads/ 及其子目录存在且可写
配置
- [ ] Nginx 已加
data/拒绝访问规则 - [ ] Nginx 已加
uploads/*.php拒绝执行规则 - [ ] 访问
/gacha/自动跳转 install.php - [ ] 安装向导所有检查项 ✓
- [ ] 管理员创建成功
- [ ] 能登录后台
- [ ] 后台能登出再登入
功能
- [ ] 能创建角色
- [ ] 能上传图片
- [ ] 能创建卡池
- [ ] 能关联角色到卡池
- [ ] 前台能看到卡池
- [ ] 能单抽
- [ ] 能十连
- [ ] 十连过场正常
- [ ] 概率公示弹窗正常
- [ ] 角色图鉴正常
- [ ] 能导出备份
- [ ] 能导入备份
- [ ] 主题切换正常
- [ ] 时区显示正确
安全
- [ ] 直接访问
/gacha/data/gacha.sqlite返回 404 - [ ] 直接访问
/gacha/data/返回 404 - [ ]
uploads/目录下的.php文件无法执行
许可
可自由使用、修改、分发。
祝使用愉快。 🎲











