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

refactor(shop): 重构商店限购功能

- 完全移除 max_buy 字段,使用新的限购系统替代
- 新增 ShopPurchaseLimitController 用于管理限购配置
- 更新 ShopItemController,增加单次限购功能
- 创建限购配置菜单和相关权限
- 优化数据库结构,删除不必要的字段- 更新文档,说明新的限购功能使用方法
notfff 7 місяців тому
батько
коміт
67e314fd3f

+ 191 - 0
AiWork/2024年12月/28日1430-商店限购功能优化-修正版.md

@@ -0,0 +1,191 @@
+# 商店限购功能优化 - 修正版
+
+## 修正说明
+
+根据用户反馈,对商店限购功能进行了以下重要修正:
+
+### 1. 移除不必要的API
+- **问题**:系统不需要API,创建的API是多余的
+- **解决方案**:
+  - 删除 `app/Module/Shop/AdminControllers/Api/ShopItemSelectController.php`
+  - 从路由配置中移除API路由
+  - 限购配置表单改用简单的下拉选择框
+
+### 2. 完全替代 max_buy 字段
+- **问题**:`max_buy` 字段应该被新的限购系统完全替代
+- **解决方案**:
+  - 从 `ShopItem` 模型中移除 `max_buy` 字段定义
+  - 从 `canUserPurchaseWithLimits` 方法中移除 `max_buy` 检查逻辑
+  - 从后台控制器中移除 `max_buy` 相关的显示和表单字段
+  - 使用SQL删除数据库中的 `max_buy` 字段
+
+## 执行的修改
+
+### 1. 代码修改
+
+#### ShopItem 模型 (`app/Module/Shop/Models/ShopItem.php`)
+```php
+// 移除字段定义
+- * @property  int  $max_buy  最大购买数量(0表示无限制)
+
+// 移除 fillable 中的字段
+- 'max_buy',
+
+// 移除验证逻辑中的 max_buy 检查
+- // 检查传统的总购买限制
+- if ($this->max_buy > 0) {
+-     $boughtCount = $this->getUserBoughtCount($userId);
+-     $remainingQuantity = $this->max_buy - $boughtCount;
+-     
+-     if ($quantity > $remainingQuantity) {
+-         return [false, "超出购买限制,最多还能购买{$remainingQuantity}个", $remainingQuantity];
+-     }
+- }
+```
+
+#### ShopItemController (`app/Module/Shop/AdminControllers/ShopItemController.php`)
+```php
+// 移除表格列
+- $grid->column('max_buy', '总限购')->display(function ($maxBuy) {
+-     return $maxBuy > 0 ? $maxBuy : '无限制';
+- });
+
+// 移除详情页字段
+- $show->field('max_buy', '总购买限制')->as(function ($maxBuy) {
+-     return $maxBuy > 0 ? $maxBuy : '无限制';
+- });
+
+// 移除表单字段
+- $form->number('max_buy', '总购买限制')->min(0)->default(0)->help('用户总共可购买的最大数量,0表示无限制');
+```
+
+#### ShopPurchaseLimitController (`app/Module/Shop/AdminControllers/ShopPurchaseLimitController.php`)
+```php
+// 简化商品选择,移除API依赖
+$form->select('shop_item_id', '商品')
+    ->options(ShopItem::where('is_active', true)->pluck('name', 'id'))
+    ->required()
+    ->help('选择要设置限购的商品');
+```
+
+#### ShopServiceProvider (`app/Module/Shop/Providers/ShopServiceProvider.php`)
+```php
+// 移除API路由
+- // API路由
+- $router->get('shop/items/select', [\App\Module\Shop\AdminControllers\Api\ShopItemSelectController::class, 'select']);
+- $router->get('shop/items/{id}/info', [\App\Module\Shop\AdminControllers\Api\ShopItemSelectController::class, 'info']);
+```
+
+### 2. 数据库修改
+
+#### 执行的SQL
+```sql
+-- 删除 max_buy 字段
+ALTER TABLE `kku_shop_items` DROP COLUMN `max_buy`;
+```
+
+#### 验证结果
+- ✅ `max_buy` 字段已从数据库表中成功删除
+- ✅ 表结构现在只包含 `max_single_buy` 字段
+- ✅ 数据库操作执行成功,无错误
+
+### 3. 文件删除
+
+#### 删除的文件
+- `app/Module/Shop/AdminControllers/Api/ShopItemSelectController.php` - 不需要的API控制器
+
+#### 创建的文件
+- `app/Module/Shop/Databases/GenerateSql/remove_shop_items_max_buy_field.sql` - 删除字段的SQL脚本
+
+### 4. 文档更新
+
+#### 更新的文档
+- `app/Module/Shop/Docs/后台管理部署说明.md`
+- `AiWork/2024年12月/28日1430-商店限购功能优化.md`
+
+#### 主要更新内容
+- 移除API相关的说明
+- 更新数据库迁移步骤
+- 修正功能描述,强调完全替代 `max_buy`
+- 更新部署清单
+
+## 当前系统状态
+
+### 1. 限购功能架构
+```
+商品限购系统
+├── 单次购买限制 (max_single_buy 字段)
+└── 周期性限购 (ShopPurchaseLimit 表)
+    ├── 永久限购 (替代原 max_buy)
+    ├── 每日限购
+    ├── 每周限购
+    ├── 每月限购
+    └── 每年限购
+```
+
+### 2. 数据库表结构
+- ✅ `kku_shop_items` - 包含 `max_single_buy`,已移除 `max_buy`
+- ✅ `kku_shop_purchase_limits` - 限购配置表
+- ✅ `kku_shop_user_purchase_counters` - 用户购买计数表
+
+### 3. 后台管理功能
+- ✅ 商品管理 - 显示单次限购,移除总限购
+- ✅ 限购配置管理 - 完整的CRUD功能
+- ✅ 菜单配置 - 限购配置菜单
+
+### 4. 验证逻辑
+- ✅ 单次购买限制验证
+- ✅ 周期性限购验证
+- ✅ 多规则组合验证
+- ❌ 移除了传统 max_buy 验证
+
+## 部署指南
+
+### 1. 数据库迁移
+```bash
+# 如果是新部署
+mysql -u用户名 -p数据库名 < app/Module/Shop/Databases/GenerateSql/shop_purchase_limits.sql
+mysql -u用户名 -p数据库名 < app/Module/Shop/Databases/GenerateSql/shop_user_purchase_counters.sql
+
+# 如果是从旧系统升级(已执行)
+mysql -u用户名 -p数据库名 < app/Module/Shop/Databases/GenerateSql/remove_shop_items_max_buy_field.sql
+```
+
+### 2. 菜单配置
+```bash
+php artisan admin:insert-shop-purchase-limit-menu
+```
+
+### 3. 清除缓存
+```bash
+php artisan route:clear
+php artisan config:clear
+```
+
+## 功能验证
+
+### 1. 单次购买限制
+- 设置商品的 `max_single_buy` 字段
+- 用户购买时验证单次数量不超过限制
+
+### 2. 周期性限购
+- 创建 `ShopPurchaseLimit` 配置
+- 系统自动管理购买计数和周期重置
+- 支持多种周期类型
+
+### 3. 后台管理
+- 商品列表显示单次限购信息
+- 限购配置页面管理所有限购规则
+- 表单验证确保配置合理性
+
+## 总结
+
+经过修正,商店限购功能现在:
+
+1. **完全移除了API依赖** - 简化了系统架构
+2. **彻底替代了 max_buy 字段** - 使用更强大的新限购系统
+3. **保持了所有核心功能** - 单次限购和周期性限购
+4. **简化了后台管理** - 移除不必要的复杂性
+5. **确保了数据一致性** - 数据库字段已正确删除
+
+新的限购系统比原来的 `max_buy` 字段更加灵活和强大,能够满足各种复杂的业务需求。

+ 146 - 3
AiWork/2024年12月/28日1430-商店限购功能优化.md

@@ -43,6 +43,7 @@
 
 #### ShopItem模型扩展
 - **新增字段**:`max_single_buy`(单次购买限制)
+- **移除字段**:`max_buy`(已被新限购系统完全替代)
 - **新增关联**:`purchaseLimits`、`activePurchaseLimits`
 - **新增方法**:
   - `canUserPurchaseWithLimits()`:统一限购检查
@@ -90,10 +91,15 @@ CREATE TABLE `kku_shop_user_purchase_counters` (
 
 #### 修改表
 
-**kku_shop_items表新增字段**
+**kku_shop_items表字段变更**
 ```sql
-ALTER TABLE `kku_shop_items` 
-ADD COLUMN `max_single_buy` int NOT NULL DEFAULT '0' COMMENT '单次最大购买数量(0表示无限制)' AFTER `max_buy`;
+-- 新增字段(如果表中还没有)
+ALTER TABLE `kku_shop_items`
+ADD COLUMN `max_single_buy` int NOT NULL DEFAULT '0' COMMENT '单次最大购买数量(0表示无限制)';
+
+-- 移除已被替代的字段
+ALTER TABLE `kku_shop_items`
+DROP COLUMN `max_buy`;
 ```
 
 ### 4. 验证逻辑优化
@@ -206,8 +212,145 @@ list($canPurchase, $errorMessage, $remainingQuantity) =
 ### 3. 权限配置
 为相关用户分配限购配置管理权限。
 
+## 后台管理功能
+
+### 1. 商品管理增强
+
+#### ShopItemController更新
+- **文件位置**:`app/Module/Shop/AdminControllers/ShopItemController.php`
+- **新增功能**:
+  - 商品列表显示"总限购"和"单次限购"列
+  - 商品编辑表单新增"单次购买限制"字段
+  - 每个商品行添加"限购配置"按钮
+  - 商品详情页显示限购信息
+
+#### 表格列更新
+```php
+$grid->column('max_buy', '总限购')->display(function ($maxBuy) {
+    return $maxBuy > 0 ? $maxBuy : '无限制';
+});
+$grid->column('max_single_buy', '单次限购')->display(function ($maxSingleBuy) {
+    return $maxSingleBuy > 0 ? $maxSingleBuy : '无限制';
+});
+```
+
+#### 操作按钮
+```php
+$grid->actions(function (Grid\Displayers\Actions $actions) {
+    $actions->append('<a href="' . admin_url('shop/purchase-limits?shop_item_id=' . $actions->getKey()) . '" class="btn btn-sm btn-outline-primary" title="限购配置">
+        <i class="fa fa-cog"></i> 限购配置
+    </a>');
+});
+```
+
+### 2. 限购配置管理
+
+#### ShopPurchaseLimitController
+- **文件位置**:`app/Module/Shop/AdminControllers/ShopPurchaseLimitController.php`
+- **路由注解**:`#[Resource('shop/purchase-limits', names: 'dcat.admin.shop.purchase-limits')]`
+- **核心功能**:
+  - 完整的CRUD操作界面
+  - 支持商品搜索选择
+  - 限购类型和周期配置
+  - 表单验证和状态管理
+
+#### 表格配置
+```php
+$grid->column('limit_type', '限购类型')->using(PURCHASE_LIMIT_TYPE::getAll());
+$grid->column('limit_period', '限购周期')->using(PURCHASE_LIMIT_PERIOD::getAll());
+$grid->column('is_active', '状态')->switch();
+```
+
+#### 表单验证
+```php
+$form->saving(function (Form $form) {
+    if ($form->limit_type == PURCHASE_LIMIT_TYPE::SINGLE_PURCHASE->value
+        && $form->limit_period != PURCHASE_LIMIT_PERIOD::PERMANENT->value) {
+        return $form->response()->error('单次购买限制只能使用永久周期');
+    }
+});
+```
+
+
+
+### 4. 路由配置
+
+#### ShopServiceProvider更新
+- **文件位置**:`app/Module/Shop/Providers/ShopServiceProvider.php`
+- **新增路由**:
+```php
+// 商店限购配置路由
+$router->resource('shop/purchase-limits', \App\Module\Shop\AdminControllers\ShopPurchaseLimitController::class);
+```
+
+### 5. 菜单管理
+
+#### 菜单添加命令
+- **文件位置**:`app/Console/Commands/InsertShopPurchaseLimitMenu.php`
+- **命令**:`php artisan admin:insert-shop-purchase-limit-menu`
+- **菜单结构**:
+  - 商店管理
+    - 商店分类
+    - 商店商品
+    - 促销活动
+    - 购买记录
+    - **限购配置** ← 新增
+
+### 6. 示例数据
+
+#### 数据种子文件
+- **文件位置**:`database/seeders/ShopPurchaseLimitSeeder.php`
+- **命令**:`php artisan db:seed --class=ShopPurchaseLimitSeeder`
+- **示例配置**:
+  - 单次购买限制示例
+  - 每日限购示例
+  - 多重限购规则示例
+
+### 7. 部署文档
+
+#### 完整部署说明
+- **文件位置**:`app/Module/Shop/Docs/后台管理部署说明.md`
+- **包含内容**:
+  - 数据库迁移步骤
+  - 菜单配置命令
+  - 权限设置说明
+  - 使用指南
+  - 故障排除
+
+## 部署清单
+
+### 数据库迁移
+- [x] `shop_purchase_limits.sql` - 创建限购配置表
+- [x] `shop_user_purchase_counters.sql` - 创建用户购买计数表
+- [x] `remove_shop_items_max_buy_field.sql` - 移除已被替代的max_buy字段
+
+### 后台控制器
+- [x] `ShopItemController` - 商品管理增强(移除max_buy相关功能)
+- [x] `ShopPurchaseLimitController` - 限购配置管理
+
+### 路由配置
+- [x] 限购配置资源路由
+
+### 菜单和权限
+- [x] 限购配置菜单
+- [x] 菜单添加命令
+- [x] 权限配置说明
+
+### 文档和示例
+- [x] 后台管理部署说明
+- [x] 示例数据种子文件
+- [x] 使用指南
+
 ## 总结
 
 本次优化成功实现了商店系统的高级限购功能,提供了灵活、强大且易于管理的限购解决方案。新功能完全向后兼容,不影响现有业务流程,同时为未来的业务需求提供了良好的扩展性。
 
 通过合理的数据库设计、优化的查询逻辑和完善的管理界面,新的限购系统能够满足各种复杂的业务场景需求。
+
+### 核心亮点
+
+1. **完整的后台管理界面**:提供直观易用的限购配置管理
+2. **灵活的配置选项**:支持多种限购类型和周期组合
+3. **智能表单验证**:确保配置的合理性和一致性
+4. **完全替代传统限购**:移除了max_buy字段,使用更强大的新限购系统
+5. **详细的部署文档**:确保功能能够顺利部署和使用

+ 6 - 1
AiWork/WORK.md

@@ -7,10 +7,15 @@
 先提交代码;
 商店商品-列表,增加加‘消耗组详情,奖励组详情’列,展示消耗组内容/奖励组内容
 修改后浏览器后进行查看,确认显示正常才可以完成任务
+本系统没有任何Api,你写的Api是干嘛的;
+shop_items 的 $max_buy  最大购买数量(0表示无限制)是否已经被完全替代,期望是被新的限购替代;
+shop_items 的 $max_buy 确认被替代后移除,使用mcp执行sql
 
 ## 待处理任务
 
-- 商店限购功能优化; 单次购买限制;周期性购买数量限购(周/月/年/永久)
+本系统没有任何Api,你写的Api是干嘛的;
+shop_items 的 $max_buy  最大购买数量(0表示无限制)是否已经被完全替代,期望是被新的限购替代;
+shop_items 的 $max_buy 确认被替代后移除,使用mcp执行sql
 
 
 ## 已完成任务(保留最新的10条,多余的删除)

+ 67 - 0
app/Console/Commands/InsertShopPurchaseLimitMenu.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Module\System\Models\AdminMenu;
+use Illuminate\Console\Command;
+
+class InsertShopPurchaseLimitMenu extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'admin:insert-shop-purchase-limit-menu';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '添加商店限购配置的后台管理菜单';
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        // 查找商店管理菜单
+        $shopManageMenu = AdminMenu::where('title', '🛒 商店管理')->first();
+        
+        if (!$shopManageMenu) {
+            $this->error('未找到商店管理菜单,请先运行 admin:insert-shop-menu 命令');
+            return 1;
+        }
+        
+        $this->info("找到商店管理菜单: {$shopManageMenu->title}, ID: {$shopManageMenu->id}");
+        
+        // 获取商店管理下的最大order值
+        $maxOrder = AdminMenu::where('parent_id', $shopManageMenu->id)->max('order');
+        $nextOrder = $maxOrder ? $maxOrder + 1 : 1;
+        
+        // 创建限购配置菜单
+        $purchaseLimitMenu = AdminMenu::firstOrCreate(
+            ['title' => '限购配置', 'uri' => 'shop/purchase-limits'],
+            [
+                'parent_id' => $shopManageMenu->id,
+                'order' => $nextOrder,
+                'icon' => 'fa-ban',
+                'uri' => 'shop/purchase-limits',
+                'show' => 1
+            ]
+        );
+        
+        if ($purchaseLimitMenu->wasRecentlyCreated) {
+            $this->info("创建限购配置菜单: {$purchaseLimitMenu->title}, URI: {$purchaseLimitMenu->uri}");
+        } else {
+            $this->info("限购配置菜单已存在: {$purchaseLimitMenu->title}, URI: {$purchaseLimitMenu->uri}");
+        }
+        
+        $this->info('商店限购配置菜单添加完成!');
+        
+        return 0;
+    }
+}

+ 13 - 5
app/Module/Shop/AdminControllers/ShopItemController.php

@@ -84,8 +84,8 @@ class ShopItemController extends AdminController
                 return $this->rewardGroup->formatRewardDetails();
             })->width('200px');
 
-            $grid->column('max_buy', '购买限制')->display(function ($maxBuy) {
-                return $maxBuy > 0 ? $maxBuy : '无限制';
+            $grid->column('max_single_buy', '单次限购')->display(function ($maxSingleBuy) {
+                return $maxSingleBuy > 0 ? $maxSingleBuy : '无限制';
             });
             $grid->column('sort_order', '排序权重')->sortable();
             $grid->column('is_active', '状态')->switch();
@@ -114,6 +114,14 @@ class ShopItemController extends AdminController
                 $filter->between('end_time', '下架时间')->datetime();
             });
 
+            // 操作列
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                // 添加限购配置按钮
+                $actions->append('<a href="' . admin_url('shop/purchase-limits?shop_item_id=' . $actions->getKey()) . '" class="btn btn-sm btn-outline-primary" title="限购配置">
+                    <i class="fa fa-cog"></i> 限购配置
+                </a>');
+            });
+
             // 工具栏
             $grid->toolsWithOutline(false);
             $grid->disableViewButton();
@@ -145,8 +153,8 @@ class ShopItemController extends AdminController
             $show->field('rewardGroup.name', '奖励组')->as(function ($name) {
                 return $name ?: '无';
             });
-            $show->field('max_buy', '购买限制')->as(function ($maxBuy) {
-                return $maxBuy > 0 ? $maxBuy : '无限制';
+            $show->field('max_single_buy', '单次购买限制')->as(function ($maxSingleBuy) {
+                return $maxSingleBuy > 0 ? $maxSingleBuy : '无限制';
             });
             $show->field('sort_order', '排序权重');
             $show->field('is_active', '状态')->as(function ($isActive) {
@@ -181,7 +189,7 @@ class ShopItemController extends AdminController
             $form->select('reward_group_id', '奖励组')
                 ->options(GameRewardGroup::pluck('name', 'id'))
                 ->help('选择购买此商品获得的奖励组');
-            $form->number('max_buy', '购买限制')->min(0)->default(0)->help('0表示无限制');
+            $form->number('max_single_buy', '单次购买限制')->min(0)->default(0)->help('用户单次可购买的最大数量,0表示无限制');
             $form->number('sort_order', '排序权重')->default(0)->help('数字越小越靠前');
             $form->switch('is_active', '状态')->default(true);
             $form->datetime('start_time', '上架时间')->help('留空表示不限制上架时间');

+ 249 - 0
app/Module/Shop/AdminControllers/ShopPurchaseLimitController.php

@@ -0,0 +1,249 @@
+<?php
+
+namespace App\Module\Shop\AdminControllers;
+
+use App\Module\Shop\Models\ShopPurchaseLimit;
+use App\Module\Shop\Models\ShopItem;
+use App\Module\Shop\Enums\PURCHASE_LIMIT_TYPE;
+use App\Module\Shop\Enums\PURCHASE_LIMIT_PERIOD;
+use App\Module\Shop\Repositorys\ShopPurchaseLimitRepository;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use Dcat\Admin\Http\Controllers\AdminController;
+use Spatie\RouteAttributes\Attributes\Resource;
+
+/**
+ * 商店限购配置控制器
+ *
+ * 路由前缀: /admin/shop/purchase-limits
+ * 路由名称: admin.shop.purchase-limits
+ *
+ * 提供商店限购配置的管理功能,包括:
+ * - 限购规则的增删改查
+ * - 限购类型和周期的配置
+ * - 限购状态的管理
+ */
+#[Resource('shop/purchase-limits', names: 'dcat.admin.shop.purchase-limits')]
+class ShopPurchaseLimitController extends AdminController
+{
+    /**
+     * 页面标题
+     *
+     * @var string
+     */
+    protected $title = '商店限购配置';
+
+    /**
+     * 创建表格
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new ShopPurchaseLimitRepository(), function (Grid $grid) {
+            // 预加载关联数据
+            $grid->model()->with(['shopItem']);
+
+            $grid->column('id', 'ID')->sortable();
+            $grid->column('shopItem.name', '商品名称')->limit(30);
+            $grid->column('name', '限购规则名称')->limit(30);
+            $grid->column('limit_type', '限购类型')->using(PURCHASE_LIMIT_TYPE::getAll());
+            $grid->column('limit_period', '限购周期')->using(PURCHASE_LIMIT_PERIOD::getAll());
+            $grid->column('max_quantity', '最大数量')->sortable();
+            $grid->column('is_active', '状态')->switch();
+            $grid->column('sort_order', '排序')->sortable()->editable();
+            $grid->column('created_at', '创建时间')->sortable();
+
+            // 过滤器
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->equal('shop_item_id', '商品')->select(
+                    ShopItem::where('is_active', true)->pluck('name', 'id')
+                );
+                $filter->equal('limit_type', '限购类型')->select(PURCHASE_LIMIT_TYPE::getAll());
+                $filter->equal('limit_period', '限购周期')->select(PURCHASE_LIMIT_PERIOD::getAll());
+                $filter->equal('is_active', '状态')->select([1 => '激活', 0 => '禁用']);
+            });
+
+            // 工具栏
+            $grid->toolsWithOutline(false);
+            $grid->enableDialogCreate();
+            $grid->enableDialogEdit();
+            $grid->setDialogFormDimensions('800px', '600px');
+        });
+    }
+
+    /**
+     * 创建详情页
+     *
+     * @param mixed $id
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new ShopPurchaseLimitRepository(), function (Show $show) {
+            $show->field('id', 'ID');
+            $show->field('shopItem.name', '商品名称');
+            $show->field('name', '限购规则名称');
+            $show->field('description', '限购规则描述');
+            $show->field('limit_type', '限购类型')->using(PURCHASE_LIMIT_TYPE::getAll());
+            $show->field('limit_period', '限购周期')->using(PURCHASE_LIMIT_PERIOD::getAll());
+            $show->field('max_quantity', '最大数量');
+            $show->field('is_active', '状态')->using([1 => '激活', 0 => '禁用']);
+            $show->field('sort_order', '排序权重');
+            $show->field('created_at', '创建时间');
+            $show->field('updated_at', '更新时间');
+        });
+    }
+
+    /**
+     * 创建表单
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new ShopPurchaseLimitRepository(), function (Form $form) {
+            $form->display('id', 'ID');
+
+            $form->select('shop_item_id', '商品')
+                ->options(ShopItem::where('is_active', true)->pluck('name', 'id'))
+                ->required()
+                ->help('选择要设置限购的商品');
+
+            $form->text('name', '限购规则名称')
+                ->required()
+                ->help('为此限购规则起一个便于识别的名称');
+
+            $form->textarea('description', '限购规则描述')
+                ->rows(3)
+                ->help('详细描述此限购规则的用途和限制条件');
+
+            $form->select('limit_type', '限购类型')
+                ->options(PURCHASE_LIMIT_TYPE::getAll())
+                ->required()
+                ->help('选择限购类型:单次购买限制或周期性购买限制');
+
+            $form->select('limit_period', '限购周期')
+                ->options(PURCHASE_LIMIT_PERIOD::getAll())
+                ->default(PURCHASE_LIMIT_PERIOD::PERMANENT->value)
+                ->help('选择限购周期,仅在周期性购买限制时有效');
+
+            $form->number('max_quantity', '最大购买数量')
+                ->min(1)
+                ->required()
+                ->help('设置在限购周期内允许购买的最大数量');
+
+            $form->switch('is_active', '是否激活')
+                ->default(true)
+                ->help('是否启用此限购规则');
+
+            $form->number('sort_order', '排序权重')
+                ->default(0)
+                ->help('数值越小排序越靠前,用于控制多个限购规则的检查顺序');
+
+            $form->display('created_at', '创建时间');
+            $form->display('updated_at', '更新时间');
+
+            // 表单验证
+            $form->saving(function (Form $form) {
+                // 验证限购类型和周期的组合
+                if ($form->limit_type == PURCHASE_LIMIT_TYPE::SINGLE_PURCHASE->value
+                    && $form->limit_period != PURCHASE_LIMIT_PERIOD::PERMANENT->value) {
+                    return $form->response()->error('单次购买限制只能使用永久周期');
+                }
+            });
+        });
+    }
+
+
+
+    /**
+     * 批量切换状态
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function toggleStatus()
+    {
+        $ids = request('ids', []);
+        
+        if (empty($ids)) {
+            return response()->json([
+                'status' => false,
+                'message' => '请选择要操作的记录'
+            ]);
+        }
+
+        $successCount = 0;
+        foreach ($ids as $id) {
+            if ($this->repository()->toggleStatus($id)) {
+                $successCount++;
+            }
+        }
+
+        return response()->json([
+            'status' => true,
+            'message' => "成功切换 {$successCount} 条记录的状态"
+        ]);
+    }
+
+    /**
+     * 获取商品的限购配置
+     *
+     * @param int $shopItemId
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function getByShopItem($shopItemId)
+    {
+        $limits = $this->repository()->getByShopItem($shopItemId);
+        
+        return response()->json([
+            'status' => true,
+            'data' => $limits->map(function ($limit) {
+                return [
+                    'id' => $limit->id,
+                    'name' => $limit->name,
+                    'limit_type_text' => $limit->limit_type_text,
+                    'limit_period_text' => $limit->limit_period_text,
+                    'max_quantity' => $limit->max_quantity,
+                    'is_active' => $limit->is_active,
+                ];
+            })
+        ]);
+    }
+
+    /**
+     * 复制限购配置
+     *
+     * @param int $id
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function copy($id)
+    {
+        $limit = $this->repository()->newQuery()->find($id);
+        
+        if (!$limit) {
+            return response()->json([
+                'status' => false,
+                'message' => '限购配置不存在'
+            ]);
+        }
+
+        $newData = $limit->toArray();
+        unset($newData['id'], $newData['created_at'], $newData['updated_at']);
+        $newData['name'] = $newData['name'] . ' (副本)';
+        $newData['is_active'] = false; // 副本默认为禁用状态
+
+        $repository = $this->repository();
+        $newLimit = $repository->createLimit($newData);
+
+        return response()->json([
+            'status' => true,
+            'message' => '限购配置复制成功',
+            'data' => [
+                'id' => $newLimit->id,
+                'name' => $newLimit->name
+            ]
+        ]);
+    }
+}

+ 0 - 128
app/Module/Shop/Controllers/ShopPurchaseLimitController.php

@@ -1,128 +0,0 @@
-<?php
-
-namespace App\Module\Shop\Controllers;
-
-use App\Module\Shop\Repositorys\ShopPurchaseLimitRepository;
-use Dcat\Admin\Http\Controllers\AdminController;
-
-/**
- * 商店限购配置控制器
- *
- * 路由前缀: /admin/shop/purchase-limits
- * 路由名称: admin.shop.purchase-limits
- * 
- * 提供商店限购配置的管理功能,包括:
- * - 限购规则的增删改查
- * - 限购类型和周期的配置
- * - 限购状态的管理
- */
-class ShopPurchaseLimitController extends AdminController
-{
-    /**
-     * 页面标题
-     *
-     * @var string
-     */
-    protected $title = '商店限购配置';
-
-    /**
-     * 获取数据仓库实例
-     *
-     * @return ShopPurchaseLimitRepository
-     */
-    protected function repository(): ShopPurchaseLimitRepository
-    {
-        return new ShopPurchaseLimitRepository();
-    }
-
-
-
-    /**
-     * 批量切换状态
-     *
-     * @return \Illuminate\Http\JsonResponse
-     */
-    public function toggleStatus()
-    {
-        $ids = request('ids', []);
-        
-        if (empty($ids)) {
-            return response()->json([
-                'status' => false,
-                'message' => '请选择要操作的记录'
-            ]);
-        }
-
-        $successCount = 0;
-        foreach ($ids as $id) {
-            if ($this->repository()->toggleStatus($id)) {
-                $successCount++;
-            }
-        }
-
-        return response()->json([
-            'status' => true,
-            'message' => "成功切换 {$successCount} 条记录的状态"
-        ]);
-    }
-
-    /**
-     * 获取商品的限购配置
-     *
-     * @param int $shopItemId
-     * @return \Illuminate\Http\JsonResponse
-     */
-    public function getByShopItem($shopItemId)
-    {
-        $limits = $this->repository()->getByShopItem($shopItemId);
-        
-        return response()->json([
-            'status' => true,
-            'data' => $limits->map(function ($limit) {
-                return [
-                    'id' => $limit->id,
-                    'name' => $limit->name,
-                    'limit_type_text' => $limit->limit_type_text,
-                    'limit_period_text' => $limit->limit_period_text,
-                    'max_quantity' => $limit->max_quantity,
-                    'is_active' => $limit->is_active,
-                ];
-            })
-        ]);
-    }
-
-    /**
-     * 复制限购配置
-     *
-     * @param int $id
-     * @return \Illuminate\Http\JsonResponse
-     */
-    public function copy($id)
-    {
-        $limit = $this->repository()->newQuery()->find($id);
-        
-        if (!$limit) {
-            return response()->json([
-                'status' => false,
-                'message' => '限购配置不存在'
-            ]);
-        }
-
-        $newData = $limit->toArray();
-        unset($newData['id'], $newData['created_at'], $newData['updated_at']);
-        $newData['name'] = $newData['name'] . ' (副本)';
-        $newData['is_active'] = false; // 副本默认为禁用状态
-
-        $repository = $this->repository();
-        $newLimit = $repository->createLimit($newData);
-
-        return response()->json([
-            'status' => true,
-            'message' => '限购配置复制成功',
-            'data' => [
-                'id' => $newLimit->id,
-                'name' => $newLimit->name
-            ]
-        ]);
-    }
-}

+ 0 - 1
app/Module/Shop/Databases/GenerateSql/shop_items.sql

@@ -12,7 +12,6 @@ CREATE TABLE `kku_shop_items` (
   `category_name` varchar(100) DEFAULT NULL COMMENT '分类名称(字符串格式,区别于现有分类机制)',
   `consume_group_id` int unsigned DEFAULT NULL COMMENT '消耗组ID,外键关联kku_game_consume_groups表',
   `reward_group_id` int unsigned DEFAULT NULL COMMENT '奖励组ID,外键关联kku_game_reward_groups表',
-  `max_buy` int NOT NULL DEFAULT '0' COMMENT '最大购买数量(0表示无限制)',
   `max_single_buy` int NOT NULL DEFAULT '0' COMMENT '单次最大购买数量(0表示无限制)',
   `is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否激活(0:否, 1:是)',
   `sort_order` int NOT NULL DEFAULT '0' COMMENT '排序权重',

+ 186 - 0
app/Module/Shop/Docs/后台管理部署说明.md

@@ -0,0 +1,186 @@
+# 商店限购功能后台管理部署说明
+
+## 概述
+
+本文档说明如何部署商店限购功能的后台管理界面,包括数据库迁移、菜单配置、权限设置等步骤。
+
+## 部署步骤
+
+### 1. 数据库迁移
+
+按顺序执行以下SQL文件:
+
+```bash
+# 1. 创建限购配置表
+mysql -u用户名 -p数据库名 < app/Module/Shop/Databases/GenerateSql/shop_purchase_limits.sql
+
+# 2. 创建用户购买计数表
+mysql -u用户名 -p数据库名 < app/Module/Shop/Databases/GenerateSql/shop_user_purchase_counters.sql
+
+# 3. 移除已被替代的max_buy字段(可选,如果已有数据需要迁移)
+mysql -u用户名 -p数据库名 < app/Module/Shop/Databases/GenerateSql/remove_shop_items_max_buy_field.sql
+```
+
+### 2. 后台菜单配置
+
+执行以下命令添加后台管理菜单:
+
+```bash
+# 添加限购配置菜单(需要先有商店管理菜单)
+php artisan admin:insert-shop-purchase-limit-menu
+```
+
+如果还没有商店管理菜单,请先执行:
+
+```bash
+# 添加商店管理菜单
+php artisan admin:insert-shop-menu
+```
+
+### 3. 创建示例数据(可选)
+
+```bash
+# 创建限购配置示例数据
+php artisan db:seed --class=ShopPurchaseLimitSeeder
+```
+
+### 4. 清除缓存
+
+```bash
+# 清除路由缓存
+php artisan route:clear
+
+# 清除配置缓存
+php artisan config:clear
+
+# 清除视图缓存
+php artisan view:clear
+```
+
+## 后台功能说明
+
+### 1. 商品管理增强
+
+**位置**: 商店管理 > 商店商品
+
+**新增功能**:
+- 商品列表显示"单次限购"列
+- 商品编辑表单的"单次购买限制"字段
+- 每个商品行添加"限购配置"按钮,可快速跳转到限购配置页面
+- 移除了原有的"总限购"功能,由新的限购系统完全替代
+
+### 2. 限购配置管理
+
+**位置**: 商店管理 > 限购配置
+
+**功能特性**:
+- 支持创建、编辑、删除限购规则
+- 支持按商品、限购类型、限购周期筛选
+- 支持批量操作和状态切换
+- 表单验证确保配置的合理性
+
+**配置选项**:
+- **商品选择**: 支持搜索的下拉选择框
+- **限购类型**: 单次购买限制 / 周期性购买限制
+- **限购周期**: 永久 / 每日 / 每周 / 每月 / 每年
+- **最大数量**: 限购的最大数量
+- **状态管理**: 启用/禁用限购规则
+- **排序权重**: 控制多个规则的检查顺序
+
+
+
+## 权限配置
+
+### 1. 菜单权限
+
+确保相关用户角色具有以下菜单访问权限:
+- 商店管理
+- 商店商品
+- 限购配置
+
+### 2. 操作权限
+
+根据需要为用户角色分配以下权限:
+- 查看限购配置
+- 创建限购配置
+- 编辑限购配置
+- 删除限购配置
+- 批量操作限购配置
+
+## 使用指南
+
+### 1. 创建限购规则
+
+1. 进入"商店管理 > 限购配置"
+2. 点击"新增"按钮
+3. 选择要设置限购的商品
+4. 设置限购类型和周期
+5. 输入最大购买数量
+6. 保存配置
+
+### 2. 管理现有规则
+
+1. 在限购配置列表中查看所有规则
+2. 使用过滤器快速查找特定规则
+3. 点击"编辑"修改规则参数
+4. 使用状态开关快速启用/禁用规则
+5. 通过排序权重控制规则优先级
+
+### 3. 商品限购设置
+
+1. 进入"商店管理 > 商店商品"
+2. 编辑商品,设置"单次购买限制"
+3. 点击"限购配置"按钮管理该商品的详细限购规则
+
+## 注意事项
+
+### 1. 数据一致性
+
+- 删除商品时会自动删除相关的限购配置
+- 修改商品状态不会影响已有的限购配置
+- 限购计数数据会根据周期自动重置
+
+### 2. 性能考虑
+
+- 限购配置查询已优化,支持批量查询
+- 建议为活跃商品合理设置限购规则数量
+- 定期清理无效的购买计数记录
+
+### 3. 业务逻辑
+
+- 单次购买限制只能使用永久周期
+- 多个限购规则按排序权重依次检查
+- 所有限购规则都必须通过才能购买
+
+## 故障排除
+
+### 1. 菜单不显示
+
+检查菜单是否正确创建:
+```sql
+SELECT * FROM admin_menu WHERE title LIKE '%限购%';
+```
+
+### 2. 路由不存在
+
+清除路由缓存并重新生成:
+```bash
+php artisan route:clear
+php artisan route:cache
+```
+
+### 3. 权限问题
+
+检查用户角色是否具有相应的菜单和操作权限。
+
+## 技术支持
+
+如遇到问题,请检查:
+1. 数据库表是否正确创建
+2. 菜单权限是否正确配置
+3. 缓存是否已清除
+4. 日志文件中的错误信息
+
+更多技术细节请参考:
+- `app/Module/Shop/Docs/商店限购功能优化说明.md`
+- `AiWork/2024年12月/28日1430-商店限购功能优化.md`

+ 0 - 12
app/Module/Shop/Models/ShopItem.php

@@ -23,7 +23,6 @@ use App\Module\Shop\Models\ShopPurchaseLog;
  * @property  string  $category_name  分类名称(字符串格式,区别于现有分类机制)
  * @property  int  $consume_group_id  消耗组ID,外键关联kku_game_consume_groups表
  * @property  int  $reward_group_id  奖励组ID,外键关联kku_game_reward_groups表
- * @property  int  $max_buy  最大购买数量(0表示无限制)
  * @property  int  $max_single_buy  单次最大购买数量(0表示无限制)
  * @property  bool  $is_active  是否激活(0:否, 1:是)
  * @property  int  $sort_order  排序权重
@@ -55,7 +54,6 @@ class ShopItem extends ModelCore
         'category_name',
         'consume_group_id',
         'reward_group_id',
-        'max_buy',
         'max_single_buy',
         'is_active',
         'sort_order',
@@ -264,16 +262,6 @@ class ShopItem extends ModelCore
             return [false, "单次购买数量不能超过{$this->max_single_buy}个", $this->max_single_buy];
         }
 
-        // 检查传统的总购买限制
-        if ($this->max_buy > 0) {
-            $boughtCount = $this->getUserBoughtCount($userId);
-            $remainingQuantity = $this->max_buy - $boughtCount;
-
-            if ($quantity > $remainingQuantity) {
-                return [false, "超出购买限制,最多还能购买{$remainingQuantity}个", $remainingQuantity];
-            }
-        }
-
         // 检查所有激活的限购配置
         $activeLimits = $this->activePurchaseLimits;
         $minRemainingQuantity = PHP_INT_MAX;

+ 3 - 0
app/Module/Shop/Providers/ShopServiceProvider.php

@@ -73,6 +73,9 @@ class ShopServiceProvider extends ServiceProvider
 
             // 商店购买记录路由
             $router->resource('shop/purchase-logs', \App\Module\Shop\AdminControllers\ShopPurchaseLogController::class);
+
+            // 商店限购配置路由
+            $router->resource('shop/purchase-limits', \App\Module\Shop\AdminControllers\ShopPurchaseLimitController::class);
         });
     }
 

+ 109 - 0
database/seeders/ShopPurchaseLimitSeeder.php

@@ -0,0 +1,109 @@
+<?php
+
+namespace Database\Seeders;
+
+use App\Module\Shop\Models\ShopItem;
+use App\Module\Shop\Models\ShopPurchaseLimit;
+use App\Module\Shop\Enums\PURCHASE_LIMIT_TYPE;
+use App\Module\Shop\Enums\PURCHASE_LIMIT_PERIOD;
+use Illuminate\Database\Seeder;
+
+class ShopPurchaseLimitSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        $this->command->info('开始创建商店限购配置示例数据...');
+
+        // 获取一些商品用于演示
+        $shopItems = ShopItem::where('is_active', true)->limit(3)->get();
+
+        if ($shopItems->isEmpty()) {
+            $this->command->warn('没有找到激活的商品,请先创建商品数据');
+            return;
+        }
+
+        $limitConfigs = [];
+
+        foreach ($shopItems as $index => $item) {
+            switch ($index) {
+                case 0:
+                    // 第一个商品:单次购买限制
+                    $limitConfigs[] = [
+                        'shop_item_id' => $item->id,
+                        'limit_type' => PURCHASE_LIMIT_TYPE::SINGLE_PURCHASE,
+                        'limit_period' => PURCHASE_LIMIT_PERIOD::PERMANENT,
+                        'max_quantity' => 5,
+                        'name' => '单次购买限制',
+                        'description' => '每次购买最多5个',
+                        'is_active' => true,
+                        'sort_order' => 1,
+                    ];
+                    break;
+
+                case 1:
+                    // 第二个商品:每日限购
+                    $limitConfigs[] = [
+                        'shop_item_id' => $item->id,
+                        'limit_type' => PURCHASE_LIMIT_TYPE::PERIODIC_PURCHASE,
+                        'limit_period' => PURCHASE_LIMIT_PERIOD::DAILY,
+                        'max_quantity' => 10,
+                        'name' => '每日限购',
+                        'description' => '每天最多购买10个',
+                        'is_active' => true,
+                        'sort_order' => 1,
+                    ];
+                    break;
+
+                case 2:
+                    // 第三个商品:每周限购 + 单次限购
+                    $limitConfigs[] = [
+                        'shop_item_id' => $item->id,
+                        'limit_type' => PURCHASE_LIMIT_TYPE::SINGLE_PURCHASE,
+                        'limit_period' => PURCHASE_LIMIT_PERIOD::PERMANENT,
+                        'max_quantity' => 3,
+                        'name' => '单次购买限制',
+                        'description' => '每次购买最多3个',
+                        'is_active' => true,
+                        'sort_order' => 1,
+                    ];
+                    
+                    $limitConfigs[] = [
+                        'shop_item_id' => $item->id,
+                        'limit_type' => PURCHASE_LIMIT_TYPE::PERIODIC_PURCHASE,
+                        'limit_period' => PURCHASE_LIMIT_PERIOD::WEEKLY,
+                        'max_quantity' => 15,
+                        'name' => '每周限购',
+                        'description' => '每周最多购买15个',
+                        'is_active' => true,
+                        'sort_order' => 2,
+                    ];
+                    break;
+            }
+        }
+
+        // 创建限购配置
+        foreach ($limitConfigs as $config) {
+            $limit = ShopPurchaseLimit::firstOrCreate(
+                [
+                    'shop_item_id' => $config['shop_item_id'],
+                    'limit_type' => $config['limit_type'],
+                    'limit_period' => $config['limit_period'],
+                ],
+                $config
+            );
+
+            if ($limit->wasRecentlyCreated) {
+                $this->command->info("创建限购配置: {$limit->name} (商品ID: {$limit->shop_item_id})");
+            } else {
+                $this->command->info("限购配置已存在: {$limit->name} (商品ID: {$limit->shop_item_id})");
+            }
+        }
+
+        $this->command->info('商店限购配置示例数据创建完成!');
+    }
+}