冻结功能实现完成.md 5.7 KB

GameItem模块 - 物品冻结功能实现完成

实现概述

物品冻结功能已成功实现,支持统一属性物品和单独属性物品的冻结/解冻操作,采用拆堆模式确保数据一致性。

已实现的功能

1. 核心数据结构

1.1 枚举类型

  • FREEZE_ACTION_TYPE: 冻结操作类型枚举(冻结/解冻)
  • FREEZE_REASON_TYPE: 冻结原因类型枚举(交易订单、管理员冻结、系统冻结等)

1.2 数据模型

  • ItemFreezeLog: 冻结记录模型,记录所有冻结/解冻操作
  • ItemUser: 扩展了冻结相关字段(is_frozen、frozen_log_id)

1.3 数据库表结构

  • kku_item_freeze_logs: 冻结记录表
  • kku_item_users: 添加了冻结状态字段和相关索引

2. 核心业务逻辑

2.1 ItemFreeze逻辑类

  • freezeNormalItem(): 冻结统一属性物品(拆堆模式)
  • freezeUniqueItem(): 冻结单独属性物品
  • unfreezeByLogId(): 通过冻结日志ID解冻物品
  • getAvailableQuantity(): 获取可用数量(排除冻结)
  • batchFreezeItems(): 批量冻结操作
  • getFrozenItems(): 获取冻结物品列表
  • getFreezeStatistics(): 获取冻结统计信息

2.2 ItemService服务类扩展

  • freezeItem(): 冻结物品服务接口
  • unfreezeItem(): 解冻物品服务接口
  • getAvailableQuantity(): 获取可用数量服务接口
  • getFrozenItems(): 获取冻结物品服务接口
  • batchFreezeItems(): 批量冻结服务接口
  • getFreezeStatistics(): 获取冻结统计服务接口

3. 集成改进

3.1 现有逻辑修改

  • 物品消耗逻辑: 修改了consumeNormalItem()consumeUniqueItem()方法,确保只消耗未冻结的物品
  • 物品添加逻辑: 修改了addNormalItem()方法,确保查找可堆叠物品时排除冻结的物品

3.2 数据查询优化

  • 添加了多个索引以优化冻结状态查询性能
  • 实现了可用数量的快速查询方法

核心特性

1. 拆堆模式冻结

  • 冻结时将原堆叠拆分为冻结部分和可用部分
  • 例如:1000个物品冻结200个 → 200个(冻结)+ 800个(可用)
  • 确保冻结操作的精确性和可追溯性

2. 独立解冻机制

  • 解冻后不自动合并堆叠,保持独立状态
  • 通过frozen_log_id精确定位需要解冻的物品
  • 支持部分解冻和批量解冻操作

3. 完整的日志追踪

  • 记录所有冻结/解冻操作的详细信息
  • 支持按原因、来源类型、操作员等维度查询
  • 提供完整的操作审计轨迹

4. 业务场景支持

  • 交易订单: 卖出订单时自动冻结物品
  • 管理员操作: 支持管理员手动冻结/解冻
  • 系统冻结: 支持系统自动冻结(如异常检测)
  • 拍卖系统: 支持拍卖物品冻结
  • 任务系统: 支持任务物品冻结

使用示例

1. 冻结统一属性物品

use App\Module\GameItems\Services\ItemService;
use App\Module\GameItems\Enums\FREEZE_REASON_TYPE;

// 冻结用户的物品
$result = ItemService::freezeItem(
    $userId,
    $itemId,
    null, // 统一属性物品
    20,   // 冻结数量
    '交易订单冻结',
    [
        'reason_type' => FREEZE_REASON_TYPE::TRADE_ORDER->value,
        'source_id' => $orderId,
        'source_type' => 'order'
    ]
);

2. 解冻物品

// 通过冻结日志ID解冻
$result = ItemService::unfreezeItem($freezeLogId);

3. 查询可用数量

// 获取用户可用物品数量(排除冻结的)
$availableQuantity = ItemService::getAvailableQuantity($userId, $itemId);

4. 批量冻结

$items = [
    ['item_id' => 1001, 'quantity' => 10],
    ['item_id' => 1002, 'quantity' => 5],
];

$result = ItemService::batchFreezeItems(
    $userId,
    $items,
    '系统批量冻结',
    ['reason_type' => FREEZE_REASON_TYPE::SYSTEM_FREEZE->value]
);

数据库变更

1. 新增表

-- 冻结记录表
CREATE TABLE `kku_item_freeze_logs` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `item_id` int NOT NULL,
  `instance_id` int DEFAULT NULL,
  `quantity` int NOT NULL,
  `action_type` tinyint NOT NULL,
  `reason` varchar(255) NOT NULL,
  `source_id` int DEFAULT NULL,
  `source_type` varchar(50) DEFAULT NULL,
  `operator_id` int DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  -- 索引省略...
);

2. 修改表

-- 为item_users表添加冻结字段
ALTER TABLE `kku_item_users`
ADD COLUMN `is_frozen` tinyint(1) NOT NULL DEFAULT 0,
ADD COLUMN `frozen_log_id` int DEFAULT NULL,
-- 索引省略...

测试覆盖

已创建完整的测试用例覆盖以下场景:

  • 统一属性物品冻结/解冻
  • 单独属性物品冻结/解冻
  • 消耗物品时排除冻结物品
  • 批量冻结操作
  • 冻结统计信息查询

性能考虑

  1. 索引优化: 添加了针对冻结状态查询的复合索引
  2. 查询优化: 可用数量查询使用聚合函数,避免大量数据传输
  3. 事务保护: 所有冻结/解冻操作都在事务中执行,确保数据一致性

注意事项

  1. 事务要求: 所有冻结/解冻操作必须在事务中执行
  2. 数量验证: 冻结前会验证可用数量是否足够
  3. 日志完整性: 每次冻结/解冻操作都会记录详细日志
  4. 解冻独立性: 解冻后的物品保持独立,不会自动合并堆叠

后续扩展

  1. 自动解冻: 可以根据业务需求添加定时解冻机制
  2. 冻结过期: 可以为冻结操作添加过期时间
  3. 冻结通知: 可以添加冻结/解冻的事件通知机制
  4. 管理界面: 可以在后台管理系统中添加冻结管理界面

实现完成时间: 2025年06月12日
版本: v1.0
状态: 已完成并测试通过