Parcourir la source

为PetUser表增加软删除功能

- 在PetUser模型中添加SoftDeletes trait和deleted_at字段
- 更新模型的field注释块和casts数组,包含deleted_at字段
- 创建数据库迁移文件添加deleted_at字段和索引
- 更新SQL生成文件包含deleted_at字段定义
- 为后台管理添加软删除支持,包括deleted_at列显示和筛选功能
- 创建完整的软删除测试用例,验证软删除、恢复和强制删除功能
- 手动执行SQL添加deleted_at字段到数据库表
- 通过测试验证软删除功能完全正常工作
notfff il y a 7 mois
Parent
commit
ba8719c839

+ 6 - 0
app/Module/Pet/AdminControllers/PetUserController.php

@@ -50,6 +50,7 @@ class PetUserController extends AdminController
             $helper->columnPetStatus('status');
             $grid->column('created_at', '创建时间');
             $grid->column('updated_at', '更新时间');
+            $grid->column('deleted_at', '删除时间');
 
             // 筛选
             $grid->filter(function ($filter) {
@@ -60,6 +61,10 @@ class PetUserController extends AdminController
 
                 $filter->between('level', '等级');
                 $helper->equalRadioPetStatus('status', '状态');
+
+                // 添加软删除筛选
+                $filter->scope('trashed', '已删除')->onlyTrashed();
+                $filter->scope('with_trashed', '包含已删除')->withTrashed();
             });
 
             return $grid;
@@ -86,6 +91,7 @@ class PetUserController extends AdminController
             $helper->fieldPetStatus('status');
             $show->field('created_at', '创建时间');
             $show->field('updated_at', '更新时间');
+            $show->field('deleted_at', '删除时间');
 
             // 显示技能使用记录
             $show->skillLogs('技能使用记录', function ($skillLogs) {

+ 13 - 0
app/Module/Pet/Databases/AddSoftDeletesToPetUsers.sql

@@ -0,0 +1,13 @@
+-- ******************************************************************
+-- 为 kku_pet_users 表添加软删除字段
+-- 对应的Model: App\Module\Pet\Models\PetUser
+-- 执行时间: 2025年06月07日
+-- ******************************************************************
+
+-- 添加 deleted_at 字段
+ALTER TABLE `kku_pet_users` 
+ADD COLUMN `deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间' AFTER `updated_at`;
+
+-- 为 deleted_at 字段添加索引(可选,用于提高软删除查询性能)
+ALTER TABLE `kku_pet_users` 
+ADD INDEX `idx_deleted_at` (`deleted_at`);

+ 1 - 0
app/Module/Pet/Databases/GenerateSql/pet_users.sql

@@ -17,6 +17,7 @@ CREATE TABLE `kku_pet_users` (
   `status` tinyint unsigned DEFAULT '1' COMMENT '宠物状态:0未知,1正常,2战斗中,3死亡',
   `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
   `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间',
   PRIMARY KEY (`id`) USING BTREE,
   KEY `idx_user` (`user_id`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户的宠物';

+ 6 - 2
app/Module/Pet/Models/PetUser.php

@@ -6,6 +6,7 @@ use UCore\ModelCore;
 use App\Module\Pet\Enums\PetStatus;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\SoftDeletes;
 
 /**
  * 宠物模型
@@ -21,12 +22,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
  * @property  int  $max_experience  最高经验
  * @property  int  $max_stamina  体力 上限
  * @property  \App\Module\Pet\Enums\PetStatus  $status  宠物状态:0未知,1正常,2战斗中,3死亡
- * @property  \Carbon\Carbon  $created_at  
- * @property  \Carbon\Carbon  $updated_at  
+ * @property  \Carbon\Carbon  $created_at
+ * @property  \Carbon\Carbon  $updated_at
+ * @property  \Carbon\Carbon  $deleted_at  删除时间
  * field end
  */
 class PetUser extends ModelCore
 {
+    use SoftDeletes;
 
     /**
      * 与模型关联的表名
@@ -69,6 +72,7 @@ class PetUser extends ModelCore
         'grade'      => 'integer',
         'created_at' => 'datetime',
         'updated_at' => 'datetime',
+        'deleted_at' => 'datetime',
     ];
 
     /**

+ 211 - 0
app/Module/Pet/Tests/PetUserSoftDeleteTest.php

@@ -0,0 +1,211 @@
+<?php
+
+namespace App\Module\Pet\Tests;
+
+use App\Module\Pet\Models\PetUser;
+use App\Module\Pet\Enums\PetGrade;
+use App\Module\Pet\Enums\PetStatus;
+use Tests\TestCase;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+
+/**
+ * 宠物用户软删除测试
+ */
+class PetUserSoftDeleteTest extends TestCase
+{
+    use RefreshDatabase;
+
+    /**
+     * 测试软删除功能
+     */
+    public function test_soft_delete(): void
+    {
+        // 创建测试宠物
+        $pet = PetUser::create([
+            'user_id' => 1,
+            'name' => '测试宠物',
+            'grade' => PetGrade::FIRST,
+            'level' => 1,
+            'experience' => 0,
+            'stamina' => 100,
+            'max_experience' => 100,
+            'max_stamina' => 100,
+            'status' => PetStatus::NORMAL,
+        ]);
+
+        // 验证宠物存在
+        $this->assertDatabaseHas('kku_pet_users', [
+            'id' => $pet->id,
+            'name' => '测试宠物',
+            'user_id' => 1,
+        ]);
+
+        // 软删除宠物
+        $pet->delete();
+
+        // 验证宠物在正常查询中不可见
+        $this->assertDatabaseMissing('kku_pet_users', [
+            'id' => $pet->id,
+            'name' => '测试宠物',
+            'user_id' => 1,
+            'deleted_at' => null,
+        ]);
+
+        // 验证宠物在软删除表中可见
+        $this->assertSoftDeleted('kku_pet_users', [
+            'id' => $pet->id,
+            'name' => '测试宠物',
+            'user_id' => 1,
+        ]);
+
+        // 验证通过模型查询不到已删除的宠物
+        $foundPet = PetUser::find($pet->id);
+        $this->assertNull($foundPet);
+
+        // 验证通过withTrashed可以查询到已删除的宠物
+        $trashedPet = PetUser::withTrashed()->find($pet->id);
+        $this->assertNotNull($trashedPet);
+        $this->assertTrue($trashedPet->trashed());
+
+        // 恢复宠物
+        $trashedPet->restore();
+
+        // 验证宠物恢复后可见
+        $this->assertDatabaseHas('kku_pet_users', [
+            'id' => $pet->id,
+            'name' => '测试宠物',
+            'user_id' => 1,
+            'deleted_at' => null,
+        ]);
+
+        // 验证通过模型可以查询到恢复的宠物
+        $restoredPet = PetUser::find($pet->id);
+        $this->assertNotNull($restoredPet);
+        $this->assertFalse($restoredPet->trashed());
+    }
+
+    /**
+     * 测试强制删除功能
+     */
+    public function test_force_delete(): void
+    {
+        // 创建测试宠物
+        $pet = PetUser::create([
+            'user_id' => 2,
+            'name' => '测试宠物2',
+            'grade' => PetGrade::SECOND,
+            'level' => 5,
+            'experience' => 50,
+            'stamina' => 80,
+            'max_experience' => 200,
+            'max_stamina' => 100,
+            'status' => PetStatus::NORMAL,
+        ]);
+
+        // 软删除宠物
+        $pet->delete();
+
+        // 验证软删除成功
+        $this->assertSoftDeleted('kku_pet_users', [
+            'id' => $pet->id,
+            'name' => '测试宠物2',
+            'user_id' => 2,
+        ]);
+
+        // 强制删除宠物
+        $pet->forceDelete();
+
+        // 验证宠物完全删除
+        $this->assertDatabaseMissing('kku_pet_users', [
+            'id' => $pet->id,
+            'name' => '测试宠物2',
+            'user_id' => 2,
+        ]);
+
+        // 验证即使使用withTrashed也查询不到
+        $deletedPet = PetUser::withTrashed()->find($pet->id);
+        $this->assertNull($deletedPet);
+    }
+
+    /**
+     * 测试软删除对关联查询的影响
+     */
+    public function test_soft_delete_with_relations(): void
+    {
+        // 创建测试宠物
+        $pet = PetUser::create([
+            'user_id' => 3,
+            'name' => '测试宠物3',
+            'grade' => PetGrade::THIRD,
+            'level' => 10,
+            'experience' => 100,
+            'stamina' => 90,
+            'max_experience' => 300,
+            'max_stamina' => 100,
+            'status' => PetStatus::NORMAL,
+        ]);
+
+        // 验证可以通过用户ID查询到宠物
+        $userPets = PetUser::where('user_id', 3)->get();
+        $this->assertCount(1, $userPets);
+
+        // 软删除宠物
+        $pet->delete();
+
+        // 验证软删除后通过用户ID查询不到宠物
+        $userPetsAfterDelete = PetUser::where('user_id', 3)->get();
+        $this->assertCount(0, $userPetsAfterDelete);
+
+        // 验证使用withTrashed可以查询到
+        $userPetsWithTrashed = PetUser::withTrashed()->where('user_id', 3)->get();
+        $this->assertCount(1, $userPetsWithTrashed);
+    }
+
+    /**
+     * 测试软删除的查询作用域
+     */
+    public function test_soft_delete_scopes(): void
+    {
+        // 创建多个测试宠物
+        $pet1 = PetUser::create([
+            'user_id' => 4,
+            'name' => '正常宠物',
+            'grade' => PetGrade::FIRST,
+            'level' => 1,
+            'experience' => 0,
+            'stamina' => 100,
+            'max_experience' => 100,
+            'max_stamina' => 100,
+            'status' => PetStatus::NORMAL,
+        ]);
+
+        $pet2 = PetUser::create([
+            'user_id' => 4,
+            'name' => '将被删除的宠物',
+            'grade' => PetGrade::SECOND,
+            'level' => 2,
+            'experience' => 20,
+            'stamina' => 90,
+            'max_experience' => 150,
+            'max_stamina' => 100,
+            'status' => PetStatus::NORMAL,
+        ]);
+
+        // 软删除第二个宠物
+        $pet2->delete();
+
+        // 测试默认查询(不包含已删除)
+        $normalPets = PetUser::where('user_id', 4)->get();
+        $this->assertCount(1, $normalPets);
+        $this->assertEquals('正常宠物', $normalPets->first()->name);
+
+        // 测试withTrashed(包含已删除)
+        $allPets = PetUser::withTrashed()->where('user_id', 4)->get();
+        $this->assertCount(2, $allPets);
+
+        // 测试onlyTrashed(只查询已删除)
+        $trashedPets = PetUser::onlyTrashed()->where('user_id', 4)->get();
+        $this->assertCount(1, $trashedPets);
+        $this->assertEquals('将被删除的宠物', $trashedPets->first()->name);
+    }
+}

+ 28 - 0
database/migrations/2025_06_07_113048_add_soft_deletes_to_pet_users_table.php

@@ -0,0 +1,28 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::table('kku_pet_users', function (Blueprint $table) {
+            $table->softDeletes()->comment('删除时间');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('kku_pet_users', function (Blueprint $table) {
+            $table->dropSoftDeletes();
+        });
+    }
+};