From aeffb8e4d4648609822cdd02fe97710b14f33751 Mon Sep 17 00:00:00 2001 From: lkddi Date: Sat, 28 Feb 2026 14:03:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=EF=BC=9A=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E9=9B=B6=E6=95=A3=E8=BF=81=E7=A7=BB=E6=96=87=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?36=E4=B8=AA=E7=AE=80=E5=8C=96=E4=B8=BA24=E4=B8=AA=E7=BA=AF?= =?UTF-8?q?=E5=BB=BA=E8=A1=A8=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - users 表:吸收 s_color类型变更/sign/question/answer/vip_level_id/has_received_new_gift - rooms 表:吸收 visit_num、announcement - sysparam 表:吸收全部 seed(99级经验/权限等级/钓鱼/魅力/排行榜,直接写最终值) - 新增 create_shop_tables(shop_items+user_purchases+username_blacklist+默认商品) - 新增 create_user_currency_logs_table(积分流水表含完整索引) - 删除 14 个已吸收的 add_column / seed 零散迁移 --- .../0001_01_01_000000_create_users_table.php | 116 ++++++++++++++++ .../0001_01_01_000001_create_cache_table.php | 35 +++++ .../0001_01_01_000002_create_jobs_table.php | 57 ++++++++ .../2026_02_26_040510_create_rooms_table.php | 44 ++++++ ...6_02_26_040521_create_audit_logs_table.php | 30 ++++ ...6_02_26_040521_create_guestbooks_table.php | 37 +++++ ...026_02_26_040521_create_ip_locks_table.php | 30 ++++ ...026_02_26_040521_create_messages_table.php | 35 +++++ ...2026_02_26_040522_create_actions_table.php | 32 +++++ ...6_02_26_040522_create_admin_logs_table.php | 48 +++++++ ...02_26_040522_create_friend_calls_table.php | 32 +++++ ...26_040522_create_friend_requests_table.php | 30 ++++ ...2026_02_26_040523_create_ip_logs_table.php | 30 ++++ ...26_02_26_040523_create_marriages_table.php | 33 +++++ ...040523_create_room_descriptions_table.php} | 11 +- ...6_02_26_040523_create_scroll_ads_table.php | 30 ++++ ...6_02_26_040523_create_user_items_table.php | 32 +++++ ...026_02_26_092923_create_sysparam_table.php | 82 +++++++++++ ...2026_02_26_094113_create_autoact_table.php | 73 ++++++++++ ...6_02_26_132014_create_vip_levels_table.php | 129 ++++++++++++++++++ .../2026_02_26_132600_create_ai_tables.php | 70 ++++++++++ .../2026_02_27_005300_create_gifts_table.php | 57 ++++++++ ...6_02_27_074855_create_shop_items_table.php | 44 ------ .../2026_02_27_074855_create_shop_tables.php | 86 ++++++++++++ ..._27_074855_create_user_purchases_table.php | 49 ------- ...074856_create_username_blacklist_table.php | 36 ----- ...123839_create_user_currency_logs_table.php | 58 ++++---- resources/views/admin/layouts/app.blade.php | 9 +- 28 files changed, 1186 insertions(+), 169 deletions(-) create mode 100644 database/migrations/0001_01_01_000000_create_users_table.php create mode 100644 database/migrations/0001_01_01_000001_create_cache_table.php create mode 100644 database/migrations/0001_01_01_000002_create_jobs_table.php create mode 100644 database/migrations/2026_02_26_040510_create_rooms_table.php create mode 100644 database/migrations/2026_02_26_040521_create_audit_logs_table.php create mode 100644 database/migrations/2026_02_26_040521_create_guestbooks_table.php create mode 100644 database/migrations/2026_02_26_040521_create_ip_locks_table.php create mode 100644 database/migrations/2026_02_26_040521_create_messages_table.php create mode 100644 database/migrations/2026_02_26_040522_create_actions_table.php create mode 100644 database/migrations/2026_02_26_040522_create_admin_logs_table.php create mode 100644 database/migrations/2026_02_26_040522_create_friend_calls_table.php create mode 100644 database/migrations/2026_02_26_040522_create_friend_requests_table.php create mode 100644 database/migrations/2026_02_26_040523_create_ip_logs_table.php create mode 100644 database/migrations/2026_02_26_040523_create_marriages_table.php rename database/migrations/{2026_02_27_091852_add_has_received_new_gift_to_users_table.php => 2026_02_26_040523_create_room_descriptions_table.php} (50%) create mode 100644 database/migrations/2026_02_26_040523_create_scroll_ads_table.php create mode 100644 database/migrations/2026_02_26_040523_create_user_items_table.php create mode 100644 database/migrations/2026_02_26_092923_create_sysparam_table.php create mode 100644 database/migrations/2026_02_26_094113_create_autoact_table.php create mode 100644 database/migrations/2026_02_26_132014_create_vip_levels_table.php create mode 100644 database/migrations/2026_02_26_132600_create_ai_tables.php create mode 100644 database/migrations/2026_02_27_005300_create_gifts_table.php delete mode 100644 database/migrations/2026_02_27_074855_create_shop_items_table.php create mode 100644 database/migrations/2026_02_27_074855_create_shop_tables.php delete mode 100644 database/migrations/2026_02_27_074855_create_user_purchases_table.php delete mode 100644 database/migrations/2026_02_27_074856_create_username_blacklist_table.php diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php new file mode 100644 index 0000000..66d346f --- /dev/null +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -0,0 +1,116 @@ +id(); + $table->string('username', 50)->unique()->comment('用户名'); + $table->string('password')->comment('密码 (MD5 or Bcrypt)'); + $table->string('email', 250)->nullable()->comment('邮箱'); + $table->string('question', 100)->nullable()->comment('密保问题'); + $table->string('answer', 100)->nullable()->comment('密保答案'); + $table->tinyInteger('sex')->default(0)->comment('性别 (0保密 1男 2女)'); + $table->string('sign', 255)->nullable()->comment('个性签名'); + $table->tinyInteger('user_level')->default(1)->comment('用户等级'); + $table->dateTime('log_time')->nullable()->comment('登录时间'); + $table->integer('visit_num')->default(0)->comment('访问次数'); + $table->dateTime('in_time')->nullable()->comment('进房时间'); + $table->tinyInteger('out_info')->default(0)->comment('退出信息'); + $table->dateTime('out_time')->nullable()->comment('退出时间'); + $table->integer('exp_num')->default(0)->index()->comment('经验值'); + $table->tinyInteger('f_size')->nullable()->comment('字体大小'); + $table->tinyInteger('l_height')->nullable()->comment('行高'); + $table->tinyInteger('n_color')->nullable()->comment('名称颜色'); + // s_color 直接以 varchar 存储 hex 颜色(如 #ff0000) + $table->string('s_color', 10)->nullable()->comment('发言颜色(hex,如 #ff0000)'); + $table->string('remand', 250)->nullable()->comment('密码提示问题'); + $table->string('bgcolor', 50)->nullable()->comment('背景颜色'); + $table->string('temppass', 20)->nullable()->comment('临时密码'); + $table->string('oicq', 30)->nullable()->comment('QQ号'); + $table->tinyInteger('saved')->nullable()->comment('是否保存'); + $table->string('first_ip', 50)->nullable()->comment('首次IP'); + $table->string('last_ip', 50)->nullable()->comment('最后IP'); + $table->string('aihaos', 250)->nullable()->comment('爱好'); + $table->string('friends', 250)->nullable()->comment('好友列表'); + $table->integer('headface')->nullable()->comment('头像'); + $table->integer('room_id')->default(0)->index()->comment('所在房间'); + $table->tinyInteger('auto_update')->nullable()->comment('自动刷新'); + $table->string('ppass', 50)->nullable()->comment('二级密码'); + $table->integer('jjb')->default(0)->comment('交友币/金币'); + $table->string('love', 50)->nullable()->comment('伴侣'); + $table->string('gzdw', 50)->nullable()->comment('工作单位'); + $table->integer('photo')->nullable()->comment('照片'); + $table->integer('hj')->default(0)->comment('呼叫状态'); + $table->string('djname', 50)->nullable()->comment('等级名称'); + $table->string('usersf', 50)->nullable()->comment('用户身份(头像图片名)'); + $table->integer('yh')->nullable()->comment('隐身状态'); + $table->text('userpassword')->nullable()->comment('备用密码'); + $table->string('huiyuan', 50)->nullable()->comment('会员组别'); + // VIP 会员等级 ID(关联 vip_levels 表) + $table->unsignedBigInteger('vip_level_id')->nullable()->comment('会员等级ID'); + $table->dateTime('hy_time')->nullable()->comment('会员到期时间'); + $table->string('tuijian', 50)->nullable()->comment('推荐人'); + $table->string('tuijian_ip', 50)->nullable()->comment('推荐IP'); + $table->string('xiaohai', 50)->nullable()->comment('小孩'); + $table->string('qingren', 50)->nullable()->comment('情人'); + $table->string('zhufang', 50)->nullable()->comment('住房'); + $table->string('zuoqiimg', 50)->nullable()->comment('坐骑图片'); + $table->string('zuoqi', 50)->nullable()->comment('坐骑名称'); + $table->integer('guanli')->nullable()->comment('管理员标记'); + $table->integer('meili')->nullable()->comment('魅力值'); + $table->integer('teshu')->nullable()->comment('特殊权限'); + $table->dateTime('xr_time')->nullable()->comment('仙人时间'); + $table->dateTime('yx_time')->nullable()->comment('英雄时间'); + $table->integer('q1')->nullable(); + $table->integer('q2')->nullable(); + $table->integer('q3')->nullable(); + $table->string('hua', 255)->nullable()->comment('鲜花'); + $table->dateTime('sj')->nullable()->comment('注册/更新时间'); + $table->string('pig', 255)->nullable()->comment('宠物'); + $table->text('qianming')->nullable()->comment('个性签名(旧字段)'); + $table->dateTime('q3_time')->nullable(); + // 新人礼包是否已领取(首次入场赠送 6666 金币) + $table->boolean('has_received_new_gift')->default(false)->comment('是否已领取新人礼包'); + + $table->rememberToken(); + $table->timestamps(); + + // VIP 外键(引用 vip_levels 表,vip_levels 在后续迁移中创建) + // 注意:外键在 create_vip_levels_table 之后才添加 + }); + + Schema::create('password_reset_tokens', function (Blueprint $table) { + $table->string('email')->primary(); + $table->string('token'); + $table->timestamp('created_at')->nullable(); + }); + + Schema::create('sessions', function (Blueprint $table) { + $table->string('id')->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->string('ip_address', 45)->nullable(); + $table->text('user_agent')->nullable(); + $table->longText('payload'); + $table->integer('last_activity')->index(); + }); + } + + /** + * 回滚:删除用户相关表 + */ + public function down(): void + { + Schema::dropIfExists('users'); + Schema::dropIfExists('password_reset_tokens'); + Schema::dropIfExists('sessions'); + } +}; diff --git a/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php new file mode 100644 index 0000000..ed758bd --- /dev/null +++ b/database/migrations/0001_01_01_000001_create_cache_table.php @@ -0,0 +1,35 @@ +string('key')->primary(); + $table->mediumText('value'); + $table->integer('expiration')->index(); + }); + + Schema::create('cache_locks', function (Blueprint $table) { + $table->string('key')->primary(); + $table->string('owner'); + $table->integer('expiration')->index(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('cache'); + Schema::dropIfExists('cache_locks'); + } +}; diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php new file mode 100644 index 0000000..425e705 --- /dev/null +++ b/database/migrations/0001_01_01_000002_create_jobs_table.php @@ -0,0 +1,57 @@ +id(); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + + Schema::create('job_batches', function (Blueprint $table) { + $table->string('id')->primary(); + $table->string('name'); + $table->integer('total_jobs'); + $table->integer('pending_jobs'); + $table->integer('failed_jobs'); + $table->longText('failed_job_ids'); + $table->mediumText('options')->nullable(); + $table->integer('cancelled_at')->nullable(); + $table->integer('created_at'); + $table->integer('finished_at')->nullable(); + }); + + Schema::create('failed_jobs', function (Blueprint $table) { + $table->id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jobs'); + Schema::dropIfExists('job_batches'); + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/database/migrations/2026_02_26_040510_create_rooms_table.php b/database/migrations/2026_02_26_040510_create_rooms_table.php new file mode 100644 index 0000000..55ea6a2 --- /dev/null +++ b/database/migrations/2026_02_26_040510_create_rooms_table.php @@ -0,0 +1,44 @@ +id(); + $table->string('room_name', 10)->unique()->comment('房间标识/名称'); + $table->string('room_auto', 10)->nullable()->comment('房间别名/自动属性'); + $table->string('room_owner', 10)->nullable()->comment('房主'); + $table->string('room_des', 250)->nullable()->comment('房间描述'); + $table->string('announcement', 500)->nullable()->comment('房间公告/祝福语(滚动显示)'); + $table->string('room_top', 100)->nullable()->comment('置顶信息'); + $table->string('room_title', 250)->nullable()->comment('房间标题'); + $table->tinyInteger('room_keep')->default(0)->comment('是否保留'); + $table->dateTime('room_time')->nullable()->comment('建立/最后时间'); + $table->tinyInteger('room_tt')->default(0)->comment('相关开关'); + $table->tinyInteger('room_html')->default(0)->comment('是否允许HTML'); + $table->integer('room_exp')->default(0)->comment('所需经验'); + $table->dateTime('build_time')->nullable()->comment('建立时间'); + $table->tinyInteger('permit_level')->default(1)->comment('允许进入的最低等级'); + $table->tinyInteger('door_open')->default(1)->comment('大门是否开启 (1开 0关)'); + $table->integer('ooooo')->nullable()->comment('未知/扩展属性'); + $table->unsignedBigInteger('visit_num')->default(0)->comment('房间人气(总访问人次)'); + $table->timestamps(); + }); + } + + /** + * 回滚:删除 rooms 表 + */ + public function down(): void + { + Schema::dropIfExists('rooms'); + } +}; diff --git a/database/migrations/2026_02_26_040521_create_audit_logs_table.php b/database/migrations/2026_02_26_040521_create_audit_logs_table.php new file mode 100644 index 0000000..6014241 --- /dev/null +++ b/database/migrations/2026_02_26_040521_create_audit_logs_table.php @@ -0,0 +1,30 @@ +id(); + $table->dateTime('occ_time')->nullable()->index()->comment('发生时间'); + $table->text('occ_env')->nullable()->comment('发生环境/详情'); + $table->tinyInteger('stype')->default(0)->comment('类别标识'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('audit_logs'); + } +}; diff --git a/database/migrations/2026_02_26_040521_create_guestbooks_table.php b/database/migrations/2026_02_26_040521_create_guestbooks_table.php new file mode 100644 index 0000000..45435d0 --- /dev/null +++ b/database/migrations/2026_02_26_040521_create_guestbooks_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('who', 50)->index()->comment('留言人'); + $table->string('towho', 50)->nullable()->index()->comment('给谁留言'); + $table->tinyInteger('secret')->default(0)->comment('是否悄悄话 (1是 0否)'); + $table->string('ip', 50)->nullable()->comment('留言者IP'); + $table->string('email', 250)->nullable()->comment('留言者邮箱'); + $table->string('web', 250)->nullable()->comment('留言者网站'); + $table->string('addr', 250)->nullable()->comment('留言者地址'); + $table->dateTime('post_time')->nullable()->index()->comment('留言时间'); + $table->string('text_title', 250)->nullable()->comment('留言标题'); + $table->text('text_body')->nullable()->comment('留言内容'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('guestbooks'); + } +}; diff --git a/database/migrations/2026_02_26_040521_create_ip_locks_table.php b/database/migrations/2026_02_26_040521_create_ip_locks_table.php new file mode 100644 index 0000000..2aa3677 --- /dev/null +++ b/database/migrations/2026_02_26_040521_create_ip_locks_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('ip', 20)->unique()->comment('封锁的IP'); + $table->dateTime('end_time')->nullable()->comment('封禁结束时间'); + $table->tinyInteger('act_level')->unsigned()->default(1)->comment('封禁级别'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('ip_locks'); + } +}; diff --git a/database/migrations/2026_02_26_040521_create_messages_table.php b/database/migrations/2026_02_26_040521_create_messages_table.php new file mode 100644 index 0000000..afecdea --- /dev/null +++ b/database/migrations/2026_02_26_040521_create_messages_table.php @@ -0,0 +1,35 @@ +id(); + $table->integer('room_id')->index()->comment('房间ID'); + $table->string('from_user', 50)->index()->comment('发送者'); + $table->string('to_user', 50)->nullable()->index()->comment('接收者'); + $table->text('content')->comment('消息内容'); + $table->tinyInteger('is_secret')->default(0)->comment('是否私聊'); + $table->string('font_color', 50)->nullable()->comment('字体颜色'); + $table->string('action', 50)->nullable()->comment('动作'); + $table->dateTime('sent_at')->useCurrent()->index()->comment('发送时间'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('messages'); + } +}; diff --git a/database/migrations/2026_02_26_040522_create_actions_table.php b/database/migrations/2026_02_26_040522_create_actions_table.php new file mode 100644 index 0000000..9dc2a5e --- /dev/null +++ b/database/migrations/2026_02_26_040522_create_actions_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('act_name', 50)->unique()->comment('动作名称'); + $table->string('alias', 50)->nullable()->comment('动作别名'); + $table->string('toall', 200)->nullable()->comment('对所有人表现'); + $table->string('toself', 200)->nullable()->comment('对自己的表现'); + $table->string('toother', 200)->nullable()->comment('对其他人的表现'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('actions'); + } +}; diff --git a/database/migrations/2026_02_26_040522_create_admin_logs_table.php b/database/migrations/2026_02_26_040522_create_admin_logs_table.php new file mode 100644 index 0000000..3db8006 --- /dev/null +++ b/database/migrations/2026_02_26_040522_create_admin_logs_table.php @@ -0,0 +1,48 @@ +id(); + $table->string('username', 50)->index()->comment('管理员账号'); + $table->integer('uu_level')->nullable()->comment('管理员等级'); + $table->dateTime('in_time')->nullable()->comment('进入时间'); + $table->integer('out_time')->nullable()->comment('离开时间'); + $table->text('caozuo')->nullable()->comment('操作详情'); + $table->integer('fs_sl')->default(0)->comment('封杀数量'); + $table->text('fs_name')->nullable()->comment('封杀名单'); + $table->integer('tr_sl')->default(0)->comment('踢人数量'); + $table->text('tr_name')->nullable()->comment('踢人名单'); + $table->integer('jg_sl')->default(0)->comment('警告数量'); + $table->text('jg_name')->nullable()->comment('警告名单'); + $table->integer('dj_sl')->default(0)->comment('冻结数量'); + $table->text('dj_name')->nullable()->comment('冻结名单'); + $table->integer('yjdj_sl')->default(0)->comment('永久冻结数量'); + $table->text('yjdj_name')->nullable()->comment('永久冻结名单'); + $table->integer('fip_sl')->default(0)->comment('封IP数量'); + $table->text('fip_name')->nullable()->comment('封IP名单'); + $table->integer('fjj_sl')->default(0)->comment('发奖金数量'); + $table->integer('fjy_sl')->default(0)->comment('发经验数量'); + $table->integer('flh_sl')->default(0)->comment('发老虎数量'); + $table->dateTime('jl_time')->nullable()->index()->comment('记录时间'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admin_logs'); + } +}; diff --git a/database/migrations/2026_02_26_040522_create_friend_calls_table.php b/database/migrations/2026_02_26_040522_create_friend_calls_table.php new file mode 100644 index 0000000..260495d --- /dev/null +++ b/database/migrations/2026_02_26_040522_create_friend_calls_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('who', 50)->index()->comment('呼叫人'); + $table->string('towho', 50)->index()->comment('被呼叫人'); + $table->text('callmess')->nullable()->comment('呼叫信息'); + $table->dateTime('calltime')->nullable()->index()->comment('呼叫时间'); + $table->tinyInteger('read')->default(0)->comment('是否已读 (1是 0否)'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('friend_calls'); + } +}; diff --git a/database/migrations/2026_02_26_040522_create_friend_requests_table.php b/database/migrations/2026_02_26_040522_create_friend_requests_table.php new file mode 100644 index 0000000..e40a1ec --- /dev/null +++ b/database/migrations/2026_02_26_040522_create_friend_requests_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('who', 50)->index()->comment('申请人'); + $table->string('towho', 50)->index()->comment('被申请人'); + $table->dateTime('sub_time')->nullable()->index()->comment('申请时间'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('friend_requests'); + } +}; diff --git a/database/migrations/2026_02_26_040523_create_ip_logs_table.php b/database/migrations/2026_02_26_040523_create_ip_logs_table.php new file mode 100644 index 0000000..1bf7b9d --- /dev/null +++ b/database/migrations/2026_02_26_040523_create_ip_logs_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('ip', 50)->index()->comment('登录IP'); + $table->dateTime('sdate')->nullable()->index()->comment('登录时间'); + $table->string('uuname', 50)->index()->comment('登录用户名'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('ip_logs'); + } +}; diff --git a/database/migrations/2026_02_26_040523_create_marriages_table.php b/database/migrations/2026_02_26_040523_create_marriages_table.php new file mode 100644 index 0000000..28d92e9 --- /dev/null +++ b/database/migrations/2026_02_26_040523_create_marriages_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('hyname', 50)->index()->comment('夫'); + $table->string('hyname1', 50)->index()->comment('妻'); + $table->dateTime('hytime')->nullable()->comment('结婚时间'); + $table->string('hygb', 50)->nullable()->comment('婚姻状态/广播'); + $table->string('hyjb', 50)->nullable()->comment('婚姻级别'); + $table->integer('i')->nullable()->comment('亲密度/属性'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('marriages'); + } +}; diff --git a/database/migrations/2026_02_27_091852_add_has_received_new_gift_to_users_table.php b/database/migrations/2026_02_26_040523_create_room_descriptions_table.php similarity index 50% rename from database/migrations/2026_02_27_091852_add_has_received_new_gift_to_users_table.php rename to database/migrations/2026_02_26_040523_create_room_descriptions_table.php index b3db8a9..7cf8477 100644 --- a/database/migrations/2026_02_27_091852_add_has_received_new_gift_to_users_table.php +++ b/database/migrations/2026_02_26_040523_create_room_descriptions_table.php @@ -11,8 +11,11 @@ return new class extends Migration */ public function up(): void { - Schema::table('users', function (Blueprint $table) { - $table->boolean('has_received_new_gift')->default(false)->after('id')->comment('是否已领取新人礼包'); + Schema::create('room_descriptions', function (Blueprint $table) { + $table->id(); + $table->string('alias', 10)->unique()->comment('房间别名关联'); + $table->string('describ', 254)->nullable()->comment('房间详细描述文本'); + $table->timestamps(); }); } @@ -21,8 +24,6 @@ return new class extends Migration */ public function down(): void { - Schema::table('users', function (Blueprint $table) { - $table->dropColumn('has_received_new_gift'); - }); + Schema::dropIfExists('room_descriptions'); } }; diff --git a/database/migrations/2026_02_26_040523_create_scroll_ads_table.php b/database/migrations/2026_02_26_040523_create_scroll_ads_table.php new file mode 100644 index 0000000..f4cf6b5 --- /dev/null +++ b/database/migrations/2026_02_26_040523_create_scroll_ads_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('ad_title', 250)->comment('广告/公告标题'); + $table->string('ad_link', 250)->nullable()->comment('链接地址'); + $table->tinyInteger('ad_new_flag')->default(0)->comment('新窗口打开标识 (1是 0否)'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('scroll_ads'); + } +}; diff --git a/database/migrations/2026_02_26_040523_create_user_items_table.php b/database/migrations/2026_02_26_040523_create_user_items_table.php new file mode 100644 index 0000000..f738d4f --- /dev/null +++ b/database/migrations/2026_02_26_040523_create_user_items_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('name', 50)->index()->comment('使用者'); + $table->dateTime('times')->nullable()->index()->comment('获得时间'); + $table->text('gg')->nullable()->comment('道具类型/说明'); + $table->integer('dayy')->nullable()->comment('道具天数/数量'); + $table->string('lx', 50)->nullable()->comment('道具种类'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('user_items'); + } +}; diff --git a/database/migrations/2026_02_26_092923_create_sysparam_table.php b/database/migrations/2026_02_26_092923_create_sysparam_table.php new file mode 100644 index 0000000..88033d8 --- /dev/null +++ b/database/migrations/2026_02_26_092923_create_sysparam_table.php @@ -0,0 +1,82 @@ +id(); + $table->string('alias', 100)->unique()->comment('参数别名(唯一标识)'); + $table->text('body')->nullable()->comment('参数值'); + $table->string('guidetxt', 500)->nullable()->comment('参数说明(后台显示)'); + $table->timestamps(); + }); + + // 生成 99 级经验阶梯(level^2.5 曲线,取整到十位) + $thresholds = []; + for ($level = 1; $level <= 99; $level++) { + $thresholds[] = (int) (ceil(10 * pow($level, 2.5) / 10) * 10); + } + $levelExpStr = implode(',', $thresholds); + + $now = now(); + + DB::table('sysparam')->insert([ + // ── 等级体系(99 级)──────────────────────────────────────── + ['alias' => 'levelexp', 'body' => $levelExpStr, 'guidetxt' => '等级经验阈值配置(逗号分隔,第N个=升到N级所需累计经验)', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'maxlevel', 'body' => '99', 'guidetxt' => '用户最高可达等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'superlevel', 'body' => '100', 'guidetxt' => '管理员级别(= 最高等级 + 1,拥有最高权限的等级阈值)', 'created_at' => $now, 'updated_at' => $now], + + // ── 心跳奖励 ────────────────────────────────────────────── + ['alias' => 'exp_per_heartbeat', 'body' => '1', 'guidetxt' => '⚡ 每次心跳经验奖励(支持固定值如"1"或范围如"1-10";0关闭)', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'jjb_per_heartbeat', 'body' => '1-3', 'guidetxt' => '💰 每次心跳金币奖励(支持固定值如"1"或范围如"1-5";0关闭)', 'created_at' => $now, 'updated_at' => $now], + + // ── 管理操作权限等级 ────────────────────────────────────── + ['alias' => 'level_warn', 'body' => '5', 'guidetxt' => '警告所需等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'level_mute', 'body' => '50', 'guidetxt' => '禁言所需等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'level_kick', 'body' => '60', 'guidetxt' => '踢人所需等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'level_announcement','body' => '60', 'guidetxt' => '设置公告所需等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'level_ban', 'body' => '80', 'guidetxt' => '封号所需等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'level_banip', 'body' => '90', 'guidetxt' => '封IP所需等级', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'level_freeze', 'body' => '14', 'guidetxt' => '冻结账号所需等级', 'created_at' => $now, 'updated_at' => $now], + + // ── 随机事件 ────────────────────────────────────────────── + ['alias' => 'auto_event_chance','body' => '10', 'guidetxt' => '随机事件触发概率(百分比,1-100)', 'created_at' => $now, 'updated_at' => $now], + + // ── 钓鱼系统 ────────────────────────────────────────────── + ['alias' => 'fishing_cost', 'body' => '5', 'guidetxt' => '每次钓鱼花费金币数量', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'fishing_cooldown', 'body' => '300', 'guidetxt' => '钓鱼冷却时间(秒,默认300=5分钟)', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'fishing_wait_min', 'body' => '8', 'guidetxt' => '钓鱼最短等待上钩时间(秒)', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'fishing_wait_max', 'body' => '15', 'guidetxt' => '钓鱼最长等待上钩时间(秒)', 'created_at' => $now, 'updated_at' => $now], + + // ── 魅力系统 ────────────────────────────────────────────── + ['alias' => 'charm_cross_sex', 'body' => '2', 'guidetxt' => '异性聊天每条消息增加的魅力值', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'charm_same_sex', 'body' => '1', 'guidetxt' => '同性聊天每条消息增加的魅力值', 'created_at' => $now, 'updated_at' => $now], + ['alias' => 'charm_hourly_limit','body' => '20', 'guidetxt' => '每小时通过聊天获取的魅力值上限(防刷屏)', 'created_at' => $now, 'updated_at' => $now], + + // ── 排行榜 ──────────────────────────────────────────────── + ['alias' => 'leaderboard_limit','body' => '20', 'guidetxt' => '🏆 排行榜每榜显示人数', 'created_at' => $now, 'updated_at' => $now], + ]); + } + + /** + * 回滚:删除 sysparam 表 + */ + public function down(): void + { + Schema::dropIfExists('sysparam'); + } +}; diff --git a/database/migrations/2026_02_26_094113_create_autoact_table.php b/database/migrations/2026_02_26_094113_create_autoact_table.php new file mode 100644 index 0000000..78df96e --- /dev/null +++ b/database/migrations/2026_02_26_094113_create_autoact_table.php @@ -0,0 +1,73 @@ +id(); + $table->string('text_body', 500)->comment('事件文本内容(支持变量替换)'); + $table->string('event_type', 20)->default('neutral')->comment('事件类型:good=好运, bad=坏运, neutral=中性'); + $table->integer('exp_change')->default(0)->comment('经验变化值(正=奖励, 负=惩罚)'); + $table->integer('jjb_change')->default(0)->comment('金币变化值(正=奖励, 负=惩罚)'); + $table->boolean('enabled')->default(true)->comment('是否启用'); + $table->timestamps(); + }); + + // 插入默认随机事件 + $events = [ + // 好运事件(奖励经验/金币) + ['text_body' => '🎉 恭喜【{username}】路遇仙人指点,获得 100 经验值!', 'event_type' => 'good', 'exp_change' => 100, 'jjb_change' => 0], + ['text_body' => '💰 【{username}】在路边捡到一袋金币,获得 500 金币!', 'event_type' => 'good', 'exp_change' => 0, 'jjb_change' => 500], + ['text_body' => '🌟 天降祥瑞!【{username}】获得 200 经验 + 200 金币!', 'event_type' => 'good', 'exp_change' => 200, 'jjb_change' => 200], + ['text_body' => '🎊 【{username}】参加武林大会获胜,奖励 300 经验!', 'event_type' => 'good', 'exp_change' => 300, 'jjb_change' => 0], + ['text_body' => '🏆 【{username}】完成了一个神秘任务,获得 150 金币!', 'event_type' => 'good', 'exp_change' => 0, 'jjb_change' => 150], + ['text_body' => '✨ 【{username}】领悟了一招绝学,经验暴增 500!', 'event_type' => 'good', 'exp_change' => 500, 'jjb_change' => 0], + ['text_body' => '🎁 系统随机赠送【{username}】100 金币,请查收!', 'event_type' => 'good', 'exp_change' => 0, 'jjb_change' => 100], + + // 坏运事件(扣除经验/金币) + ['text_body' => '💀 【{username}】不小心踩到陷阱,损失 50 经验!', 'event_type' => 'bad', 'exp_change' => -50, 'jjb_change' => 0], + ['text_body' => '😱 【{username}】遭遇山贼打劫,被抢走 100 金币!', 'event_type' => 'bad', 'exp_change' => 0, 'jjb_change' => -100], + ['text_body' => '🌧️ 【{username}】在雨中迷路,消耗 80 经验值。', 'event_type' => 'bad', 'exp_change' => -80, 'jjb_change' => 0], + ['text_body' => '🐍 【{username}】被毒蛇咬了一口,损失 30 经验和 50 金币!', 'event_type' => 'bad', 'exp_change' => -30, 'jjb_change' => -50], + + // 中性事件(纯文字,不奖惩) + ['text_body' => '🔮 星海小博士:【{username}】今天运势不错,继续加油!', 'event_type' => 'neutral', 'exp_change' => 0, 'jjb_change' => 0], + ['text_body' => '📜 星海小博士:有人说"坚持就是胜利",【{username}】觉得呢?', 'event_type' => 'neutral', 'exp_change' => 0, 'jjb_change' => 0], + ['text_body' => '🌈 星海小博士:【{username}】今天心情如何?记得多喝水哦!', 'event_type' => 'neutral', 'exp_change' => 0, 'jjb_change' => 0], + ['text_body' => '🎵 星海小博士:送给【{username}】一首歌,祝你天天开心!', 'event_type' => 'neutral', 'exp_change' => 0, 'jjb_change' => 0], + ]; + + $now = now(); + foreach ($events as &$event) { + $event['enabled'] = true; + $event['created_at'] = $now; + $event['updated_at'] = $now; + } + + DB::table('autoact')->insert($events); + } + + /** + * 回滚:删除 autoact 表 + */ + public function down(): void + { + Schema::dropIfExists('autoact'); + } +}; diff --git a/database/migrations/2026_02_26_132014_create_vip_levels_table.php b/database/migrations/2026_02_26_132014_create_vip_levels_table.php new file mode 100644 index 0000000..f9f64f4 --- /dev/null +++ b/database/migrations/2026_02_26_132014_create_vip_levels_table.php @@ -0,0 +1,129 @@ +id(); + $table->string('name', 50)->comment('会员名称(如:白银会员)'); + $table->string('icon', 20)->default('⭐')->comment('等级图标/emoji'); + $table->string('color', 10)->default('#f59e0b')->comment('等级颜色(hex)'); + $table->decimal('exp_multiplier', 3, 1)->default(1.0)->comment('经验倍率'); + $table->decimal('jjb_multiplier', 3, 1)->default(1.0)->comment('金币倍率'); + $table->text('join_templates')->nullable()->comment('进入聊天室专属欢迎语 JSON 数组'); + $table->text('leave_templates')->nullable()->comment('离开聊天室专属提示语 JSON 数组'); + $table->tinyInteger('sort_order')->default(0)->comment('排序(越大越高级)'); + $table->integer('price')->default(0)->comment('赞助金额(元,供展示参考)'); + $table->integer('duration_days')->default(30)->comment('有效天数(0=永久)'); + $table->timestamps(); + }); + + // 默认种子数据(后台可随时修改/删除/新增) + $now = now(); + DB::table('vip_levels')->insert([ + [ + 'name' => '白银会员', + 'icon' => '🥈', + 'color' => '#94a3b8', + 'exp_multiplier' => 1.5, + 'jjb_multiplier' => 1.2, + 'join_templates' => json_encode([ + '白银贵宾{username}乘坐银色马车缓缓驶入,气质不凡!', + '白银贵宾{username}手持银色令牌,大步流星走了进来!', + ], JSON_UNESCAPED_UNICODE), + 'leave_templates' => json_encode([ + '白银贵宾{username}挥了挥手,潇洒离去', + '白银贵宾{username}骑着银色骏马飘然而去', + ], JSON_UNESCAPED_UNICODE), + 'sort_order' => 1, + 'price' => 10, + 'duration_days' => 30, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'name' => '黄金会员', + 'icon' => '🥇', + 'color' => '#f59e0b', + 'exp_multiplier' => 2.0, + 'jjb_multiplier' => 1.5, + 'join_templates' => json_encode([ + '黄金贵宾{username}踩着金光闪闪的地毯,王者归来!', + '黄金贵宾{username}开着金色豪车呼啸而至,全场瞩目!', + ], JSON_UNESCAPED_UNICODE), + 'leave_templates' => json_encode([ + '黄金贵宾{username}乘金色祥云腾空而去,霸气侧漏!', + '黄金贵宾{username}微微拱手,金光一闪消失不见', + ], JSON_UNESCAPED_UNICODE), + 'sort_order' => 2, + 'price' => 30, + 'duration_days' => 30, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'name' => '钻石会员', + 'icon' => '💎', + 'color' => '#3b82f6', + 'exp_multiplier' => 3.0, + 'jjb_multiplier' => 2.0, + 'join_templates' => json_encode([ + '钻石贵宾{username}踏着星辰大海从天而降,万众敬仰!', + '钻石贵宾{username}驾驭钻石巨龙破空而来,威震四方!', + ], JSON_UNESCAPED_UNICODE), + 'leave_templates' => json_encode([ + '钻石贵宾{username}化作一道星光冲天而去,令人叹服!', + '钻石贵宾{username}乘坐钻石飞船消失在银河尽头', + ], JSON_UNESCAPED_UNICODE), + 'sort_order' => 3, + 'price' => 50, + 'duration_days' => 30, + 'created_at' => $now, + 'updated_at' => $now, + ], + [ + 'name' => '至尊会员', + 'icon' => '👑', + 'color' => '#a855f7', + 'exp_multiplier' => 5.0, + 'jjb_multiplier' => 3.0, + 'join_templates' => json_encode([ + '👑至尊{username}御驾亲临!九天雷鸣,万物俯首!众卿接驾!', + '👑至尊{username}脚踏七彩祥云,身披紫金龙袍,驾临此地!天地为之变色!', + ], JSON_UNESCAPED_UNICODE), + 'leave_templates' => json_encode([ + '👑至尊{username}龙袍一甩,紫气东来,瞬间消失在九天之上!', + '👑至尊{username}御驾回宫,百鸟齐鸣相送!', + ], JSON_UNESCAPED_UNICODE), + 'sort_order' => 4, + 'price' => 100, + 'duration_days' => 30, + 'created_at' => $now, + 'updated_at' => $now, + ], + ]); + } + + /** + * 回滚:删除 vip_levels 表 + */ + public function down(): void + { + Schema::dropIfExists('vip_levels'); + } +}; diff --git a/database/migrations/2026_02_26_132600_create_ai_tables.php b/database/migrations/2026_02_26_132600_create_ai_tables.php new file mode 100644 index 0000000..b917c85 --- /dev/null +++ b/database/migrations/2026_02_26_132600_create_ai_tables.php @@ -0,0 +1,70 @@ +id(); + $table->string('provider', 50)->index()->comment('厂商标识(如 deepseek, qwen, openai)'); + $table->string('name', 100)->comment('厂商显示名称'); + $table->text('api_key')->comment('API Key(加密存储)'); + $table->string('api_endpoint', 255)->comment('API 端点地址'); + $table->string('model', 100)->comment('使用的模型名称'); + $table->decimal('temperature', 3, 2)->default(0.30)->comment('温度参数'); + $table->integer('max_tokens')->default(2048)->comment('最大 Token 数'); + $table->boolean('is_enabled')->default(true)->index()->comment('是否启用'); + $table->boolean('is_default')->default(false)->comment('是否为默认厂商'); + $table->integer('sort_order')->default(0)->comment('排序(故障转移时按此顺序)'); + $table->timestamps(); + }); + + // AI 使用日志表 + Schema::create('ai_usage_logs', function (Blueprint $table) { + $table->id(); + $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete()->comment('使用者'); + $table->string('provider', 50)->comment('AI 厂商标识'); + $table->string('model', 100)->comment('使用的模型'); + $table->string('action', 50)->default('chatbot')->comment('操作类型'); + $table->integer('prompt_tokens')->default(0)->comment('输入 Token 数'); + $table->integer('completion_tokens')->default(0)->comment('输出 Token 数'); + $table->integer('total_tokens')->default(0)->comment('总 Token 数'); + $table->decimal('cost', 10, 6)->default(0)->comment('费用'); + $table->integer('response_time_ms')->default(0)->comment('响应时间(毫秒)'); + $table->boolean('success')->default(true)->comment('是否成功'); + $table->text('error_message')->nullable()->comment('错误信息'); + $table->timestamps(); + + // 索引 + $table->index(['provider', 'created_at']); + }); + } + + /** + * 回滚迁移:删除 AI 相关的两张数据表 + */ + public function down(): void + { + Schema::dropIfExists('ai_usage_logs'); + Schema::dropIfExists('ai_provider_configs'); + } +}; diff --git a/database/migrations/2026_02_27_005300_create_gifts_table.php b/database/migrations/2026_02_27_005300_create_gifts_table.php new file mode 100644 index 0000000..7230a0a --- /dev/null +++ b/database/migrations/2026_02_27_005300_create_gifts_table.php @@ -0,0 +1,57 @@ +id(); + $table->string('name', 50)->comment('礼物名称'); + $table->string('emoji', 10)->comment('显示图标/emoji'); + $table->string('image', 100)->nullable()->comment('礼物图片路径(相对 /images/gifts/)'); + $table->unsignedInteger('cost')->default(0)->comment('消耗金币数'); + $table->unsignedInteger('charm')->default(1)->comment('增加魅力值'); + $table->unsignedTinyInteger('sort_order')->default(0)->comment('排序(越小越靠前)'); + $table->boolean('is_active')->default(true)->comment('是否启用'); + $table->timestamps(); + }); + + // 填充默认鲜花数据(图片文件名与 sort_order 对应) + DB::table('gifts')->insert([ + ['name' => '小雏菊', 'emoji' => '🌼', 'image' => 'daisy.png', 'cost' => 5, 'charm' => 1, 'sort_order' => 1, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '玫瑰花', 'emoji' => '🌹', 'image' => 'rose.png', 'cost' => 10, 'charm' => 2, 'sort_order' => 2, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '向日葵', 'emoji' => '🌻', 'image' => 'sunflower.png', 'cost' => 20, 'charm' => 5, 'sort_order' => 3, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '樱花束', 'emoji' => '🌸', 'image' => 'sakura.png', 'cost' => 50, 'charm' => 12, 'sort_order' => 4, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '满天星', 'emoji' => '💐', 'image' => 'bouquet.png', 'cost' => 100, 'charm' => 30, 'sort_order' => 5, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '蓝色妖姬', 'emoji' => '🪻', 'image' => 'bluerose.png', 'cost' => 200, 'charm' => 66, 'sort_order' => 6, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '钻石花冠', 'emoji' => '👑', 'image' => 'crown.png', 'cost' => 520, 'charm' => 188, 'sort_order' => 7, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ]); + } + + /** + * 回滚:删除 gifts 表 + */ + public function down(): void + { + Schema::dropIfExists('gifts'); + } +}; diff --git a/database/migrations/2026_02_27_074855_create_shop_items_table.php b/database/migrations/2026_02_27_074855_create_shop_items_table.php deleted file mode 100644 index 6a00345..0000000 --- a/database/migrations/2026_02_27_074855_create_shop_items_table.php +++ /dev/null @@ -1,44 +0,0 @@ -id(); - $table->string('name', 50)->comment('商品名称'); - $table->string('slug', 50)->unique()->comment('商品唯一标识'); - $table->string('description', 255)->nullable()->comment('商品描述'); - $table->string('icon', 20)->default('🛍')->comment('商品图标 emoji'); - $table->unsignedInteger('price')->comment('价格(金币)'); - // type: instant=单次立即执行, duration=有时效, one_time=一次性道具 - $table->enum('type', ['instant', 'duration', 'one_time'])->comment('商品类型'); - $table->unsignedTinyInteger('duration_days')->nullable()->comment('有效天数(duration 类型用)'); - $table->unsignedTinyInteger('sort_order')->default(0)->comment('排序'); - $table->boolean('is_active')->default(true)->comment('是否上架'); - $table->timestamps(); - }); - } - - /** - * 回滚迁移:删除商品表 - */ - public function down(): void - { - Schema::dropIfExists('shop_items'); - } -}; diff --git a/database/migrations/2026_02_27_074855_create_shop_tables.php b/database/migrations/2026_02_27_074855_create_shop_tables.php new file mode 100644 index 0000000..5cfdf0d --- /dev/null +++ b/database/migrations/2026_02_27_074855_create_shop_tables.php @@ -0,0 +1,86 @@ +id(); + $table->string('name', 50)->comment('商品名称'); + $table->string('slug', 50)->unique()->comment('唯一标识(如 once_fireworks)'); + $table->string('description', 255)->nullable()->comment('商品描述'); + $table->string('icon', 20)->nullable()->comment('显示图标 emoji'); + $table->unsignedInteger('price')->default(0)->comment('金币价格'); + $table->string('type', 20)->default('instant')->comment('类型:instant=单次 / duration=周卡 / rename=改名'); + $table->unsignedTinyInteger('duration_days')->nullable()->comment('有效天数(duration 类型)'); + $table->unsignedTinyInteger('sort_order')->default(0)->comment('排序(越小越靠前)'); + $table->boolean('is_active')->default(true)->comment('是否上架'); + $table->timestamps(); + }); + + // 填充默认商品 + DB::table('shop_items')->insert([ + ['name' => '🎆 单次烟花', 'slug' => 'once_fireworks', 'description' => '全场燃放一次烟花特效', 'icon' => '🎆', 'price' => 888, 'type' => 'instant', 'duration_days' => null, 'sort_order' => 1, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '🌧️ 单次下雨', 'slug' => 'once_rain', 'description' => '全场下一次雨特效', 'icon' => '🌧️', 'price' => 888, 'type' => 'instant', 'duration_days' => null, 'sort_order' => 2, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '⚡ 单次雷电', 'slug' => 'once_lightning', 'description' => '全场一次雷电特效', 'icon' => '⚡', 'price' => 888, 'type' => 'instant', 'duration_days' => null, 'sort_order' => 3, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '❄️ 单次下雪', 'slug' => 'once_snow', 'description' => '全场下一次雪特效', 'icon' => '❄️', 'price' => 888, 'type' => 'instant', 'duration_days' => null, 'sort_order' => 4, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '🎆 烟花周卡', 'slug' => 'week_fireworks', 'description' => '7天内进房间自动放烟花', 'icon' => '🎆', 'price' => 8888, 'type' => 'duration', 'duration_days' => 7, 'sort_order' => 5, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '🌧️ 下雨周卡', 'slug' => 'week_rain', 'description' => '7天内进房间自动下雨', 'icon' => '🌧️', 'price' => 8888, 'type' => 'duration', 'duration_days' => 7, 'sort_order' => 6, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '⚡ 雷电周卡', 'slug' => 'week_lightning', 'description' => '7天内进房间自动雷电', 'icon' => '⚡', 'price' => 8888, 'type' => 'duration', 'duration_days' => 7, 'sort_order' => 7, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '❄️ 下雪周卡', 'slug' => 'week_snow', 'description' => '7天内进房间自动下雪', 'icon' => '❄️', 'price' => 8888, 'type' => 'duration', 'duration_days' => 7, 'sort_order' => 8, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ['name' => '✏️ 改名卡', 'slug' => 'rename_card', 'description' => '修改一次用户名(受黑名单限制)', 'icon' => '✏️', 'price' => 5000, 'type' => 'rename', 'duration_days' => null, 'sort_order' => 9, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()], + ]); + + // ── 购买记录表 ──────────────────────────────────────────────── + Schema::create('user_purchases', function (Blueprint $table) { + $table->id(); + $table->unsignedBigInteger('user_id')->index()->comment('购买用户 ID'); + $table->unsignedBigInteger('shop_item_id')->comment('商品 ID'); + $table->string('status', 20)->default('active')->comment('状态:active / used / expired'); + $table->unsignedInteger('price_paid')->default(0)->comment('实际支付金币数'); + $table->timestamp('expires_at')->nullable()->comment('过期时间(duration 类型有效)'); + $table->timestamp('used_at')->nullable()->comment('使用时间(instant 类型有效)'); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete(); + $table->foreign('shop_item_id')->references('id')->on('shop_items')->cascadeOnDelete(); + }); + + // ── 用户名黑名单表 ──────────────────────────────────────────── + Schema::create('username_blacklist', function (Blueprint $table) { + $table->id(); + $table->string('username', 50)->index()->comment('被保留的旧用户名'); + $table->timestamp('reserved_until')->nullable()->comment('保留截止时间(过期后可被注册)'); + $table->timestamp('created_at')->nullable()->comment('写入时间'); + }); + } + + /** + * 回滚:删除商店相关三张表 + */ + public function down(): void + { + Schema::dropIfExists('user_purchases'); + Schema::dropIfExists('shop_items'); + Schema::dropIfExists('username_blacklist'); + } +}; diff --git a/database/migrations/2026_02_27_074855_create_user_purchases_table.php b/database/migrations/2026_02_27_074855_create_user_purchases_table.php deleted file mode 100644 index 30c69dd..0000000 --- a/database/migrations/2026_02_27_074855_create_user_purchases_table.php +++ /dev/null @@ -1,49 +0,0 @@ -id(); - $table->unsignedBigInteger('user_id')->comment('购买用户 ID'); - $table->unsignedBigInteger('shop_item_id')->comment('商品 ID'); - // status: - // active = 有效中(周卡 / 改名卡未使用) - // expired = 已过期(周卡到期) - // used = 已使用(单次卡已播 / 改名卡已用) - // cancelled = 被新购买的周卡覆盖作废(金币不退) - $table->enum('status', ['active', 'expired', 'used', 'cancelled'])->default('active'); - $table->unsignedInteger('price_paid')->comment('购买时实际扣除金币'); - $table->timestamp('expires_at')->nullable()->comment('到期时间(duration 类型使用)'); - $table->timestamp('used_at')->nullable()->comment('使用时间(one_time/instant 使用)'); - $table->timestamps(); - - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - $table->foreign('shop_item_id')->references('id')->on('shop_items')->onDelete('cascade'); - $table->index(['user_id', 'status']); - }); - } - - /** - * 回滚迁移:删除购买记录表 - */ - public function down(): void - { - Schema::dropIfExists('user_purchases'); - } -}; diff --git a/database/migrations/2026_02_27_074856_create_username_blacklist_table.php b/database/migrations/2026_02_27_074856_create_username_blacklist_table.php deleted file mode 100644 index fcdd8c5..0000000 --- a/database/migrations/2026_02_27_074856_create_username_blacklist_table.php +++ /dev/null @@ -1,36 +0,0 @@ -id(); - $table->string('username', 20)->unique()->comment('被保留的旧用户名'); - $table->timestamp('reserved_until')->comment('保留到期时间(默认30天)'); - $table->timestamp('created_at')->nullable(); - }); - } - - /** - * 回滚迁移:删除黑名单表 - */ - public function down(): void - { - Schema::dropIfExists('username_blacklist'); - } -}; diff --git a/database/migrations/2026_02_28_123839_create_user_currency_logs_table.php b/database/migrations/2026_02_28_123839_create_user_currency_logs_table.php index 98a19bb..8e97a04 100644 --- a/database/migrations/2026_02_28_123839_create_user_currency_logs_table.php +++ b/database/migrations/2026_02_28_123839_create_user_currency_logs_table.php @@ -1,9 +1,8 @@ id(); - // 真实身份锚点:使用 user_id,即使用户改名历史记录仍可准确归属 - $table->unsignedBigInteger('user_id')->index()->comment('用户 ID(身份锚点,不随改名变化)'); + // 用户锚点:以 user_id 为不变标识,username 仅为当时的快照(用户可改名) + $table->unsignedBigInteger('user_id')->index()->comment('用户 ID(不变锚点)'); + $table->string('username', 50)->comment('用户名快照(记录时的名称)'); - // 写入时的用户名快照:仅用于日志可读性,排行榜展示取 users.username 当前值 - $table->string('username', 50)->comment('操作时刻用户名快照'); + // 货币类型:exp=经验 / gold=金币 / charm=魅力 + $table->string('currency', 10)->comment('货币类型(exp/gold/charm)'); - // 货币类型(对应 CurrencySource 枚举,varchar 允许未来无缝新增) - $table->string('currency', 20)->comment('货币类型: exp / gold / charm / 以后可自由扩展'); + // 变动量(正=增加,负=消耗) + $table->integer('amount')->comment('变动量(正数=增加,负数=消耗)'); - // 变更量(正数增加,负数扣除) - $table->integer('amount')->comment('变更量,正数为增加,负数为扣除'); + // 变动后的余额快照(便于追溯异常) + $table->integer('balance_after')->comment('变动后余额'); - // 变更后余额(方便对账,无需重算历史) - $table->integer('balance_after')->comment('变更后余额快照'); + // 来源标识(由 CurrencySource enum 管理,如 auto_save / fishing_gain / admin_adjust 等) + $table->string('source', 30)->index()->comment('来源(CurrencySource 枚举值)'); - // 来源活动(varchar 非 ENUM,新增活动无需改表,只在 CurrencySource 枚举加一行) - $table->string('source', 30)->comment('来源标识: auto_save / fishing_gain / send_gift / ...'); + // 备注(可选,附加上下文信息) + $table->string('remark', 200)->nullable()->comment('备注信息'); - // 备注(补充说明,如"送花给流星") - $table->string('remark', 255)->default('')->comment('操作备注'); + // 发生房间(可选) + $table->unsignedBigInteger('room_id')->nullable()->comment('操作所在房间ID'); - // 发生所在房间(部分操作无房间) - $table->unsignedInteger('room_id')->nullable()->comment('所在房间 ID,无则为 null'); + // 只记录创建时间,流水不允许更新 + $table->timestamp('created_at')->nullable()->index()->comment('记录时间'); - // 只记录创建时间,流水不可修改 - $table->timestamp('created_at')->useCurrent()->comment('记录时间'); + // 复合索引:高效支持今日排行榜查询(按日期+货币+用户汇总) + $table->index(['currency', 'created_at'], 'idx_currency_date'); - // ── 索引(按高频查询场景设计)──────────────────────────── - // 今日排行快速聚合:按货币类型 + 日期 + 金额 - $table->index(['currency', 'created_at', 'amount'], 'idx_daily_board'); + // 复合索引:高效支持用户个人日志查询 + $table->index(['user_id', 'currency', 'created_at'], 'idx_user_currency_date'); - // 用户个人流水查询:按 user_id + 货币类型 + 时间 - $table->index(['user_id', 'currency', 'created_at'], 'idx_user_log'); - - // 活动统计聚合:按来源 + 货币类型 + 日期 - $table->index(['source', 'currency', 'created_at'], 'idx_source_stat'); + // 复合索引:高效支持活动来源统计 + $table->index(['source', 'currency', 'created_at'], 'idx_source_currency_date'); }); } /** - * 回滚:删除流水表。 + * 回滚:删除流水表 */ public function down(): void { diff --git a/resources/views/admin/layouts/app.blade.php b/resources/views/admin/layouts/app.blade.php index 3b8dba2..7d7c9c8 100644 --- a/resources/views/admin/layouts/app.blade.php +++ b/resources/views/admin/layouts/app.blade.php @@ -22,6 +22,10 @@ class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.dashboard') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}"> 📊 仪表盘 + + 📈 积分流水统计 + @if (Auth::id() === 1) @@ -48,10 +52,7 @@ class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}"> 👑 VIP 会员等级 - - 📈 积分流水统计 - + @if (Auth::id() === 1)