You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Helper;
use Hyperf\Database\Model\Collection;
use Hyperf\Database\Query\Builder;
use Hyperf\DbConnection\Db as DB;
class DataList implements Logic
{
public $name;
protected $params;
protected $page;
protected $limit;
protected $offset;
protected $pagination;
protected $records = [];
protected $isGroupQuery = false;
protected $withoutPaginate = false;
protected $isQuickPaginate = false;
protected $isSpanRow = false;
/**
* @param array $params 查询数据
*/
public function __construct(array $params = [])
{
$this->params = $params;
$this->check();
$this->init();
}
protected function init()
{
}
protected function beforeGenerate($items)
{
return $items;
}
protected function afterGenerate()
{
}
public function generateRecords($items)
{
$items = $this->beforeGenerate($items);
$this->records = [];
if ($this->isSpanRow) {
foreach ($items as $item) {
$this->records = array_merge($this->records, $this->toArray($item));
}
} else {
foreach ($items as $item) {
$this->records[] = $this->toArray($item);
}
}
$this->afterGenerate();
}
public function toArray($item)
{
return null;
}
public function query()
{
return null;
}
protected function statOffset($page, $limit)
{
return ($page - 1) * $limit;
}
public function paginate(): DataList
{
[$records, $pagination] = $this->doPaginate();
$this->pagination = $pagination;
$this->generateRecords($records);
return $this;
}
public function doPaginate(): array
{
$count = 0;
$this->page = $page = intval($this->params['page'] ?? 1);
$this->limit = $limit = intval($this->params['limit'] ?? 10);
$this->offset = $offset = $this->statOffset($page, $limit);
$records = new Collection([]);
$query = $this->query();
if (is_null($query)) {
$pagination = $this->generatePagination($page, $limit, $this->getCount());
return [$records, $pagination];
}
if ($this->withoutPaginate) {
$searchQuery = clone $query;
return [$searchQuery->get(), null];
}
// 临时快速分页
if ($this->isQuickPaginate) {
return $this->quickPaginate(clone $query, $page, $limit);
} else {
$count = $this->getCount();
if ($count) {
$searchQuery = clone $query;
$records = $searchQuery->offset($offset)->limit($limit)->get();
}
$pagination = $this->generatePagination($page, $limit, $count);
}
return [$records, $pagination];
}
protected function quickPaginate($query, $page, $limit)
{
$count = 1;
$offset = $this->statOffset($page, $limit);
$records = $query->offset($offset)->limit($limit+1)->get();
$recordCount = $records->count();
if ($recordCount < $limit+1) {
$hasMroe = false;
} else {
$records->pop();
$hasMroe = true;
}
$pagination = $this->generatePagination($page, $limit, $count, $hasMroe);
return [$records, $pagination];
}
protected function generatePagination($page, $limit, $count, $hasMroe = false)
{
$pageCount = intval(ceil($count/$limit));
if (! $hasMroe) {
if ($page < $pageCount) {
$hasMroe = true;
}
}
return [
'page' => $page,
'count' => $count,
'page_count' => $pageCount,
'limit' => $limit,
'has_more'=> $hasMroe,
];
}
public function getCount()
{
$query = $this->query();
if (is_null($query)) {
return 0;
}
$countQuery = clone $query;
if ($this->isGroupQuery) {
$countQuery->select([DB::raw('1')]);
return DB::table(DB::raw("({$countQuery->toSql()}) as temp_count_table"))
->mergeBindings($query instanceof Builder ? $countQuery : $countQuery->getQuery())
->count();
} else {
return $countQuery->count();
}
}
public function getPagination(): ?array
{
return $this->pagination;
}
public function setWithoutPaginate($withoutPaginate)
{
$this->withoutPaginate = $withoutPaginate;
return $this;
}
public function getRecords()
{
return $this->records;
}
public function getSummary()
{
return [];
}
public function check()
{
}
/**
* 获取 记录(records)/分页(pagination)/汇总(summary)
* @param array $appendOptions 追加信息一起返回
* @return array
*/
public function all($appendOptions = [])
{
$data = [
'records' => $this->getRecords(),
'pagination' => $this->getPagination(),
'summary' => $this->getSummary(),
];
return array_merge($data, $appendOptions);
}
}