Files
datahub/backend/app/Controller/AbstractDataController.php
2026-03-13 09:33:15 +08:00

161 lines
4.7 KiB
PHP
Raw Permalink 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
declare(strict_types=1);
namespace App\Controller;
use Hyperf\Database\Model\Builder;
use Psr\Http\Message\ResponseInterface;
/**
* 数据实体 Controller 基类
*
* 封装通用的列表分页/筛选/字段选择/DataScope 逻辑,
* 子类仅需定义字段集、筛选规则和 Model 类即可获得完整的列表+详情能力。
*/
abstract class AbstractDataController extends AbstractController
{
/** 实体模型类名 */
abstract protected function getModelClass(): string;
/** 列表返回字段 */
abstract protected function getListFields(): array;
/** 详情返回字段 */
abstract protected function getDetailFields(): array;
/** 允许的筛选参数 => 筛选方式(exact/like/date_from/date_to */
abstract protected function getAllowedFilters(): array;
/** 默认排序字段 */
protected function getDefaultSort(): string
{
return 'created_at';
}
/** 默认排序方向 */
protected function getDefaultSortDirection(): string
{
return 'desc';
}
/**
* 通用列表方法:分页 + 筛选 + DataScope + 字段选择
*/
public function index(): ResponseInterface|array
{
$model_class = $this->getModelClass();
$query = $model_class::query()->select($this->getListFields());
// DataScope 过滤
$this->applyDataScope($query);
// 应用筛选条件
$this->applyFilters($query);
// 排序
$query->orderBy($this->getDefaultSort(), $this->getDefaultSortDirection());
// 分页
$per_page = min((int) ($this->request->input('per_page', 15)), 100);
$per_page = max($per_page, 1);
$page = max((int) ($this->request->input('page', 1)), 1);
$total = $query->count();
$items = $query->offset(($page - 1) * $per_page)
->limit($per_page)
->get();
return [
'code' => 0,
'message' => '获取成功',
'data' => [
'items' => $items,
'total' => $total,
'page' => $page,
'per_page' => $per_page,
],
];
}
/**
* 通用详情方法:字段选择 + DataScope 校验
*/
public function show(int $id): ResponseInterface|array
{
$model_class = $this->getModelClass();
$fields = $this->getDetailFields();
$query = $model_class::query();
if ($fields !== ['*']) {
$query->select($fields);
}
// DataScope 过滤(确保只能查看权限范围内的数据)
$this->applyDataScope($query);
$record = $query->where('id', $id)->first();
if (!$record) {
return $this->response->json([
'code' => 404,
'message' => '数据不存在',
])->withStatus(404);
}
return [
'code' => 0,
'message' => '获取成功',
'data' => $record,
];
}
/**
* 应用 DataScope 过滤
*
* 读取 PermissionMiddleware 注入的 scope_type / scope_ids 属性,
* 自动添加 WHERE 条件限制查询范围。
*/
protected function applyDataScope(Builder $query): void
{
$scope_type = $this->request->getAttribute('scope_type');
$scope_ids = $this->request->getAttribute('scope_ids', []);
if ($scope_type === 'store') {
$query->whereIn('store_id', $scope_ids);
} elseif ($scope_type === 'platform') {
$query->whereIn('platform_id', $scope_ids);
}
// 'all' → 不附加条件
}
/**
* 应用筛选条件
*
* 根据 getAllowedFilters() 定义的参数名和筛选方式,
* 从请求参数中提取值并构建 WHERE 子句。
*
* 支持的筛选方式:
* - exact: 精确匹配(WHERE col = value
* - like: 模糊搜索(WHERE col ILIKE %value%
* - date_from: 日期下界(WHERE col >= value),参数名需以 _from 结尾
* - date_to: 日期上界(WHERE col <= value 23:59:59),参数名需以 _to 结尾
*/
protected function applyFilters(Builder $query): void
{
foreach ($this->getAllowedFilters() as $param => $type) {
$value = $this->request->input($param);
if ($value === null || $value === '') {
continue;
}
match ($type) {
'exact' => $query->where($param, $value),
'like' => $query->where($param, 'ilike', "%{$value}%"),
'date_from' => $query->where(str_replace('_from', '', $param), '>=', $value),
'date_to' => $query->where(str_replace('_to', '', $param), '<=', $value . ' 23:59:59'),
};
}
}
}