model = new \app\common\model\GameConfig(); return null; } /** * 将「可访问管理员 ID」转为「其负责的渠道 ID」,供 queryBuilder 使用 channel_id IN (...) * * @return list */ protected function getDataLimitAdminIds(): array { if (!$this->dataLimit || !$this->auth || $this->auth->isSuperAdmin()) { return []; } $adminIds = parent::getDataLimitAdminIds(); if ($adminIds === []) { return []; } $channelIds = Db::name('game_channel')->where('admin_id', 'in', $adminIds)->column('id'); if ($channelIds === []) { return [-1]; } return array_values(array_unique($channelIds)); } /** * @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->auth->isSuperAdmin()) { $allowedChannelIds = $this->getDataLimitAdminIds(); $cid = $data['channel_id'] ?? null; if ($cid === null || $cid === '') { return $this->error(__('Parameter %s can not be empty', ['channel_id'])); } if ($allowedChannelIds !== [] && !in_array($cid, $allowedChannelIds)) { return $this->error(__('You have no permission')); } } $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 $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 */ 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 中对应方法至此进行重写 */ }