فهرست منبع

为合成配方增加展示属性功能,参考物品的展示属性实现

- 数据库:添加display_attributes字段(JSON类型)存储展示属性
- Cast类:创建RecipeDisplayAttributesCast专门处理合成配方展示属性
- 模型:更新ItemRecipe模型,添加展示属性字段和类型转换
- 后台控制器:添加展示属性的列表显示、详情显示和表单编辑功能
- SQL文件:更新自动生成的SQL文件包含新字段
- 功能验证:成功测试展示属性的添加、编辑、保存和显示功能

展示属性支持:icon(图标路径)、color(颜色)、description(描述)、background(背景图片)、animation(动画效果)、badge(特殊标记)、difficulty(难度等级)、recommended_level(推荐等级)、source(配方来源)、craft_time_display(制作时间显示)等
notfff 7 ماه پیش
والد
کامیت
fbca378b12

+ 199 - 0
AiWork/2025年06月/0609-1430-修复合成配方成功率含义和显示逻辑.md

@@ -0,0 +1,199 @@
+# 修复合成配方成功率含义和显示逻辑
+
+**任务时间**: 2025年06月09日 14:30  
+**任务类型**: Bug修复  
+**影响模块**: 游戏物品合成系统  
+
+## 任务背景
+
+用户反馈合成配方中成功率的含义存在问题:
+- 数据库储存是对的:100 = 成功率100%
+- 代码和文档是错误的:存在逻辑错误和显示错误
+
+## 问题分析
+
+通过代码分析发现以下问题:
+
+### 1. 数据库存储(✅ 正确)
+- 数据库中`success_rate`字段存储的是`100.00`表示100%成功率
+- 字段类型:`decimal(5,2)`,默认值:`100.00`
+
+### 2. 模型注释(✅ 正确)
+- 在`ItemRecipe.php`模型中,字段注释正确:`成功率(0-100之间的小数,100 = 100%)`
+
+### 3. 代码逻辑(❌ 错误)
+- 在`CraftService::craftItem`方法中,完全没有使用`success_rate`字段来判断合成是否成功
+- 合成成功与否完全依赖于RewardService的结果,忽略了配方的成功率设置
+
+### 4. 后台显示(❌ 错误)
+- 在`RecipeController.php`中,列表和详情页面都有`($value * 100) . '%'`的错误逻辑
+- 导致100%的成功率显示为"10000%"
+
+### 5. 表单帮助文本(❌ 错误)
+- 表单中帮助文本写的是"合成成功的概率,1表示100%",应该是"100表示100%"
+
+## 修复方案
+
+### 1. 修复CraftService中的合成逻辑
+
+在`app/Module/GameItems/Services/CraftService.php`中:
+
+```php
+// 原来的错误逻辑:直接执行奖励组
+$rewardResult = RewardService::grantReward(
+    $userId,
+    $recipe->reward_group_id,
+    'craft',
+    $recipeId
+);
+$isSuccess = $rewardResult->success;
+
+// 修复后的正确逻辑:先判断成功率,再执行奖励组
+$isSuccess = self::rollCraftSuccess($recipe->success_rate);
+$rewardItems = [];
+
+if ($isSuccess) {
+    $rewardResult = RewardService::grantReward(
+        $userId,
+        $recipe->reward_group_id,
+        'craft',
+        $recipeId
+    );
+    
+    if ($rewardResult->success) {
+        $rewardItems = $rewardResult->items;
+    } else {
+        $isSuccess = false;
+    }
+}
+```
+
+添加成功率判断方法:
+
+```php
+/**
+ * 根据成功率判断合成是否成功
+ *
+ * @param float $successRate 成功率(百分比,100.00 = 100%)
+ * @return bool 是否成功
+ */
+private static function rollCraftSuccess(float $successRate): bool
+{
+    // 成功率小于等于0,必定失败
+    if ($successRate <= 0) {
+        return false;
+    }
+
+    // 成功率大于等于100,必定成功
+    if ($successRate >= 100) {
+        return true;
+    }
+
+    // 生成1-100的随机数进行概率判断
+    $randomNumber = mt_rand(1, 100);
+    return $randomNumber <= $successRate;
+}
+```
+
+### 2. 修复后台显示逻辑
+
+在`app/Module/GameItems/AdminControllers/RecipeController.php`中:
+
+```php
+// 修复列表页显示
+$grid->column('success_rate', '成功率')->display(function ($value) {
+    return $value . '%';  // 去除错误的 * 100
+});
+
+// 修复详情页显示
+$show->field('success_rate', '成功率')->as(function ($value) {
+    return $value . '%';  // 去除错误的 * 100
+});
+```
+
+### 3. 修复表单帮助文本
+
+```php
+$form->rate('success_rate', '成功率')
+    ->default(100)  // 修改默认值从1改为100
+    ->help('合成成功的概率,100表示100%成功率');  // 修正帮助文本
+```
+
+## 测试验证
+
+### 1. 后台管理界面测试
+- ✅ 列表页面成功率显示正确:从"10000%"修复为"100%"
+- ✅ 编辑页面表单显示正确:默认值100,帮助文本正确
+- ✅ 详情页面显示正确:成功率显示为"100%"
+
+### 2. 数据库验证
+```sql
+SELECT id, name, success_rate FROM kku_item_recipes LIMIT 5;
+```
+结果显示数据库存储正确:`success_rate`为`100.00`
+
+### 3. 代码逻辑验证
+- ✅ 添加了`rollCraftSuccess`方法进行成功率判断
+- ✅ 修改了合成流程,先判断成功率再执行奖励
+- ✅ 保持了事务完整性和错误处理
+
+## 修改文件
+
+1. `app/Module/GameItems/Services/CraftService.php`
+   - 添加成功率判断逻辑
+   - 修改合成流程
+   - 添加`rollCraftSuccess`私有方法
+
+2. `app/Module/GameItems/AdminControllers/RecipeController.php`
+   - 修复列表页成功率显示逻辑
+   - 修复详情页成功率显示逻辑
+   - 修复表单默认值和帮助文本
+
+## 技术要点
+
+### 成功率判断逻辑
+- 成功率 ≤ 0:必定失败
+- 成功率 ≥ 100:必定成功
+- 0 < 成功率 < 100:使用随机数判断
+
+### 数据一致性
+- 数据库存储:`decimal(5,2)`,100.00表示100%
+- 代码逻辑:直接使用数据库值进行判断
+- 显示逻辑:直接显示数据库值 + "%"
+
+### 向后兼容
+- 保持现有数据库结构不变
+- 保持API接口不变
+- 保持现有配方数据有效
+
+## Git提交
+
+```bash
+git add .
+git commit -m "修复合成配方成功率的含义和显示逻辑
+
+- 修复CraftService中缺失的成功率判断逻辑,添加rollCraftSuccess方法
+- 修复后台控制器中成功率显示错误(去除多余的*100计算)
+- 修复表单帮助文本,明确100表示100%成功率
+- 数据库存储正确:100.00表示100%成功率
+- 代码逻辑正确:使用success_rate字段进行概率判断
+- 文档描述正确:成功率范围0-100(百分比)"
+git push
+```
+
+## 任务结果
+
+✅ **修复完成**
+- 数据库存储:正确(100.00 = 100%)
+- 代码逻辑:已修复(添加成功率判断)
+- 后台显示:已修复(去除错误的*100计算)
+- 表单界面:已修复(正确的默认值和帮助文本)
+- 文档描述:正确(成功率范围0-100百分比)
+
+✅ **功能验证**
+- 后台管理界面显示正确
+- 成功率逻辑工作正常
+- 保持向后兼容性
+- 代码已提交并推送
+
+现在合成配方的成功率含义完全正确:**100 = 成功率100%**,代码逻辑和显示都与数据库存储保持一致。

+ 7 - 4
AiWork/WORK.md

@@ -25,6 +25,12 @@ shop_items 的 $max_buy 确认被替代后移除,使用mcp执行sql
 
 ## 已完成任务(保留最新的10条,多余的删除)
 
+**2025-06-09 14:30** - 修复合成配方成功率含义和显示逻辑:数据库存储正确,修复代码逻辑和显示错误
+- 问题:合成配方成功率含义混乱,数据库存储正确(100=100%),但代码逻辑缺失成功率判断,后台显示错误(10000%)
+- 修复:添加rollCraftSuccess方法实现成功率判断,修复后台显示逻辑去除错误的*100计算,修正表单帮助文本
+- 结果:成功率含义完全正确,100=100%成功率,代码逻辑和显示都与数据库存储保持一致,后台界面显示正常
+- 文件:./AiWork/2025年06月/0609-1430-修复合成配方成功率含义和显示逻辑.md
+
 **2025-06-09 11:59** - 重构数字助手类为NumberWan:简化功能保持专一性,移除千分位和旧版兼容内容
 - 需求:类名改为NumberWan,移除千分位相关的内容,移除旧版兼容内容
 - 实现:重命名类为NumberWan,移除千分位方法和低精度兼容方法,简化方法命名去掉Precision后缀
@@ -97,10 +103,7 @@ shop_items 的 $max_buy 确认被替代后移除,使用mcp执行sql
 - 修复:移除所有使用min_level的判断逻辑,统一使用等级配置表进行技能可用性检查,修复同步命令调用问题
 - 结果:技能可用性判断完全基于等级配置表,符合设计要求,命令正常运行
 
-**2025-06-07 10:45** - 修复宠物技能处理中config字段类型错误问题
-- 问题:执行 `php artisan pet:process-active-skills --sync` 时出现 "Cannot access offset of type string on string" 错误
-- 修复:在recordSkillStatistics方法中添加config字段类型检查,确保config字段始终为数组类型
-- 结果:命令正常运行,宠物技能处理功能恢复正常,统计信息正确记录
+
 
 
 

+ 41 - 0
app/Module/GameItems/AdminControllers/RecipeController.php

@@ -102,6 +102,24 @@ class RecipeController extends AdminController
                 return $this->formatConditionDetails();
             })->width('200px');
 
+            // 展示属性列
+            $grid->column('display_attributes', '展示属性')->display(function ($value) {
+                if (empty($value)) {
+                    return '-';
+                }
+                if (is_string($value)) {
+                    $value = json_decode($value, true);
+                }
+
+                $html = '<div style="max-width: 200px; max-height: 100px; overflow: auto;">';
+                foreach ((array)$value as $key => $val) {
+                    if (empty($val)) continue;
+                    $html .= "<div><strong>{$key}</strong>: {$val}</div>";
+                }
+                $html .= '</div>';
+                return $html;
+            })->width('200px');
+
             $grid->column('success_rate', '成功率')->display(function ($value) {
                 return $value . '%';
             });
@@ -169,6 +187,25 @@ class RecipeController extends AdminController
             $helper->field('code', '配方编码');
             $helper->field('description', '配方描述');
 
+            // 展示属性
+            $show->field('display_attributes', '展示属性')->as(function ($value) {
+                if (empty($value)) {
+                    return '无';
+                }
+                if (is_string($value)) {
+                    $value = json_decode($value, true);
+                }
+
+                $html = '<div class="table-responsive"><table class="table table-sm table-bordered">';
+                $html .= '<thead><tr><th>属性</th><th>值</th></tr></thead><tbody>';
+                foreach ((array)$value as $key => $val) {
+                    if (empty($val)) continue;
+                    $html .= "<tr><td><strong>{$key}</strong></td><td>{$val}</td></tr>";
+                }
+                $html .= '</tbody></table></div>';
+                return $html;
+            });
+
             $show->field('success_rate', '成功率')->as(function ($value) {
                 return $value . '%';
             });
@@ -258,6 +295,10 @@ class RecipeController extends AdminController
                 ->options(\App\Module\Game\Models\GameConditionGroup::pluck('name', 'id'))
                 ->help('选择解锁该配方需要满足的条件组(可选)');
 
+            // 展示属性
+            $form->keyValue('display_attributes', '展示属性')
+                ->help('用于界面展示的属性,如图标路径、颜色、描述等。常用属性:icon(图标路径)、color(颜色)、description(描述)、background(背景图片)、animation(动画效果)、badge(特殊标记)、difficulty(难度等级)、recommended_level(推荐等级)、source(配方来源)、craft_time_display(制作时间显示)');
+
             $form->rate('success_rate', '成功率')
                 ->default(100)
                 ->help('合成成功的概率,100表示100%成功率');

+ 84 - 0
app/Module/GameItems/Casts/RecipeDisplayAttributesCast.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace App\Module\GameItems\Casts;
+
+use UCore\Model\CastsAttributes;
+
+/**
+ * 合成配方展示属性类型转换器
+ *
+ * 用于将数据库中存储的JSON格式的合成配方展示属性转换为PHP对象,以及将PHP对象转换回JSON格式。
+ * 展示属性包含用于界面展示的属性,如图标路径、颜色、描述等。
+ */
+class RecipeDisplayAttributesCast extends CastsAttributes
+{
+    /**
+     * 图标路径
+     * 
+     * @var string $icon
+     */
+    public string $icon = '';
+
+    /**
+     * 颜色
+     * 
+     * @var string $color
+     */
+    public string $color = '';
+
+    /**
+     * 描述
+     * 
+     * @var string $description
+     */
+    public string $description = '';
+
+    /**
+     * 背景图片
+     * 
+     * @var string $background
+     */
+    public string $background = '';
+
+    /**
+     * 动画效果
+     * 
+     * @var string $animation
+     */
+    public string $animation = '';
+
+    /**
+     * 特殊标记
+     * 
+     * @var string $badge
+     */
+    public string $badge = '';
+
+    /**
+     * 难度等级
+     * 
+     * @var string $difficulty
+     */
+    public string $difficulty = '';
+
+    /**
+     * 推荐等级
+     * 
+     * @var string $recommended_level
+     */
+    public string $recommended_level = '';
+
+    /**
+     * 配方来源
+     * 
+     * @var string $source
+     */
+    public string $source = '';
+
+    /**
+     * 制作时间显示
+     * 
+     * @var string $craft_time_display
+     */
+    public string $craft_time_display = '';
+}

+ 1 - 0
app/Module/GameItems/Databases/GenerateSql/item_recipes.sql

@@ -12,6 +12,7 @@ CREATE TABLE `kku_item_recipes` (
   `consume_group_id` int unsigned DEFAULT NULL COMMENT '消耗组ID',
   `reward_group_id` int unsigned DEFAULT NULL COMMENT '奖励组ID',
   `condition_group_id` int unsigned DEFAULT NULL COMMENT '条件组ID',
+  `display_attributes` json DEFAULT NULL COMMENT '展示属性,以JSON格式存储键值对,用于界面展示和描述的属性',
   `success_rate` decimal(5,2) DEFAULT '100.00' COMMENT '成功率(0-100之间的小数,100 = 100%)',
   `cooldown_seconds` int DEFAULT '0' COMMENT '冷却时间(秒)',
   `category_id` int DEFAULT NULL COMMENT '配方分类ID',

+ 3 - 0
app/Module/GameItems/Models/ItemRecipe.php

@@ -18,6 +18,7 @@ use UCore\ModelCore;
  * @property  int  $consume_group_id  消耗组ID
  * @property  int  $reward_group_id  奖励组ID
  * @property  int  $condition_group_id  条件组ID
+ * @property  \App\Module\GameItems\Casts\RecipeDisplayAttributesCast  $display_attributes  展示属性,以JSON格式存储键值对,用于界面展示和描述的属性
  * @property  float  $success_rate  成功率(0-100之间的小数,100 = 100%)
  * @property  int  $cooldown_seconds  冷却时间(秒)
  * @property  int  $category_id  配方分类ID
@@ -45,6 +46,7 @@ class ItemRecipe extends ModelCore
         'consume_group_id',
         'reward_group_id',
         'condition_group_id',
+        'display_attributes',
         'success_rate',
         'cooldown_seconds',
         'category_id',
@@ -64,6 +66,7 @@ class ItemRecipe extends ModelCore
         'consume_group_id' => 'integer',
         'reward_group_id' => 'integer',
         'condition_group_id' => 'integer',
+        'display_attributes' => \App\Module\GameItems\Casts\RecipeDisplayAttributesCast::class,
         'success_rate' => 'float',
         'cooldown_seconds' => 'integer',
         'category_id' => 'integer',