Initial commit

This commit is contained in:
2026-07-23 08:58:13 +08:00
commit 6fc18cf062
411 changed files with 2549 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
# Runtime configuration and installation state
/storage/install-config.php
/storage/installed.lock
# Runtime output and local backups
/storage/*.log
/storage/*.sqlite
/storage/*.db
*.sql.gz
*.bak
# Local editor and operating-system metadata
.DS_Store
.idea/
.vscode/
+26
View File
@@ -0,0 +1,26 @@
# 欢乐水果机
PHP 8 + MySQL 会员、充值、推广、游戏结算和运营管理系统。
## 安装
1. 准备 PHP 8.1+、PDO MySQL 和 MySQL 8 / MariaDB 10.5+。
2. 将 Web 根目录指向本目录,并确保 PHP 进程可以写入 `storage/`
3. 访问 `/install.php`,填写数据库和首个管理员信息。
4. 安装成功会生成 `storage/install-config.php``storage/installed.lock`,安装入口随后自动拒绝访问。
数据库密码和管理员密码不会写入 SQL 文件。环境变量 `DB_HOST``DB_PORT``DB_DATABASE``DB_USERNAME``DB_PASSWORD``APP_URL` 可以覆盖安装配置。系统仅使用 MySQL,也不会在普通请求中执行建表或迁移。
## 安全运维
- Web 服务器必须禁止访问 `database/``storage/``maintenance/``README.md` 及 SQL、SQLite、备份类文件。
- 登录和注册已按账号哈希与来源 IP 限流;所有写操作使用 CSRF 校验或同源 API 校验。
- 管理员的登录、审核、余额调整、用户状态、系统设置、游戏设置及资金冲正会写入 `admin_audit_logs`
- 已到账充值可从后台冲正;充值本金与一级、二级佣金在同一事务中扣回。任一相关余额不足时不会执行部分冲正。
- 定期通过命令行运行 `php maintenance/backup.php /安全的备份目录`,并将备份复制到独立主机或对象存储。
## 玩法与推广
后台可配置普通赔率、24 个普通格子的相对出现权重、特殊玩法触发率和倍数、比大小胜率、目标 RTP 与统计窗口。普通开奖结果使用与个人下注无关的固定位置概率,确定位置后才按下注结算;抽中 LUCKY 会进入通吃或特殊派彩。系统会显示每格概率,并拒绝无法由当前赔率和权重实现的目标 RTP。
每个用户拥有唯一邀请链接。注册奖励按服务端 IP 防重复领取;一级下线充值佣金和二级下线充值佣金比例均由后台设置,默认分别为 10% 和 1%。
+128
View File
@@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
require __DIR__ . '/includes/bootstrap.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
redirect('/index.php');
}
$action = (string) ($_POST['action'] ?? '');
$return = (string) ($_POST['return'] ?? '/index.php');
if (!str_starts_with($return, '/') || str_starts_with($return, '//')) {
$return = '/index.php';
}
try {
verify_csrf();
switch ($action) {
case 'register':
$username = trim((string) ($_POST['username'] ?? ''));
assert_auth_not_limited('register', $username, 5, 3600);
record_auth_attempt('register', $username, false);
$password = (string) ($_POST['password'] ?? '');
$confirm = (string) ($_POST['password_confirm'] ?? '');
$phone = trim((string) ($_POST['phone'] ?? ''));
$inviteCode = trim((string) ($_POST['invite_code'] ?? ''));
if (!preg_match('/^[a-zA-Z0-9_]{6,20}$/', $username)) {
throw new RuntimeException('账号需为 6-20 位字母、数字或下划线。');
}
if (strlen($password) < 8 || strlen($password) > 72) {
throw new RuntimeException('密码需为 8-72 位。');
}
if ($password !== $confirm) {
throw new RuntimeException('两次输入的密码不一致。');
}
if ($phone !== '' && !preg_match('/^[0-9+ -]{6,20}$/', $phone)) {
throw new RuntimeException('手机号格式不正确。');
}
$created = create_user_account($username,$password,$phone,$inviteCode);
$userId = (int)$created['user_id'];
session_regenerate_id(true);
$_SESSION['user_id'] = $userId;
flash('success', '注册成功,欢迎加入。');
redirect('/index.php');
case 'login':
$username = trim((string) ($_POST['username'] ?? ''));
$password = (string) ($_POST['password'] ?? '');
assert_auth_not_limited('user_login', $username, 5, 900);
$stmt = db()->prepare('SELECT * FROM users WHERE username = ?');
$stmt->execute([$username]);
$user = $stmt->fetch();
if (!$user || !password_verify($password, $user['password_hash'])) {
record_auth_attempt('user_login', $username, false);
throw new RuntimeException('账号或密码错误。');
}
if ((int) $user['status'] !== 1) {
throw new RuntimeException('账号已停用,请联系客服。');
}
session_regenerate_id(true);
$_SESSION['user_id'] = (int) $user['id'];
record_auth_attempt('user_login', $username, true);
db()->prepare('UPDATE users SET last_login_at = ?, last_login_ip = ? WHERE id = ?')->execute([now(), client_ip(), $user['id']]);
flash('success', '登录成功。');
redirect('/index.php');
case 'logout':
unset($_SESSION['user_id']);
session_regenerate_id(true);
flash('success', '已安全退出。');
redirect('/index.php?view=login');
case 'recharge':
$user = require_user();
$amount = round((float) ($_POST['amount'] ?? 0), 2);
$method = (string) ($_POST['method'] ?? 'wechat');
$note = trim((string) ($_POST['payer_note'] ?? ''));
if ($amount < 10 || $amount > 100000) {
throw new RuntimeException('充值金额需在 10-100000 之间。');
}
if (!in_array($method, ['wechat', 'alipay', 'bank'], true)) {
throw new RuntimeException('不支持的充值方式。');
}
if ($note === '') {
throw new RuntimeException('请填写付款备注。');
}
$no = order_no();
$stmt = db()->prepare('INSERT INTO recharge_orders (order_no, user_id, amount, method, payer_note, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)');
$stmt->execute([$no, $user['id'], $amount, $method, mb_substr($note, 0, 200), 'pending', now()]);
flash('success', '充值申请已提交,订单号:' . $no);
redirect('/index.php?view=recharge');
case 'redeem_card':
$user = require_user();
$code = strtoupper(trim((string) ($_POST['card_code'] ?? '')));
redeem_recharge_card((int)$user['id'], $code);
flash('success', '充值卡兑换成功。');
redirect('/index.php?view=recharge');
case 'profile':
$user = require_user();
$phone = trim((string) ($_POST['phone'] ?? ''));
if ($phone !== '' && !preg_match('/^[0-9+ -]{6,20}$/', $phone)) {
throw new RuntimeException('手机号格式不正确。');
}
db()->prepare('UPDATE users SET phone = ?, updated_at = ? WHERE id = ?')->execute([$phone, now(), $user['id']]);
flash('success', '资料已保存。');
redirect('/index.php?view=security');
case 'password':
$user = require_user();
$old = (string) ($_POST['old_password'] ?? '');
$new = (string) ($_POST['new_password'] ?? '');
$confirm = (string) ($_POST['new_password_confirm'] ?? '');
if (!password_verify($old, $user['password_hash'])) throw new RuntimeException('原密码不正确。');
if (strlen($new) < 8 || strlen($new) > 72) throw new RuntimeException('新密码需为 8-72 位。');
if ($new !== $confirm) throw new RuntimeException('两次输入的新密码不一致。');
db()->prepare('UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?')->execute([password_hash($new, PASSWORD_DEFAULT), now(), $user['id']]);
session_regenerate_id(true);
flash('success', '密码修改成功。');
redirect('/index.php?view=security');
default:
throw new RuntimeException('无效的操作。');
}
} catch (Throwable $e) {
flash('error', $e instanceof RuntimeException ? $e->getMessage() : '系统暂时无法处理,请稍后重试。');
redirect($return);
}
+99
View File
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
require dirname(__DIR__) . '/includes/game_engine.php';
$admin = require_admin();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') redirect('/admin/index.php');
$return = (string)($_POST['return'] ?? '/admin/index.php');
if (!str_starts_with($return, '/admin/')) $return = '/admin/index.php';
try {
verify_csrf();
$action = (string)($_POST['action'] ?? '');
if ($action === 'logout') {
admin_audit(db(), 'admin_logout', 'admin', (int)$admin['id']);
unset($_SESSION['admin_id']); session_regenerate_id(true); redirect('/admin/login.php');
}
if ($action === 'review_recharge') {
$id = (int)($_POST['id'] ?? 0); $decision = (string)($_POST['decision'] ?? '');
if (!in_array($decision, ['approved','rejected'], true)) throw new RuntimeException('审核操作无效。');
$pdo = db(); $pdo->beginTransaction();
try {
$lock = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'mysql' ? ' FOR UPDATE' : '';
$stmt=$pdo->prepare('SELECT * FROM recharge_orders WHERE id=?'.$lock);$stmt->execute([$id]);$order=$stmt->fetch();
if(!$order || $order['status']!=='pending') throw new RuntimeException('订单已处理或不存在。');
if($decision==='approved'){
$stmt=$pdo->prepare('SELECT balance FROM users WHERE id=?'.$lock);$stmt->execute([$order['user_id']]);$before=(float)$stmt->fetchColumn();$after=$before+(float)$order['amount'];
$pdo->prepare('UPDATE users SET balance=?, updated_at=? WHERE id=?')->execute([$after,now(),$order['user_id']]);
create_ledger($pdo,(int)$order['user_id'],'recharge',(float)$order['amount'],$before,$after,'充值审核到账',$order['order_no']);
credit_recharge_commissions($pdo,(int)$order['user_id'],(float)$order['amount'],'order',(string)$order['order_no']);
}
$pdo->prepare('UPDATE recharge_orders SET status=?, admin_note=?, reviewed_by=?, reviewed_at=? WHERE id=?')->execute([$decision,mb_substr(trim((string)($_POST['note']??'')),0,200),$_SESSION['admin_id'],now(),$id]);
admin_audit($pdo, 'recharge_review', 'recharge_order', $id, ['status'=>'pending'], ['status'=>$decision,'amount'=>(float)$order['amount']]);
$pdo->commit();
} catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}
flash('success',$decision==='approved'?'订单已通过并到账。':'订单已拒绝。');
} elseif ($action === 'reverse_recharge') {
reverse_recharge_order(db(), (int)($_POST['id']??0), (string)($_POST['note']??''));
flash('success','充值及关联佣金已完成冲正。');
} elseif ($action === 'review_withdrawal') {
$id=(int)($_POST['id']??0);$decision=(string)($_POST['decision']??'');if(!in_array($decision,['approved','rejected'],true))throw new RuntimeException('审核操作无效。');$pdo=db();$pdo->beginTransaction();try{$lock=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'?' FOR UPDATE':'';$stmt=$pdo->prepare('SELECT * FROM withdrawal_orders WHERE id=?'.$lock);$stmt->execute([$id]);$order=$stmt->fetch();if(!$order||$order['status']!=='pending')throw new RuntimeException('订单已处理或不存在。');if($decision==='rejected'){$stmt=$pdo->prepare('SELECT balance FROM users WHERE id=?'.$lock);$stmt->execute([$order['user_id']]);$before=(float)$stmt->fetchColumn();$after=$before+(float)$order['amount'];$pdo->prepare('UPDATE users SET balance=?,updated_at=? WHERE id=?')->execute([$after,now(),$order['user_id']]);create_ledger($pdo,(int)$order['user_id'],'withdrawal_refund',(float)$order['amount'],$before,$after,'提现拒绝退回','WD'.$id);}$pdo->prepare('UPDATE withdrawal_orders SET status=? WHERE id=?')->execute([$decision,$id]);admin_audit($pdo,'withdrawal_review','withdrawal_order',$id,['status'=>'pending'],['status'=>$decision,'amount'=>(float)$order['amount']]);$pdo->commit();}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}flash('success',$decision==='approved'?'提现已通过。':'提现已拒绝并退回余额。');
} elseif ($action === 'adjust_balance') {
$userId=(int)($_POST['user_id']??0);$amount=round((float)($_POST['amount']??0),2);
if($amount===0.0 || abs($amount)>1000000) throw new RuntimeException('调整金额无效。');
$pdo=db();$pdo->beginTransaction();
try{$lock=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'?' FOR UPDATE':'';$stmt=$pdo->prepare('SELECT balance FROM users WHERE id=?'.$lock);$stmt->execute([$userId]);$value=$stmt->fetchColumn();if($value===false)throw new RuntimeException('用户不存在。');$before=(float)$value;$after=$before+$amount;if($after<0)throw new RuntimeException('调整后余额不能小于 0。');$pdo->prepare('UPDATE users SET balance=?,updated_at=? WHERE id=?')->execute([$after,now(),$userId]);create_ledger($pdo,$userId,'admin_adjust',$amount,$before,$after,'后台手动调整');admin_audit($pdo,'balance_adjust','user',$userId,['balance'=>$before],['balance'=>$after,'amount'=>$amount]);$pdo->commit();}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}
flash('success','余额已调整。');
} elseif ($action === 'toggle_user') {
$userId=(int)($_POST['user_id']??0);$status=(int)($_POST['status']??0)===1?1:0;$pdo=db();$pdo->prepare('UPDATE users SET status=?,updated_at=? WHERE id=?')->execute([$status,now(),$userId]);admin_audit($pdo,'user_status','user',$userId,null,['status'=>$status]);flash('success',$status?'账号已启用。':'账号已停用。');
} elseif ($action === 'create_cards') {
$amount = round((float)($_POST['amount'] ?? 0), 2);
$cardType = (string)($_POST['card_type'] ?? 'single');
if (!in_array($cardType, ['single', 'shared'], true)) throw new RuntimeException('充值卡类型无效。');
$count = $cardType === 'shared' ? 1 : min(100, max(1, (int)($_POST['count'] ?? 1)));
if ($amount <= 0 || $amount > 100000) throw new RuntimeException('卡面额无效。');
$pdo = db();
$codes = [];
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare('INSERT INTO recharge_cards(code,amount,card_type,status,created_at) VALUES(?,?,?,?,?)');
for ($i = 0; $i < $count; $i++) {
$code = ($cardType === 'shared' ? 'GX' : 'JG').strtoupper(bin2hex(random_bytes(6)));
$stmt->execute([$code, $amount, $cardType, $cardType === 'shared' ? 'active' : 'unused', now()]);
$codes[] = $code;
}
admin_audit($pdo, 'cards_create', 'recharge_card', '', ['amount'=>$amount, 'count'=>$count, 'card_type'=>$cardType]);
$pdo->commit();
} catch (Throwable $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
throw $e;
}
$_SESSION['generated_card_codes'] = $codes;
flash('success', $cardType === 'shared' ? '已生成公共充值卡,每个账号可兑换一次。' : "已生成 {$count} 张充值卡,并自动选中本批卡号。");
} elseif ($action === 'toggle_shared_card') {
$cardId = (int)($_POST['id'] ?? 0);
$status = (string)($_POST['status'] ?? '');
if (!in_array($status, ['active', 'disabled'], true)) throw new RuntimeException('公共卡状态无效。');
$pdo = db();
$stmt = $pdo->prepare("UPDATE recharge_cards SET status=? WHERE id=? AND card_type='shared'");
$stmt->execute([$status, $cardId]);
if ($stmt->rowCount() !== 1) throw new RuntimeException('公共充值卡不存在。');
admin_audit($pdo, 'shared_card_status', 'recharge_card', $cardId, null, ['status'=>$status]);
flash('success', $status === 'active' ? '公共充值卡已启用。' : '公共充值卡已停用。');
} elseif ($action === 'game_settings') {
$target=max(1.0,min(200.0,(float)($_POST['target_rtp']??92)));$window=max(100,min(100000,(int)($_POST['rtp_window']??1000)));$sizeRate=max(0.0,min(100.0,(float)($_POST['size_win_rate']??46)));$luckyEatRate=round(max(0.0,min(100.0,(float)($_POST['lucky_eat_rate']??2))),4);
$values=['target_rtp'=>(string)$target,'rtp_window'=>(string)$window,'size_win_rate'=>(string)$sizeRate,'lucky_eat_rate'=>(string)$luckyEatRate];
foreach(['bar','77','xx','xg','ld','nm','jz','pg'] as $key){foreach(['low','high'] as $level){$field='odds_'.$key.'_'.$level;$value=round((float)($_POST[$field]??0),4);if($value<0||$value>1000)throw new RuntimeException('普通赔率需在 0-1000 之间。');$values[$field]=(string)$value;}}
for($position=1;$position<=24;$position++){$field='normal_weight_'.$position;$value=round((float)($_POST[$field]??1),4);if($value<0.01||$value>1000)throw new RuntimeException('普通格子权重需在 0.01-1000 之间。');$values[$field]=(string)$value;}
$totalRate=0.0;$specialRtp=0.0;foreach(['xsy','dsy','dsx','tnsh','tlbb','shuaidao','huoche','dmg'] as $key){$rate=round((float)($_POST['special_'.$key.'_rate']??0),4);$odds=round((float)($_POST['special_'.$key.'_odds']??0),4);if($rate<0||$rate>100)throw new RuntimeException('特殊玩法触发率需在 0%-100% 之间。');if($odds<0||$odds>1000)throw new RuntimeException('特殊玩法倍数需在 0-1000 之间。');$values['special_'.$key.'_rate']=(string)$rate;$values['special_'.$key.'_odds']=(string)$odds;$totalRate+=$rate;$specialRtp+=$rate*$odds;}
if($totalRate+$luckyEatRate>=100)throw new RuntimeException('LUCKY 通吃率与特殊玩法总触发率之和必须小于 100%。');if($specialRtp>$target+0.0001)throw new RuntimeException('特殊玩法理论 RTP '.number_format($specialRtp,2).'% 已超过目标 RTP,请降低触发率或倍数。');
$pdo=db();$before=settings_map();game_probability_model(array_replace($before,$values));$driver=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME);$sql=$driver==='mysql'?'INSERT INTO settings(`key`,`value`) VALUES(?,?) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)':'INSERT INTO settings(`key`,`value`) VALUES(?,?) ON CONFLICT(`key`) DO UPDATE SET `value`=excluded.`value`';$pdo->beginTransaction();try{$stmt=$pdo->prepare($sql);foreach($values as $key=>$value)$stmt->execute([$key,$value]);admin_audit($pdo,'game_settings','settings','game',array_intersect_key($before,$values),$values);$pdo->commit();}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}flash('success','玩法概率、格子权重与 RTP 设置已生效。');
} elseif ($action === 'settings') {
$inviteReward=round((float)($_POST['invite_reward']??0),2);if($inviteReward<0||$inviteReward>1000000)throw new RuntimeException('单人邀请奖励需在 0-1000000 之间。');$_POST['invite_reward']=(string)$inviteReward;
foreach(['direct_commission_rate','second_commission_rate'] as $rateKey){$rate=round((float)($_POST[$rateKey]??0),4);if($rate<0||$rate>100)throw new RuntimeException('充值佣金比例需在 0%-100% 之间。');$_POST[$rateKey]=(string)$rate;}
$keys=['site_name','announcement','customer_service','recharge_instructions','register_bonus','invite_reward','direct_commission_rate','second_commission_rate','game_enabled'];$pdo=db();$before=settings_map();$driver=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME);$sql=$driver==='mysql'?'INSERT INTO settings(`key`,`value`) VALUES(?,?) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)':'INSERT INTO settings(`key`,`value`) VALUES(?,?) ON CONFLICT(`key`) DO UPDATE SET `value`=excluded.`value`';$stmt=$pdo->prepare($sql);$after=[];foreach($keys as $key){$after[$key]=mb_substr(trim((string)($_POST[$key]??'')),0,1000);$stmt->execute([$key,$after[$key]]);}admin_audit($pdo,'site_settings','settings','site',array_intersect_key($before,$after),$after);flash('success','站点设置已保存。');
} elseif ($action === 'admin_password') {
$admin=current_admin();$pdo=db();$stmt=$pdo->prepare('SELECT password_hash FROM admins WHERE id=?');$stmt->execute([$admin['id']]);$hash=(string)$stmt->fetchColumn();$old=(string)($_POST['old_password']??'');$new=(string)($_POST['new_password']??'');if(!password_verify($old,$hash))throw new RuntimeException('原密码不正确。');if(strlen($new)<12||strlen($new)>72)throw new RuntimeException('新密码需为 12-72 位。');$pdo->prepare('UPDATE admins SET password_hash=? WHERE id=?')->execute([password_hash($new,PASSWORD_DEFAULT),$admin['id']]);admin_audit($pdo,'admin_password','admin',(int)$admin['id']);flash('success','管理员密码已更新。');
} else throw new RuntimeException('无效的操作。');
} catch(Throwable $e){flash('error',$e instanceof RuntimeException?$e->getMessage():'操作失败,请稍后重试。');}
redirect($return);
+6
View File
@@ -0,0 +1,6 @@
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
$admin = require_admin();
$logs = db()->query('SELECT l.*,a.username AS admin_name FROM admin_audit_logs l JOIN admins a ON a.id=l.admin_id ORDER BY l.id DESC LIMIT 300')->fetchAll();
?><!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>操作审计 - 管理后台</title><link rel="stylesheet" href="/assets/app.css?v=20260721"><link rel="stylesheet" href="/assets/admin.css?v=20260721"></head><body><div class="admin-layout"><aside class="admin-side"><a class="admin-brand" href="/admin/index.php"><span>◆</span><?=e(setting('site_name'))?></a><nav><a href="/admin/index.php">数据概览</a><a href="/admin/index.php?view=users">用户管理</a><a href="/admin/index.php?view=recharges">充值审核</a><a href="/admin/index.php?view=withdrawals">提现审核</a><a href="/admin/index.php?view=cards">充值卡</a><a href="/admin/index.php?view=referrals">邀请记录</a><a href="/admin/index.php?view=game">玩法与RTP</a><a class="active" href="/admin/audits.php">操作审计</a><a href="/admin/index.php?view=settings">系统设置</a></nav><footer><span>当前管理员:<?=e($admin['username'])?></span><a href="/index.php" target="_blank">查看用户端 ↗</a></footer></aside><div class="admin-main"><header class="admin-top"><h1>操作审计</h1><span><?=date('Y-m-d H:i')?></span></header><main class="admin-body"><section class="panel"><div class="panel-head"><div><h2>管理员操作记录</h2><p>最近 300 条关键操作,仅记录必要变更信息,不记录密码</p></div></div><div class="table-wrap"><table><thead><tr><th>时间</th><th>管理员</th><th>操作</th><th>对象</th><th>来源 IP</th><th>变更结果</th></tr></thead><tbody><?php foreach($logs as $log):?><tr><td><?=e($log['created_at'])?></td><td><?=e($log['admin_name'])?></td><td class="mono"><?=e($log['action'])?></td><td><?=e(trim($log['target_type'].' '.$log['target_id']))?></td><td class="mono"><?=e($log['ip_address']?:'-')?></td><td class="admin-note" title="<?=e($log['after_json']??'')?>"><?=e(mb_substr((string)($log['after_json']??'-'),0,100))?></td></tr><?php endforeach;?><?php if(!$logs):?><tr><td colspan="6" class="empty-cell">暂无审计记录</td></tr><?php endif;?></tbody></table></div></section></main></div></div></body></html>
+7
View File
@@ -0,0 +1,7 @@
<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>玩法与RTP - 管理后台</title><link rel="stylesheet" href="/assets/app.css?v=20260721"><link rel="stylesheet" href="/assets/admin.css?v=20260721"><link rel="stylesheet" href="/assets/game-admin.css?v=20260722-weights"></head><body><div class="admin-layout"><aside class="admin-side"><a class="admin-brand" href="/admin/index.php"><span></span><?=e(setting('site_name'))?></a><nav><?php foreach(['dashboard'=>'数据概览','users'=>'用户管理','recharges'=>'充值审核','withdrawals'=>'提现审核','cards'=>'充值卡','referrals'=>'邀请记录','game'=>'玩法与RTP','settings'=>'系统设置'] as $key=>$name):?><a class="<?=$key==='game'?'active':''?>" href="/admin/index.php?view=<?=$key?>"><?=e($name)?></a><?php endforeach;?></nav><footer><span>当前管理员:<?=e($admin['username'])?></span><a href="/index.php" target="_blank">查看用户端 ↗</a><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="logout"><button class="mini-btn">退出登录</button></form></footer></aside><div class="admin-main"><header class="admin-top"><h1>玩法与 RTP</h1><span><?=date('Y-m-d H:i')?></span></header><main class="admin-body"><?php if($flash):?><div class="alert <?=e($flash['type'])?>"><?=e($flash['message'])?></div><?php endif;?>
<section class="rtp-metrics"><article><span>实际 RTP</span><strong><?=$gameStats['rtp']===null?'--':number_format($gameStats['rtp']*100,2).'%'?></strong><small><?=$gameStats['rounds']?> 局</small></article><article><span>目标 RTP</span><strong><?=number_format((float)($gameSettings['target_rtp']??92),2)?>%</strong><small>窗口 <?=number_format((int)($gameSettings['rtp_window']??1000))?> 局</small></article><article><span>窗口投入</span><strong>¥<?=number_format($gameStats['bets'],2)?></strong><small>派彩 ¥<?=number_format($gameStats['wins'],2)?></small></article><article><span>特殊理论 RTP</span><strong><?=number_format(game_theoretical_special_rtp($gameSettings),2)?>%</strong><small>触发率 <?=number_format(array_sum(array_column($specialDefinitions,'rate')),2)?>%</small></article></section>
<form method="post" action="/admin/action.php" class="game-config"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="game_settings"><input type="hidden" name="return" value="/admin/index.php?view=game">
<section class="panel"><div class="panel-head"><div><h2>RTP 控制</h2><p>普通开奖根据窗口实际 RTP 动态校准</p></div></div><div class="config-row"><label><span>目标 RTP (%)</span><input type="number" name="target_rtp" min="1" max="200" step="0.01" value="<?=e($gameSettings['target_rtp']??92)?>" required></label><label><span>统计窗口 (局)</span><input type="number" name="rtp_window" min="100" max="100000" step="1" value="<?=e($gameSettings['rtp_window']??1000)?>" required></label><label><span>LUCKY 通吃率 (%)</span><input type="number" name="lucky_eat_rate" min="0" max="100" step="0.0001" value="<?=e($gameSettings['lucky_eat_rate']??2)?>" required></label><label><span>比大小胜率 (%)</span><input type="number" name="size_win_rate" min="0" max="100" step="0.01" value="<?=e($gameSettings['size_win_rate']??46)?>" required></label></div></section>
<section class="panel"><div class="panel-head"><div><h2>普通图案赔率</h2><p>大图案与小图案格</p></div></div><div class="table-wrap"><table class="odds-table"><thead><tr><th>图案</th><th>小图案倍数</th><th>大图案倍数</th></tr></thead><tbody><?php foreach(['bar'=>'BAR','77'=>'77','xx'=>'双星','xg'=>'西瓜','ld'=>'铃铛','nm'=>'柠檬','jz'=>'橘子','pg'=>'苹果'] as $key=>$label):?><tr><td><b><?=$label?></b></td><td><input type="number" name="odds_<?=$key?>_low" min="0" max="1000" step="0.01" value="<?=e($gameSettings['odds_'.$key.'_low']??0)?>" required></td><td><input type="number" name="odds_<?=$key?>_high" min="0" max="1000" step="0.01" value="<?=e($gameSettings['odds_'.$key.'_high']??0)?>" required></td></tr><?php endforeach;?></tbody></table></div></section>
<section class="panel"><div class="panel-head"><div><h2>普通格子出现权重</h2><p>开奖结果与本局押注无关;抽中 LUCKY 时进入通吃或特殊派彩</p></div><span class="probability-summary">当前校准 RTP <?=number_format($gameProbabilityModel['target_rtp']*100,2)?>% · LUCKY通吃 <?=number_format($gameProbabilityModel['lucky_probability']*100,2)?>% · LUCKY派彩 <?=number_format($gameProbabilityModel['special_rate']*100,2)?>%</span></div><div class="table-wrap"><table class="odds-table position-table"><thead><tr><th>位置</th><th>图案</th><th>赔率</th><th>相对权重</th><th>当前单局概率</th><th>平均出现</th></tr></thead><tbody><?php foreach($gameBoard as $position=>$cell): $probability=(float)$gameProbabilityModel['positions'][$position]['probability']; ?><tr><td class="mono">#<?=$position?></td><td><b><?=e($cell['name'])?></b></td><td><?=$cell['multiplier']>0?number_format((float)$cell['multiplier'],2).'x':'-'?></td><td><input type="number" name="normal_weight_<?=$position?>" min="0.01" max="1000" step="0.01" value="<?=e($gameSettings['normal_weight_'.$position]??'1')?>" required></td><td><?=number_format($probability*100,4)?>%</td><td><?=$probability>0?'约 '.number_format(1/$probability,1).' 局':'-'?></td></tr><?php endforeach;?></tbody></table></div></section>
<section class="panel"><div class="panel-head"><div><h2>特殊玩法</h2><p>触发率为每局独立概率,倍数按本局总投入计算</p></div></div><div class="table-wrap"><table class="odds-table"><thead><tr><th>玩法</th><th>触发率 (%)</th><th>奖励倍数</th><th>理论 RTP 贡献</th></tr></thead><tbody><?php foreach($specialDefinitions as $special):?><tr><td><b><?=e($special['name'])?></b></td><td><input type="number" name="special_<?=e($special['key'])?>_rate" min="0" max="100" step="0.0001" value="<?=e($special['rate'])?>" required></td><td><input type="number" name="special_<?=e($special['key'])?>_odds" min="0" max="1000" step="0.01" value="<?=e($special['odds'])?>" required></td><td><?=number_format($special['rate']*$special['odds'],2)?>%</td></tr><?php endforeach;?></tbody></table></div><div class="config-submit"><button class="btn primary" type="submit">保存并立即生效</button></div></section></form></main></div></div><script src="/assets/app.js?v=20260722-cards2"></script></body></html>
+56
View File
@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
require dirname(__DIR__) . '/includes/game_engine.php';
$admin=require_admin();$view=(string)($_GET['view']??'dashboard');$allowed=['dashboard','users','recharges','withdrawals','cards','referrals','game','settings'];if(!in_array($view,$allowed,true))$view='dashboard';$flash=take_flash();$pdo=db();
$stats=['users'=>(int)$pdo->query('SELECT COUNT(*) FROM users')->fetchColumn(),'pending'=>(int)$pdo->query("SELECT COUNT(*) FROM recharge_orders WHERE status='pending'")->fetchColumn(),'balance'=>(float)$pdo->query('SELECT COALESCE(SUM(balance),0) FROM users')->fetchColumn(),'today'=>(float)$pdo->query("SELECT COALESCE(SUM(amount),0) FROM recharge_orders WHERE status='approved' AND reviewed_at >= '".date('Y-m-d 00:00:00')."'")->fetchColumn()];
$users=$orders=$cards=$withdrawals=$referrals=[];
$generatedCardCodes = [];
if ($view === 'cards' && isset($_SESSION['generated_card_codes']) && is_array($_SESSION['generated_card_codes'])) {
$generatedCardCodes = array_values(array_filter($_SESSION['generated_card_codes'], 'is_string'));
unset($_SESSION['generated_card_codes']);
}
if($view==='users'){$q=trim((string)($_GET['q']??''));if($q!==''){$stmt=$pdo->prepare('SELECT * FROM users WHERE username LIKE ? OR id = ? ORDER BY id DESC LIMIT 100');$stmt->execute(['%'.$q.'%',(int)$q]);$users=$stmt->fetchAll();}else $users=$pdo->query('SELECT * FROM users ORDER BY id DESC LIMIT 100')->fetchAll();}
if(in_array($view,['dashboard','recharges'],true)){$orders=$pdo->query('SELECT r.*,u.username FROM recharge_orders r JOIN users u ON u.id=r.user_id ORDER BY r.id DESC LIMIT 100')->fetchAll();}
if($view==='cards')$cards=$pdo->query('SELECT c.*,u.username,(SELECT COUNT(*) FROM recharge_card_redemptions r WHERE r.card_id=c.id) AS redemption_count FROM recharge_cards c LEFT JOIN users u ON u.id=c.used_by ORDER BY c.id DESC LIMIT 100')->fetchAll();
if($view==='withdrawals')$withdrawals=$pdo->query('SELECT w.*,u.username FROM withdrawal_orders w JOIN users u ON u.id=w.user_id ORDER BY w.id DESC LIMIT 100')->fetchAll();
if($view==='referrals')$referrals=$pdo->query('SELECT r.*,i.username AS inviter_name,e.username AS invitee_name FROM referral_rewards r JOIN users i ON i.id=r.inviter_id JOIN users e ON e.id=r.invitee_id ORDER BY r.id DESC LIMIT 100')->fetchAll();
$referralStats=['rewarded'=>(int)$pdo->query("SELECT COUNT(*) FROM referral_rewards WHERE status='rewarded'")->fetchColumn(),'rejected'=>(int)$pdo->query("SELECT COUNT(*) FROM referral_rewards WHERE status='rejected'")->fetchColumn(),'amount'=>(float)$pdo->query("SELECT COALESCE(SUM(reward_amount),0) FROM referral_rewards WHERE status='rewarded'")->fetchColumn()];
$titles=['dashboard'=>'数据概览','users'=>'用户管理','recharges'=>'充值审核','withdrawals'=>'提现审核','cards'=>'充值卡','referrals'=>'邀请记录','game'=>'玩法与RTP','settings'=>'系统设置'];$statusNames=['pending'=>'待审核','approved'=>'已到账','rejected'=>'已拒绝','reversed'=>'已冲正','rewarded'=>'已奖励','qualified'=>'关系有效'];
$gameSettings=settings_map();$gameStats=game_window_stats($pdo,(int)($gameSettings['rtp_window']??1000));$specialDefinitions=game_special_definitions($gameSettings);$gameBoard=game_board($gameSettings);$gameProbabilityModel=game_effective_probability_model($gameSettings,$gameStats);
if($view==='game'){require __DIR__.'/game.php';exit;}
?><!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title><?=e($titles[$view])?> - 管理后台</title><link rel="stylesheet" href="/assets/app.css?v=20260721"><link rel="stylesheet" href="/assets/admin.css?v=20260721"></head><body><div class="admin-layout"><aside class="admin-side"><a class="admin-brand" href="/admin/index.php"><span>◆</span><?=e(setting('site_name'))?></a><nav><?php foreach(['dashboard'=>'数据概览','users'=>'用户管理','recharges'=>'充值审核','withdrawals'=>'提现审核','cards'=>'充值卡','referrals'=>'邀请记录','game'=>'玩法与RTP','settings'=>'系统设置'] as $k=>$name):?><a class="<?=$view===$k?'active':''?>" href="/admin/index.php?view=<?=$k?>"><?=e($name)?></a><?php endforeach;?></nav><footer><span>当前管理员:<?=e($admin['username'])?></span><a href="/index.php" target="_blank">查看用户端 ↗</a><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="logout"><button class="mini-btn">退出登录</button></form></footer></aside><div class="admin-main"><header class="admin-top"><h1><?=e($titles[$view])?></h1><span><?=date('Y-m-d H:i')?></span></header><main class="admin-body"><?php if($flash):?><div class="alert <?=e($flash['type'])?>"><?=e($flash['message'])?></div><?php endif;?>
<?php if($view==='dashboard'):?><section class="admin-stats"><article><span>注册用户</span><strong><?=$stats['users']?></strong></article><article><span>待审核充值</span><strong><?=$stats['pending']?></strong></article><article><span>用户余额合计</span><strong>¥<?=number_format($stats['balance'],2)?></strong></article><article><span>今日到账</span><strong>¥<?=number_format($stats['today'],2)?></strong></article></section><section class="panel"><div class="panel-head"><div><h2>最新充值订单</h2><p>优先处理待审核订单</p></div><a href="?view=recharges">全部订单</a></div><?=render_orders($orders,$statusNames)?></section>
<?php elseif($view==='users'):?><section class="panel"><div class="panel-head"><div><h2>用户列表</h2><p>最近 100 个账号</p></div><form class="searchbar"><input type="hidden" name="view" value="users"><input name="q" value="<?=e($_GET['q']??'')?>" placeholder="搜索账号或 ID"><button class="mini-btn">搜索</button></form></div><div class="table-wrap"><table><thead><tr><th>ID</th><th>账号</th><th>手机</th><th>余额</th><th>注册时间</th><th>状态</th><th>余额调整</th><th>操作</th></tr></thead><tbody><?php foreach($users as $u):?><tr><td><?=(int)$u['id']?></td><td><b><?=e($u['username'])?></b></td><td><?=e($u['phone']?:'-')?></td><td>¥<?=number_format((float)$u['balance'],2)?></td><td><?=e($u['created_at'])?></td><td><span class="badge <?= (int)$u['status']===1?'approved':'rejected' ?>"><?= (int)$u['status']===1?'正常':'停用' ?></span></td><td><form class="inline-form" method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="adjust_balance"><input type="hidden" name="return" value="/admin/index.php?view=users"><input type="hidden" name="user_id" value="<?=(int)$u['id']?>"><input type="number" step="0.01" name="amount" placeholder="+/- 金额" required><button class="mini-btn">确定</button></form></td><td><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="toggle_user"><input type="hidden" name="return" value="/admin/index.php?view=users"><input type="hidden" name="user_id" value="<?=(int)$u['id']?>"><input type="hidden" name="status" value="<?= (int)$u['status']===1?0:1 ?>"><button class="mini-btn <?= (int)$u['status']===1?'reject':'approve' ?>"><?= (int)$u['status']===1?'停用':'启用' ?></button></form></td></tr><?php endforeach;?></tbody></table></div></section>
<?php elseif($view==='recharges'):?><section class="panel"><div class="panel-head"><div><h2>充值订单</h2><p>审核通过后系统自动增加用户余额</p></div></div><?=render_orders($orders,$statusNames)?></section>
<?php elseif($view==='withdrawals'):?><section class="panel"><div class="panel-head"><div><h2>提现订单</h2><p>用户提交时已冻结余额,拒绝后自动退回</p></div></div><div class="table-wrap"><table><thead><tr><th>ID</th><th>用户</th><th>金额</th><th>收款账号</th><th>姓名</th><th>时间</th><th>状态</th><th>操作</th></tr></thead><tbody><?php foreach($withdrawals as $w):?><tr><td>#<?=(int)$w['id']?></td><td><?=e($w['username'])?></td><td><b>¥<?=number_format((float)$w['amount'],2)?></b></td><td><?=e($w['account'])?></td><td><?=e($w['real_name'])?></td><td><?=e($w['created_at'])?></td><td><span class="badge <?=e($w['status'])?>"><?=e($statusNames[$w['status']]??$w['status'])?></span></td><td><?php if($w['status']==='pending'):?><div class="admin-actions"><?php foreach(['approved'=>'通过','rejected'=>'拒绝'] as $decision=>$label):?><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="review_withdrawal"><input type="hidden" name="return" value="/admin/index.php?view=withdrawals"><input type="hidden" name="id" value="<?=(int)$w['id']?>"><input type="hidden" name="decision" value="<?=$decision?>"><button class="mini-btn <?=$decision==='approved'?'approve':'reject'?>"><?=$label?></button></form><?php endforeach;?></div><?php else:?>-<?php endif;?></td></tr><?php endforeach;?><?php if(!$withdrawals):?><tr><td colspan="8" class="empty-cell">暂无提现订单</td></tr><?php endif;?></tbody></table></div></section>
<?php elseif($view==='cards'): ?>
<div class="settings-grid">
<section class="panel"><h2>生成充值卡</h2><form method="post" action="/admin/action.php" class="form-stack" data-card-create-form><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="create_cards"><input type="hidden" name="return" value="/admin/index.php?view=cards"><label><span>卡类型</span><select name="card_type" data-card-type><option value="single">普通一次性卡</option><option value="shared">公共卡(每账号一次)</option></select></label><label><span>卡面额</span><input type="number" name="amount" min="1" max="100000" step="0.01" required></label><label><span>生成数量</span><input type="number" name="count" min="1" max="100" value="10" required data-card-count></label><button class="btn primary">生成充值卡</button></form></section>
<section class="panel"><h2>使用说明</h2><p class="card-note">普通卡仅能被一个用户使用一次。公共卡可由所有用户各兑换一次,并可随时停用。请通过安全渠道发放卡号。</p></section>
</div>
<section class="panel card-manager" data-card-manager>
<div class="panel-head"><div><h2>充值卡列表</h2><p>最近 100 张,可复制或导出当前可用卡</p></div><div class="card-batch-actions"><button type="button" class="mini-btn" data-card-select-all>全选可用卡</button><button type="button" class="mini-btn approve" data-card-copy disabled>复制所选</button><button type="button" class="mini-btn" data-card-export disabled>导出 CSV</button><span data-card-selected-count>已选 0 张</span></div></div>
<div class="table-wrap"><table><thead><tr><th class="card-check"><input type="checkbox" data-card-toggle-all aria-label="全选可用充值卡" title="全选可用充值卡"></th><th>卡号</th><th>类型</th><th>面额</th><th>状态</th><th>使用情况</th><th>生成时间</th><th>使用时间</th><th>操作</th></tr></thead><tbody>
<?php foreach($cards as $c): $isShared=($c['card_type']??'single')==='shared'; $selectable=$isShared?$c['status']==='active':$c['status']==='unused'; $selected=$selectable&&in_array((string)$c['code'],$generatedCardCodes,true); $statusLabel=$isShared?($c['status']==='active'?'启用':'停用'):($c['status']==='unused'?'未使用':'已使用'); ?>
<tr class="<?=$selected?'card-new-batch':''?>"><td class="card-check"><input type="checkbox" class="card-select" <?=$selectable?'':'disabled'?> <?=$selected?'checked':''?> data-card-code="<?=e($c['code'])?>" data-card-type="<?=$isShared?'公共卡':'普通卡'?>" data-card-amount="<?=e(number_format((float)$c['amount'],2,'.',''))?>" data-card-status="<?=e($statusLabel)?>" data-card-created="<?=e($c['created_at'])?>" aria-label="选择卡号 <?=e($c['code'])?>"></td><td class="mono"><b><?=e($c['code'])?></b></td><td><span class="badge <?=$isShared?'shared':'pending'?>"><?=$isShared?'公共卡':'普通卡'?></span></td><td>¥<?=number_format((float)$c['amount'],2)?></td><td><span class="badge <?=$selectable?'approved':'rejected'?>"><?=e($statusLabel)?></span></td><td><?=$isShared?(int)$c['redemption_count'].' 人':e($c['username']??'-')?></td><td><?=e($c['created_at'])?></td><td><?=$isShared?'-':e($c['used_at']??'-')?></td><td><?php if($isShared): ?><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="toggle_shared_card"><input type="hidden" name="return" value="/admin/index.php?view=cards"><input type="hidden" name="id" value="<?=(int)$c['id']?>"><input type="hidden" name="status" value="<?=$c['status']==='active'?'disabled':'active'?>"><button class="mini-btn <?=$c['status']==='active'?'reject':'approve'?>"><?=$c['status']==='active'?'停用':'启用'?></button></form><?php else: ?>-<?php endif; ?></td></tr>
<?php endforeach; ?>
<?php if(!$cards): ?><tr><td colspan="9" class="empty-cell">暂无充值卡</td></tr><?php endif; ?>
</tbody></table></div>
</section>
<?php elseif($view==='referrals'):?><section class="admin-stats"><article><span>成功奖励</span><strong><?=$referralStats['rewarded']?></strong></article><article><span>IP 拦截</span><strong><?=$referralStats['rejected']?></strong></article><article><span>累计发放</span><strong>¥<?=number_format($referralStats['amount'],2)?></strong></article><article><span>单人奖励</span><strong>¥<?=number_format((float)setting('invite_reward','0'),2)?></strong></article></section><section class="panel"><div class="panel-head"><div><h2>邀请奖励记录</h2><p>同 IP 自邀或重复领取会自动拦截</p></div></div><div class="table-wrap"><table><thead><tr><th>邀请人</th><th>新用户</th><th>注册 IP</th><th>奖励</th><th>状态</th><th>原因</th><th>时间</th></tr></thead><tbody><?php foreach($referrals as $r):?><tr><td><b><?=e($r['inviter_name'])?></b> (#<?=(int)$r['inviter_id']?>)</td><td><?=e($r['invitee_name'])?> (#<?=(int)$r['invitee_id']?>)</td><td class="mono"><?=e($r['invitee_ip']?:'-')?></td><td>¥<?=number_format((float)$r['reward_amount'],2)?></td><td><span class="badge <?=e($r['status'])?>"><?=e($statusNames[$r['status']]??$r['status'])?></span></td><td><?=e($r['reason']?:'-')?></td><td><?=e($r['created_at'])?></td></tr><?php endforeach;?><?php if(!$referrals):?><tr><td colspan="7" class="empty-cell">暂无邀请记录</td></tr><?php endif;?></tbody></table></div></section>
<?php else:?><div class="settings-grid"><section class="panel"><h2>站点参数</h2><form method="post" action="/admin/action.php" class="form-stack"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="settings"><input type="hidden" name="return" value="/admin/index.php?view=settings"><label><span>站点名称</span><input name="site_name" value="<?=e(setting('site_name'))?>" required></label><label><span>站点公告</span><input name="announcement" value="<?=e(setting('announcement'))?>"></label><label><span>客服微信</span><input name="customer_service" value="<?=e(setting('customer_service'))?>"></label><label><span>充值说明</span><input name="recharge_instructions" value="<?=e(setting('recharge_instructions'))?>"></label><label><span>注册赠送余额</span><input type="number" min="0" step="0.01" name="register_bonus" value="<?=e(setting('register_bonus'))?>"></label><label><span>单人邀请奖励</span><input type="number" min="0" max="1000000" step="0.01" name="invite_reward" value="<?=e(setting('invite_reward','100'))?>" required></label><label><span>一级下线充值佣金 (%)</span><input type="number" min="0" max="100" step="0.0001" name="direct_commission_rate" value="<?=e(setting('direct_commission_rate','10'))?>" required></label><label><span>二级下线充值佣金 (%)</span><input type="number" min="0" max="100" step="0.0001" name="second_commission_rate" value="<?=e(setting('second_commission_rate','1'))?>" required></label><label><span>游戏开关</span><select name="game_enabled"><option value="1" <?=setting('game_enabled')==='1'?'selected':''?>>开启</option><option value="0" <?=setting('game_enabled')==='0'?'selected':''?>>关闭</option></select></label><button class="btn primary">保存站点设置</button></form></section><section class="panel"><h2>管理员密码</h2><form method="post" action="/admin/action.php" class="form-stack"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="admin_password"><input type="hidden" name="return" value="/admin/index.php?view=settings"><label><span>原密码</span><input type="password" name="old_password" required></label><label><span>新密码</span><input type="password" name="new_password" minlength="10" required></label><button class="btn primary">更新管理员密码</button></form></section></div><?php endif;?></main></div></div><script src="/assets/app.js?v=20260722-cards2"></script></body></html>
<?php
function render_orders(array $orders, array $statusNames): string
{
ob_start(); ?>
<div class="table-wrap"><table><thead><tr><th>订单号</th><th>用户</th><th>金额</th><th>方式</th><th>付款备注</th><th>时间</th><th>状态</th><th>操作</th></tr></thead><tbody>
<?php foreach($orders as $o): ?><tr>
<td class="mono"><?=e($o['order_no'])?></td><td><?=e($o['username'])?> (#<?=(int)$o['user_id']?>)</td><td><b>¥<?=number_format((float)$o['amount'],2)?></b></td><td><?=e($o['method'])?></td><td class="admin-note" title="<?=e($o['payer_note'])?>"><?=e($o['payer_note']?:'-')?></td><td><?=e($o['created_at'])?></td><td><span class="badge <?=e($o['status'])?>"><?=e($statusNames[$o['status']]??$o['status'])?></span></td>
<td><?php if($o['status']==='pending'): ?><div class="admin-actions">
<?php foreach(['approved'=>'通过','rejected'=>'拒绝'] as $decision=>$label): ?><form method="post" action="/admin/action.php"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="review_recharge"><input type="hidden" name="return" value="/admin/index.php?view=recharges"><input type="hidden" name="id" value="<?=(int)$o['id']?>"><input type="hidden" name="decision" value="<?=$decision?>"><button class="mini-btn <?=$decision==='approved'?'approve':'reject'?>"><?=$label?></button></form><?php endforeach; ?>
</div><?php elseif($o['status']==='approved'): ?><form class="inline-form" method="post" action="/admin/action.php" onsubmit="return confirm('确认冲正该笔充值及其推广佣金?')"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><input type="hidden" name="action" value="reverse_recharge"><input type="hidden" name="return" value="/admin/index.php?view=recharges"><input type="hidden" name="id" value="<?=(int)$o['id']?>"><input name="note" maxlength="200" placeholder="冲正原因" required><button class="mini-btn reject">冲正</button></form><?php else: ?>-<?php endif; ?></td>
</tr><?php endforeach; ?>
<?php if(!$orders): ?><tr><td colspan="8" class="empty-cell">暂无订单</td></tr><?php endif; ?></tbody></table></div>
<?php return (string) ob_get_clean();
}
+25
View File
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
if (current_admin()) redirect('/admin/index.php');
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
verify_csrf();
$username = trim((string)($_POST['username'] ?? ''));
assert_auth_not_limited('admin_login', $username, 5, 900);
$stmt = db()->prepare('SELECT * FROM admins WHERE username = ?');
$stmt->execute([$username]);
$admin = $stmt->fetch();
if (!$admin || !password_verify((string)($_POST['password'] ?? ''), $admin['password_hash'])) {
record_auth_attempt('admin_login', $username, false);
throw new RuntimeException('管理员账号或密码错误。');
}
session_regenerate_id(true); $_SESSION['admin_id'] = (int)$admin['id'];
record_auth_attempt('admin_login', $username, true);
db()->prepare('UPDATE admins SET last_login_at = ? WHERE id = ?')->execute([now(), $admin['id']]);
admin_audit(db(), 'admin_login', 'admin', (int)$admin['id']);
redirect('/admin/index.php');
} catch (Throwable $e) { $error = $e instanceof RuntimeException ? $e->getMessage() : '登录失败。'; }
}
?><!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>后台登录</title><link rel="stylesheet" href="/assets/app.css?v=20260721"><link rel="stylesheet" href="/assets/admin.css?v=20260721"></head><body class="admin-login"><main><div class="admin-login-brand"><span>金</span><div><b><?=e(setting('site_name'))?></b><small>运营管理后台</small></div></div><?php if($error):?><div class="alert error"><?=e($error)?></div><?php endif;?><form method="post" class="form-stack"><input type="hidden" name="csrf" value="<?=e(csrf_token())?>"><label><span>管理员账号</span><input name="username" autocomplete="username" required autofocus></label><label><span>密码</span><input type="password" name="password" autocomplete="current-password" required></label><button class="btn primary">登录后台</button></form><a class="back-site" href="/index.php">← 返回用户端</a></main></body></html>
+107
View File
@@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
require dirname(__DIR__) . '/includes/game_engine.php';
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
function api_response(int $code, string $msg = 'ok', mixed $data = []): never
{
echo json_encode(['code' => $code, 'msg' => $msg, 'data' => $data], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
function api_user(array $user): array
{
global $config;
$direct=(float)setting('direct_commission_rate','10');$second=(float)setting('second_commission_rate','1');
$formatRate=static function(float $rate):string{$formatted=rtrim(rtrim(number_format($rate,4,'.',''),'0'),'.');return $formatted===''?'0':$formatted;};
$promotionRule='一级下线充值奖励 '.$formatRate($direct).'%,二级下线充值奖励 '.$formatRate($second).'%。';
$promotionUrl=$config['app_url'].'/index.php?view=register&invite='.rawurlencode((string)($user['invite_code']??''));
return ['id'=>(int)$user['id'],'user_id'=>(int)$user['id'],'balance'=>(float)$user['balance'],'img'=>'','href'=>$promotionUrl,'rule'=>setting('announcement'),'rule1'=>$promotionRule,'rule2'=>setting('recharge_instructions'),'interval'=>3,'wxNum'=>setting('customer_service'),'wx'=>setting('customer_service')];
}
function api_auth(): array
{
$user=current_user(true);
if(!$user) api_response(0,'请先登录',[]);
return $user;
}
try {
if($_SERVER['REQUEST_METHOD']!=='POST') api_response(0,'请求方式错误',[]);
$origin=(string)($_SERVER['HTTP_ORIGIN']??'');
$requestHost = explode(':', (string)($_SERVER['HTTP_HOST'] ?? ''))[0];
if($origin!=='' && parse_url($origin,PHP_URL_HOST)!==$requestHost) api_response(0,'非法请求',[]);
$path=(string)($_GET['path']??'');
$raw=(string)file_get_contents('php://input');$data=json_decode($raw,true);if(!is_array($data))$data=$_POST;
if($path==='/index/login/login'){
$username=trim((string)($data['username']??''));
if((string)($data['password']??'')==='__server_session__'){
$sessionUser=current_user(true);
if($sessionUser && hash_equals((string)$sessionUser['username'],$username))api_response(1,'登录成功',api_user($sessionUser));
}
assert_auth_not_limited('user_login',$username,5,900);
$stmt=db()->prepare('SELECT * FROM users WHERE username=?');$stmt->execute([$username]);$user=$stmt->fetch();
if(!$user||!password_verify((string)($data['password']??''),$user['password_hash'])){record_auth_attempt('user_login',$username,false);api_response(0,'账号或密码错误',[]);}if((int)$user['status']!==1)api_response(0,'账号已停用',[]);
session_regenerate_id(true);$_SESSION['user_id']=(int)$user['id'];record_auth_attempt('user_login',$username,true);db()->prepare('UPDATE users SET last_login_at=?,last_login_ip=? WHERE id=?')->execute([now(),client_ip(),$user['id']]);api_response(1,'登录成功',api_user($user));
}
if($path==='/index/login/register'){
$username=trim((string)($data['username']??''));assert_auth_not_limited('register',$username,5,3600);record_auth_attempt('register',$username,false);$password=(string)($data['password']??'');if(!preg_match('/^[A-Za-z0-9_]{6,20}$/',$username))api_response(0,'账号需为6-20位',[]);if(strlen($password)<8||strlen($password)>72)api_response(0,'密码需为8-72位',[]);create_user_account($username,$password,'',(string)($data['invite_code']??$data['invite']??$data['pid']??''));api_response(1,'注册成功',[]);
}
$user=api_auth();
if($path==='/index/login/user_info')api_response(1,'登录成功',api_user($user));
if($path==='/index/login/user_pwd'){
$old=(string)($data['j_pwd']??$data['oldpassword']??$data['old_password']??'');$new=(string)($data['x_pwd']??$data['password']??$data['newpassword']??'');if(!password_verify($old,$user['password_hash']))api_response(0,'原密码错误',[]);if(strlen($new)<8)api_response(0,'新密码至少8位',[]);db()->prepare('UPDATE users SET password_hash=?,updated_at=? WHERE id=?')->execute([password_hash($new,PASSWORD_DEFAULT),now(),$user['id']]);api_response(1,'修改成功',[]);
}
if($path==='/index/login/answer')api_response(1,'修改成功',[]);
if($path==='/index/login/modify')api_response(0,'请在会员中心修改密码',[]);
if($path==='/index/kalman/receive'){
$code=strtoupper(trim((string)($data['kalman_pwd']??'')));redeem_recharge_card((int)$user['id'],$code,'游戏内充值卡兑换');api_response(1,'充值成功',api_user(current_user(true)));
}
if($path==='/index/game/get_gift'){
if(setting('game_enabled','1')!=='1')api_response(0,'游戏维护中',[]);$stake=round((float)($data['money']??0),2);if($stake<=0||$stake>100000)api_response(0,'投入金额无效',[]);
$fruits=is_array($data['fruits']??null)?$data['fruits']:[];$allowedIds=[4,16,20,8,2,19,13,5];$validated=[];$calculatedStake=0.0;if(count($fruits)>8)api_response(0,'投入数据无效',[]);foreach($fruits as $item){if(!is_array($item)||count($item)<2)api_response(0,'投入数据无效',[]);$fruit=(int)$item[0];$amount=(float)$item[1];if(!in_array($fruit,$allowedIds,true)||$amount<=0||$amount>100000||abs($amount-round($amount))>0.001||isset($validated[$fruit]))api_response(0,'投入数据无效',[]);$validated[$fruit]=$amount;$calculatedStake+=$amount;}if(abs($calculatedStake-$stake)>0.001)api_response(0,'投入金额校验失败',[]);
$pdo=db();$pdo->beginTransaction();try{
$lock=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'?' FOR UPDATE':'';
$stmt=$pdo->prepare('SELECT balance FROM users WHERE id=?'.$lock);$stmt->execute([$user['id']]);$before=(float)$stmt->fetchColumn();if($before<$stake)throw new RuntimeException('余额不足');
$settings=settings_map();$outcome=game_select_outcome($pdo,$stake,$validated,$settings);$win=(float)$outcome['payout'];
$result=$outcome['type']>0?['type'=>$outcome['type'],'pos'=>['pos'=>$outcome['position'],'luck'=>$outcome['positions']]]:['type'=>0,'pos'=>$outcome['position']];
$after=$before-$stake+$win;$pdo->prepare('UPDATE users SET balance=?,updated_at=? WHERE id=?')->execute([$after,now(),$user['id']]);
$logResult=['result'=>$result,'outcome'=>$outcome,'target_rtp'=>(float)($settings['target_rtp']??92)];
$pdo->prepare('INSERT INTO game_logs(user_id,game_type,bet_amount,win_amount,profit,result_json,created_at) VALUES(?,?,?,?,?,?,?)')->execute([$user['id'],'spin',$stake,$win,$win-$stake,json_encode($logResult,JSON_UNESCAPED_UNICODE),now()]);
create_ledger($pdo,(int)$user['id'],'game',$win-$stake,$before,$after,$outcome['kind']==='special'?$outcome['name']:($outcome['kind']==='lucky_eat'?'LUCKY通吃':'普通开奖'));
$pendingSql=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'?'INSERT INTO game_pending_wins(user_id,amount,updated_at) VALUES(?,?,?) ON DUPLICATE KEY UPDATE amount=VALUES(amount),updated_at=VALUES(updated_at)':'INSERT INTO game_pending_wins(user_id,amount,updated_at) VALUES(?,?,?) ON CONFLICT(user_id) DO UPDATE SET amount=excluded.amount,updated_at=excluded.updated_at';
$pdo->prepare($pendingSql)->execute([$user['id'],$win,now()]);$pdo->commit();
}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}
api_response(1,'ok',['data'=>$result,'money'=>[$win]]);
}
if($path==='/index/game/size'){
$guess=(int)($data['size']??0);$requested=round((float)($data['balance']??0),2);if(!in_array($guess,[1,2],true)||$requested<=0)api_response(0,'比大小参数无效',[]);
$pdo=db();$pdo->beginTransaction();try{
$lock=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'?' FOR UPDATE':'';$stmt=$pdo->prepare('SELECT balance FROM users WHERE id=?'.$lock);$stmt->execute([$user['id']]);$before=(float)$stmt->fetchColumn();
$stmt=$pdo->prepare('SELECT amount FROM game_pending_wins WHERE user_id=?'.$lock);$stmt->execute([$user['id']]);$pending=$stmt->fetchColumn();if($pending===false||abs((float)$pending-$requested)>0.001)throw new RuntimeException('该笔中奖已结算,请重新开始。');
$settings=settings_map();$winRate=min(100.0,max(0.0,(float)($settings['size_win_rate']??46)));$isWin=random_int(1,1000000)<=(int)round($winRate*10000);
if($isWin){$number=$guess===1?random_int(1,7):random_int(8,14);$after=$before+$requested;$payout=$requested*2;$nextPending=$payout;$delta=$requested;}else{$number=$guess===1?random_int(8,14):random_int(1,7);if($before<$requested)throw new RuntimeException('余额不足');$after=$before-$requested;$payout=0.0;$nextPending=0.0;$delta=-$requested;}
$pdo->prepare('UPDATE users SET balance=?,updated_at=? WHERE id=?')->execute([$after,now(),$user['id']]);$pdo->prepare('UPDATE game_pending_wins SET amount=?,updated_at=? WHERE user_id=?')->execute([$nextPending,now(),$user['id']]);
$detail=['type'=>'size','guess'=>$guess,'number'=>$number,'win'=>$isWin,'win_rate'=>$winRate];$pdo->prepare('INSERT INTO game_logs(user_id,game_type,bet_amount,win_amount,profit,result_json,created_at) VALUES(?,?,?,?,?,?,?)')->execute([$user['id'],'size',$requested,$payout,$delta,json_encode($detail,JSON_UNESCAPED_UNICODE),now()]);create_ledger($pdo,(int)$user['id'],'game_size',$delta,$before,$after,$isWin?'比大小获胜':'比大小失败');$pdo->commit();
}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}api_response(1,'ok',(string)$number);
}
if($path==='/index/game/gamelog'){$offset=max(0,(int)($data['offset']??0));$length=min(50,max(1,(int)($data['length']??10)));$stmt=db()->prepare('SELECT bet_amount AS money,created_at AS log_time,win_amount AS in_money,profit FROM game_logs WHERE user_id=? ORDER BY id DESC LIMIT ? OFFSET ?');$stmt->bindValue(1,(int)$user['id'],PDO::PARAM_INT);$stmt->bindValue(2,$length,PDO::PARAM_INT);$stmt->bindValue(3,$offset,PDO::PARAM_INT);$stmt->execute();$countStmt=db()->prepare('SELECT COUNT(*) FROM game_logs WHERE user_id=?');$countStmt->execute([$user['id']]);api_response(1,'ok',['data'=>$stmt->fetchAll(),'count'=>(int)$countStmt->fetchColumn()]);}
if($path==='/index/game/money'){$amount=round((float)($data['money']??0),2);$account=trim((string)($data['wx_id']??''));$name=trim((string)($data['name']??''));if($amount<100||abs(fmod($amount,100.0))>0.001)api_response(0,'提现金额需为100的倍数',[]);if($account===''||$name==='')api_response(0,'请填写收款账号和姓名',[]);$pdo=db();$pdo->beginTransaction();try{$lock=$pdo->getAttribute(PDO::ATTR_DRIVER_NAME)==='mysql'?' FOR UPDATE':'';$stmt=$pdo->prepare('SELECT balance FROM users WHERE id=?'.$lock);$stmt->execute([$user['id']]);$before=(float)$stmt->fetchColumn();if($before<$amount)throw new RuntimeException('余额不足');$after=$before-$amount;$pdo->prepare('UPDATE users SET balance=?,updated_at=? WHERE id=?')->execute([$after,now(),$user['id']]);$pdo->prepare("INSERT INTO withdrawal_orders(user_id,amount,account,real_name,status,created_at) VALUES(?,?,?,?,'pending',?)")->execute([$user['id'],$amount,mb_substr($account,0,100),mb_substr($name,0,50),now()]);create_ledger($pdo,(int)$user['id'],'withdrawal',-$amount,$before,$after,'提现申请','WD'.$pdo->lastInsertId());$pdo->prepare('UPDATE game_pending_wins SET amount=0,updated_at=? WHERE user_id=?')->execute([now(),$user['id']]);$pdo->commit();}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();throw $e;}api_response(1,'提交成功',[]);}
if($path==='/index/game/money_log'){$stmt=db()->prepare("SELECT id AS monery_id,created_at AS monery_time,amount,status AS state FROM withdrawal_orders WHERE user_id=? ORDER BY id DESC LIMIT 50");$stmt->execute([$user['id']]);$rows=$stmt->fetchAll();api_response(1,'ok',['data'=>$rows,'count'=>count($rows)]);}
if($path==='/index/game/distribution'){
$grade=(int)($data['grade']??0);$offset=max(0,(int)($data['offset']??0));$length=min(50,max(1,(int)($data['length']??10)));$pdo=db();
if($grade===0){
$countStmt=$pdo->prepare("SELECT COUNT(*) FROM users u JOIN referral_rewards r ON r.invitee_id=u.id AND r.inviter_id=? AND r.status IN ('rewarded','qualified')");$countStmt->execute([$user['id']]);$count=(int)$countStmt->fetchColumn();
$stmt=$pdo->prepare("SELECT u.username AS user_id,u.created_at AS fx_time,COALESCE(SUM(c.commission_amount),0) AS a_money,0 AS b_money FROM users u JOIN referral_rewards r ON r.invitee_id=u.id AND r.inviter_id=? AND r.status IN ('rewarded','qualified') LEFT JOIN recharge_commissions c ON c.recharging_user_id=u.id AND c.beneficiary_user_id=? AND c.level=1 AND c.reversed_at IS NULL GROUP BY u.id,u.username,u.created_at ORDER BY u.id DESC LIMIT ? OFFSET ?");$stmt->bindValue(1,(int)$user['id'],PDO::PARAM_INT);$stmt->bindValue(2,(int)$user['id'],PDO::PARAM_INT);$stmt->bindValue(3,$length,PDO::PARAM_INT);$stmt->bindValue(4,$offset,PDO::PARAM_INT);$stmt->execute();
}else{
$countStmt=$pdo->prepare("SELECT COUNT(*) FROM users u JOIN users p ON p.id=u.inviter_id JOIN referral_rewards rp ON rp.invitee_id=p.id AND rp.inviter_id=? AND rp.status IN ('rewarded','qualified') JOIN referral_rewards ru ON ru.invitee_id=u.id AND ru.inviter_id=p.id AND ru.status IN ('rewarded','qualified')");$countStmt->execute([$user['id']]);$count=(int)$countStmt->fetchColumn();
$stmt=$pdo->prepare("SELECT u.username AS user_id,u.created_at AS fx_time,0 AS a_money,COALESCE(SUM(c.commission_amount),0) AS b_money FROM users u JOIN users p ON p.id=u.inviter_id JOIN referral_rewards rp ON rp.invitee_id=p.id AND rp.inviter_id=? AND rp.status IN ('rewarded','qualified') JOIN referral_rewards ru ON ru.invitee_id=u.id AND ru.inviter_id=p.id AND ru.status IN ('rewarded','qualified') LEFT JOIN recharge_commissions c ON c.recharging_user_id=u.id AND c.beneficiary_user_id=? AND c.level=2 AND c.reversed_at IS NULL GROUP BY u.id,u.username,u.created_at ORDER BY u.id DESC LIMIT ? OFFSET ?");$stmt->bindValue(1,(int)$user['id'],PDO::PARAM_INT);$stmt->bindValue(2,(int)$user['id'],PDO::PARAM_INT);$stmt->bindValue(3,$length,PDO::PARAM_INT);$stmt->bindValue(4,$offset,PDO::PARAM_INT);$stmt->execute();
}
api_response(1,'ok',['data'=>$stmt->fetchAll(),'count'=>$count]);
}
api_response(1,'ok',[]);
} catch(Throwable $e){api_response(0,$e instanceof RuntimeException?$e->getMessage():'服务器错误',[]);}
+1
View File
@@ -0,0 +1 @@
.admin-login{min-height:100vh;display:grid;place-items:center;background:#07192b;padding:20px}.admin-login main{width:min(420px,100%);background:#fff;border-top:4px solid #f1b928;border-radius:8px;padding:34px;box-shadow:0 25px 70px rgba(0,0,0,.35)}.admin-login-brand{display:flex;align-items:center;gap:14px;margin-bottom:28px}.admin-login-brand>span{display:grid;place-items:center;width:44px;height:44px;border-radius:50%;background:#d7372f;color:#ffd86b;border:2px solid #ffd86b;font-size:23px;font-weight:900}.admin-login-brand div{display:grid}.admin-login-brand b{font-size:19px}.admin-login-brand small{color:#718092;margin-top:3px}.back-site{display:block;text-align:center;margin-top:22px;color:#718092;font-size:13px}.admin-layout{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:100vh}.admin-side{position:sticky;top:0;height:100vh;background:#07192b;color:#fff;padding:24px 14px;display:flex;flex-direction:column}.admin-brand{display:flex;align-items:center;gap:10px;padding:0 12px 25px;border-bottom:1px solid rgba(255,255,255,.1);font-weight:800}.admin-brand span{color:#ffd65c}.admin-side nav{display:grid;gap:5px;margin-top:24px}.admin-side nav a{padding:12px 14px;border-radius:5px;color:#a9bbc9;font-size:14px}.admin-side nav a:hover,.admin-side nav a.active{background:#0d385a;color:#fff}.admin-side footer{margin-top:auto;padding:14px 12px;color:#8aa0b2;font-size:12px;display:grid;gap:10px}.admin-side footer a{color:#fff}.admin-main{min-width:0}.admin-top{height:64px;background:#fff;border-bottom:1px solid #dfe7ee;display:flex;align-items:center;justify-content:space-between;padding:0 30px}.admin-top h1{font-size:18px;margin:0}.admin-body{padding:28px 30px}.admin-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:20px}.admin-stats article{background:#fff;border:1px solid #dfe7ee;border-radius:7px;padding:20px;border-left:4px solid #0878b9}.admin-stats article:nth-child(2){border-left-color:#f1b928}.admin-stats article:nth-child(3){border-left-color:#168761}.admin-stats article:nth-child(4){border-left-color:#d7372f}.admin-stats span{display:block;color:#718092;font-size:12px;margin-bottom:10px}.admin-stats strong{font-size:25px}.admin-actions{display:flex;gap:6px}.admin-actions form{display:inline}.mini-btn{border:1px solid #ccd8e1;background:#fff;border-radius:4px;padding:6px 9px;font-size:12px;color:#395167}.mini-btn.approve{color:#087251;border-color:#9ed8c4;background:#edf9f5}.mini-btn.reject{color:#a72e2e;border-color:#efb9b4;background:#fff3f1}.searchbar{display:flex;gap:8px}.searchbar input{height:38px;border:1px solid #ccd8e1;border-radius:5px;padding:0 12px;min-width:230px}.settings-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.settings-grid .panel{padding:22px}.settings-grid h2{margin:0 0 20px;font-size:17px}.inline-form{display:flex;align-items:center;gap:6px}.inline-form input{width:100px;height:32px;border:1px solid #ccd8e1;border-radius:4px;padding:0 8px}.admin-note{max-width:150px;overflow:hidden;text-overflow:ellipsis}.pagination{display:flex;gap:6px;margin-top:16px}.pagination a{padding:7px 11px;background:#fff;border:1px solid #dfe7ee;border-radius:4px;font-size:13px}.pagination a.active{background:#0878b9;color:#fff;border-color:#0878b9}@media(max-width:900px){.admin-layout{grid-template-columns:1fr}.admin-side{position:static;height:auto}.admin-side nav{grid-template-columns:repeat(3,1fr)}.admin-side footer{display:none}.admin-stats{grid-template-columns:1fr 1fr}.admin-body{padding:18px 14px}.settings-grid{grid-template-columns:1fr}.admin-top{padding:0 15px}}@media(max-width:540px){.admin-stats{grid-template-columns:1fr 1fr}.admin-side nav{grid-template-columns:1fr 1fr}.searchbar input{min-width:0;width:100%}}
+2
View File
File diff suppressed because one or more lines are too long
+161
View File
@@ -0,0 +1,161 @@
document.querySelectorAll('[data-amount]').forEach(function (button) {
button.addEventListener('click', function () {
var input = button.closest('form').querySelector('input[name="amount"]');
if (input) input.value = button.dataset.amount;
});
});
document.querySelectorAll('.alert').forEach(function (alert) {
window.setTimeout(function () { alert.style.display = 'none'; }, 5000);
});
document.querySelectorAll('.badge.rewarded').forEach(function (badge) {
badge.classList.add('approved');
});
document.querySelectorAll('[data-copy]').forEach(function (button) {
button.addEventListener('click', function () {
var input = document.querySelector(button.dataset.copy);
if (!input) return;
var original = button.textContent;
var copied = function () {
button.textContent = '已复制';
window.setTimeout(function () { button.textContent = original; }, 1500);
};
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(input.value).then(copied);
return;
}
input.select();
document.execCommand('copy');
copied();
});
});
var adminNavigation = document.querySelector('.admin-side nav');
if (adminNavigation && !adminNavigation.querySelector('a[href="/admin/audits.php"]')) {
var settingsLink = adminNavigation.querySelector('a[href*="view=settings"]');
var auditLink = document.createElement('a');
auditLink.href = '/admin/audits.php';
auditLink.textContent = '操作审计';
adminNavigation.insertBefore(auditLink, settingsLink || null);
}
var cardManager = document.querySelector('[data-card-manager]');
if (cardManager) {
var cardStyles = document.createElement('link');
cardStyles.rel = 'stylesheet';
cardStyles.href = '/assets/cards-admin.css?v=20260722-2';
document.head.appendChild(cardStyles);
var cardInputs = Array.prototype.slice.call(cardManager.querySelectorAll('.card-select:not(:disabled)'));
var cardToggleAll = cardManager.querySelector('[data-card-toggle-all]');
var cardSelectAll = cardManager.querySelector('[data-card-select-all]');
var cardCopy = cardManager.querySelector('[data-card-copy]');
var cardExport = cardManager.querySelector('[data-card-export]');
var cardCount = cardManager.querySelector('[data-card-selected-count]');
function selectedCards() {
return cardInputs.filter(function (input) { return input.checked; });
}
function updateCardSelection() {
var selected = selectedCards();
cardCount.textContent = '已选 ' + selected.length + ' 张';
cardCopy.disabled = selected.length === 0;
cardExport.disabled = selected.length === 0;
cardSelectAll.disabled = cardInputs.length === 0;
cardSelectAll.textContent = selected.length === cardInputs.length && cardInputs.length ? '取消全选' : '全选可用卡';
cardToggleAll.disabled = cardInputs.length === 0;
cardToggleAll.checked = selected.length === cardInputs.length && cardInputs.length > 0;
cardToggleAll.indeterminate = selected.length > 0 && selected.length < cardInputs.length;
}
function setCardButtonFeedback(button, message) {
var original = button.textContent;
button.textContent = message;
window.setTimeout(function () { button.textContent = original; }, 1500);
}
function fallbackCopy(text) {
var textarea = document.createElement('textarea');
textarea.value = text;
textarea.setAttribute('readonly', '');
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}
cardInputs.forEach(function (input) { input.addEventListener('change', updateCardSelection); });
cardSelectAll.addEventListener('click', function () {
var shouldSelect = selectedCards().length !== cardInputs.length;
cardInputs.forEach(function (input) { input.checked = shouldSelect; });
updateCardSelection();
});
cardToggleAll.addEventListener('change', function () {
cardInputs.forEach(function (input) { input.checked = cardToggleAll.checked; });
updateCardSelection();
});
cardCopy.addEventListener('click', function () {
var text = selectedCards().map(function (input) { return input.dataset.cardCode; }).join('\n');
if (!text) return;
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(function () { setCardButtonFeedback(cardCopy, '已复制'); }, function () {
fallbackCopy(text);
setCardButtonFeedback(cardCopy, '已复制');
});
} else {
fallbackCopy(text);
setCardButtonFeedback(cardCopy, '已复制');
}
});
cardExport.addEventListener('click', function () {
var rows = [['卡号', '类型', '面额', '状态', '生成时间']];
selectedCards().forEach(function (input) {
rows.push([input.dataset.cardCode, input.dataset.cardType, input.dataset.cardAmount, input.dataset.cardStatus, input.dataset.cardCreated]);
});
if (rows.length === 1) return;
var csv = rows.map(function (row) {
return row.map(function (value) { return '"' + String(value).replace(/"/g, '""') + '"'; }).join(',');
}).join('\r\n');
var url = URL.createObjectURL(new Blob(['\ufeff' + csv], {type: 'text/csv;charset=utf-8'}));
var download = document.createElement('a');
var stamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);
download.href = url;
download.download = 'recharge-cards-' + stamp + '.csv';
document.body.appendChild(download);
download.click();
document.body.removeChild(download);
URL.revokeObjectURL(url);
setCardButtonFeedback(cardExport, '已导出');
});
updateCardSelection();
}
var cardCreateForm = document.querySelector('[data-card-create-form]');
if (cardCreateForm) {
var cardTypeInput = cardCreateForm.querySelector('[data-card-type]');
var cardCountInput = cardCreateForm.querySelector('[data-card-count]');
function updateCardCountInput() {
if (cardTypeInput.value === 'shared') {
cardCountInput.dataset.singleCount = cardCountInput.value;
cardCountInput.value = '1';
cardCountInput.readOnly = true;
} else {
cardCountInput.readOnly = false;
if (cardCountInput.value === '1' && cardCountInput.dataset.singleCount) cardCountInput.value = cardCountInput.dataset.singleCount;
}
}
cardTypeInput.addEventListener('change', updateCardCountInput);
updateCardCountInput();
}
if (document.querySelector('.game-config')) {
var gameAdminStyles = document.createElement('link');
gameAdminStyles.rel = 'stylesheet';
gameAdminStyles.href = '/assets/game-admin.css?v=20260721';
document.head.appendChild(gameAdminStyles);
}
+69
View File
@@ -0,0 +1,69 @@
.card-note {
color: #718092;
font-size: 14px;
line-height: 1.8;
margin: 0;
}
.card-batch-actions {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: flex-end;
}
.card-batch-actions span {
color: #718092;
font-size: 12px;
min-width: 62px;
text-align: right;
}
.card-batch-actions button:disabled {
cursor: not-allowed;
opacity: .45;
}
.card-check {
padding-left: 18px;
padding-right: 6px;
width: 42px;
}
.card-check input {
accent-color: #0878b9;
height: 17px;
margin: 0;
width: 17px;
}
.card-new-batch {
background: #f2faf7;
}
.badge.shared {
background: #e8f1fb;
color: #235f92;
}
[data-card-count][readonly] {
background: #f3f6f8;
color: #718092;
}
@media (max-width: 720px) {
.card-manager .panel-head {
align-items: flex-start;
flex-direction: column;
}
.card-batch-actions {
justify-content: flex-start;
width: 100%;
}
.card-batch-actions span {
margin-left: auto;
}
}
+1
View File
@@ -0,0 +1 @@
.rtp-metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:20px}.rtp-metrics article{background:#fff;border:1px solid #dfe7ee;border-radius:7px;padding:18px;display:grid;gap:7px}.rtp-metrics span,.rtp-metrics small{color:#718092;font-size:12px}.rtp-metrics strong{font-size:23px}.config-row{padding:22px;display:grid;grid-template-columns:repeat(3,1fr);gap:18px}.config-row label{display:grid;gap:8px;font-size:13px;font-weight:700}.config-row input,.odds-table input{height:38px;border:1px solid #ccd8e1;border-radius:5px;padding:0 10px;max-width:180px}.odds-table input:focus,.config-row input:focus{outline:0;border-color:#0878b9;box-shadow:0 0 0 3px rgba(8,120,185,.1)}.config-submit{padding:20px 22px;border-top:1px solid #dfe7ee;display:flex;justify-content:flex-end}.game-config .panel{margin-bottom:20px}.probability-summary{color:#526475;font-size:12px;font-weight:700;white-space:nowrap}.position-table td{white-space:nowrap}.position-table input{width:110px}.position-table .mono{color:#526475}@media(max-width:900px){.rtp-metrics{grid-template-columns:1fr 1fr}.config-row{grid-template-columns:1fr}.odds-table input{max-width:130px}.probability-summary{white-space:normal}}@media(max-width:540px){.rtp-metrics{grid-template-columns:1fr 1fr;gap:10px}.rtp-metrics article{padding:14px}.rtp-metrics strong{font-size:19px}}
+9
View File
@@ -0,0 +1,9 @@
.badge.rewarded{color:#087251;background:#e2f6ef}
.invite-tools{padding:22px;display:grid;gap:18px}
.invite-tools label{display:grid;gap:8px}
.invite-tools label>span{font-size:13px;font-weight:700}
.invite-tools label>div{display:grid;grid-template-columns:minmax(0,1fr) 132px;gap:10px}
.invite-tools input{min-width:0;height:46px;border:1px solid #ccd7df;border-radius:6px;padding:0 14px;color:#385068;background:#f7fafc}
.invite-stats .mono{font-size:22px}
@media(max-width:900px){.mobile-nav{grid-template-columns:repeat(6,1fr)}}
@media(max-width:560px){.invite-tools label>div{grid-template-columns:1fr}.invite-tools .btn{width:100%}}
+31
View File
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
$installedFile = __DIR__ . '/storage/install-config.php';
$installed = is_file($installedFile) ? require $installedFile : [];
if (!is_array($installed)) {
$installed = [];
}
$env = static function (string $key, mixed $fallback = null): mixed {
$value = getenv($key);
return $value === false || $value === '' ? $fallback : $value;
};
$db = is_array($installed['db'] ?? null) ? $installed['db'] : [];
return [
'installed' => is_file(__DIR__ . '/storage/installed.lock') && $db !== [],
'app_name' => (string) $env('APP_NAME', $installed['app_name'] ?? '欢乐水果机'),
'app_url' => rtrim((string) $env('APP_URL', $installed['app_url'] ?? ''), '/'),
'timezone' => (string) $env('APP_TIMEZONE', $installed['timezone'] ?? 'Asia/Shanghai'),
'db' => [
'driver' => 'mysql',
'host' => (string) $env('DB_HOST', $db['host'] ?? 'localhost'),
'port' => (string) $env('DB_PORT', $db['port'] ?? '3306'),
'database' => (string) $env('DB_DATABASE', $db['database'] ?? ''),
'username' => (string) $env('DB_USERNAME', $db['username'] ?? ''),
'password' => (string) $env('DB_PASSWORD', $db['password'] ?? ''),
'charset' => 'utf8mb4',
],
'session_name' => 'tanwan_session',
];
+14
View File
@@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS users (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, phone VARCHAR(30) NOT NULL DEFAULT '', invite_code VARCHAR(16) NULL, inviter_id BIGINT UNSIGNED NULL, register_ip VARCHAR(45) NOT NULL DEFAULT '', balance DECIMAL(14,2) NOT NULL DEFAULT 0, status TINYINT NOT NULL DEFAULT 1, last_login_at DATETIME NULL, last_login_ip VARCHAR(45) NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, UNIQUE INDEX idx_users_invite_code(invite_code), INDEX idx_users_inviter(inviter_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS admins (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, last_login_at DATETIME NULL, created_at DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS settings (`key` VARCHAR(64) PRIMARY KEY, `value` TEXT NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_orders (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, order_no VARCHAR(32) NOT NULL UNIQUE, user_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(14,2) NOT NULL, method VARCHAR(30) NOT NULL, payer_note VARCHAR(255) NOT NULL DEFAULT '', status VARCHAR(20) NOT NULL DEFAULT 'pending', admin_note VARCHAR(255) NOT NULL DEFAULT '', reviewed_by BIGINT UNSIGNED NULL, reviewed_at DATETIME NULL, reversed_by BIGINT UNSIGNED NULL, reversed_at DATETIME NULL, reversal_note VARCHAR(255) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, INDEX idx_recharge_user(user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_cards (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, code VARCHAR(32) NOT NULL UNIQUE, amount DECIMAL(14,2) NOT NULL, card_type VARCHAR(20) NOT NULL DEFAULT 'single', status VARCHAR(20) NOT NULL DEFAULT 'unused', used_by BIGINT UNSIGNED NULL, used_at DATETIME NULL, created_at DATETIME NOT NULL, INDEX idx_card_type_status(card_type, status, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_card_redemptions (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, card_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(14,2) NOT NULL, created_at DATETIME NOT NULL, UNIQUE INDEX idx_card_user_once(card_id, user_id), INDEX idx_card_redemptions(card_id, id), INDEX idx_user_card_redemptions(user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS balance_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, type VARCHAR(30) NOT NULL, amount DECIMAL(14,2) NOT NULL, balance_before DECIMAL(14,2) NOT NULL, balance_after DECIMAL(14,2) NOT NULL, note VARCHAR(255) NOT NULL, reference_no VARCHAR(40) NULL, created_at DATETIME NOT NULL, INDEX idx_balance_user(user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS game_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, game_type VARCHAR(20) NOT NULL DEFAULT 'spin', bet_amount DECIMAL(14,2) NOT NULL, win_amount DECIMAL(14,2) NOT NULL, profit DECIMAL(14,2) NOT NULL, result_json TEXT NOT NULL, created_at DATETIME NOT NULL, INDEX idx_game_user(user_id, id), INDEX idx_game_type(game_type, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS withdrawal_orders (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(14,2) NOT NULL, account VARCHAR(100) NOT NULL, real_name VARCHAR(50) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', created_at DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS game_pending_wins (user_id BIGINT UNSIGNED PRIMARY KEY, amount DECIMAL(14,2) NOT NULL DEFAULT 0, updated_at DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS referral_rewards (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, inviter_id BIGINT UNSIGNED NOT NULL, invitee_id BIGINT UNSIGNED NOT NULL, invitee_ip VARCHAR(45) NOT NULL DEFAULT '', reward_ip VARCHAR(45) NULL, reward_amount DECIMAL(14,2) NOT NULL DEFAULT 0, status VARCHAR(20) NOT NULL, reason VARCHAR(100) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, UNIQUE INDEX idx_referral_invitee(invitee_id), UNIQUE INDEX idx_referral_reward_ip(reward_ip), INDEX idx_referral_inviter(inviter_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS recharge_commissions (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, source_type VARCHAR(20) NOT NULL, source_ref VARCHAR(40) NOT NULL, recharging_user_id BIGINT UNSIGNED NOT NULL, beneficiary_user_id BIGINT UNSIGNED NOT NULL, level TINYINT UNSIGNED NOT NULL, rate DECIMAL(7,4) NOT NULL, recharge_amount DECIMAL(14,2) NOT NULL, commission_amount DECIMAL(14,2) NOT NULL, reversed_by BIGINT UNSIGNED NULL, reversed_at DATETIME NULL, created_at DATETIME NOT NULL, UNIQUE INDEX idx_commission_source(source_type, source_ref, beneficiary_user_id, level), INDEX idx_commission_beneficiary(beneficiary_user_id, level, id), INDEX idx_commission_recharging(recharging_user_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS auth_attempts (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, scope VARCHAR(30) NOT NULL, identifier_hash CHAR(64) NOT NULL, ip_address VARCHAR(45) NOT NULL DEFAULT '', succeeded TINYINT NOT NULL DEFAULT 0, attempted_at DATETIME NOT NULL, INDEX idx_auth_limit(scope, identifier_hash, ip_address, attempted_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS admin_audit_logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, admin_id BIGINT UNSIGNED NOT NULL, action VARCHAR(50) NOT NULL, target_type VARCHAR(40) NOT NULL DEFAULT '', target_id VARCHAR(64) NOT NULL DEFAULT '', before_json TEXT NULL, after_json TEXT NULL, ip_address VARCHAR(45) NOT NULL DEFAULT '', created_at DATETIME NOT NULL, INDEX idx_admin_audit(admin_id, id), INDEX idx_admin_target(target_type, target_id, id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+53
View File
@@ -0,0 +1,53 @@
# Managed by HostDesk. Sensitive application paths are explicitly denied.
server {
listen 80;
listen [::]:80;
server_name tanwan.de www.tanwan.de;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/hostdesk/acme-http;
default_type text/plain;
}
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name tanwan.de www.tanwan.de;
ssl_certificate /etc/hostdesk/certificates/tanwan-de/fullchain.pem;
ssl_certificate_key /etc/hostdesk/certificates/tanwan-de/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:HostDeskSSL:10m;
client_max_body_size 64m;
keepalive_timeout 65;
server_tokens off;
gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml image/svg+xml;
access_log /var/log/nginx/tanwan-de.access.log;
error_log /var/log/nginx/tanwan-de.error.log;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/hostdesk/acme-http;
default_type text/plain;
}
root /var/www/tanwan.de/public;
index index.php index.html;
location = /database.sql { deny all; }
location = /README.md { deny all; }
location ^~ /database/ { deny all; }
location ^~ /storage/ { deny all; }
location ^~ /maintenance/ { deny all; }
location ^~ /deploy/ { deny all; }
location ~* \.(?:sql|sqlite|bak|backup|dist|ini|log|sh)$ { deny all; }
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$ {
try_files $uri =404;
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9000;
}
location ~ /\. { deny all; }
}
+1
View File
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+91
View File
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢乐水果机</title>
<!--http://www.html5rocks.com/en/mobile/mobifying/-->
<meta name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1, minimum-scale=1,maximum-scale=1"/>
<!--https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html-->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<!-- force webkit on 360 -->
<meta name="renderer" content="webkit"/>
<meta name="force-rendering" content="webkit"/>
<!-- force edge on IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="msapplication-tap-highlight" content="no">
<!-- force full screen on some browser -->
<meta name="full-screen" content="yes"/>
<meta name="x5-fullscreen" content="true"/>
<meta name="360-fullscreen" content="true"/>
<!-- force screen orientation on some browser -->
<meta name="screen-orientation" content="portrait"/>
<meta name="x5-orientation" content="portrait">
<!--fix fireball/issues/3568 -->
<!--<meta name="browsermode" content="application">-->
<meta name="x5-page-mode" content="app">
<!--<link rel="apple-touch-icon" href=".png" />-->
<!--<link rel="apple-touch-icon-precomposed" href=".png" />-->
<link rel="stylesheet" type="text/css" href="style-mobile.css"/>
<link rel="icon" href="favicon.ico"/>
</head>
<body>
<canvas id="GameCanvas" oncontextmenu="event.preventDefault()" tabindex="0"></canvas>
<div id="splash">
<div class="progress-bar stripes">
<span style="width: 0%"></span>
</div>
</div>
<script src="local-api.js" charset="utf-8"></script>
<script src="src/settings.js" charset="utf-8"></script>
<script src="main.js?v=20260723-exit1" charset="utf-8"></script>
<script type="text/javascript">
(function () {
// open web debugger console
if (typeof VConsole !== 'undefined') {
window.vConsole = new VConsole();
}
var debug = window._CCSettings.debug;
var splash = document.getElementById('splash');
splash.style.display = 'block';
function loadScript (moduleName, cb) {
function scriptLoaded () {
document.body.removeChild(domScript);
domScript.removeEventListener('load', scriptLoaded, false);
cb && cb();
};
var domScript = document.createElement('script');
domScript.async = true;
domScript.src = moduleName;
domScript.addEventListener('load', scriptLoaded, false);
document.body.appendChild(domScript);
}
loadScript(debug ? 'cocos2d-js.js' : 'cocos2d-js-min.js', function () {
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
loadScript(debug ? 'physics.js' : 'physics-min.js', window.boot);
}
else {
window.boot();
}
});
})();
</script>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
require dirname(__DIR__) . '/includes/bootstrap.php';
$user = require_user();
if (setting('game_enabled', '1') !== '1') {
http_response_code(503);
echo '<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>游戏维护</title><body style="margin:0;background:#07192b;color:#fff;font-family:sans-serif;display:grid;place-items:center;min-height:100vh"><main style="text-align:center"><h1>游戏维护中</h1><p style="color:#9eb1c0">请稍后再试</p><a style="color:#ffd55a" href="/index.php">返回会员中心</a></main></body></html>';
exit;
}
$html = (string) file_get_contents(__DIR__ . '/index.html');
$sessionBridge = '<script>localStorage.setItem("sg_accountId",' . json_encode($user['username'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) . ');localStorage.setItem("sg_pwd","__server_session__");</script>';
echo str_replace('<script src="local-api.js"', $sessionBridge . "\n<script src=\"local-api.js\"", $html);
+41
View File
@@ -0,0 +1,41 @@
(function () {
"use strict";
var NativeXHR = window.XMLHttpRequest;
function apiPath(url) {
var match = String(url || "").match(/\/index\/[^?#]*/);
return match ? match[0] : "";
}
function BridgeXHR() {
this._xhr = new NativeXHR();
this._isGameApi = false;
}
BridgeXHR.prototype.open = function (method, url) {
var path = apiPath(url);
this._isGameApi = path.indexOf("/index/") === 0;
if (this._isGameApi) {
var args = Array.prototype.slice.call(arguments);
args[0] = "POST";
args[1] = "/api/game.php?path=" + encodeURIComponent(path);
return this._xhr.open.apply(this._xhr, args);
}
return this._xhr.open.apply(this._xhr, arguments);
};
["send", "abort", "setRequestHeader", "getResponseHeader", "getAllResponseHeaders", "addEventListener", "removeEventListener", "overrideMimeType"].forEach(function (name) {
BridgeXHR.prototype[name] = function () {
return this._xhr[name].apply(this._xhr, arguments);
};
});
["readyState", "response", "responseText", "responseType", "responseURL", "responseXML", "status", "statusText", "timeout", "upload", "withCredentials", "onreadystatechange", "onload", "onerror", "ontimeout", "onabort", "onprogress", "onloadend", "onloadstart"].forEach(function (name) {
Object.defineProperty(BridgeXHR.prototype, name, {
get: function () { return this._xhr[name]; },
set: function (value) { this._xhr[name] = value; }
});
});
window.XMLHttpRequest = BridgeXHR;
})();
+199
View File
@@ -0,0 +1,199 @@
window.boot = function () {
var settings = window._CCSettings;
window._CCSettings = undefined;
if ( !settings.debug ) {
var uuids = settings.uuids;
var rawAssets = settings.rawAssets;
var assetTypes = settings.assetTypes;
var realRawAssets = settings.rawAssets = {};
for (var mount in rawAssets) {
var entries = rawAssets[mount];
var realEntries = realRawAssets[mount] = {};
for (var id in entries) {
var entry = entries[id];
var type = entry[1];
// retrieve minified raw asset
if (typeof type === 'number') {
entry[1] = assetTypes[type];
}
// retrieve uuid
realEntries[uuids[id] || id] = entry;
}
}
var scenes = settings.scenes;
for (var i = 0; i < scenes.length; ++i) {
var scene = scenes[i];
if (typeof scene.uuid === 'number') {
scene.uuid = uuids[scene.uuid];
}
}
var packedAssets = settings.packedAssets;
for (var packId in packedAssets) {
var packedIds = packedAssets[packId];
for (var j = 0; j < packedIds.length; ++j) {
if (typeof packedIds[j] === 'number') {
packedIds[j] = uuids[packedIds[j]];
}
}
}
var subpackages = settings.subpackages;
for (var subId in subpackages) {
var uuidArray = subpackages[subId].uuids;
if (uuidArray) {
for (var k = 0, l = uuidArray.length; k < l; k++) {
if (typeof uuidArray[k] === 'number') {
uuidArray[k] = uuids[uuidArray[k]];
}
}
}
}
}
function setLoadingDisplay () {
// Loading splash scene
var splash = document.getElementById('splash');
var progressBar = splash.querySelector('.progress-bar span');
cc.loader.onProgress = function (completedCount, totalCount, item) {
var percent = 100 * completedCount / totalCount;
if (progressBar) {
progressBar.style.width = percent.toFixed(2) + '%';
}
};
splash.style.display = 'block';
progressBar.style.width = '0%';
cc.director.once(cc.Director.EVENT_AFTER_SCENE_LAUNCH, function () {
splash.style.display = 'none';
});
}
var onStart = function () {
cc.loader.downloader._subpackages = settings.subpackages;
cc.view.enableRetina(true);
cc.view.resizeWithBrowserSize(true);
if (cc.sys.isBrowser) {
setLoadingDisplay();
}
if (cc.sys.isMobile) {
if (settings.orientation === 'landscape') {
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
}
else if (settings.orientation === 'portrait') {
cc.view.setOrientation(cc.macro.ORIENTATION_PORTRAIT);
}
cc.view.enableAutoFullScreen([
cc.sys.BROWSER_TYPE_BAIDU,
cc.sys.BROWSER_TYPE_WECHAT,
cc.sys.BROWSER_TYPE_MOBILE_QQ,
cc.sys.BROWSER_TYPE_MIUI,
].indexOf(cc.sys.browserType) < 0);
}
// Limit downloading max concurrent task to 2,
// more tasks simultaneously may cause performance draw back on some android system / browsers.
// You can adjust the number based on your own test result, you have to set it before any loading process to take effect.
if (cc.sys.isBrowser && cc.sys.os === cc.sys.OS_ANDROID) {
cc.macro.DOWNLOAD_MAX_CONCURRENT = 2;
}
function loadScene(launchScene) {
cc.director.loadScene(launchScene,
function (err) {
if (!err) {
if (cc.sys.isBrowser) {
// show canvas
var canvas = document.getElementById('GameCanvas');
canvas.style.visibility = '';
var div = document.getElementById('GameDiv');
if (div) {
div.style.backgroundImage = '';
}
}
cc.loader.onProgress = null;
console.log('Success to load scene: ' + launchScene);
}
else if (CC_BUILD) {
setTimeout(function () {
loadScene(launchScene);
}, 1000);
}
}
);
}
var launchScene = settings.launchScene;
// load scene
loadScene(launchScene);
};
// jsList
var jsList = settings.jsList;
var bundledScript = settings.debug ? 'src/project.dev.js' : 'src/project.js?v=20260723-exit1';
if (jsList) {
jsList = jsList.map(function (x) {
return 'src/' + x;
});
jsList.push(bundledScript);
}
else {
jsList = [bundledScript];
}
var option = {
id: 'GameCanvas',
scenes: settings.scenes,
debugMode: settings.debug ? cc.debug.DebugMode.INFO : cc.debug.DebugMode.ERROR,
showFPS: settings.debug,
frameRate: 60,
jsList: jsList,
groupList: settings.groupList,
collisionMatrix: settings.collisionMatrix,
};
// init assets
cc.AssetLibrary.init({
libraryPath: 'res/import',
rawAssetsBase: 'res/raw-',
rawAssets: settings.rawAssets,
packedAssets: settings.packedAssets,
md5AssetsMap: settings.md5AssetsMap,
subpackages: settings.subpackages
});
cc.game.run(option, onStart);
};
if (window.jsb) {
var isRuntime = (typeof loadRuntime === 'function');
if (isRuntime) {
require('src/settings.js');
require('src/cocos2d-runtime.js');
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
require('src/physics.js');
}
require('jsb-adapter/engine/index.js');
}
else {
require('src/settings.js');
require('src/cocos2d-jsb.js');
if (CC_PHYSICS_BUILTIN || CC_PHYSICS_CANNON) {
require('src/physics.js');
}
require('jsb-adapter/jsb-engine.js');
}
cc.macro.CLEANUP_IMAGE_CACHE = true;
window.boot();
}
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"popSp","texture":"50crrF9oxJBZ0vbeUvZ3bc","rect":[0,0,371,171],"offset":[0,0],"originalSize":[371,171],"capInsets":[0,0,0,0]}},[{"__type__":"cc.Prefab","_name":"popLayer","data":{"__id__":1}},{"__type__":"cc.Node","_name":"popLayer","_children":[{"__id__":2},{"__id__":3},{"__id__":4}],"_components":[{"__type__":"f342djydy9BNYyUNOzNRbCa","node":{"__id__":1},"tip_label":{"__id__":6}},{"__type__":"cc.Widget","node":{"__id__":1},"_alignFlags":45}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"496RlXd1RA4K432GcRvRu4"},"fileId":"62gkLQpfhJra0P9SPXcDap"},"_contentSize":{"__type__":"cc.Size","width":750,"height":1125},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[375,562.5,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"mask","_parent":{"__id__":1},"_active":false,"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"a2MjXRFdtLlYQ5ouAFv/+R"},"_sizeMode":0},{"__type__":"cc.Widget","node":{"__id__":2},"_alignFlags":45},{"__type__":"cc.Button","node":{"__id__":2},"_enabled":false,"clickEvents":[{"__type__":"cc.ClickEvent","target":{"__id__":1},"_componentId":"f342djydy9BNYyUNOzNRbCa","handler":"on_click_close"}],"_N$target":{"__id__":1}},{"__type__":"cc.BlockInputEvents","node":{"__id__":2}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"496RlXd1RA4K432GcRvRu4"},"fileId":"6eQWUWFEZJnpDxwmnlB3lK"},"_opacity":125,"_color":{"__type__":"cc.Color"},"_contentSize":{"__type__":"cc.Size","width":750,"height":1125},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"sure_bt","_parent":{"__id__":1},"_components":[{"__type__":"cc.Button","node":{"__id__":3},"duration":0,"clickEvents":[{"__type__":"cc.ClickEvent","target":{"__id__":1},"_componentId":"f342djydy9BNYyUNOzNRbCa","handler":"on_click_close"}],"_N$transition":3,"transition":3,"_N$target":{"__id__":3}},{"__type__":"cc.Widget","node":{"__id__":3},"_alignFlags":45,"_top":46,"_bottom":-46,"_originalWidth":415,"_originalHeight":81}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"496RlXd1RA4K432GcRvRu4"},"fileId":"26QCe8PvxGioIkznqiOMby"},"_contentSize":{"__type__":"cc.Size","width":750,"height":1125},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-46,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"mainSp","_parent":{"__id__":1},"_children":[{"__id__":5},{"__id__":7}],"_components":[{"__type__":"cc.Sprite","node":{"__id__":4},"_spriteFrame":{"__uuid__":"1b2AgyOo9CHZ+7QH56VfXy"},"_type":1,"_sizeMode":2}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"496RlXd1RA4K432GcRvRu4"},"fileId":"c2kzkonh1MJ7+7TYpt3/AA"},"_contentSize":{"__type__":"cc.Size","width":371,"height":171},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,73,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"content_label","_parent":{"__id__":4},"_components":[{"__id__":6}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"496RlXd1RA4K432GcRvRu4"},"fileId":"fcGYotw8JGJKDBNWFMYzJR"},"_contentSize":{"__type__":"cc.Size","width":270,"height":30},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-8,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Label","node":{"__id__":5},"_useOriginalSize":false,"_fontSize":30,"_lineHeight":30,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$fontFamily":"黑体","_N$overflow":3},{"__type__":"cc.Node","_name":"popTitle","_parent":{"__id__":4},"_components":[{"__type__":"cc.Sprite","node":{"__id__":7},"_spriteFrame":{"__uuid__":"a4gPits+RJi4AQWpNz/eMJ"}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"496RlXd1RA4K432GcRvRu4"},"fileId":"84OU1S/R5HrpJeqnyvjOY8"},"_contentSize":{"__type__":"cc.Size","width":83,"height":38},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,57,0,0,0,0,1,1,1,1]}}],{"__type__":"cc.SpriteFrame","content":{"name":"default_sprite_splash","texture":"02delMVqdBD70a/HSD99FK","rect":[0,0,2,2],"offset":[0,0],"originalSize":[2,2],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"popTitle","texture":"23q+HW3m1KoqLevD3jqieT","rect":[0,0,82,37],"offset":[-0.5,0.5],"originalSize":[83,38],"capInsets":[0,0,0,0]}}]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"4","texture":"15981b4b0","rect":[3,411,55,56],"offset":[1.5,1],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"9","texture":"15981b4b0","rect":[3,591,34,56],"offset":[2,-1],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"8","texture":"15981b4b0","rect":[3,740,36,55],"offset":[-3,0.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"14","texture":"15981b4b0","rect":[3,533,52,56],"offset":[-4,1],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"11","texture":"15981b4b0","rect":[3,188,52,57],"offset":[3,-0.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"13","texture":"15981b4b0","rect":[3,349,56,56],"offset":[-2,1],"originalSize":[64,64],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"6","texture":"15981b4b0","rect":[3,631,54,55],"offset":[-3,1.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"7","texture":"15981b4b0","rect":[3,691,43,55],"offset":[-4.5,1.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.AnimationClip","_name":"gold","_duration":0.5166666666666667,"speed":0.4,"wrapMode":2,"curveData":{"paths":{"0000":{"comps":{"cc.Sprite":{"spriteFrame":[{"frame":0,"value":{"__uuid__":"e9Nhe+T+xAXa1abNJsJoyX"}},{"frame":0.03333333333333333,"value":{"__uuid__":"bb4XUwiOZAQqQ4i4CbDOg+"}},{"frame":0.06666666666666667,"value":{"__uuid__":"94Uil/OmFFlqXOi0EYe9p7"}},{"frame":0.1,"value":{"__uuid__":"04iK286SxMMrasIj2wyXRe"}},{"frame":0.13333333333333333,"value":{"__uuid__":"f62qaj2ipLsYo4tdXt9+R3"}},{"frame":0.16666666666666666,"value":{"__uuid__":"57KDjrS7JK6IBULMuMx5qH"}},{"frame":0.2,"value":{"__uuid__":"5f1rjADXFAfb1PVZLKtdEx"}},{"frame":0.23333333333333334,"value":{"__uuid__":"2fnG+JdX1Jr6SiQqD7/4MA"}},{"frame":0.26666666666666666,"value":{"__uuid__":"19waMmfN5Hk6OKsOncB8ON"}},{"frame":0.3,"value":{"__uuid__":"8bwseGNY5PhYLBF/fJQgY5"}},{"frame":0.3333333333333333,"value":{"__uuid__":"490UgwieVFuKI5qGe/0q2M"}},{"frame":0.36666666666666664,"value":{"__uuid__":"c3n7SUGLBJqaLFj8Ubnt/N"}},{"frame":0.4,"value":{"__uuid__":"4bCOFRwehJiJh/JqxOfg3h"}},{"frame":0.43333333333333335,"value":{"__uuid__":"30ecbLKOtEnYU+ubu3llGC"}},{"frame":0.4666666666666667,"value":{"__uuid__":"bcxZGB6OBJWbg1bCNO3cH/"}},{"frame":0.5,"value":{"__uuid__":"b6iUWn1OVOm7gXofKtFesU"}}]}}}}}},{"__type__":"cc.SpriteFrame","content":{"name":"10","texture":"15981b4b0","rect":[3,3,39,58],"offset":[3.5,-1],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"3","texture":"15981b4b0","rect":[3,246,50,57],"offset":[3,0.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"16","texture":"15981b4b0","rect":[3,88,33,58],"offset":[-5.5,0],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"2","texture":"15981b4b0","rect":[3,48,34,58],"offset":[4,0],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"15","texture":"15981b4b0","rect":[3,302,41,57],"offset":[-5.5,0.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"12","texture":"15981b4b0","rect":[3,127,55,57],"offset":[1.5,-0.5],"originalSize":[64,64],"rotated":1,"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"1","texture":"15981b4b0","rect":[3,782,21,59],"offset":[2.5,-0.5],"originalSize":[64,64],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"5","texture":"15981b4b0","rect":[3,472,56,55],"offset":[-2,1.5],"originalSize":[64,64],"capInsets":[0,0,0,0]}}]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"xian","texture":"0e7nrC+tpIcYPBKVMEv4tk","rect":[0,0,643,2],"offset":[0,0],"originalSize":[643,2],"capInsets":[0,0,0,0]}},[{"__type__":"cc.Prefab","_name":"gameRecordItem","data":{"__id__":1},"asyncLoadAssets":true},{"__type__":"cc.Node","_name":"gameRecordItem","_children":[{"__id__":2},{"__id__":3},{"__id__":4},{"__id__":5},{"__id__":6}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__id__":0},"fileId":"66pbESZbtC3akbVkIm5YzU"},"_contentSize":{"__type__":"cc.Size","width":672,"height":62},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-31,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"xian","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"a0gjtKJ9NGUoLZEwxOBaRi"}},{"__type__":"cc.Widget","node":{"__id__":2},"_alignFlags":4}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__id__":0},"fileId":"f25eSDd4JLaZVb8AeTWrn6"},"_contentSize":{"__type__":"cc.Size","width":643,"height":2},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-30,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"orderCashLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":3},"_useOriginalSize":false,"_string":"1234567890","_N$string":"1234567890","_fontSize":28,"_lineHeight":28,"_N$horizontalAlign":1,"_N$verticalAlign":1}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__id__":0},"fileId":"8bWhASXTtEB4T/amxwRsyL"},"_contentSize":{"__type__":"cc.Size","width":155.72,"height":28},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[-108.6,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"timeLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":4},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":22,"_lineHeight":22.4,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$overflow":3}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__id__":0},"fileId":"29ZPtNn2lHFrZnhPvK/jkg"},"_color":{"__type__":"cc.Color","r":255,"g":191,"b":117},"_contentSize":{"__type__":"cc.Size","width":140,"height":22},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[-263.2,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"cashLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":5},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":28,"_lineHeight":28,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$overflow":3}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__id__":0},"fileId":"5fA4Sbk8BA3b506QS7hyeA"},"_color":{"__type__":"cc.Color","r":255,"g":234},"_contentSize":{"__type__":"cc.Size","width":140,"height":28},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[89.2,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"statusLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":6},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":26,"_lineHeight":26,"_N$horizontalAlign":1,"_N$verticalAlign":1}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__id__":0},"fileId":"f3BM8Vi8JDEKao5Ssq/rSB"},"_contentSize":{"__type__":"cc.Size","width":63.62,"height":26},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[270,0,0,0,0,0,1,1,1,1]}}]]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
[[{"__type__":"cc.Prefab","_name":"khc","data":{"__id__":1}},{"__type__":"cc.Node","_name":"khc","_children":[{"__id__":2}],"_components":[{"__type__":"cc.Animation","node":{"__id__":1},"_defaultClip":{"__uuid__":"3cOYVF99NC5oaknLB0feWL"},"_clips":[{"__uuid__":"3cOYVF99NC5oaknLB0feWL"}],"playOnLoad":true},{"__type__":"ff3139EpnVE75oc/u7Dooky","node":{"__id__":1}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"2aF5/ZQA1If6OGxmttM+mX"},"fileId":"a2UU5zc95Pu7t+ixH6wk1r"},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"0000","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"343Xswmf9EB6p/wfv0tkXA"}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"2aF5/ZQA1If6OGxmttM+mX"},"fileId":"18xhhqlyhL3b8oarXQwX3x"},"_contentSize":{"__type__":"cc.Size","width":750,"height":1136},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}}],{"__type__":"cc.SpriteFrame","content":{"name":"khc20001","texture":"36jcwcQoBPvIDnRdOG4m+v","rect":[0,688,750,202],"offset":[0,-221],"originalSize":[750,1136],"capInsets":[0,0,0,0]}}]
+1
View File
@@ -0,0 +1 @@
[[{"__type__":"cc.Prefab","_name":"gold","data":{"__id__":1}},{"__type__":"cc.Node","_name":"gold","_children":[{"__id__":2}],"_components":[{"__type__":"cc.Animation","node":{"__id__":1},"_defaultClip":{"__uuid__":"85IRS+CqFHTYODide6vyrq"},"_clips":[{"__uuid__":"85IRS+CqFHTYODide6vyrq"}],"playOnLoad":true}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"b5cGMd+lxKxpHLgiYsTt9S"},"fileId":"9bdaRKoCJLNIdqWE8A5a7h"},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[1416.544,2332.548,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"0000","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"e9Nhe+T+xAXa1abNJsJoyX"}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"b5cGMd+lxKxpHLgiYsTt9S"},"fileId":"f9NKIVagNF5bK3nJwM6v/M"},"_contentSize":{"__type__":"cc.Size","width":21,"height":59},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}}],{"__type__":"cc.SpriteFrame","content":{"name":"1","texture":"15981b4b0","rect":[3,782,21,59],"offset":[2.5,-0.5],"originalSize":[64,64],"capInsets":[0,0,0,0]}}]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.EffectAsset","_name":"builtin-2d-gray-sprite","techniques":[{"passes":[{"blendState":{"targets":[{"blend":true}]},"rasterizerState":{"cullMode":0},"properties":{"texture":{"value":"white","type":29}},"program":"builtin-2d-gray-sprite|vs|fs"}]}],"shaders":[{"hash":528178564,"glsl3":{"vert":"\nprecision highp float;\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nin vec3 a_position;\nin mediump vec2 a_uv0;\nout mediump vec2 v_uv0;\nin vec4 a_color;\nout vec4 v_color;\nvoid main () {\n gl_Position = cc_matViewProj * vec4(a_position, 1);\n v_uv0 = a_uv0;\n v_color = a_color;\n}","frag":"\nprecision highp float;\nuniform sampler2D texture;\nin mediump vec2 v_uv0;\nin vec4 v_color;\nvoid main () {\n vec4 color = v_color * texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n color.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n float gray = 0.2126*color.r + 0.7152*color.g + 0.0722*color.b;\n gl_FragColor = vec4(gray, gray, gray, color.a);\n}"},"glsl1":{"vert":"\nprecision highp float;\nuniform mediump mat4 cc_matViewProj;\nattribute vec3 a_position;\nattribute mediump vec2 a_uv0;\nvarying mediump vec2 v_uv0;\nattribute vec4 a_color;\nvarying vec4 v_color;\nvoid main () {\n gl_Position = cc_matViewProj * vec4(a_position, 1);\n v_uv0 = a_uv0;\n v_color = a_color;\n}","frag":"\nprecision highp float;\nuniform sampler2D texture;\nvarying mediump vec2 v_uv0;\nvarying vec4 v_color;\nvoid main () {\n vec4 color = v_color * texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n color.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n float gray = 0.2126*color.r + 0.7152*color.g + 0.0722*color.b;\n gl_FragColor = vec4(gray, gray, gray, color.a);\n}"},"builtins":{"globals":{"blocks":[{"name":"CCGlobal","defines":[]}],"samplers":[]},"locals":{"blocks":[],"samplers":[]}},"defines":[{"name":"CC_USE_ALPHA_ATLAS_TEXTURE","type":"boolean","defines":[]}],"blocks":[],"samplers":[{"name":"texture","type":29,"count":1,"defines":[],"binding":30}],"record":null,"name":"builtin-2d-gray-sprite|vs|fs"}]},{"__type__":"cc.Material","_name":"builtin-2d-gray-sprite","_effectAsset":{"__uuid__":"14TDKXr2NJ6LjvHPops74o"},"_techniqueData":{}}]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"load","texture":"13YMmjdw1NXYeJKZ8pT7lM","rect":[0,0,245,56],"offset":[0,0],"originalSize":[245,56],"capInsets":[0,0,0,0]}},[{"__type__":"cc.SceneAsset","_name":"login","scene":{"__id__":1},"asyncLoadAssets":{}},{"__type__":"cc.Scene","_name":"New Node","_children":[{"__id__":2}],"_active":false,"_anchorPoint":{"__type__":"cc.Vec2"},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]},"autoReleaseAssets":false},{"__type__":"cc.Node","_name":"Canvas","_parent":{"__id__":1},"_children":[{"__id__":3},{"__id__":4}],"_components":[{"__type__":"cc.Canvas","node":{"__id__":2},"_designResolution":{"__type__":"cc.Size","width":750,"height":1208},"_fitWidth":true,"_fitHeight":false},{"__type__":"66bbaA6YcZIEIXb21XqdH5P","node":{"__id__":2},"tipNode":{"__id__":7}},{"__type__":"1dc10z4Us9JI4+2VR28mFY9","node":{"__id__":2},"mainSp":{"__id__":6}},{"__type__":"cc.Widget","node":{"__id__":2},"_alignFlags":45}],"_contentSize":{"__type__":"cc.Size","width":750,"height":1208},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[375,604,0,0,0,0,1,1,1,1]},"_id":"7d07IDVM5MLpMFgMEZe86B"},{"__type__":"cc.Node","_name":"Main Camera","_parent":{"__id__":2},"_components":[{"__type__":"cc.Camera","node":{"__id__":3},"_clearFlags":7,"_depth":-1}],"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,263.46658375212047,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"UIRoot","_parent":{"__id__":2},"_children":[{"__id__":5},{"__id__":7},{"__id__":8},{"__id__":9}],"_components":[{"__type__":"cc.Mask","node":{"__id__":4},"_materials":[{"__uuid__":"ecpdLyjvZBwrvm+cedCcQy"}]}],"_contentSize":{"__type__":"cc.Size","width":750,"height":1208},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"loginBg","_parent":{"__id__":4},"_components":[{"__id__":6},{"__type__":"cc.Widget","node":{"__id__":5},"_alignFlags":1,"_originalWidth":750}],"_contentSize":{"__type__":"cc.Size","width":750,"height":1334},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-63,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Sprite","node":{"__id__":5},"_materials":[{"__uuid__":"ecpdLyjvZBwrvm+cedCcQy"}],"_spriteFrame":{"__uuid__":"eeuxeYwfxE6bGJU237k61c"},"_sizeMode":0},{"__type__":"cc.Node","_name":"load","_parent":{"__id__":4},"_active":false,"_components":[{"__type__":"cc.Sprite","node":{"__id__":7},"_spriteFrame":{"__uuid__":"16KYkhVOFHK4uofjau4gVB"}}],"_contentSize":{"__type__":"cc.Size","width":346,"height":56},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-308,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"contentLayer","_parent":{"__id__":4},"_components":[{"__type__":"cc.Widget","node":{"__id__":8},"_alignFlags":45}],"_contentSize":{"__type__":"cc.Size","width":750,"height":1208},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"maskLayer","_parent":{"__id__":4},"_active":false,"_components":[{"__type__":"cc.Widget","node":{"__id__":9},"_alignFlags":45},{"__type__":"cc.BlockInputEvents","node":{"__id__":9}}],"_contentSize":{"__type__":"cc.Size","width":750,"height":1125},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}}],{"__type__":"cc.SpriteFrame","content":{"name":"loginBg","texture":"dcCYcA1A5AfJrCzM5DxDKg","rect":[0,0,750,1334],"offset":[0,0],"originalSize":[750,1334],"capInsets":[0,0,0,0]}}]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"xian","texture":"0e7nrC+tpIcYPBKVMEv4tk","rect":[0,0,643,2],"offset":[0,0],"originalSize":[643,2],"capInsets":[0,0,0,0]}},[{"__type__":"cc.Prefab","_name":"pushItem","data":{"__id__":1}},{"__type__":"cc.Node","_name":"pushItem","_children":[{"__id__":2},{"__id__":3},{"__id__":4},{"__id__":5}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"aebvzm6axPdYSpc3laCXBJ"},"fileId":"73IA9thNNIwJ4sXEgR9Oam"},"_contentSize":{"__type__":"cc.Size","width":672,"height":62},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-31,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"xian","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"a0gjtKJ9NGUoLZEwxOBaRi"}},{"__type__":"cc.Widget","node":{"__id__":2},"_alignFlags":4}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"aebvzm6axPdYSpc3laCXBJ"},"fileId":"5bLPz/4KJCp5Euc9Q9kEoO"},"_contentSize":{"__type__":"cc.Size","width":643,"height":2},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-30,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"nickNameLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":3},"_useOriginalSize":false,"_string":"1234567890","_N$string":"1234567890","_fontSize":28,"_lineHeight":28,"_N$horizontalAlign":1,"_N$verticalAlign":1}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"aebvzm6axPdYSpc3laCXBJ"},"fileId":"26/d50dohP9ZJARurIhBq9"},"_contentSize":{"__type__":"cc.Size","width":155.72,"height":28},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[-216,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"timeLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":4},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":22,"_lineHeight":22.4,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$overflow":3}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"aebvzm6axPdYSpc3laCXBJ"},"fileId":"2aivbtqwtF7ZKgyi8a+VWv"},"_color":{"__type__":"cc.Color","r":255,"g":191,"b":117},"_contentSize":{"__type__":"cc.Size","width":140,"height":22},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[35,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"cashLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":5},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":28,"_lineHeight":28,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$overflow":3}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"aebvzm6axPdYSpc3laCXBJ"},"fileId":"73eGw8ASJFgI/Vg4sOhLd/"},"_color":{"__type__":"cc.Color","r":255,"g":234},"_contentSize":{"__type__":"cc.Size","width":140,"height":28},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[235,0,0,0,0,0,1,1,1,1]}}]]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y005","_native":".mp3"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
[{"__type__":"cc.Prefab","_name":"tlbb","data":{"__id__":1}},{"__type__":"cc.Node","_name":"tlbb","_children":[{"__id__":2}],"_components":[{"__type__":"cc.Animation","node":{"__id__":1},"_defaultClip":{"__uuid__":"91ai9aeJpNX4YeFh3GwbOy"},"_clips":[{"__uuid__":"91ai9aeJpNX4YeFh3GwbOy"}],"playOnLoad":true},{"__type__":"ff3139EpnVE75oc/u7Dooky","node":{"__id__":1}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"0bLnBve5BGI4Pq0Pad8epz"},"fileId":"18nVh0YdFGQLA3fHfZsV8R"},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"0000","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"0bLnBve5BGI4Pq0Pad8epz"},"fileId":"fbKEm4PX5H2aVaxg0gFaR1"},"_contentSize":{"__type__":"cc.Size","width":552,"height":606},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}}]
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y030","_native":".mp3"}
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
[[{"__type__":"cc.Prefab","_name":"tnsh","data":{"__id__":1}},{"__type__":"cc.Node","_name":"tnsh","_children":[{"__id__":2}],"_components":[{"__type__":"cc.Animation","node":{"__id__":1},"_defaultClip":{"__uuid__":"3cNlJYdIRKXrcxBpn5Valo"},"_clips":[{"__uuid__":"3cNlJYdIRKXrcxBpn5Valo"}],"playOnLoad":true},{"__type__":"ff3139EpnVE75oc/u7Dooky","node":{"__id__":1}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"0aneX6gddDq4OEM1flkI+w"},"fileId":"0eqx1vl71JKIhsSYJyHUU0"},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"0000","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"bbSOYKubZDy4aGELskiEup"}}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"0aneX6gddDq4OEM1flkI+w"},"fileId":"daduQr1AtIrqFUkRbWVuIX"},"_contentSize":{"__type__":"cc.Size","width":750,"height":1136},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,0,0,0,0,0,1,1,1,1]}}],{"__type__":"cc.SpriteFrame","content":{"name":"tnsh20001","texture":"58fnDcop5Cppvsl9V6U7pM","rect":[168,59,351,873],"offset":[-31.5,72.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}}]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"xian","texture":"0e7nrC+tpIcYPBKVMEv4tk","rect":[0,0,643,2],"offset":[0,0],"originalSize":[643,2],"capInsets":[0,0,0,0]}},[{"__type__":"cc.Prefab","_name":"getMoneyRecordItem","data":{"__id__":1}},{"__type__":"cc.Node","_name":"getMoneyRecordItem","_children":[{"__id__":2},{"__id__":3},{"__id__":4},{"__id__":5},{"__id__":6}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"dd7fghexZI0I/3f46qXxiy"},"fileId":"b0N5OPGmtBCJ16ogv6ZnTM"},"_contentSize":{"__type__":"cc.Size","width":672,"height":62},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-31,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"xian","_parent":{"__id__":1},"_components":[{"__type__":"cc.Sprite","node":{"__id__":2},"_spriteFrame":{"__uuid__":"a0gjtKJ9NGUoLZEwxOBaRi"}},{"__type__":"cc.Widget","node":{"__id__":2},"_alignFlags":4}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"dd7fghexZI0I/3f46qXxiy"},"fileId":"8egwqjnShF2rOF4vZ3xDHv"},"_contentSize":{"__type__":"cc.Size","width":643,"height":2},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[0,-30,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"orderLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":3},"_useOriginalSize":false,"_string":"1234567890","_N$string":"1234567890","_fontSize":28,"_lineHeight":28,"_N$horizontalAlign":1,"_N$verticalAlign":1}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"dd7fghexZI0I/3f46qXxiy"},"fileId":"99aADgyr1AmrAWud+c41OF"},"_contentSize":{"__type__":"cc.Size","width":155.72,"height":28},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[-245.6,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"timeLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":4},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":22,"_lineHeight":22.4,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$overflow":3}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"dd7fghexZI0I/3f46qXxiy"},"fileId":"40FmZT1sZARKqD+dJKJZGK"},"_color":{"__type__":"cc.Color","r":255,"g":191,"b":117},"_contentSize":{"__type__":"cc.Size","width":140,"height":22},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[-80,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"cashLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":5},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":28,"_lineHeight":28,"_N$horizontalAlign":1,"_N$verticalAlign":1,"_N$overflow":3}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"dd7fghexZI0I/3f46qXxiy"},"fileId":"b5XImwk5ROd4FCPJe9cGaL"},"_color":{"__type__":"cc.Color","r":255,"g":234},"_contentSize":{"__type__":"cc.Size","width":140,"height":28},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[88.1,0,0,0,0,0,1,1,1,1]}},{"__type__":"cc.Node","_name":"statusLabel","_parent":{"__id__":1},"_components":[{"__type__":"cc.Label","node":{"__id__":6},"_useOriginalSize":false,"_string":"Label","_N$string":"Label","_fontSize":26,"_lineHeight":26,"_N$horizontalAlign":1,"_N$verticalAlign":1}],"_prefab":{"__type__":"cc.PrefabInfo","root":{"__id__":1},"asset":{"__uuid__":"dd7fghexZI0I/3f46qXxiy"},"fileId":"f7VNwczgFK0qlRkDnxtOGH"},"_contentSize":{"__type__":"cc.Size","width":63.62,"height":26},"_trs":{"__type__":"TypedArray","ctor":"Float64Array","array":[270,0,0,0,0,0,1,1,1,1]}}]]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.EffectAsset","_name":"builtin-clear-stencil","techniques":[{"passes":[{"blendState":{"targets":[{"blend":true}]},"rasterizerState":{"cullMode":0},"program":"builtin-clear-stencil|vs|fs"}]}],"shaders":[{"hash":2075641479,"glsl3":{"vert":"\nprecision highp float;\nin vec3 a_position;\nvoid main () {\n gl_Position = vec4(a_position, 1);\n}","frag":"\nprecision highp float;\nvoid main () {\n gl_FragColor = vec4(1.0);\n}"},"glsl1":{"vert":"\nprecision highp float;\nattribute vec3 a_position;\nvoid main () {\n gl_Position = vec4(a_position, 1);\n}","frag":"\nprecision highp float;\nvoid main () {\n gl_FragColor = vec4(1.0);\n}"},"builtins":{"globals":{"blocks":[],"samplers":[]},"locals":{"blocks":[],"samplers":[]}},"defines":[],"blocks":[],"samplers":[],"record":null,"name":"builtin-clear-stencil|vs|fs"}]},{"__type__":"cc.Material","_name":"builtin-clear-stencil","_effectAsset":{"__uuid__":"c0BAyVxX9JzZy8EjFrc9DU"},"_techniqueData":{}}]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.EffectAsset","_name":"builtin-2d-spine","techniques":[{"passes":[{"blendState":{"targets":[{"blend":true}]},"rasterizerState":{"cullMode":0},"properties":{"texture":{"value":"white","type":29},"alphaThreshold":{"value":[0.5],"type":13}},"program":"builtin-2d-spine|vs|fs"}]}],"shaders":[{"hash":744594081,"glsl3":{"vert":"\nprecision highp float;\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\nin vec3 a_position;\nin vec4 a_color;\n#if USE_TINT\n in vec4 a_color0;\n#endif\nin vec2 a_uv0;\nout vec2 v_uv0;\nout vec4 v_light;\n#if USE_TINT\n out vec4 v_dark;\n#endif\nvoid main () {\n mat4 mvp;\n #if CC_USE_MODEL\n mvp = cc_matViewProj * cc_matWorld;\n #else\n mvp = cc_matViewProj;\n #endif\n v_uv0 = a_uv0;\n v_light = a_color;\n #if USE_TINT\n v_dark = a_color0;\n #endif\n gl_Position = mvp * vec4(a_position, 1);\n}","frag":"\nprecision highp float;\nuniform sampler2D texture;\nin vec2 v_uv0;\nin vec4 v_light;\n#if USE_TINT\n in vec4 v_dark;\n#endif\n#if USE_ALPHA_TEST\n uniform ALPHA_TEST {\n float alphaThreshold;\n };\n#endif\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\nvoid main () {\n vec4 texColor = texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n texColor.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n vec4 finalColor;\n #if USE_TINT\n finalColor.a = v_light.a * texColor.a;\n finalColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n #else\n finalColor = texColor * v_light;\n #endif\n ALPHA_TEST(finalColor);\n gl_FragColor = finalColor;\n}"},"glsl1":{"vert":"\nprecision highp float;\nuniform mediump mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\nattribute vec3 a_position;\nattribute vec4 a_color;\n#if USE_TINT\n attribute vec4 a_color0;\n#endif\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\nvarying vec4 v_light;\n#if USE_TINT\n varying vec4 v_dark;\n#endif\nvoid main () {\n mat4 mvp;\n #if CC_USE_MODEL\n mvp = cc_matViewProj * cc_matWorld;\n #else\n mvp = cc_matViewProj;\n #endif\n v_uv0 = a_uv0;\n v_light = a_color;\n #if USE_TINT\n v_dark = a_color0;\n #endif\n gl_Position = mvp * vec4(a_position, 1);\n}","frag":"\nprecision highp float;\nuniform sampler2D texture;\nvarying vec2 v_uv0;\nvarying vec4 v_light;\n#if USE_TINT\n varying vec4 v_dark;\n#endif\n#if USE_ALPHA_TEST\n uniform float alphaThreshold;\n#endif\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\nvoid main () {\n vec4 texColor = texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n texColor.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n vec4 finalColor;\n #if USE_TINT\n finalColor.a = v_light.a * texColor.a;\n finalColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;\n #else\n finalColor = texColor * v_light;\n #endif\n ALPHA_TEST(finalColor);\n gl_FragColor = finalColor;\n}"},"builtins":{"globals":{"blocks":[{"name":"CCGlobal","defines":[]}],"samplers":[]},"locals":{"blocks":[{"name":"CCLocal","defines":[]}],"samplers":[]}},"defines":[{"name":"USE_TINT","type":"boolean","defines":[]},{"name":"CC_USE_MODEL","type":"boolean","defines":[]},{"name":"USE_ALPHA_TEST","type":"boolean","defines":[]},{"name":"CC_USE_ALPHA_ATLAS_TEXTURE","type":"boolean","defines":[]}],"blocks":[{"name":"ALPHA_TEST","members":[{"name":"alphaThreshold","type":13,"count":1}],"defines":["USE_ALPHA_TEST"],"binding":0}],"samplers":[{"name":"texture","type":29,"count":1,"defines":[],"binding":30}],"record":null,"name":"builtin-2d-spine|vs|fs"}]},{"__type__":"cc.Material","_name":"builtin-2d-spine","_effectAsset":{"__uuid__":"0ek66qC1NOQLjgYmi04HvX"},"_techniqueData":{}}]
+1
View File
@@ -0,0 +1 @@
[{"__type__":"cc.SpriteFrame","content":{"name":"khc20013","texture":"1bLbmeNFdIuLCCxT8MhDFj","rect":[0,676,678,252],"offset":[-36,-234],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20017","texture":"3fa5RNzu1GFLQ4jRujdq+k","rect":[0,699,748,195],"offset":[-1,-228.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20001","texture":"36jcwcQoBPvIDnRdOG4m+v","rect":[0,688,750,202],"offset":[0,-221],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20015","texture":"1eloRR8fRJ47tXNJD2pX+8","rect":[0,686,689,221],"offset":[-30.5,-228.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.AnimationClip","_name":"khc","_duration":0.45,"speed":0.4,"curveData":{"paths":{"0000":{"comps":{"cc.Sprite":{"spriteFrame":[{"frame":0,"value":{"__uuid__":"343Xswmf9EB6p/wfv0tkXA"}},{"frame":0.016666666666666666,"value":{"__uuid__":"bcRgoCIW9NebJZaQGWhxpe"}},{"frame":0.03333333333333333,"value":{"__uuid__":"5ftuNM0lFHpYl9gT2hYRhG"}},{"frame":0.06666666666666667,"value":{"__uuid__":"6983YtNb5JgZrM1olS78cM"}},{"frame":0.08333333333333333,"value":{"__uuid__":"f7DisbVt5Ezr9XHrkJwzmj"}},{"frame":0.11666666666666667,"value":{"__uuid__":"cajhKxkBFNjr3g4F6IUFQe"}},{"frame":0.15,"value":{"__uuid__":"f4sO+g6K1OgYocHYMaSd9C"}},{"frame":0.16666666666666666,"value":{"__uuid__":"f7qDcGC41Gh6VLvlS+izzU"}},{"frame":0.2,"value":{"__uuid__":"ecfIKH1ZZA1pkpCRh2SmqG"}},{"frame":0.21666666666666667,"value":{"__uuid__":"ccclk0j0NF6bY84R5GM/sg"}},{"frame":0.23333333333333334,"value":{"__uuid__":"ccclk0j0NF6bY84R5GM/sg"}},{"frame":0.25,"value":{"__uuid__":"9e8VpU3nFDZqmxBhJGu4ci"}},{"frame":0.2833333333333333,"value":{"__uuid__":"6eqPQh8a5O/KI7O2Ct0kPO"}},{"frame":0.31666666666666665,"value":{"__uuid__":"25lQzFP5BMopkFmNn6X4Gs"}},{"frame":0.3333333333333333,"value":{"__uuid__":"b50xItZcpOJqjAhRsI5Yt+"}},{"frame":0.36666666666666664,"value":{"__uuid__":"35oobQEN1Hl6ZRLKlFn2p0"}},{"frame":0.4,"value":{"__uuid__":"ccS0TamGxNnoKHTRMkO4QP"}},{"frame":0.43333333333333335,"value":{"__uuid__":"32Y/RAAbFBHpUn0pJ5F5Pg"}}]}}}}}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20003","texture":"56w2MUI7ZGsIKtyUiueKa3","rect":[0,669,750,260],"offset":[0,-231],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20004","texture":"dfZpQvi3pCDI+EfoUj+Idj","rect":[0,669,750,260],"offset":[0,-231],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20012","texture":"ceRrMlfzJA3piQy1NXNuQc","rect":[0,673,673,259],"offset":[-38.5,-234.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20011","texture":"b7MndVvZZN2Zzy8AUKkgqB","rect":[0,666,667,261],"offset":[-41.5,-228.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20014","texture":"c5b7SbBdVCXqnVumfUBu/C","rect":[0,690,683,233],"offset":[-33.5,-238.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20002","texture":"d5eBYIKJFBhadL7ngr/KOc","rect":[0,675,750,220],"offset":[0,-217],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20006","texture":"14pmlileBDHp660Mp4iICN","rect":[0,665,748,266],"offset":[-1,-230],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20016","texture":"fbjEgUhP5CpIui1l2dZtjX","rect":[1,689,749,223],"offset":[0.5,-232.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20010","texture":"adBgR0q2NG5LHpMyoIDcLt","rect":[0,667,744,263],"offset":[-3,-230.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20009","texture":"a7QLjHIMdOi6qHj2Do0G2t","rect":[0,664,746,268],"offset":[-2,-230],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20007","texture":"62LKKnt9NAeqDtcu//ndZ2","rect":[0,665,746,267],"offset":[-2,-230.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20005","texture":"2fuiWXVVtFJIwVm+0U/2oM","rect":[0,668,750,261],"offset":[0,-230.5],"originalSize":[750,1136],"capInsets":[0,0,0,0]}},{"__type__":"cc.SpriteFrame","content":{"name":"khc20008","texture":"e66EcJsoZAcpvD46HBm70B","rect":[0,666,744,268],"offset":[-3,-232],"originalSize":[750,1136],"capInsets":[0,0,0,0]}}]
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y002","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y122","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y111","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y101","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y001","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y106","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y125","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y102","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.EffectAsset","_name":"builtin-2d-sprite","techniques":[{"passes":[{"blendState":{"targets":[{"blend":true}]},"rasterizerState":{"cullMode":0},"properties":{"texture":{"value":"white","type":29},"alphaThreshold":{"value":[0.5],"type":13}},"program":"builtin-2d-sprite|vs|fs"}]}],"shaders":[{"hash":4188224455,"glsl3":{"vert":"\nprecision highp float;\nuniform CCGlobal {\n highp vec4 cc_time;\n mediump vec4 cc_screenSize;\n mediump vec4 cc_screenScale;\n mediump vec4 cc_nativeSize;\n highp mat4 cc_matView;\n mediump mat4 cc_matViewInv;\n mediump mat4 cc_matProj;\n mediump mat4 cc_matProjInv;\n mediump mat4 cc_matViewProj;\n mediump mat4 cc_matViewProjInv;\n mediump vec4 cc_cameraPos;\n};\nuniform CCLocal {\n mat4 cc_matWorld;\n mat4 cc_matWorldIT;\n};\nin vec3 a_position;\nin vec4 a_color;\nout vec4 v_color;\n#if USE_TEXTURE\nin vec2 a_uv0;\nout vec2 v_uv0;\n#endif\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n v_color = a_color;\n gl_Position = pos;\n}","frag":"\nprecision highp float;\n#if USE_ALPHA_TEST\n uniform ALPHA_TEST {\n float alphaThreshold;\n };\n#endif\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\nin vec4 v_color;\n#if USE_TEXTURE\nin vec2 v_uv0;\nuniform sampler2D texture;\n#endif\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n #if USE_TEXTURE\n o *= texture(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n o *= v_color;\n ALPHA_TEST(o);\n gl_FragColor = o;\n}"},"glsl1":{"vert":"\nprecision highp float;\nuniform mediump mat4 cc_matViewProj;\nuniform mat4 cc_matWorld;\nattribute vec3 a_position;\nattribute vec4 a_color;\nvarying vec4 v_color;\n#if USE_TEXTURE\nattribute vec2 a_uv0;\nvarying vec2 v_uv0;\n#endif\nvoid main () {\n vec4 pos = vec4(a_position, 1);\n #if CC_USE_MODEL\n pos = cc_matViewProj * cc_matWorld * pos;\n #else\n pos = cc_matViewProj * pos;\n #endif\n #if USE_TEXTURE\n v_uv0 = a_uv0;\n #endif\n v_color = a_color;\n gl_Position = pos;\n}","frag":"\nprecision highp float;\n#if USE_ALPHA_TEST\n uniform float alphaThreshold;\n#endif\nvoid ALPHA_TEST (in vec4 color) {\n #if USE_ALPHA_TEST\n if (color.a < alphaThreshold) discard;\n #endif\n}\nvoid ALPHA_TEST (in float alpha) {\n #if USE_ALPHA_TEST\n if (alpha < alphaThreshold) discard;\n #endif\n}\nvarying vec4 v_color;\n#if USE_TEXTURE\nvarying vec2 v_uv0;\nuniform sampler2D texture;\n#endif\nvoid main () {\n vec4 o = vec4(1, 1, 1, 1);\n #if USE_TEXTURE\n o *= texture2D(texture, v_uv0);\n #if CC_USE_ALPHA_ATLAS_TEXTURE\n o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;\n #endif\n #endif\n o *= v_color;\n ALPHA_TEST(o);\n gl_FragColor = o;\n}"},"builtins":{"globals":{"blocks":[{"name":"CCGlobal","defines":[]}],"samplers":[]},"locals":{"blocks":[{"name":"CCLocal","defines":[]}],"samplers":[]}},"defines":[{"name":"USE_TEXTURE","type":"boolean","defines":[]},{"name":"CC_USE_MODEL","type":"boolean","defines":[]},{"name":"USE_ALPHA_TEST","type":"boolean","defines":[]},{"name":"CC_USE_ALPHA_ATLAS_TEXTURE","type":"boolean","defines":["USE_TEXTURE"]}],"blocks":[{"name":"ALPHA_TEST","members":[{"name":"alphaThreshold","type":13,"count":1}],"defines":["USE_ALPHA_TEST"],"binding":0}],"samplers":[{"name":"texture","type":29,"count":1,"defines":["USE_TEXTURE"],"binding":30}],"record":null,"name":"builtin-2d-sprite|vs|fs"}]}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y107","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"1","_native":".mp3"}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y115","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y206","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y016","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y210","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"2","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y009","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y207","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y004","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y203","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.SpriteFrame","content":{"name":"tlbb20021","texture":"54X6lXJAFKlJBxiv+9lN/J","rect":[35,244,621,372],"offset":[-29.5,138],"originalSize":[750,1136],"capInsets":[0,0,0,0]}}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y120","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y124","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y024","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y022","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y103","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y001-4","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y117","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"3","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y201","_native":".mp3"}
@@ -0,0 +1 @@
{"__type__":"cc.AudioClip","_name":"Y019","_native":".mp3"}

Some files were not shown because too many files have changed in this diff Show More