diff --git a/app/Model/Campus.php b/app/Model/Campus.php index bc7ce3e..79d9719 100644 --- a/app/Model/Campus.php +++ b/app/Model/Campus.php @@ -51,6 +51,12 @@ class Campus extends AetherModel 'deleted_at' => 'datetime', ]; + protected array $search = [ + 'parent_id' => '=', + ]; + + protected array|bool|string $sortable = false; + /** * 获取父级校区. * @return BelongsTo diff --git a/extend/Aether/PHP/Hyperf/AetherModel.php b/extend/Aether/PHP/Hyperf/AetherModel.php index 8cca9e9..06b8c99 100644 --- a/extend/Aether/PHP/Hyperf/AetherModel.php +++ b/extend/Aether/PHP/Hyperf/AetherModel.php @@ -63,7 +63,7 @@ abstract class AetherModel extends HyperfModel implements CacheableInterface * - 字符串: 排序字段(默认升序) * - 数组: ['field' => '字段名', 'direction' => 'asc/desc']. */ - protected array|bool|string $sortable = 'sort'; // 默认按sort字段升序 + protected array|bool|string $sortable = false; // 'sort'; // 默认按sort字段升序 public function __construct(array $attributes = []) { @@ -140,12 +140,101 @@ abstract class AetherModel extends HyperfModel implements CacheableInterface /** * 列表查询. */ + // public function list(array $params = []): array + // { + // $query = $this->buildQueryFromParams($params); + // return $this->listResult($query, $params); + // } + public function list(array $params = []): array { - $query = $this->buildQueryFromParams($params); - return $this->listResult($query, $params); + $query = static::query(); + + // 通过模型配置自动应用所有搜索条件 + $this->applySearch($query, $params); + + // 动态应用排序 + if ($this->sortable) { + $sortConfig = $this->getSortConfig(); + $query->orderBy($sortConfig['field'], $sortConfig['direction']); + } + + $withDeleted = filter_var($params['with_deleted'] ?? false, FILTER_VALIDATE_BOOLEAN); + if ($withDeleted) { + $query->withTrashed(); + } + + // 存在分页参数(page或size)则进行分页查询 + if (isset($params['page']) || isset($params['size'])) { + $page = (int) ($params['page'] ?? 1); + $size = (int) ($params['size'] ?? 10); + // 确保分页参数合法性 + $page = max(1, $page); + $size = max(1, min(100, $size)); // 限制最大页大小为100 + + $result = $query->paginate($size, ['*'], 'page', $page); + return [ + 'list' => $result->items(), + 'total' => $result->total(), + ]; + } + + // 无分页参数时返回完整数据集合 + $items = $query->get()->toArray(); + + // 若模型支持树形结构则构建树形,否则返回普通数组 + if ($this instanceof TreeableInterface) { + return $this::buildTree($items, (int) ($params['parent_id'] ?? 0)); + } + + return $items; } + /** + * 根据模型的$search配置,自动应用搜索条件到查询构建器. + */ + // public function applySearch(Builder $query, array $params): void + // { + // foreach ($this->search as $field => $rule) { + // // 跳过未传递的参数 + // if (!isset($params[$field])) { + // continue; + // } + // + // $value = $params[$field]; + // $this->applySearchRule($query, $field, $value, $rule); + // } + // } + // + // /** + // * 应用单个搜索规则 + // */ + // protected function applySearchRule(Builder $query, string $field, $value, $rule): void + // { + // // 处理规则格式(支持字符串简写或数组配置) + // $config = is_array($rule) ? $rule : ['type' => $rule]; + // $type = $config['type']; + // + // switch ($type) { + // case '=': // 精确匹配 + // $query->where($field, $value); + // break; + // case 'like': // 模糊匹配 + // $query->where($field, 'like', "%{$value}%"); + // break; + // case 'between': // 范围查询(支持数组或两个参数) + // $values = is_array($value) ? $value : [$value, $params[$field . '_end'] ?? $value]; + // $query->whereBetween($field, $values); + // break; + // case 'callback': // 自定义回调 + // if (isset($config['handler']) && is_callable($config['handler'])) { + // call_user_func($config['handler'], $query, $value); + // } + // break; + // // 可扩展其他类型:in、>、< 等 + // } + // } + /** * 快捷创建. */ @@ -293,30 +382,6 @@ abstract class AetherModel extends HyperfModel implements CacheableInterface return Db::transaction($closure); } - /** - * 根据参数构建查询. - */ - protected function buildQueryFromParams(array $params = []): Builder - { - // 创建查询构建器 - $query = static::query(); - - // 应用搜索条件 - // if (isset($params['search'])) { - // $this->applySearch($query, $params['search']); - // } - $this->applySearch($query, $params); - // 应用排序 - $this->applySorting($query, $params); - - // 处理软删除 - if (isset($params['withTrashed']) && $params['withTrashed']) { - $query->withTrashed(); - } - - return $query; - } - /** * 应用排序. */ @@ -527,35 +592,35 @@ abstract class AetherModel extends HyperfModel implements CacheableInterface protected function applySearch(Builder $query, array $conditions): void { foreach ($conditions as $field => $value) { - // 跳过非字符串的字段名(防止索引数组键导致的类型错误) - if (! is_string($field)) { + // 基础过滤:非字符串字段名或未设置值的参数直接跳过 + if (! is_string($field) || ! isset($value)) { continue; } - // 处理嵌套关系查询(如:user.name) + // 核心限制:只处理$search数组中定义的字段 + if (! isset($this->search[$field])) { + continue; + } + + // 处理嵌套关系查询(如:user.name,需在$search中配置完整键名) if (str_contains($field, '.')) { [$relation, $relationField] = explode('.', $field, 2); $query->whereHas($relation, function ($q) use ($relationField, $value) { + // 嵌套查询默认使用精确匹配,如需特殊规则可在$search中自定义处理 $q->where($relationField, $value); }); continue; } - // 检查是否有自定义搜索器方法 + // 优先使用自定义搜索器方法(仅对$search中存在的字段生效) $searchMethod = 'search' . ucfirst($field); if (method_exists($this, $searchMethod)) { $this->{$searchMethod}($query, $value); continue; } - // 应用搜索规则配置 - if (isset($this->search[$field])) { - $this->applySearchRule($query, $field, $value, $this->search[$field]); - continue; - } - - // 默认精确匹配(仅对$search中允许的字段生效,因已通过白名单过滤) - $query->where($field, $value); + // 应用$search中定义的搜索规则(如=、like等) + $this->applySearchRule($query, $field, $value, $this->search[$field]); } } diff --git a/extend/Aether/PHP/Hyperf/RpcExceptionHandler.php b/extend/Aether/PHP/Hyperf/RpcExceptionHandler.php index e43240c..169f6df 100644 --- a/extend/Aether/PHP/Hyperf/RpcExceptionHandler.php +++ b/extend/Aether/PHP/Hyperf/RpcExceptionHandler.php @@ -16,7 +16,6 @@ class RpcExceptionHandler extends ExceptionHandler { public function handle(Throwable $throwable, ResponseInterface $response): ResponseInterface { - var_dump($throwable->getMessage()); try { // 获取请求ID(用于日志追踪) $requestId = Context::get('request_id', '');