232 lines
5.5 KiB
PHP
232 lines
5.5 KiB
PHP
<?php
|
|
namespace Builder\View\Grid\Exporters;
|
|
use Hyperf\HttpMessage\Stream\SwooleStream;
|
|
use Builder\View\Grid\Column;
|
|
class CsvExporter extends AbstractExporter
|
|
{
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $filename;
|
|
|
|
/**
|
|
* @var \Closure
|
|
*/
|
|
protected $callback;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $exceptColumns;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $onlyColumns;
|
|
|
|
/**
|
|
* @var []\Closure
|
|
*/
|
|
protected $columnCallbacks;
|
|
|
|
/**
|
|
* @var []\Closure
|
|
*/
|
|
protected $titleCallbacks;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $visibleColumns;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $columnUseOriginalValue;
|
|
|
|
/**
|
|
* @param string $filename
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function filename(string $filename = ''): self
|
|
{
|
|
$this->filename = $filename;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param \Closure $closure
|
|
*/
|
|
public function setCallback(\Closure $closure): self
|
|
{
|
|
$this->callback = $closure;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array $columns
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function except(array $columns = []): self
|
|
{
|
|
$this->exceptColumns = $columns;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array $columns
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function only(array $columns = []): self
|
|
{
|
|
$this->onlyColumns = $columns;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array $columns
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function originalValue($columns = []): self
|
|
{
|
|
$this->columnUseOriginalValue = $columns;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param \Closure $callback
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function column(string $name, \Closure $callback): self
|
|
{
|
|
$this->columnCallbacks[$name] = $callback;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param \Closure $callback
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function title(string $name, \Closure $callback): self
|
|
{
|
|
$this->titleCallbacks[$name] = $callback;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function export()
|
|
{
|
|
if ($this->callback) {
|
|
call_user_func($this->callback, $this);
|
|
}
|
|
$titles = [];
|
|
$items = collect();
|
|
$columns = $this->grid->getColumns();
|
|
//增加一个bom头避免再微软office下打开乱码
|
|
$csv = "\xEF\xBB\xBF";
|
|
$csv .= implode(",", $this->getVisiableTitles()) . PHP_EOL;
|
|
$this->chunk(function ($data, $page) use ($items, $columns, &$csv) {
|
|
$original = $data->toArray();
|
|
// Write rows
|
|
foreach ($original as $index => $record) {
|
|
$cols = $this->getVisiableFields($record, $original[$index]);
|
|
foreach ($cols as $k => $col)
|
|
$cols[$k] = '"'.$col.'"';//避免字段中遇到,以及换行符等,直接以文本格式处理
|
|
$csv .= implode(",",$cols). PHP_EOL;
|
|
}
|
|
}, 100);
|
|
if (!$this->filename) {
|
|
$this->filename = $this->grid->getTable() . ".csv";
|
|
}
|
|
$response = new \Hyperf\HttpServer\Response();
|
|
$response = $response->withHeader('Content-Type', 'text/csv;charset=UTF-8');
|
|
$response = $response->withHeader('Expires', '0');
|
|
$response = $response->withHeader('Pragma', 'public');
|
|
$response = $response->withHeader('Content-Transfer-Encoding', 'binary');
|
|
$response = $response->withHeader('Content-Disposition', 'attachment;filename=' . $this->filename);
|
|
return $response->withBody(new SwooleStream($csv));
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
protected function getVisiableTitles()
|
|
{
|
|
$titles = collect($this->grid->getColumns())
|
|
->mapWithKeys(function (Column $column) {
|
|
$columnName = $column->getName();
|
|
$columnTitle = $column->getLabel();
|
|
if (isset($this->titleCallbacks[$columnName])) {
|
|
$columnTitle = $this->titleCallbacks[$columnName]($columnTitle);
|
|
}
|
|
return [$columnName => $columnTitle];
|
|
});
|
|
|
|
if ($this->onlyColumns) {
|
|
$titles = $titles->only($this->onlyColumns);
|
|
}
|
|
if ($this->exceptColumns) {
|
|
$titles = $titles->except($this->exceptColumns);
|
|
}
|
|
$this->visibleColumns = $titles->keys();
|
|
return $titles->values()->toArray();
|
|
}
|
|
|
|
/**
|
|
* @param array $value
|
|
* @param array $original
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getVisiableFields(array $value, array $original): array
|
|
{
|
|
$fields = [];
|
|
foreach ($this->visibleColumns as $column) {
|
|
$fields[] = $this->getColumnValue(
|
|
$column,
|
|
data_get($value, $column),
|
|
data_get($original, $column)
|
|
);
|
|
}
|
|
return $fields;
|
|
}
|
|
|
|
/**
|
|
* @param string $column
|
|
* @param mixed $value
|
|
* @param mixed $original
|
|
*
|
|
* @return mixed
|
|
*/
|
|
protected function getColumnValue(string $column, $value, $original)
|
|
{
|
|
if (!empty($this->columnUseOriginalValue)
|
|
&& in_array($column, $this->columnUseOriginalValue)) {
|
|
return $original;
|
|
}
|
|
|
|
if (isset($this->columnCallbacks[$column])) {
|
|
return $this->columnCallbacks[$column]($value, $original);
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
}
|