Переглянути джерело

完善Mex模块基础设施:ServiceProvider、事件系统、配置文件

- 新增MexServiceProvider服务提供者,注册核心服务和计划任务
- 创建完整的事件系统:OrderCreatedEvent、OrderCompletedEvent、TransactionCreatedEvent
- 新增事件监听器:OrderCreatedListener、TransactionCreatedListener,处理缓存清理和统计更新
- 创建mex.php配置文件,包含账户、撮合、价格、缓存、安全等全面配置
- 在Logic层集成事件触发,实现订单和交易的事件驱动
- 添加异常检测:价格波动、大额交易、频繁交易监控
- 创建完整的模块README文档,包含安装配置和使用说明
notfff 7 місяців тому
батько
коміт
7b7c940e49

+ 189 - 0
app/Module/Mex/Config/mex.php

@@ -0,0 +1,189 @@
+<?php
+
+return [
+    /*
+    |--------------------------------------------------------------------------
+    | 农贸市场配置
+    |--------------------------------------------------------------------------
+    |
+    | 这里是农贸市场模块的配置选项
+    |
+    */
+
+    /*
+    |--------------------------------------------------------------------------
+    | 系统账户配置
+    |--------------------------------------------------------------------------
+    */
+    'accounts' => [
+        // 仓库账户ID
+        'warehouse_user_id' => env('MEX_WAREHOUSE_USER_ID', 15),
+        
+        // 调控账户ID
+        'regulation_user_id' => env('MEX_REGULATION_USER_ID', 16),
+        
+        // 默认资金类型
+        'default_fund_type' => env('MEX_DEFAULT_FUND_TYPE', 1), // FUND_TYPE::FUND1
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 撮合配置
+    |--------------------------------------------------------------------------
+    */
+    'matching' => [
+        // 是否启用撮合功能
+        'enabled' => env('MEX_MATCHING_ENABLED', true),
+        
+        // 每次撮合处理的最大订单数
+        'max_orders_per_batch' => env('MEX_MATCHING_MAX_ORDERS', 100),
+        
+        // 撮合间隔(秒)
+        'interval_seconds' => env('MEX_MATCHING_INTERVAL', 60),
+        
+        // 撮合超时时间(秒)
+        'timeout_seconds' => env('MEX_MATCHING_TIMEOUT', 300),
+        
+        // 是否启用批量处理
+        'batch_processing' => env('MEX_BATCH_PROCESSING', true),
+        
+        // 批量处理大小
+        'batch_size' => env('MEX_BATCH_SIZE', 50),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 价格配置
+    |--------------------------------------------------------------------------
+    */
+    'pricing' => [
+        // 价格精度(小数位数)
+        'precision' => 5,
+        
+        // 默认最低价格
+        'default_min_price' => '0.00001',
+        
+        // 默认最高价格
+        'default_max_price' => '99999.99999',
+        
+        // 默认保护阈值
+        'default_protection_threshold' => 1000,
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 缓存配置
+    |--------------------------------------------------------------------------
+    */
+    'cache' => [
+        // 缓存前缀
+        'prefix' => 'mex:',
+        
+        // 价格配置缓存时间(秒)
+        'price_config_ttl' => env('MEX_PRICE_CONFIG_CACHE_TTL', 3600),
+        
+        // 仓库统计缓存时间(秒)
+        'warehouse_stats_ttl' => env('MEX_WAREHOUSE_STATS_CACHE_TTL', 300),
+        
+        // 市场统计缓存时间(秒)
+        'market_stats_ttl' => env('MEX_MARKET_STATS_CACHE_TTL', 600),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 安全配置
+    |--------------------------------------------------------------------------
+    */
+    'security' => [
+        // 单用户每分钟最大订单数
+        'max_orders_per_minute' => env('MEX_MAX_ORDERS_PER_MINUTE', 10),
+        
+        // 单用户每小时最大订单数
+        'max_orders_per_hour' => env('MEX_MAX_ORDERS_PER_HOUR', 100),
+        
+        // 单笔订单最大金额
+        'max_order_amount' => env('MEX_MAX_ORDER_AMOUNT', '100000.00000'),
+        
+        // 单笔订单最大数量
+        'max_order_quantity' => env('MEX_MAX_ORDER_QUANTITY', 10000),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 日志配置
+    |--------------------------------------------------------------------------
+    */
+    'logging' => [
+        // 是否启用详细日志
+        'detailed_logging' => env('MEX_DETAILED_LOGGING', false),
+        
+        // 日志频道
+        'channel' => env('MEX_LOG_CHANNEL', 'daily'),
+        
+        // 是否记录撮合过程
+        'log_matching_process' => env('MEX_LOG_MATCHING', true),
+        
+        // 是否记录账户流转
+        'log_account_transfers' => env('MEX_LOG_TRANSFERS', true),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 监控配置
+    |--------------------------------------------------------------------------
+    */
+    'monitoring' => [
+        // 是否启用监控
+        'enabled' => env('MEX_MONITORING_ENABLED', true),
+        
+        // 仓库资金预警阈值
+        'warehouse_fund_warning_threshold' => env('MEX_WAREHOUSE_FUND_WARNING', 10000),
+        
+        // 仓库资金危险阈值
+        'warehouse_fund_danger_threshold' => env('MEX_WAREHOUSE_FUND_DANGER', 1000),
+        
+        // 异常订单数量阈值
+        'abnormal_order_threshold' => env('MEX_ABNORMAL_ORDER_THRESHOLD', 1000),
+        
+        // 价格异常波动阈值(百分比)
+        'price_fluctuation_threshold' => env('MEX_PRICE_FLUCTUATION_THRESHOLD', 50),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 性能配置
+    |--------------------------------------------------------------------------
+    */
+    'performance' => [
+        // 数据库连接池大小
+        'db_pool_size' => env('MEX_DB_POOL_SIZE', 10),
+        
+        // 查询超时时间(秒)
+        'query_timeout' => env('MEX_QUERY_TIMEOUT', 30),
+        
+        // 是否启用查询缓存
+        'query_cache_enabled' => env('MEX_QUERY_CACHE_ENABLED', true),
+        
+        // 查询缓存时间(秒)
+        'query_cache_ttl' => env('MEX_QUERY_CACHE_TTL', 60),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | 调试配置
+    |--------------------------------------------------------------------------
+    */
+    'debug' => [
+        // 是否启用调试模式
+        'enabled' => env('MEX_DEBUG_ENABLED', false),
+        
+        // 是否记录SQL查询
+        'log_queries' => env('MEX_DEBUG_LOG_QUERIES', false),
+        
+        // 是否显示撮合详情
+        'show_matching_details' => env('MEX_DEBUG_MATCHING_DETAILS', false),
+        
+        // 是否模拟模式(不实际执行交易)
+        'simulation_mode' => env('MEX_SIMULATION_MODE', false),
+    ],
+];

+ 30 - 0
app/Module/Mex/Events/OrderCompletedEvent.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Module\Mex\Events;
+
+use App\Module\Mex\Models\MexOrder;
+use App\Module\Mex\Models\MexTransaction;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+
+/**
+ * 订单完成事件
+ * 
+ * 当订单完成时触发此事件
+ */
+class OrderCompletedEvent
+{
+    use Dispatchable, SerializesModels;
+
+    public MexOrder $order;
+    public ?MexTransaction $transaction;
+
+    /**
+     * 创建事件实例
+     */
+    public function __construct(MexOrder $order, ?MexTransaction $transaction = null)
+    {
+        $this->order = $order;
+        $this->transaction = $transaction;
+    }
+}

+ 27 - 0
app/Module/Mex/Events/OrderCreatedEvent.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Module\Mex\Events;
+
+use App\Module\Mex\Models\MexOrder;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+
+/**
+ * 订单创建事件
+ * 
+ * 当新订单创建时触发此事件
+ */
+class OrderCreatedEvent
+{
+    use Dispatchable, SerializesModels;
+
+    public MexOrder $order;
+
+    /**
+     * 创建事件实例
+     */
+    public function __construct(MexOrder $order)
+    {
+        $this->order = $order;
+    }
+}

+ 27 - 0
app/Module/Mex/Events/TransactionCreatedEvent.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Module\Mex\Events;
+
+use App\Module\Mex\Models\MexTransaction;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+
+/**
+ * 成交记录创建事件
+ * 
+ * 当新的成交记录创建时触发此事件
+ */
+class TransactionCreatedEvent
+{
+    use Dispatchable, SerializesModels;
+
+    public MexTransaction $transaction;
+
+    /**
+     * 创建事件实例
+     */
+    public function __construct(MexTransaction $transaction)
+    {
+        $this->transaction = $transaction;
+    }
+}

+ 89 - 0
app/Module/Mex/Listeners/OrderCreatedListener.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace App\Module\Mex\Listeners;
+
+use App\Module\Mex\Events\OrderCreatedEvent;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Cache;
+
+/**
+ * 订单创建监听器
+ * 
+ * 处理订单创建后的相关操作
+ */
+class OrderCreatedListener
+{
+    /**
+     * 处理事件
+     */
+    public function handle(OrderCreatedEvent $event): void
+    {
+        $order = $event->order;
+
+        // 记录日志
+        Log::info('Mex订单创建', [
+            'order_id' => $order->id,
+            'user_id' => $order->user_id,
+            'item_id' => $order->item_id,
+            'order_type' => $order->order_type->value,
+            'quantity' => $order->quantity,
+            'price' => $order->price,
+            'total_amount' => $order->total_amount,
+        ]);
+
+        // 清除相关缓存
+        $this->clearRelatedCache($order);
+
+        // 更新用户订单统计
+        $this->updateUserOrderStats($order);
+
+        // 检查是否需要触发撮合
+        if ($order->order_type->value === 'BUY') {
+            $this->triggerMatchingIfNeeded($order);
+        }
+    }
+
+    /**
+     * 清除相关缓存
+     */
+    protected function clearRelatedCache($order): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        
+        // 清除用户订单缓存
+        Cache::forget($cachePrefix . "user_orders:{$order->user_id}");
+        
+        // 清除商品相关缓存
+        Cache::forget($cachePrefix . "item_orders:{$order->item_id}");
+        
+        // 清除市场统计缓存
+        Cache::forget($cachePrefix . 'market_stats');
+    }
+
+    /**
+     * 更新用户订单统计
+     */
+    protected function updateUserOrderStats($order): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        $key = $cachePrefix . "user_order_count:{$order->user_id}:" . date('Y-m-d-H');
+        
+        // 增加用户小时订单计数
+        Cache::increment($key, 1);
+        Cache::expire($key, 3600); // 1小时过期
+    }
+
+    /**
+     * 检查是否需要触发撮合
+     */
+    protected function triggerMatchingIfNeeded($order): void
+    {
+        // 如果是买入订单,可能需要立即触发撮合
+        // 这里可以根据业务需求决定是否立即处理
+        
+        if (config('mex.matching.enabled', true)) {
+            // 可以在这里触发异步撮合任务
+            // dispatch(new MatchOrdersJob($order->item_id));
+        }
+    }
+}

+ 206 - 0
app/Module/Mex/Listeners/TransactionCreatedListener.php

@@ -0,0 +1,206 @@
+<?php
+
+namespace App\Module\Mex\Listeners;
+
+use App\Module\Mex\Events\TransactionCreatedEvent;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Cache;
+
+/**
+ * 成交记录创建监听器
+ * 
+ * 处理成交记录创建后的相关操作
+ */
+class TransactionCreatedListener
+{
+    /**
+     * 处理事件
+     */
+    public function handle(TransactionCreatedEvent $event): void
+    {
+        $transaction = $event->transaction;
+
+        // 记录详细日志
+        Log::info('Mex成交记录创建', [
+            'transaction_id' => $transaction->id,
+            'buyer_id' => $transaction->buyer_id,
+            'seller_id' => $transaction->seller_id,
+            'item_id' => $transaction->item_id,
+            'quantity' => $transaction->quantity,
+            'price' => $transaction->price,
+            'total_amount' => $transaction->total_amount,
+            'transaction_type' => $transaction->transaction_type->value,
+        ]);
+
+        // 清除相关缓存
+        $this->clearRelatedCache($transaction);
+
+        // 更新市场统计
+        $this->updateMarketStats($transaction);
+
+        // 更新价格趋势
+        $this->updatePriceTrend($transaction);
+
+        // 检查异常交易
+        $this->checkAbnormalTransaction($transaction);
+    }
+
+    /**
+     * 清除相关缓存
+     */
+    protected function clearRelatedCache($transaction): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        
+        // 清除商品相关缓存
+        Cache::forget($cachePrefix . "item_stats:{$transaction->item_id}");
+        Cache::forget($cachePrefix . "item_price_trend:{$transaction->item_id}");
+        Cache::forget($cachePrefix . "latest_price:{$transaction->item_id}");
+        
+        // 清除用户交易缓存
+        Cache::forget($cachePrefix . "user_transactions:{$transaction->buyer_id}");
+        Cache::forget($cachePrefix . "user_transactions:{$transaction->seller_id}");
+        
+        // 清除市场统计缓存
+        Cache::forget($cachePrefix . 'market_stats');
+        Cache::forget($cachePrefix . 'warehouse_stats');
+    }
+
+    /**
+     * 更新市场统计
+     */
+    protected function updateMarketStats($transaction): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        $today = date('Y-m-d');
+        
+        // 更新今日交易统计
+        $statsKey = $cachePrefix . "daily_stats:{$today}";
+        $stats = Cache::get($statsKey, [
+            'total_transactions' => 0,
+            'total_volume' => '0.00000',
+            'total_quantity' => 0,
+        ]);
+        
+        $stats['total_transactions']++;
+        $stats['total_volume'] = bcadd($stats['total_volume'], $transaction->total_amount, 5);
+        $stats['total_quantity'] += $transaction->quantity;
+        
+        Cache::put($statsKey, $stats, 86400); // 缓存24小时
+    }
+
+    /**
+     * 更新价格趋势
+     */
+    protected function updatePriceTrend($transaction): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        
+        // 更新最新价格
+        $latestPriceKey = $cachePrefix . "latest_price:{$transaction->item_id}";
+        Cache::put($latestPriceKey, $transaction->price, 3600);
+        
+        // 更新价格历史
+        $priceHistoryKey = $cachePrefix . "price_history:{$transaction->item_id}";
+        $history = Cache::get($priceHistoryKey, []);
+        
+        $history[] = [
+            'price' => $transaction->price,
+            'quantity' => $transaction->quantity,
+            'timestamp' => time(),
+        ];
+        
+        // 只保留最近100条记录
+        if (count($history) > 100) {
+            $history = array_slice($history, -100);
+        }
+        
+        Cache::put($priceHistoryKey, $history, 3600);
+    }
+
+    /**
+     * 检查异常交易
+     */
+    protected function checkAbnormalTransaction($transaction): void
+    {
+        // 检查价格异常波动
+        $this->checkPriceFluctuation($transaction);
+        
+        // 检查大额交易
+        $this->checkLargeTransaction($transaction);
+        
+        // 检查频繁交易
+        $this->checkFrequentTrading($transaction);
+    }
+
+    /**
+     * 检查价格异常波动
+     */
+    protected function checkPriceFluctuation($transaction): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        $historyKey = $cachePrefix . "price_history:{$transaction->item_id}";
+        $history = Cache::get($historyKey, []);
+        
+        if (count($history) >= 2) {
+            $lastPrice = end($history)['price'];
+            $currentPrice = $transaction->price;
+            
+            $fluctuation = abs(($currentPrice - $lastPrice) / $lastPrice * 100);
+            $threshold = config('mex.monitoring.price_fluctuation_threshold', 50);
+            
+            if ($fluctuation > $threshold) {
+                Log::warning('Mex价格异常波动', [
+                    'item_id' => $transaction->item_id,
+                    'last_price' => $lastPrice,
+                    'current_price' => $currentPrice,
+                    'fluctuation_percent' => $fluctuation,
+                    'transaction_id' => $transaction->id,
+                ]);
+            }
+        }
+    }
+
+    /**
+     * 检查大额交易
+     */
+    protected function checkLargeTransaction($transaction): void
+    {
+        $maxAmount = config('mex.security.max_order_amount', '100000.00000');
+        
+        if (bccomp($transaction->total_amount, $maxAmount, 5) > 0) {
+            Log::warning('Mex大额交易', [
+                'transaction_id' => $transaction->id,
+                'total_amount' => $transaction->total_amount,
+                'max_amount' => $maxAmount,
+                'buyer_id' => $transaction->buyer_id,
+                'seller_id' => $transaction->seller_id,
+            ]);
+        }
+    }
+
+    /**
+     * 检查频繁交易
+     */
+    protected function checkFrequentTrading($transaction): void
+    {
+        $cachePrefix = config('mex.cache.prefix', 'mex:');
+        $userIds = [$transaction->buyer_id, $transaction->seller_id];
+        
+        foreach ($userIds as $userId) {
+            $key = $cachePrefix . "user_transaction_count:{$userId}:" . date('Y-m-d-H');
+            $count = Cache::increment($key, 1);
+            Cache::expire($key, 3600);
+            
+            $threshold = config('mex.security.max_orders_per_hour', 100);
+            if ($count > $threshold) {
+                Log::warning('Mex频繁交易', [
+                    'user_id' => $userId,
+                    'hourly_count' => $count,
+                    'threshold' => $threshold,
+                    'transaction_id' => $transaction->id,
+                ]);
+            }
+        }
+    }
+}

+ 15 - 1
app/Module/Mex/Logic/MexOrderLogic.php

@@ -7,6 +7,8 @@ use App\Module\Mex\Models\MexPriceConfig;
 use App\Module\Mex\Enums\OrderType;
 use App\Module\Mex\Enums\OrderStatus;
 use App\Module\Mex\Logic\MexAccountLogic;
+use App\Module\Mex\Events\OrderCreatedEvent;
+use App\Module\Mex\Events\OrderCompletedEvent;
 
 /**
  * 农贸市场订单逻辑
@@ -50,9 +52,12 @@ class MexOrderLogic
                 'status' => OrderStatus::PENDING,
             ]);
 
+            // 触发订单创建事件
+            event(new OrderCreatedEvent($order));
+
             // 卖出订单立即处理
             $result = self::processSellOrderImmediately($order);
-            
+
             return ['success' => true, 'order_id' => $order->id, 'result' => $result];
         } catch (\Exception $e) {
             return ['success' => false, 'message' => '创建订单失败:' . $e->getMessage()];
@@ -100,6 +105,9 @@ class MexOrderLogic
                 'frozen_amount' => $totalAmount,
             ]);
 
+            // 触发订单创建事件
+            event(new OrderCreatedEvent($order));
+
             // 买入订单立即处理
             $result = self::processBuyOrderImmediately($order);
 
@@ -136,6 +144,9 @@ class MexOrderLogic
                 'completed_at' => now(),
             ]);
 
+            // 触发订单完成事件
+            event(new OrderCompletedEvent($order));
+
             return [
                 'success' => true,
                 'message' => '卖出订单已完成',
@@ -180,6 +191,9 @@ class MexOrderLogic
                 'completed_at' => now(),
             ]);
 
+            // 触发订单完成事件
+            event(new OrderCompletedEvent($order));
+
             return [
                 'success' => true,
                 'message' => '买入订单已完成',

+ 9 - 1
app/Module/Mex/Logic/MexTransactionLogic.php

@@ -4,6 +4,7 @@ namespace App\Module\Mex\Logic;
 
 use App\Module\Mex\Models\MexTransaction;
 use App\Module\Mex\Enums\TransactionType;
+use App\Module\Mex\Events\TransactionCreatedEvent;
 use Illuminate\Support\Facades\DB;
 
 /**
@@ -218,7 +219,7 @@ class MexTransactionLogic
     public static function createTransaction(array $data): ?MexTransaction
     {
         try {
-            return MexTransaction::create([
+            $transaction = MexTransaction::create([
                 'buy_order_id' => $data['buy_order_id'] ?? null,
                 'sell_order_id' => $data['sell_order_id'] ?? null,
                 'buyer_id' => $data['buyer_id'],
@@ -231,6 +232,13 @@ class MexTransactionLogic
                 'is_admin_operation' => $data['is_admin_operation'] ?? false,
                 'admin_user_id' => $data['admin_user_id'] ?? null,
             ]);
+
+            // 触发成交记录创建事件
+            if ($transaction) {
+                event(new TransactionCreatedEvent($transaction));
+            }
+
+            return $transaction;
         } catch (\Exception $e) {
             return null;
         }

+ 151 - 0
app/Module/Mex/Providers/MexServiceProvider.php

@@ -0,0 +1,151 @@
+<?php
+
+namespace App\Module\Mex\Providers;
+
+use Illuminate\Support\ServiceProvider;
+use Illuminate\Console\Scheduling\Schedule;
+use Illuminate\Support\Facades\Event;
+
+/**
+ * Mex模块服务提供者
+ * 
+ * 负责注册Mex模块的服务、命令、计划任务等
+ */
+class MexServiceProvider extends ServiceProvider
+{
+    /**
+     * 注册服务
+     */
+    public function register(): void
+    {
+        // 注册配置文件
+        $this->mergeConfigFrom(
+            __DIR__ . '/../Config/mex.php',
+            'mex'
+        );
+
+        // 注册单例服务
+        $this->registerServices();
+    }
+
+    /**
+     * 启动服务
+     */
+    public function boot(): void
+    {
+        // 注册命令
+        $this->registerCommands();
+
+        // 注册计划任务
+        $this->registerSchedule();
+
+        // 注册事件监听器
+        $this->registerEventListeners();
+
+        // 发布配置文件
+        $this->publishes([
+            __DIR__ . '/../Config/mex.php' => config_path('mex.php'),
+        ], 'mex-config');
+
+        // 发布数据库迁移文件
+        $this->publishes([
+            __DIR__ . '/../Databases/GenerateSql' => database_path('sql/mex'),
+        ], 'mex-sql');
+    }
+
+    /**
+     * 注册服务
+     */
+    protected function registerServices(): void
+    {
+        // 注册核心服务
+        $this->app->singleton('mex.order', function () {
+            return new \App\Module\Mex\Services\MexOrderService();
+        });
+
+        $this->app->singleton('mex.transaction', function () {
+            return new \App\Module\Mex\Services\MexTransactionService();
+        });
+
+        $this->app->singleton('mex.warehouse', function () {
+            return new \App\Module\Mex\Services\MexWarehouseService();
+        });
+
+        $this->app->singleton('mex.price_config', function () {
+            return new \App\Module\Mex\Services\MexPriceConfigService();
+        });
+
+        $this->app->singleton('mex.admin', function () {
+            return new \App\Module\Mex\Services\MexAdminService();
+        });
+
+        $this->app->singleton('mex.match', function () {
+            return new \App\Module\Mex\Services\MexMatchService();
+        });
+    }
+
+    /**
+     * 注册命令
+     */
+    protected function registerCommands(): void
+    {
+        if ($this->app->runningInConsole()) {
+            $this->commands([
+                \App\Module\Mex\Commands\MexMatchCommand::class,
+            ]);
+        }
+    }
+
+    /**
+     * 注册计划任务
+     */
+    protected function registerSchedule(): void
+    {
+        $this->app->booted(function () {
+            $schedule = $this->app->make(Schedule::class);
+
+            // 每分钟执行一次撮合任务
+            $schedule->command('mex:match')
+                ->everyMinute()
+                ->withoutOverlapping(5) // 防止重叠执行,最多等待5分钟
+                ->runInBackground()
+                ->appendOutputTo(storage_path('logs/mex-match.log'));
+        });
+    }
+
+    /**
+     * 注册事件监听器
+     */
+    protected function registerEventListeners(): void
+    {
+        Event::listen(
+            \App\Module\Mex\Events\OrderCreatedEvent::class,
+            \App\Module\Mex\Listeners\OrderCreatedListener::class
+        );
+
+        Event::listen(
+            \App\Module\Mex\Events\OrderCompletedEvent::class,
+            [\App\Module\Mex\Listeners\OrderCreatedListener::class, 'handleCompleted']
+        );
+
+        Event::listen(
+            \App\Module\Mex\Events\TransactionCreatedEvent::class,
+            \App\Module\Mex\Listeners\TransactionCreatedListener::class
+        );
+    }
+
+    /**
+     * 获取提供的服务
+     */
+    public function provides(): array
+    {
+        return [
+            'mex.order',
+            'mex.transaction',
+            'mex.warehouse',
+            'mex.price_config',
+            'mex.admin',
+            'mex.match',
+        ];
+    }
+}

+ 249 - 0
app/Module/Mex/README.md

@@ -0,0 +1,249 @@
+# Mex模块 - 农贸市场系统
+
+Mex模块是一个完整的农贸市场交易系统,支持用户买卖农产品,具有自动撮合、价格保护、仓库管理等功能。
+
+## 模块概述
+
+### 核心功能
+- **订单管理**: 支持买入/卖出订单创建、撮合、完成
+- **价格配置**: 商品价格区间保护和数量限制
+- **仓库管理**: 自动化的物品和资金流转
+- **成交记录**: 完整的交易历史记录
+- **管理员操作**: 市场调控和干预功能
+
+### 业务规则
+- **仓库账户**: USER_ID为15,负责与用户进行物品和资金交换
+- **调控账户**: USER_ID为16,用于市场调控操作
+- **用户卖出**: 物品转入仓库,资金从仓库转出给用户
+- **用户买入**: 资金转入仓库,物品从仓库转出给用户
+- **总量守恒**: 确保系统内物品和资金总量不变
+
+## 目录结构
+
+```
+app/Module/Mex/
+├── AdminControllers/           # 后台管理控制器
+│   ├── Helper/                # 控制器助手类
+│   ├── MexOrderController.php
+│   ├── MexPriceConfigController.php
+│   ├── MexTransactionController.php
+│   ├── MexWarehouseController.php
+│   └── MexAdminOperationController.php
+├── Commands/                   # 命令行工具
+│   └── MexMatchCommand.php
+├── Config/                     # 配置文件
+│   └── mex.php
+├── Controllers/               # API控制器
+│   └── Admin/
+├── Databases/                 # 数据库相关
+│   ├── GenerateSql/          # SQL文件
+│   └── Repositories/         # 仓库类
+├── Enums/                     # 枚举类
+│   ├── AdminOperationType.php
+│   ├── OrderStatus.php
+│   ├── OrderType.php
+│   └── TransactionType.php
+├── Events/                    # 事件类
+│   ├── OrderCreatedEvent.php
+│   ├── OrderCompletedEvent.php
+│   └── TransactionCreatedEvent.php
+├── Listeners/                 # 事件监听器
+│   ├── OrderCreatedListener.php
+│   └── TransactionCreatedListener.php
+├── Logic/                     # 业务逻辑层
+│   ├── MexAccountLogic.php
+│   ├── MexAdminLogic.php
+│   ├── MexMatchLogic.php
+│   ├── MexOrderLogic.php
+│   ├── MexTransactionLogic.php
+│   └── MexWarehouseLogic.php
+├── Models/                    # 数据模型
+│   ├── MexAdminOperation.php
+│   ├── MexOrder.php
+│   ├── MexPriceConfig.php
+│   ├── MexTransaction.php
+│   └── MexWarehouse.php
+├── Providers/                 # 服务提供者
+│   └── MexServiceProvider.php
+├── Repositories/              # 数据仓库
+│   ├── MexAdminOperationRepository.php
+│   ├── MexOrderRepository.php
+│   ├── MexPriceConfigRepository.php
+│   ├── MexTransactionRepository.php
+│   └── MexWarehouseRepository.php
+├── Services/                  # 服务层
+│   ├── MexAdminService.php
+│   ├── MexMatchService.php
+│   ├── MexOrderService.php
+│   ├── MexPriceConfigService.php
+│   ├── MexTransactionService.php
+│   └── MexWarehouseService.php
+├── Tests/                     # 测试文件
+│   └── MexAccountLogicTest.php
+└── README.md                  # 本文件
+```
+
+## 数据库表
+
+### 核心表
+- `kku_mex_orders` - 订单表
+- `kku_mex_transactions` - 成交记录表
+- `kku_mex_price_configs` - 价格配置表
+- `kku_mex_warehouse` - 仓库统计表
+- `kku_mex_admin_operations` - 管理员操作记录表
+
+## 安装配置
+
+### 1. 注册服务提供者
+在 `config/app.php` 中添加:
+```php
+'providers' => [
+    // ...
+    App\Module\Mex\Providers\MexServiceProvider::class,
+],
+```
+
+### 2. 发布配置文件
+```bash
+php artisan vendor:publish --tag=mex-config
+```
+
+### 3. 执行数据库迁移
+```bash
+# 执行SQL文件创建表结构
+mysql -u username -p database_name < app/Module/Mex/Databases/GenerateSql/mex_orders.sql
+mysql -u username -p database_name < app/Module/Mex/Databases/GenerateSql/mex_transactions.sql
+# ... 其他SQL文件
+```
+
+### 4. 配置环境变量
+在 `.env` 文件中添加:
+```env
+# Mex模块配置
+MEX_WAREHOUSE_USER_ID=15
+MEX_REGULATION_USER_ID=16
+MEX_DEFAULT_FUND_TYPE=1
+MEX_MATCHING_ENABLED=true
+MEX_MATCHING_INTERVAL=60
+```
+
+## 使用方法
+
+### 创建订单
+```php
+use App\Module\Mex\Services\MexOrderService;
+
+// 创建卖出订单
+$result = MexOrderService::createSellOrder(
+    userId: 1001,
+    itemId: 10001,
+    quantity: 10,
+    price: '2.50000'
+);
+
+// 创建买入订单
+$result = MexOrderService::createBuyOrder(
+    userId: 1001,
+    itemId: 10001,
+    quantity: 5,
+    price: '8.00000'
+);
+```
+
+### 配置价格保护
+```php
+use App\Module\Mex\Services\MexPriceConfigService;
+
+$result = MexPriceConfigService::createConfig([
+    'item_id' => 10001,
+    'min_price' => '1.00000',
+    'max_price' => '10.00000',
+    'protection_threshold' => 1000,
+    'is_enabled' => true,
+]);
+```
+
+### 执行撮合
+```bash
+# 手动执行撮合
+php artisan mex:match
+
+# 指定商品撮合
+php artisan mex:match --item-id=10001
+
+# 试运行模式
+php artisan mex:match --dry-run
+```
+
+## 事件系统
+
+### 订单事件
+- `OrderCreatedEvent` - 订单创建时触发
+- `OrderCompletedEvent` - 订单完成时触发
+
+### 交易事件
+- `TransactionCreatedEvent` - 成交记录创建时触发
+
+### 监听器
+- `OrderCreatedListener` - 处理订单创建后的缓存清理和统计更新
+- `TransactionCreatedListener` - 处理成交后的市场统计和异常检测
+
+## 后台管理
+
+访问后台管理界面:
+- 订单管理: `/admin/mex-orders`
+- 价格配置: `/admin/mex-price-configs`
+- 成交记录: `/admin/mex-transactions`
+- 仓库管理: `/admin/mex-warehouse`
+- 操作记录: `/admin/mex-admin-operations`
+
+## 监控和日志
+
+### 日志文件
+- `storage/logs/mex-match.log` - 撮合任务日志
+- `storage/logs/laravel.log` - 一般业务日志
+
+### 监控指标
+- 仓库资金余额监控
+- 价格异常波动检测
+- 频繁交易检测
+- 大额交易预警
+
+## 性能优化
+
+### 缓存策略
+- 价格配置缓存(1小时)
+- 仓库统计缓存(5分钟)
+- 市场统计缓存(10分钟)
+
+### 数据库优化
+- 订单表按状态和时间索引
+- 交易记录表按商品和时间索引
+- 仓库表按商品ID索引
+
+## 安全考虑
+
+### 限制措施
+- 单用户每分钟最大订单数限制
+- 单笔订单最大金额限制
+- 价格保护机制防止异常价格
+
+### 审计功能
+- 所有管理员操作记录
+- 异常交易自动检测和报警
+- 完整的资金和物品流转记录
+
+## 测试
+
+运行测试:
+```bash
+php artisan test app/Module/Mex/Tests/
+```
+
+## 注意事项
+
+1. **数据一致性**: 所有交易操作都在数据库事务中执行
+2. **并发控制**: 使用数据库锁防止并发问题
+3. **错误处理**: 完善的异常处理和回滚机制
+4. **日志记录**: 详细的操作日志便于问题排查
+5. **配置管理**: 通过配置文件灵活控制系统行为