Files
webman-buildadmin/app/admin/controller/game/Config.php

279 lines
8.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\admin\controller\game;
use Throwable;
use app\common\controller\Backend;
use support\Response;
use Webman\Http\Request as WebmanRequest;
/**
* 游戏配置
*/
class Config extends Backend
{
/**
* GameConfig模型对象
* @var object|null
* @phpstan-var \app\common\model\GameConfig|null
*/
protected ?object $model = null;
protected string|array $defaultSortField = 'group,desc';
protected array $withJoinTable = ['channel'];
protected array|string $preExcludeFields = ['create_time', 'update_time'];
protected string|array $quickSearchField = ['ID'];
/** 权重之和必须为 100 的配置标识 */
private const WEIGHT_SUM_100_NAMES = ['default_tier_weight', 'default_kill_score_weight'];
protected function initController(WebmanRequest $request): ?Response
{
$this->model = new \app\common\model\GameConfig();
return null;
}
/**
* @throws Throwable
*/
protected function _add(): Response
{
if ($this->request && $this->request->method() === 'POST') {
$data = $this->request->post();
if (!$data) {
return $this->error(__('Parameter %s can not be empty', ['']));
}
$data = $this->applyInputFilter($data);
$data = $this->excludeFields($data);
$err = $this->validateGameWeightPayload($data, null);
if ($err !== null) {
return $this->error($err);
}
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$data[$this->dataLimitField] = $this->auth->id;
}
$result = false;
$this->model->startTrans();
try {
if ($this->modelValidate) {
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
if (class_exists($validate)) {
$validate = new $validate();
if ($this->modelSceneValidate) {
$validate->scene('add');
}
$validate->check($data);
}
}
$result = $this->model->save($data);
$this->model->commit();
} catch (Throwable $e) {
$this->model->rollback();
return $this->error($e->getMessage());
}
if ($result !== false) {
return $this->success(__('Added successfully'));
}
return $this->error(__('No rows were added'));
}
return $this->error(__('Parameter error'));
}
/**
* @throws Throwable
*/
protected function _edit(): Response
{
$pk = $this->model->getPk();
$id = $this->request ? ($this->request->post($pk) ?? $this->request->get($pk)) : null;
$row = $this->model->find($id);
if (!$row) {
return $this->error(__('Record not found'));
}
$dataLimitAdminIds = $this->getDataLimitAdminIds();
if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
return $this->error(__('You have no permission'));
}
if ($this->request && $this->request->method() === 'POST') {
$data = $this->request->post();
if (!$data) {
return $this->error(__('Parameter %s can not be empty', ['']));
}
$data = $this->applyInputFilter($data);
$data = $this->excludeFields($data);
if (!$this->auth->isSuperAdmin()) {
$data['channel_id'] = $row['channel_id'];
$data['group'] = $row['group'];
$data['name'] = $row['name'];
$data['title'] = $row['title'];
}
$err = $this->validateGameWeightPayload($data, $row['value'] ?? null);
if ($err !== null) {
return $this->error($err);
}
$result = false;
$this->model->startTrans();
try {
if ($this->modelValidate) {
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
if (class_exists($validate)) {
$validate = new $validate();
if ($this->modelSceneValidate) {
$validate->scene('edit');
}
$data[$pk] = $row[$pk];
$validate->check($data);
}
}
$result = $row->save($data);
$this->model->commit();
} catch (Throwable $e) {
$this->model->rollback();
return $this->error($e->getMessage());
}
if ($result !== false) {
return $this->success(__('Update successful'));
}
return $this->error(__('No rows updated'));
}
return $this->success('', [
'row' => $row
]);
}
/**
* game_weight校验数值、键不可改编辑、和为 100特定 name
*
* @param array<string, mixed> $data
*/
private function validateGameWeightPayload(array $data, ?string $originalValue): ?string
{
$group = $data['group'] ?? '';
if ($group !== 'game_weight') {
return null;
}
$name = $data['name'] ?? '';
$value = $data['value'] ?? '';
if (!is_string($value)) {
return __('Parameter error');
}
$decoded = json_decode($value, true);
if (!is_array($decoded)) {
return __('Parameter error');
}
$keys = [];
$numbers = [];
foreach ($decoded as $item) {
if (!is_array($item)) {
return __('Parameter error');
}
foreach ($item as $k => $v) {
$keys[] = $k;
if (!is_numeric($v)) {
return __('Game config weight value must be numeric');
}
$num = (float) $v;
if ($num > 100) {
return __('Game config weight each value must not exceed 100');
}
$numbers[] = $num;
}
}
if (count($numbers) === 0) {
return __('Parameter %s can not be empty', ['value']);
}
if ($originalValue !== null && $originalValue !== '') {
$oldKeys = $this->extractGameWeightKeys($originalValue);
if ($oldKeys !== $keys) {
return __('Game config weight keys cannot be modified');
}
}
if (in_array($name, self::WEIGHT_SUM_100_NAMES, true)) {
$sum = array_sum($numbers);
if (abs($sum - 100.0) > 0.000001) {
return __('Game config weight sum must equal 100');
}
}
return null;
}
/**
* @return list<string>
*/
private function extractGameWeightKeys(string $value): array
{
$decoded = json_decode($value, true);
if (!is_array($decoded)) {
return [];
}
$keys = [];
foreach ($decoded as $item) {
if (!is_array($item)) {
continue;
}
foreach ($item as $k => $_) {
$keys[] = $k;
}
}
return $keys;
}
/**
* 查看
* @throws Throwable
*/
protected function _index(): Response
{
// 如果是 select 则转发到 select 方法,若未重写该方法,其实还是继续执行 index
if ($this->request && $this->request->get('select')) {
return $this->select($this->request);
}
/**
* 1. withJoin 不可使用 alias 方法设置表别名,别名将自动使用关联模型名称(小写下划线命名规则)
* 2. 以下的别名设置了主表别名,同时便于拼接查询参数等
* 3. paginate 数据集可使用链式操作 each(function($item, $key) {}) 遍历处理
*/
list($where, $alias, $limit, $order) = $this->queryBuilder();
$res = $this->model
->withJoin($this->withJoinTable, $this->withJoinType)
->with($this->withJoinTable)
->visible(['channel' => ['name']])
->alias($alias)
->where($where)
->order($order)
->paginate($limit);
return $this->success('', [
'list' => $res->items(),
'total' => $res->total(),
'remark' => get_route_remark(),
]);
}
/**
* 若需重写查看、编辑、删除等方法,请复制 @see \app\admin\library\traits\Backend 中对应方法至此进行重写
*/
}