| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- <?php
- namespace App\Module\Farm\AdminControllers\Helper;
- use App\Module\Farm\Enums\BUFF_TYPE;
- use App\Module\Farm\Enums\DISASTER_TYPE;
- use App\Module\Farm\Enums\GROWTH_STAGE;
- use App\Module\Farm\Enums\LAND_STATUS;
- use App\Module\Farm\Enums\LAND_TYPE;
- use App\Module\Farm\Enums\SEED_TYPE;
- use App\Module\Farm\Enums\UPGRADE_TYPE;
- use Dcat\Admin\Grid;
- use Dcat\Admin\Grid\Column;
- /**
- * 列表页辅助特性
- *
- * 提供农场模块后台控制器的列表页构建功能的具体实现
- */
- trait GridHelperTrait
- {
- /**
- * 添加神灵加持类型列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnBuffType(string $field = 'buff_type', string $label = '加持类型'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return BUFF_TYPE::getName($value);
- });
- }
- /**
- * 添加灾害类型列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnDisasterType(string $field = 'disaster_type', string $label = '灾害类型'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return DISASTER_TYPE::getName($value);
- });
- }
- /**
- * 添加土地状态列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnLandStatus(string $field = 'status', string $label = '土地状态'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return LAND_STATUS::getName($value);
- })->label([
- LAND_STATUS::IDLE->value => 'default',
- LAND_STATUS::PLANTING->value => 'primary',
- LAND_STATUS::DISASTER->value => 'warning',
- LAND_STATUS::HARVESTABLE->value => 'success',
- LAND_STATUS::WITHERED->value => 'danger',
- ]);
- }
- /**
- * 添加土地类型列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnLandType(string $field = 'land_type', string $label = '土地类型'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return LAND_TYPE::getName($value);
- })->label([
- LAND_TYPE::NORMAL->value => 'default',
- LAND_TYPE::RED->value => 'danger',
- LAND_TYPE::BLACK->value => 'dark',
- LAND_TYPE::GOLD->value => 'warning',
- LAND_TYPE::BLUE->value => 'info',
- LAND_TYPE::PURPLE->value => 'primary',
- ]);
- }
- /**
- * 添加产出详情列
- *
- * 展示该土地类型的作物种类概率和产量
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnOutputDetails(string $field = 'output_details', string $label = '产出详情'): Column
- {
- return $this->grid->column($field, $label)->display(function () {
- // 获取当前土地类型
- $landType = $this;
- $html = '<div class="output-details">';
- $html .= '<div class="mb-2"><strong>' . htmlspecialchars($landType->name) . ' (产量加成:' . ($landType->output_bonus * 100) . '%)</strong></div>';
- // 1. 显示神秘种子的产出概率和产量
- $html .= self::renderMysterySeeLOutputs($landType);
- // 2. 显示普通种子的产出
- $html .= self::renderNormalSeeLOutputs($landType);
- $html .= '</div>';
- return $html;
- })->width(500);
- }
- /**
- * 渲染神秘种子的产出详情
- *
- * 使用服务层逻辑计算神秘种子在该土地类型上的产出概率和产量
- *
- * @param \App\Module\Farm\Models\FarmLandType $landType
- * @return string
- */
- private static function renderMysterySeeLOutputs($landType): string
- {
- // 获取神秘种子
- $mysterySeeds = \App\Module\Farm\Models\FarmSeed::where('type', \App\Module\Farm\Enums\SEED_TYPE::MYSTERIOUS->value)->get();
- if ($mysterySeeds->isEmpty()) {
- return '';
- }
- $html = '<div class="mb-3">';
- $html .= '<h6 class="text-info">神秘种子产出概率</h6>';
- foreach ($mysterySeeds as $seed) {
- try {
- // 使用服务层逻辑计算概率
- $mysteryLogic = new \App\Module\Farm\Logics\MysterySeeLLogic();
- $adjustedOutputs = $mysteryLogic->calculateAdjustedProbabilities($seed->id, $landType->id);
- $html .= '<div class="mb-2">';
- $html .= '<strong>' . htmlspecialchars($seed->name) . ':</strong>';
- $html .= '<div class="table-responsive">';
- $html .= '<table class="table table-sm table-bordered">';
- $html .= '<thead><tr><th>产出物品</th><th>概率</th><th>正常产量</th><th>灾害产量</th><th>应用土地加成后(正常)</th><th>应用土地加成后(灾害)</th></tr></thead>';
- $html .= '<tbody>';
- foreach ($adjustedOutputs as $output) {
- // 跳过概率为0的产出
- if ($output['adjusted_probability'] <= 0) {
- continue;
- }
- $itemName = self::getItemName($output['item_id']);
- $probability = number_format($output['adjusted_probability'], 2) . '%';
- // 正常产量范围
- $normalMin = $output['min_amount'];
- $normalMax = $output['max_amount'];
- // 灾害产量范围 - 现在从服务层获取正确的数据
- $disasterMin = $output['disaster_min_amount'] ?? $output['min_amount'];
- $disasterMax = $output['disaster_max_amount'] ?? $output['max_amount'];
- // 应用土地加成后的产量
- $normalBonusMin = (int)($normalMin * (1 + $landType->output_bonus));
- $normalBonusMax = (int)($normalMax * (1 + $landType->output_bonus));
- $disasterBonusMin = (int)($disasterMin * (1 + $landType->output_bonus));
- $disasterBonusMax = (int)($disasterMax * (1 + $landType->output_bonus));
- $html .= '<tr>';
- $html .= '<td>' . htmlspecialchars($itemName) . '</td>';
- $html .= '<td><span class="badge badge-info">' . $probability . '</span></td>';
- $html .= '<td>' . $normalMin . '-' . $normalMax . '</td>';
- $html .= '<td class="text-warning">' . $disasterMin . '-' . $disasterMax . '</td>';
- $html .= '<td class="text-success"><strong>' . $normalBonusMin . '-' . $normalBonusMax . '</strong></td>';
- $html .= '<td class="text-danger"><strong>' . $disasterBonusMin . '-' . $disasterBonusMax . '</strong></td>';
- $html .= '</tr>';
- }
- $html .= '</tbody></table>';
- $html .= '</div>';
- $html .= '</div>';
- } catch (\Exception $e) {
- $html .= '<div class="text-danger">计算神秘种子概率失败:' . htmlspecialchars($e->getMessage()) . '</div>';
- }
- }
- $html .= '</div>';
- return $html;
- }
- /**
- * 渲染普通种子的产出详情
- *
- * @param \App\Module\Farm\Models\FarmLandType $landType
- * @return string
- */
- private static function renderNormalSeeLOutputs($landType): string
- {
- // 获取普通种子的产出配置
- $normalOutputs = \App\Module\Farm\Models\FarmSeedOutput::with(['seed', 'item'])
- ->whereHas('seed', function($query) {
- $query->where('type', '!=', \App\Module\Farm\Enums\SEED_TYPE::MYSTERIOUS->value);
- })
- ->where('is_default', true)
- ->get();
- if ($normalOutputs->isEmpty()) {
- return '';
- }
- $html = '<div class="mb-3">';
- $html .= '<h6 class="text-success">普通种子产出</h6>';
- $html .= '<div class="table-responsive">';
- $html .= '<table class="table table-sm table-bordered">';
- $html .= '<thead><tr><th>种子</th><th>产出物品</th><th>正常产量</th><th>灾害产量</th><th>应用土地加成后(正常)</th><th>应用土地加成后(灾害)</th></tr></thead>';
- $html .= '<tbody>';
- foreach ($normalOutputs as $output) {
- $seedName = $output->seed->name ?? "种子{$output->seed_id}";
- $itemName = $output->item->name ?? "物品{$output->item_id}";
- // 正常产量范围
- $normalMin = $output->min_amount;
- $normalMax = $output->max_amount;
- // 灾害产量范围
- $disasterMin = $output->disaster_min_amount ?? $output->min_amount;
- $disasterMax = $output->disaster_max_amount ?? $output->max_amount;
- // 应用土地加成后的产量
- $normalBonusMin = (int)($normalMin * (1 + $landType->output_bonus));
- $normalBonusMax = (int)($normalMax * (1 + $landType->output_bonus));
- $disasterBonusMin = (int)($disasterMin * (1 + $landType->output_bonus));
- $disasterBonusMax = (int)($disasterMax * (1 + $landType->output_bonus));
- $html .= '<tr>';
- $html .= '<td>' . htmlspecialchars($seedName) . '</td>';
- $html .= '<td>' . htmlspecialchars($itemName) . '</td>';
- $html .= '<td>' . $normalMin . '-' . $normalMax . '</td>';
- $html .= '<td class="text-warning">' . $disasterMin . '-' . $disasterMax . '</td>';
- $html .= '<td class="text-success"><strong>' . $normalBonusMin . '-' . $normalBonusMax . '</strong></td>';
- $html .= '<td class="text-danger"><strong>' . $disasterBonusMin . '-' . $disasterBonusMax . '</strong></td>';
- $html .= '</tr>';
- }
- $html .= '</tbody></table>';
- $html .= '</div>';
- $html .= '</div>';
- return $html;
- }
- /**
- * 获取物品名称
- *
- * @param int $itemId
- * @return string
- */
- private static function getItemName(int $itemId): string
- {
- try {
- $item = \App\Module\GameItems\Models\Item::find($itemId);
- return $item ? $item->name : "物品{$itemId}";
- } catch (\Exception $e) {
- return "物品{$itemId}";
- }
- }
- /**
- * 添加种子类型列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnSeedType(string $field = 'type', string $label = '种子类型'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return SEED_TYPE::getName($value);
- })->label([
- SEED_TYPE::NORMAL->value => 'default',
- SEED_TYPE::MYSTERIOUS->value => 'primary',
- SEED_TYPE::GIANT->value => 'success',
- ]);
- }
- /**
- * 添加升级类型列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnUpgradeType(string $field = 'upgrade_type', string $label = '升级类型'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return UPGRADE_TYPE::getName($value);
- })->label([
- UPGRADE_TYPE::LAND->value => 'primary',
- UPGRADE_TYPE::HOUSE->value => 'success',
- ]);
- }
- /**
- * 添加灾害情况列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnDisasters(string $field = 'disasters', string $label = '灾害情况'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- if (empty($value)) {
- return '无灾害';
- }
- $disasters = json_decode($value, true);
- if (empty($disasters)) {
- return '无灾害';
- }
- $result = [];
- foreach ($disasters as $type => $time) {
- $disasterName = DISASTER_TYPE::getName((int)$type);
- $result[] = $disasterName;
- }
- return implode('<br>', $result);
- });
- }
- /**
- * 添加是否施肥列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnFertilized(string $field = 'fertilized', string $label = '已施肥'): Column
- {
- return $this->grid->column($field, $label)->bool();
- }
- /**
- * 添加产量加成列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnOutputBonus(string $field = 'output_bonus', string $label = '产量加成'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return ($value * 100) . '%';
- });
- }
- /**
- * 添加灾害抵抗列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnDisasterResistance(string $field = 'disaster_resistance', string $label = '灾害抵抗'): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- return ($value * 100) . '%';
- });
- }
- /**
- * 添加是否特殊土地列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnIsSpecial(string $field = 'is_special', string $label = '特殊土地'): Column
- {
- return $this->grid->column($field, $label)->bool();
- }
- /**
- * 添加种子列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @param bool $showType 是否显示种子类型
- * @return Column
- */
- public function columnSeed(string $field = 'seed_id', string $label = '种子', bool $showType = true): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) use ($showType) {
- if (empty($value)) {
- return '-';
- }
- // 尝试获取种子名称
- $seed = \App\Module\Farm\Models\FarmSeed::find($value);
- if ($seed) {
- $html = "<span class='badge badge-primary'>{$seed->name}</span>";
- if ($showType) {
- $typeName = \App\Module\Farm\Enums\SEED_TYPE::getName($seed->type);
- $html .= " <span class='badge badge-info'>{$typeName}</span>";
- }
- // 如果有关联的物品ID,尝试获取物品名称
- if ($seed->item_id) {
- try {
- $item = \App\Module\GameItems\Models\Item::find($seed->item_id);
- if ($item) {
- $html .= "<br><small>物品: {$item->name} (ID: {$item->id})</small>";
- }
- } catch (\Exception $e) {
- // 忽略异常,只是不显示物品信息
- }
- }
- return $html;
- }
- return $value;
- });
- }
- /**
- * 添加物品列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @param bool $showType 是否显示物品类型
- * @return Column
- */
- public function columnItem(string $field = 'item_id', string $label = '物品', bool $showType = true): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) use ($showType) {
- if (empty($value)) {
- return '-';
- }
- // 尝试获取物品名称
- try {
- $item = \App\Module\GameItems\Models\Item::find($value);
- if ($item) {
- $html = "<span class='badge badge-success'>{$item->name}</span>";
- if ($showType && isset($item->type)) {
- try {
- $typeName = \App\Module\GameItems\Enums\ITEM_TYPE::getName($item->type);
- $html .= " <span class='badge badge-info'>{$typeName}</span>";
- } catch (\Exception $e) {
- // 忽略异常,只是不显示类型信息
- }
- }
- return $html;
- }
- } catch (\Exception $e) {
- // 忽略异常,只是不显示物品信息
- }
- return $value;
- });
- }
- /**
- * 添加模型Cast JSON列
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnModelCatsJson(string $field, string $label): Column
- {
- return $this->grid->column($field, $label)->display(function ($value) {
- if (empty($value)) {
- return '-';
- }
- if (is_string($value)) {
- $value = json_decode($value, true);
- } elseif (is_object($value)) {
- $value = (array)$value;
- }
- if (!is_array($value)) {
- return '-';
- }
- $html = '<div class="table-responsive"><table class="table table-sm table-bordered">';
- $html .= '<thead><tr><th>属性</th><th>值</th></tr></thead>';
- $html .= '<tbody>';
- foreach ($value as $key => $val) {
- if (is_array($val) || is_object($val)) {
- $val = json_encode($val, JSON_UNESCAPED_UNICODE);
- }
- $html .= "<tr><td>{$key}</td><td>{$val}</td></tr>";
- }
- $html .= '</tbody></table></div>';
- return $html;
- });
- }
- /**
- * 添加消耗组详情列
- *
- * 展示消耗组的名称和详细内容
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnConsumeGroupDetails(string $field = 'materials', string $label = '消耗组详情'): Column
- {
- return $this->grid->column($field, $label)->display(function ($materialsGroupId) {
- if (!$materialsGroupId) {
- return '<span class="text-muted">使用 materials 字段</span>';
- }
- $consumeGroup = \App\Module\Game\Models\GameConsumeGroup::with('consumeItems')->find($materialsGroupId);
- if (!$consumeGroup) {
- return '<span class="text-danger">未知消耗组 (ID: ' . $materialsGroupId . ')</span>';
- }
- $html = '<div class="consume-group-details">';
- $html .= '<div class="mb-2"><strong>' . htmlspecialchars($consumeGroup->name) . ' (' . htmlspecialchars($consumeGroup->code) . ')</strong></div>';
- if ($consumeGroup->consumeItems->isEmpty()) {
- $html .= '<div class="text-muted">暂无消耗项</div>';
- } else {
- $html .= '<div class="table-responsive">';
- $html .= '<table class="table table-sm table-bordered">';
- $html .= '<thead><tr><th>消耗类型</th><th>目标</th><th>数量</th></tr></thead>';
- $html .= '<tbody>';
- foreach ($consumeGroup->consumeItems as $item) {
- $typeName = \App\Module\Game\Enums\CONSUME_TYPE::getName($item->consume_type);
- $targetName = $item->getTargetName();
- $html .= '<tr>';
- $html .= '<td><span class="badge badge-info">' . htmlspecialchars($typeName) . '</span></td>';
- $html .= '<td>' . htmlspecialchars($targetName) . '</td>';
- $html .= '<td class="text-success"><strong>' . number_format($item->quantity) . '</strong></td>';
- $html .= '</tr>';
- }
- $html .= '</tbody></table>';
- $html .= '</div>';
- }
- $html .= '</div>';
- return $html;
- })->width(300);
- }
- /**
- * 添加条件组详情列
- *
- * 展示条件组的名称和详细内容
- *
- * @param string $field 字段名
- * @param string $label 标签名
- * @return Column
- */
- public function columnConditionGroupDetails(string $field = 'conditions', string $label = '条件组详情'): Column
- {
- return $this->grid->column($field, $label)->display(function ($conditionsGroupId) {
- if (!$conditionsGroupId) {
- return '<span class="text-muted">使用 conditions 字段</span>';
- }
- $conditionGroup = \App\Module\Game\Models\GameConditionGroup::with('conditionItems')->find($conditionsGroupId);
- if (!$conditionGroup) {
- return '<span class="text-danger">未知条件组 (ID: ' . $conditionsGroupId . ')</span>';
- }
- $html = '<div class="condition-group-details">';
- $html .= '<div class="mb-2"><strong>' . htmlspecialchars($conditionGroup->name) . ' (' . htmlspecialchars($conditionGroup->code) . ')</strong></div>';
- if ($conditionGroup->conditionItems->isEmpty()) {
- $html .= '<div class="text-muted">暂无条件项</div>';
- } else {
- $html .= '<div class="table-responsive">';
- $html .= '<table class="table table-sm table-bordered">';
- $html .= '<thead><tr><th>条件类型</th><th>目标</th><th>操作符</th><th>要求值</th></tr></thead>';
- $html .= '<tbody>';
- foreach ($conditionGroup->conditionItems as $item) {
- $typeName = \App\Module\Game\Enums\CONDITION_TYPE::getName($item->condition_type);
- $targetName = \App\Module\Game\Services\ConditionTypeDescriptor::getTargetNameFromModel($item);
- $operatorName = self::getOperatorName($item->operator);
- $html .= '<tr>';
- $html .= '<td><span class="badge badge-primary">' . htmlspecialchars($typeName) . '</span></td>';
- $html .= '<td>' . htmlspecialchars($targetName) . '</td>';
- $html .= '<td><span class="badge badge-secondary">' . htmlspecialchars($operatorName) . '</span></td>';
- $html .= '<td class="text-success"><strong>' . number_format($item->value) . '</strong></td>';
- $html .= '</tr>';
- }
- $html .= '</tbody></table>';
- $html .= '</div>';
- }
- $html .= '</div>';
- return $html;
- })->width(300);
- }
- /**
- * 获取操作符名称
- *
- * @param int $operator
- * @return string
- */
- private static function getOperatorName(int $operator): string
- {
- $operators = [
- 1 => '等于',
- 2 => '不等于',
- 3 => '小于',
- 4 => '大于等于',
- 5 => '小于等于',
- 6 => '大于',
- ];
- return $operators[$operator] ?? "未知操作符({$operator})";
- }
- }
|