功能:婚姻系统第1-3步(枚举/迁移/Seeder)

Step 1 - 枚举扩展:
- 新增 IntimacySource 枚举(7种亲密度来源)
- CurrencySource 追加7个婚姻相关来源

Step 2 - 数据库迁移(6张表):
- marriage_configs(约30条可配置参数)
- marriage_intimacy_logs(亲密度变更日志)
- wedding_tiers(5档婚礼配置)
- wedding_ceremonies(婚礼仪式记录)
- wedding_envelope_claims(红包领取记录)
- marriages 表改良(新增全部业务字段)
- users.frozen_jjb(定时婚礼金币冻结)
- shop_items.type 枚举添加 ring 类型

Step 3 - Seeder:
- 28条婚姻参数默认配置
- 5个婚礼档位
- 3种戒指道具(银/金/钻)
This commit is contained in:
2026-03-01 14:56:47 +08:00
parent 73badefcc5
commit 11dcb03924
10 changed files with 563 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
<?php
/**
* 文件功能:创建婚姻系统参数配置表 marriage_configs
*
* 键值对型配置表,存储所有婚姻系统的可调参数(魅力/亲密度/惩罚等)。
* 管理员可在后台「婚姻管理 参数配置」页面修改,不需要修改代码。
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建 marriage_configs 表。
*/
public function up(): void
{
Schema::create('marriage_configs', function (Blueprint $table) {
$table->id();
$table->string('group', 30)->index()->comment('配置分组(用于后台分组展示)');
$table->string('key', 60)->unique()->comment('配置键名(系统内部使用)');
$table->integer('value')->comment('配置值(均为整数)');
$table->string('label', 60)->comment('中文名称(后台显示)');
$table->string('description', 120)->nullable()->comment('说明(提示管理员含义)');
$table->integer('min')->nullable()->comment('允许最小值');
$table->integer('max')->nullable()->comment('允许最大值');
$table->timestamps();
});
}
/**
* 回滚:删除 marriage_configs 表。
*/
public function down(): void
{
Schema::dropIfExists('marriage_configs');
}
};

View File

@@ -0,0 +1,41 @@
<?php
/**
* 文件功能:创建婚姻亲密度日志表 marriage_intimacy_logs
*
* 记录婚姻亲密度的每一次变更,包括来源、变更量、变更后余额。
* 亲密度属于婚姻对(而非个人),独立于 user_currency_logs 存储。
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建 marriage_intimacy_logs 表。
*/
public function up(): void
{
Schema::create('marriage_intimacy_logs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('marriage_id')->index()->comment('所属婚姻记录 ID');
$table->integer('amount')->comment('变更量(正数增加,负数减少)');
$table->integer('balance_after')->comment('变更后亲密度总值');
$table->string('source', 50)->comment('来源(对应 IntimacySource 枚举值)');
$table->string('remark', 100)->nullable()->comment('备注说明');
$table->timestamp('created_at')->nullable()->comment('记录时间');
$table->foreign('marriage_id')->references('id')->on('marriages')->onDelete('cascade');
});
}
/**
* 回滚:删除亲密度日志表。
*/
public function down(): void
{
Schema::dropIfExists('marriage_intimacy_logs');
}
};

View File

@@ -0,0 +1,83 @@
<?php
/**
* 文件功能:改良 marriages 表,添加婚姻系统所需新字段
* 同时为 users 表添加 frozen_jjb定时婚礼金币冻结字段
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 执行迁移:改良 marriages 表,扩展 user_purchases.status新增 users.frozen_jjb。
*/
public function up(): void
{
// ── marriages 表:新增所有业务字段 ─────────────────────────
Schema::table('marriages', function (Blueprint $table) {
// 关联用户(将旧字符串字段升级为 FK
$table->unsignedBigInteger('user_id')->nullable()->after('id')->index()->comment('求婚发起方 user.id');
$table->unsignedBigInteger('partner_id')->nullable()->after('user_id')->index()->comment('被求婚方 user.id');
// 使用的戒指
$table->unsignedBigInteger('ring_item_id')->nullable()->after('partner_id')->comment('使用的戒指 shop_items.id');
$table->unsignedBigInteger('ring_purchase_id')->nullable()->after('ring_item_id')->comment('消耗的购买记录 user_purchases.id');
// 婚姻状态
$table->enum('status', ['pending', 'married', 'divorced', 'rejected', 'expired'])
->default('pending')->after('ring_purchase_id')->comment('婚姻状态');
// 关键时间节点
$table->timestamp('proposed_at')->nullable()->after('status')->comment('求婚时间');
$table->timestamp('expires_at')->nullable()->after('proposed_at')->comment('求婚48h后过期时间');
$table->timestamp('married_at')->nullable()->after('expires_at')->comment('结婚时间');
$table->timestamp('divorced_at')->nullable()->after('married_at')->comment('离婚时间');
// 离婚相关
$table->enum('divorce_type', ['mutual', 'forced', 'auto', 'admin'])
->nullable()->after('divorced_at')->comment('离婚类型');
$table->unsignedBigInteger('divorcer_id')->nullable()->after('divorce_type')->comment('强制离婚发起方 user.id');
$table->timestamp('divorce_requested_at')->nullable()->after('divorcer_id')->comment('协议离婚申请时间用于72h超时检测');
// 亲密度
$table->integer('intimacy')->default(0)->after('divorce_requested_at')->comment('当前亲密度积分');
$table->tinyInteger('level')->unsigned()->default(1)->after('intimacy')->comment('婚姻等级1-4');
// 统计字段
$table->integer('online_minutes')->default(0)->after('level')->comment('双方同时在线累计分钟数');
$table->integer('flower_count')->default(0)->after('online_minutes')->comment('相互送花累计次数');
$table->integer('chat_count')->default(0)->after('flower_count')->comment('私聊消息累计条数');
// 管理员备注
$table->string('admin_note', 200)->nullable()->after('chat_count')->comment('管理员操作备注');
});
// ── users 表:新增定时婚礼冻结金币字段 ──────────────────────
Schema::table('users', function (Blueprint $table) {
$table->integer('frozen_jjb')->default(0)->after('jjb')->comment('定时婚礼预冻结金币(待婚礼触发后正式扣除)');
});
}
/**
* 回滚:移除新增字段。
*/
public function down(): void
{
Schema::table('marriages', function (Blueprint $table) {
$table->dropColumn([
'user_id', 'partner_id', 'ring_item_id', 'ring_purchase_id',
'status', 'proposed_at', 'expires_at', 'married_at', 'divorced_at',
'divorce_type', 'divorcer_id', 'divorce_requested_at',
'intimacy', 'level', 'online_minutes', 'flower_count', 'chat_count',
'admin_note',
]);
});
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('frozen_jjb');
});
}
};

View File

@@ -0,0 +1,40 @@
<?php
/**
* 文件功能:创建婚礼档位配置表 wedding_tiers
*
* 固定5个档位存储普天同庆的金额/名称/描述。
* 管理员可在后台修改各档位的名称和金额,但不能增删档位。
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建 wedding_tiers 表。
*/
public function up(): void
{
Schema::create('wedding_tiers', function (Blueprint $table) {
$table->id();
$table->tinyInteger('tier')->unsigned()->unique()->comment('档位编号1-5固定');
$table->string('name', 30)->comment('档位名称(可改,如:小小祝福)');
$table->string('icon', 20)->comment('档位图标(如:⭐⭐⭐)');
$table->integer('amount')->comment('该档位总金币数');
$table->string('description', 100)->nullable()->comment('前台展示描述');
$table->boolean('is_active')->default(true)->comment('是否启用(关闭则前台不显示该档位)');
$table->timestamps();
});
}
/**
* 回滚:删除婚礼档位表。
*/
public function down(): void
{
Schema::dropIfExists('wedding_tiers');
}
};

View File

@@ -0,0 +1,51 @@
<?php
/**
* 文件功能:创建婚礼仪式记录表 wedding_ceremonies
*
* 记录每一场婚礼的档位、支付方式、举办时间及红包分发情况。
* 一段婚姻最多同时有一场 pending/active 状态的婚礼。
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建 wedding_ceremonies 表。
*/
public function up(): void
{
Schema::create('wedding_ceremonies', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('marriage_id')->index()->comment('关联婚姻 ID');
$table->unsignedBigInteger('tier_id')->nullable()->index()->comment('关联婚礼档位 IDNULL=不举办红包)');
// 快照金额:防止档位金额被修改后影响历史记录
$table->integer('total_amount')->default(0)->comment('婚礼红包总金额(快照值)');
$table->enum('payer_type', ['groom', 'joint'])->comment('支付方式groom=男方全付joint=双方各半');
$table->integer('groom_amount')->default(0)->comment('男方实际扣除金额');
$table->integer('partner_amount')->default(0)->comment('女方实际扣除金额joint时各半');
$table->enum('ceremony_type', ['immediate', 'scheduled'])->comment('婚礼类型immediate=立即scheduled=定时');
$table->timestamp('ceremony_at')->nullable()->comment('实际或计划举办时间');
$table->enum('status', ['pending', 'active', 'completed', 'cancelled', 'expired'])
->default('pending')->comment('婚礼状态');
$table->integer('online_count')->nullable()->comment('触发时在线用户数(分发后记录)');
$table->integer('claimed_count')->default(0)->comment('已领取人数');
$table->integer('claimed_amount')->default(0)->comment('已领取金额合计');
$table->timestamp('expires_at')->nullable()->comment('红包领取截止时间24h后过期');
$table->timestamps();
$table->foreign('marriage_id')->references('id')->on('marriages')->onDelete('cascade');
});
}
/**
* 回滚:删除婚礼仪式表。
*/
public function down(): void
{
Schema::dropIfExists('wedding_ceremonies');
}
};

View File

@@ -0,0 +1,43 @@
<?php
/**
* 文件功能:创建婚礼红包领取记录表 wedding_envelope_claims
*
* 婚礼触发时,给当时所有在线用户预分配随机金额并写入此表。
* 用户点击领取后标记 claimed=true24h 后未领取的自动过期。
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* 创建 wedding_envelope_claims 表。
*/
public function up(): void
{
Schema::create('wedding_envelope_claims', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('ceremony_id')->index()->comment('关联婚礼仪式 ID');
$table->unsignedBigInteger('user_id')->index()->comment('领取用户 ID');
$table->integer('amount')->comment('预分配金额(随机红包算法计算)');
$table->boolean('claimed')->default(false)->index()->comment('是否已领取');
$table->timestamp('claimed_at')->nullable()->comment('领取时间');
$table->timestamp('created_at')->nullable()->comment('分配时间');
$table->unique(['ceremony_id', 'user_id'], 'unique_ceremony_user');
$table->foreign('ceremony_id')->references('id')->on('wedding_ceremonies')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
/**
* 回滚:删除红包领取记录表。
*/
public function down(): void
{
Schema::dropIfExists('wedding_envelope_claims');
}
};

View File

@@ -0,0 +1,31 @@
<?php
/**
* 文件功能:为 shop_items.type 枚举添加 ring戒指类型
*
* 戒指道具是婚姻系统专用的一次性消耗品,与普通 one_time 类型语义不同,
* 单独用 ring 类型区分,方便后续过滤查询。
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* type 枚举新增 ring 值。
*/
public function up(): void
{
DB::statement("ALTER TABLE `shop_items` MODIFY `type` ENUM('instant','duration','one_time','ring') NOT NULL COMMENT '道具类型'");
}
/**
* 回滚:删除 ring 枚举值(先将已有 ring 类型记录改为 one_time 以防报错)。
*/
public function down(): void
{
DB::statement("UPDATE `shop_items` SET `type` = 'one_time' WHERE `type` = 'ring'");
DB::statement("ALTER TABLE `shop_items` MODIFY `type` ENUM('instant','duration','one_time') NOT NULL COMMENT '道具类型'");
}
};

View File

@@ -0,0 +1,149 @@
<?php
/**
* 文件功能:婚姻系统初始数据 Seeder
*
* 写入以下默认数据:
* 1. marriage_configs 约30条可配置参数亲密度/魅力/离婚/时间规则)
* 2. wedding_tiers 5个婚礼档位
* 3. shop_items 3种戒指道具ring_silver/ring_gold/ring_diamond
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class MarriageSystemSeeder extends Seeder
{
/**
* 写入婚姻系统初始配置数据。
*/
public function run(): void
{
$now = Carbon::now();
// ── 1. marriage_configs ──────────────────────────────────────
$configs = [
// 【亲密度加分规则】
['group' => '亲密度加分', 'key' => 'intimacy_daily_time', 'value' => 10, 'label' => '每日时间奖励', 'description' => '每天00:00给所有婚姻对各加的亲密度', 'min' => 1, 'max' => 100],
['group' => '亲密度加分', 'key' => 'intimacy_online_per_min', 'value' => 1, 'label' => '同时在线(每分钟)', 'description' => '双方同时在线每分钟增加的亲密度', 'min' => 0, 'max' => 10],
['group' => '亲密度加分', 'key' => 'intimacy_online_daily_cap', 'value' => 120, 'label' => '同时在线每日上限', 'description' => '每日因同时在线最多可得亲密度约2小时', 'min' => 0, 'max' => 1440],
['group' => '亲密度加分', 'key' => 'intimacy_recv_flower', 'value' => 2, 'label' => '收到伴侣送花(每朵)', 'description' => '收到伴侣送花时每朵花增加的亲密度', 'min' => 0, 'max' => 20],
['group' => '亲密度加分', 'key' => 'intimacy_recv_flower_cap', 'value' => 40, 'label' => '收花每日上限', 'description' => '每日因收花最多可得亲密度', 'min' => 0, 'max' => 500],
['group' => '亲密度加分', 'key' => 'intimacy_send_flower', 'value' => 1, 'label' => '向伴侣送花(每朵)', 'description' => '向伴侣送花时每朵花增加的亲密度(送方)', 'min' => 0, 'max' => 10],
['group' => '亲密度加分', 'key' => 'intimacy_send_flower_cap', 'value' => 20, 'label' => '送花每日上限', 'description' => '每日因送花最多可得亲密度', 'min' => 0, 'max' => 200],
['group' => '亲密度加分', 'key' => 'intimacy_private_chat', 'value' => 1, 'label' => '私聊加分', 'description' => '每2条私信获得1亲密度', 'min' => 0, 'max' => 10],
['group' => '亲密度加分', 'key' => 'intimacy_private_chat_cap', 'value' => 10, 'label' => '私聊每日上限', 'description' => '每日因私聊最多可得亲密度', 'min' => 0, 'max' => 100],
// 【戒指魅力加成与初始亲密度】
['group' => '戒指参数', 'key' => 'ring_silver_charm', 'value' => 50, 'label' => '银戒指魅力加成', 'description' => '双方各获得的魅力值(结婚时一次性)', 'min' => 0, 'max' => 9999],
['group' => '戒指参数', 'key' => 'ring_gold_charm', 'value' => 150, 'label' => '金戒指魅力加成', 'description' => '双方各获得的魅力值(结婚时一次性)', 'min' => 0, 'max' => 9999],
['group' => '戒指参数', 'key' => 'ring_diamond_charm', 'value' => 500, 'label' => '钻戒魅力加成', 'description' => '双方各获得的魅力值(结婚时一次性)', 'min' => 0, 'max' => 99999],
['group' => '戒指参数', 'key' => 'ring_silver_intimacy', 'value' => 10, 'label' => '银戒指初始亲密度', 'description' => '结婚时一次性赠予的亲密度(银戒)', 'min' => 0, 'max' => 500],
['group' => '戒指参数', 'key' => 'ring_gold_intimacy', 'value' => 30, 'label' => '金戒指初始亲密度', 'description' => '结婚时一次性赠予的亲密度(金戒)', 'min' => 0, 'max' => 500],
['group' => '戒指参数', 'key' => 'ring_diamond_intimacy', 'value' => 80, 'label' => '钻戒初始亲密度', 'description' => '结婚时一次性赠予的亲密度(钻戒)', 'min' => 0, 'max' => 1000],
// 【婚姻等级阈值】
['group' => '婚姻等级', 'key' => 'level2_threshold', 'value' => 200, 'label' => '等级2恩爱夫妻阈值', 'description' => '达到此亲密度后升至等级2', 'min' => 1, 'max' => 9999],
['group' => '婚姻等级', 'key' => 'level3_threshold', 'value' => 600, 'label' => '等级3情深意重阈值', 'description' => '达到此亲密度后升至等级3', 'min' => 1, 'max' => 9999],
['group' => '婚姻等级', 'key' => 'level4_threshold', 'value' => 1500, 'label' => '等级4白头偕老阈值', 'description' => '达到此亲密度后升至等级4', 'min' => 1, 'max' => 99999],
// 【离婚惩罚】
['group' => '离婚惩罚', 'key' => 'divorce_mutual_charm', 'value' => 100, 'label' => '协议离婚魅力惩罚', 'description' => '双方各扣减魅力(填正数,系统取负)', 'min' => 0, 'max' => 9999],
['group' => '离婚惩罚', 'key' => 'divorce_forced_charm', 'value' => 300, 'label' => '强制离婚魅力惩罚', 'description' => '强制方扣减魅力', 'min' => 0, 'max' => 9999],
['group' => '离婚惩罚', 'key' => 'divorce_auto_charm', 'value' => 150, 'label' => '超时自动离婚惩罚', 'description' => '发起方扣减魅力72h无响应自动解除', 'min' => 0, 'max' => 9999],
['group' => '离婚惩罚', 'key' => 'divorce_mutual_cooldown', 'value' => 70, 'label' => '协议离婚冷静期(天)', 'description' => '协议离婚后多少天内不可再次结婚', 'min' => 0, 'max' => 365],
['group' => '离婚惩罚', 'key' => 'divorce_forced_cooldown', 'value' => 90, 'label' => '强制离婚冷静期(天)', 'description' => '强制方多少天内不可再次结婚', 'min' => 0, 'max' => 365],
['group' => '离婚惩罚', 'key' => 'divorce_auto_cooldown', 'value' => 30, 'label' => '超时自动离婚冷静期', 'description' => '发起方多少天内不可再次结婚', 'min' => 0, 'max' => 365],
['group' => '离婚惩罚', 'key' => 'forced_divorce_limit_days', 'value' => 60, 'label' => '强制离婚间隔(天)', 'description' => '多少天内只能使用强制离婚1次', 'min' => 1, 'max' => 365],
// 【时间规则】
['group' => '时间规则', 'key' => 'proposal_expire_hours', 'value' => 48, 'label' => '求婚有效期(小时)', 'description' => '超时后戒指消失、求婚作废', 'min' => 1, 'max' => 168],
['group' => '时间规则', 'key' => 'divorce_request_timeout', 'value' => 72, 'label' => '离婚申请等待时长(小时)', 'description' => '协议离婚后对方多久不响应则自动升级为强制', 'min' => 1, 'max' => 168],
['group' => '时间规则', 'key' => 'envelope_expire_hours', 'value' => 24, 'label' => '婚礼红包有效期(小时)', 'description' => '超时未领取的红包自动消失(不退还)', 'min' => 1, 'max' => 72],
];
foreach ($configs as &$row) {
$row['created_at'] = $now;
$row['updated_at'] = $now;
}
unset($row);
DB::table('marriage_configs')->upsert($configs, ['key'], ['value', 'label', 'description', 'min', 'max', 'updated_at']);
// ── 2. wedding_tiers ─────────────────────────────────────────
$tiers = [
['tier' => 1, 'name' => '小小祝福', 'icon' => '⭐', 'amount' => 5888, 'description' => '小小心意,愿新人幸福美满!', 'is_active' => true],
['tier' => 2, 'name' => '甜蜜相拥', 'icon' => '⭐⭐', 'amount' => 28888, 'description' => '诚意满满,共享甜蜜时光!', 'is_active' => true],
['tier' => 3, 'name' => '盛世婚礼', 'icon' => '⭐⭐⭐', 'amount' => 68888, 'description' => '盛世婚宴,全场同贺!', 'is_active' => true],
['tier' => 4, 'name' => '豪华盛典', 'icon' => '⭐⭐⭐⭐', 'amount' => 128888, 'description' => '贵族婚礼,普天同庆,豪气冲天!', 'is_active' => true],
['tier' => 5, 'name' => '传世佳话', 'icon' => '⭐⭐⭐⭐⭐', 'amount' => 288888, 'description' => '传说级婚礼,流芳百世,共见证!', 'is_active' => true],
];
foreach ($tiers as &$t) {
$t['created_at'] = $now;
$t['updated_at'] = $now;
}
unset($t);
DB::table('wedding_tiers')->upsert($tiers, ['tier'], ['name', 'icon', 'amount', 'description', 'is_active', 'updated_at']);
// ── 3. shop_items — 三种戒指 ─────────────────────────────────
// 先查询 shop_items 的当前最大 sort_order
$maxSort = DB::table('shop_items')->max('sort_order') ?? 0;
$rings = [
[
'name' => '银戒指',
'slug' => 'ring_silver',
'icon' => '💍',
'description' => '用银戒指求婚,表达心意。结婚时双方各获 +50 魅力,初始亲密度 +10。',
'price' => 3888,
'type' => 'ring',
'duration_days' => null,
'is_active' => true,
'sort_order' => $maxSort + 1,
],
[
'name' => '金戒指',
'slug' => 'ring_gold',
'icon' => '💎',
'description' => '用金戒指求婚,彰显诚意。结婚时双方各获 +150 魅力,初始亲密度 +30。',
'price' => 12888,
'type' => 'ring',
'duration_days' => null,
'is_active' => true,
'sort_order' => $maxSort + 2,
],
[
'name' => '钻戒',
'slug' => 'ring_diamond',
'icon' => '👑',
'description' => '顶级钻戒,永结同心!结婚时双方各获 +500 魅力,初始亲密度 +80。',
'price' => 38888,
'type' => 'ring',
'duration_days' => null,
'is_active' => true,
'sort_order' => $maxSort + 3,
],
];
foreach ($rings as &$r) {
$r['created_at'] = $now;
$r['updated_at'] = $now;
}
unset($r);
DB::table('shop_items')->upsert($rings, ['slug'], [
'name', 'icon', 'description', 'price', 'type', 'duration_days', 'is_active', 'sort_order', 'updated_at',
]);
$this->command->info('✅ 婚姻系统初始数据写入完成:'.count($configs).' 条配置 + 5 个婚礼档位 + 3 种戒指');
}
}