功能:婚姻系统第4-6步(Services + Models)

Step 4 - MarriageConfigService:
- 带60min Cache 的配置读取/写入
- 支持单项/分组/全量读取,管理员保存后自动清缓存

Step 5 - MarriageIntimacyService:
- 亲密度增加 + 日志写入 + 等级自动更新
- Redis 每日上限计数器(各来源独立控制)
- onFlowerSent/onPrivateChat/onlineTick 接入点方法
- dailyBatch 批量处理(Horizon Job 用)

Step 6 - MarriageService(核心业务):
- propose/accept/reject/divorce/confirmDivorce/forceDissolve
- 所有金币魅力通过 UserCurrencyService 统一记账
- 冷静期检查/超时处理/强制离婚金币全转对方

Models 改良(Marriage/MarriageConfig/MarriageIntimacyLog)
This commit is contained in:
2026-03-01 15:03:34 +08:00
parent 11dcb03924
commit 2d07b032d9
10 changed files with 1039 additions and 16 deletions

View File

@@ -1,37 +1,43 @@
<?php
/**
* 文件功能:婚姻关系模型
* 文件功能:婚姻关系模型(改良版)
*
* 对应 ASP 文件hy / lh
* 对应 marriages 表,管理配对双方的婚姻状态、亲密度、等级及离婚信息。
* ASP 字段hyname/hyname1/hytime 等)保留向后兼容,新业务使用 user_id/partner_id。
*
* @author ChatRoom Laravel
* @author ChatRoom Laravel
*
* @version 1.0.0
* @version 2.0.0
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Marriage extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
/** @var list<string> */
protected $fillable = [
'hyname',
'hyname1',
'hytime',
'hygb',
'hyjb',
'i',
// 旧字段(兼容保留)
'hyname', 'hyname1', 'hytime', 'hygb', 'hyjb', 'i',
// 新字段
'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',
];
/**
* Get the attributes that should be cast.
* 字段类型转换。
*
* @return array<string, string>
*/
@@ -39,6 +45,128 @@ class Marriage extends Model
{
return [
'hytime' => 'datetime',
'proposed_at' => 'datetime',
'expires_at' => 'datetime',
'married_at' => 'datetime',
'divorced_at' => 'datetime',
'divorce_requested_at' => 'datetime',
'intimacy' => 'integer',
'level' => 'integer',
'online_minutes' => 'integer',
'flower_count' => 'integer',
'chat_count' => 'integer',
];
}
// ──────────────────────────── 关联关系 ────────────────────────────
/**
* 发起方用户。
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
/**
* 被求婚方用户。
*/
public function partner(): BelongsTo
{
return $this->belongsTo(User::class, 'partner_id');
}
/**
* 使用的戒指道具。
*/
public function ringItem(): BelongsTo
{
return $this->belongsTo(ShopItem::class, 'ring_item_id');
}
/**
* 亲密度变更日志。
*/
public function intimacyLogs(): HasMany
{
return $this->hasMany(MarriageIntimacyLog::class);
}
/**
* 婚礼仪式记录。
*/
public function ceremonies(): HasMany
{
return $this->hasMany(WeddingCeremony::class);
}
/**
* 最新一场婚礼。
*/
public function latestCeremony(): HasOne
{
return $this->hasOne(WeddingCeremony::class)->latestOfMany();
}
// ──────────────────────────── 查询 Scope ──────────────────────────
/**
* 仅返回已婚记录。
*/
public function scopeMarried(Builder $query): Builder
{
return $query->where('status', 'married');
}
/**
* 仅返回求婚中记录。
*/
public function scopePending(Builder $query): Builder
{
return $query->where('status', 'pending');
}
// ──────────────────────────── 业务方法 ────────────────────────────
/**
* 判断指定用户是否为婚姻一方。
*
* @param int $userId 用户 ID
*/
public function involves(int $userId): bool
{
return $this->user_id === $userId || $this->partner_id === $userId;
}
/**
* 判断两人是否已婚(静态工厂方法)。
*
* @param int $userA 用户A ID
* @param int $userB 用户B ID
*/
public static function areMárried(int $userA, int $userB): bool
{
return static::query()
->where('status', 'married')
->where(function (Builder $q) use ($userA, $userB) {
$q->where(fn ($q) => $q->where('user_id', $userA)->where('partner_id', $userB))
->orWhere(fn ($q) => $q->where('user_id', $userB)->where('partner_id', $userA));
})
->exists();
}
/**
* 获取用户当前有效婚姻pending married 状态)。
*
* @param int $userId 用户 ID
*/
public static function currentFor(int $userId): ?static
{
return static::query()
->whereIn('status', ['pending', 'married'])
->where(function (Builder $q) use ($userId) {
$q->where('user_id', $userId)->orWhere('partner_id', $userId);
})
->first();
}
}