Files
pingan_unionpay_new/app/Admin/Exporters/NewCouponExport.php
2023-02-03 13:11:10 +08:00

288 lines
8.7 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\Exporters;
use Encore\Admin\Grid\Exporters\ExcelExporter;
class NewCouponExport extends ExcelExporter
{
protected $fileName = null;
protected $debug = false;
protected $dealColumnList = [];
protected $columnCallback = null;
protected $addColumnList = [];
protected $appendColumn = [];
protected $perLimit = 1500;
/**
* 导出
*
* @return mixed|void
*/
public function export()
{
$model = $this;
$grid = $this->grid;
$columns = $this->getColumns();
$columns = $this->addingColumn($columns);
$call_back = function ($page, $limit) use ($model, $grid, $columns) {
$model->page = $page;
$grid->paginate($limit);
$model->setGrid($grid);
request()->offsetSet('per_page', $limit);
$list = $model->getQuery()->get()->toArray();
$list = $this->dealColumn($columns, $list);
if ($this->columnCallback) {
$list = call_user_func($this->columnCallback, $columns, $list);
}
return $list;
};
if ($this->debug) {
dd($columns, call_user_func($call_back, 1, 20));
}
$file_name = $this->fileName ? $this->fileName : $this->getTable().date('YmdHis');
$data_count = $this->getQuery()->count();
$perPage = request()->get('per_page', $this->perLimit);
$this->exportCsv($file_name, $columns, $call_back, $data_count, $perPage);
}
/**
* 设置文件名
*
* @param null $file_name
*/
public function setName($file_name = null)
{
if ($file_name) {
$this->fileName = $file_name;
}
}
/**
* Notes: 设置处理字段值的规则
*
* @Author: 玄尘
* @Date: 2023/2/1 15:42
* @param $column
* @param \Closure $call_back
*/
public function setColumn($column, \Closure $call_back)
{
$this->dealColumnList[$column] = $call_back;
}
/**
* 添加字段
*
* @param $column
* @param $name
* @param null|string|\Closure $after_column
* @param null|\Closure $call_back
*/
public function addColumn($column, $name, $after_column = null, $call_back = null)
{
if ($after_column instanceof \Closure) {
$this->addColumnList[$column] = $after_column;
$this->appendColumn[$column] = [$name, null];
} else {
if ($call_back instanceof \Closure) {
$this->addColumnList[$column] = $call_back;
$this->appendColumn[$column] = [$name, $after_column];
} else {
$this->appendColumn[$column] = [$name, $after_column];
}
}
}
/**
* 正式追加字段
*
* @param $columns
* @return array
*/
protected function addingColumn($columns): array
{
if (! $this->appendColumn) {
return $columns;
}
$keys = array_keys($columns);
foreach ($this->appendColumn as $column => $item) {
list ($name, $after_column) = $item;
if (! empty($after_column) && in_array($after_column, $keys)) {
$index = array_search($after_column, $keys);
array_splice($keys, $index + 1, 0, $column);
} else {
array_push($keys, $column);
}
$columns[$column] = $name;
}
$result = [];
foreach ($keys as $column) {
$result[$column] = $columns[$column] ?? $column;
}
return $result;
}
/**
* 字段值重新处理 回调函数
*
* @param \Closure $call_back
*/
public function setList(\Closure $call_back)
{
$this->columnCallback = $call_back;
}
/**
* 处理有共同特征的字段值
*
* @param $columns
* @param $list
* @return mixed
*/
protected function dealColumn($columns, $list)
{
if (! $list) {
return $list;
}
$deal = array_keys($this->dealColumnList);
$add = array_keys($this->addColumnList);
foreach ($list as $index => $data) {
foreach ($columns as $column => $name) {
switch ($column) {
case strpos($column, '.') !== false :
$keys = explode('.', $column);
$value = $data;
for ($i = 0; $i < count($keys); $i++) {
$value = $value[$keys[$i]] ?? [];
}
if (is_array($value)) {
$value = empty($value) ? '' : json_encode($value, JSON_UNESCAPED_UNICODE);
}
$data[$column] = $value;
break;
}
if ($this->dealColumnList && in_array($column, $deal)) {
$data[$column] = call_user_func_array($this->dealColumnList[$column],
[$data[$column] ?? '', $data]);
}
if ($this->addColumnList && in_array($column, $add)) {
$data[$column] = call_user_func($this->addColumnList[$column], $data);
}
}
$list[$index] = $data;
}
return $list;
}
/**
* 获取选中的导出字段
*
* @return array
*/
protected function getColumns(): array
{
$columns = [];
foreach ($this->grid->getColumns() as $column) {
$columns[$column->getName()] = $column->getLabel();
}
$column_string = request()->get('_columns_', '');
if (! $column_string) {
return $columns;
}
$column_array = explode(',', $column_string);
$column_list = [];
foreach ($columns as $column => $name) {
if (in_array($column, $column_array)) {
$column_list[$column] = $name;
}
}
return $column_list;
}
/**
* 打印
*/
public function dd()
{
$this->debug = true;
}
/**
* 导出CSV
*
* @param string $file_name 文件名
* @param array $head_list 表头
* @param int $data_count 总数
* @param int $page_limit 每页数量
* @param \Closure $call_back 获取分页数据的回调函数
*/
function exportCsv(
string $file_name,
array $head_list,
\Closure $call_back,
int $data_count,
int $page_limit = 0
) {
set_time_limit(0);
ini_set('memory_limit', -1);
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$file_name.'.csv"');
header('Cache-Control: max-age=0');
//打开PHP文件句柄,php://output 表示直接输出到浏览器
$fp = fopen('php://output', 'a');
$head = [];
//输出Excel列名信息
foreach ($head_list as $name) {
//CSV的Excel支持GBK编码一定要转换否则乱码
$head[] = iconv('utf-8', 'gbk', $name);
}
//将数据通过fputcsv写到文件句柄
fputcsv($fp, $head);
$page_limit = $data_count > $page_limit ? $page_limit : $data_count;
$page_count = ceil($data_count / $page_limit);
for ($page = 1; $page <= $page_count; $page++) {
//逐页取出数据,不浪费内存
$data_list = call_user_func($call_back, $page, $page_limit);
if (! $data_list) {
continue;
}
foreach ($data_list as $data) {
$row = [];
foreach ($head_list as $key => $name) {
$value = $data[$key] ?? '';
$row[] = iconv('utf-8', 'gbk', $value);
}
fputcsv($fp, $row);
unset($row);
}
//刷新一下输出buffer防止由于数据过多内存不足
ob_flush();
flush();
info($page.'/'.$page_count.' time= '.$this->getElapsedTime().' memory= '.$this->getMemoryUsage());
}
fclose($fp);
exit();
}
public function getElapsedTime(int $decimals = 2): string
{
return number_format(microtime(true) - request()->server('REQUEST_TIME_FLOAT'), $decimals).' s';
}
public function getMemoryUsage($precision = 2): string
{
$size = memory_get_usage(true);
$unit = ['b', 'kb', 'mb', 'gb', 'tb', 'pb'];
return round($size / pow(1024, ($i = floor(log($size, 1024)))), $precision).' '.$unit[$i];
}
}