初始化仓库
This commit is contained in:
65
admin/components/UI/Table/Action.php
Normal file
65
admin/components/UI/Table/Action.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
use admin\components\UI\Widget\Link;
|
||||
use admin\components\UI\Widget\Menu;
|
||||
|
||||
/**
|
||||
* 操作动作
|
||||
* Class Column
|
||||
* @package backend\components\UI\Filter
|
||||
*/
|
||||
class Action
|
||||
{
|
||||
|
||||
protected array $button = [];
|
||||
protected array $menu = [];
|
||||
|
||||
/**
|
||||
* 按钮
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @param string $type
|
||||
* @return Link
|
||||
*/
|
||||
public function button(string $name, string $route = '', array $params = [], string $type = 'primary'): Link
|
||||
{
|
||||
$link = new Link($name, $route, $params);
|
||||
$link->button($type);
|
||||
$this->button[] = $link;
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单按钮
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return Menu
|
||||
*/
|
||||
public function menu(string $name, string $type = 'default'): Menu
|
||||
{
|
||||
$menu = new Menu($name, $type);
|
||||
$this->menu[] = $menu;
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染组件
|
||||
* @return array
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$node = [];
|
||||
foreach ($this->menu as $menu) {
|
||||
$node[] = $menu->getRender();
|
||||
}
|
||||
foreach ($this->button as $class) {
|
||||
$node[] = $class->getRender();
|
||||
}
|
||||
return $node;
|
||||
}
|
||||
|
||||
}
|
||||
87
admin/components/UI/Table/Batch.php
Normal file
87
admin/components/UI/Table/Batch.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use admin\components\UI\Widget\Link;
|
||||
use admin\components\UI\Form\Select;
|
||||
|
||||
/**
|
||||
* 操作批量
|
||||
* Class Column
|
||||
* @package backend\components\UI\Filter
|
||||
*/
|
||||
class Batch
|
||||
{
|
||||
|
||||
protected array $nodes = [];
|
||||
protected array $select = [];
|
||||
protected array $url = [];
|
||||
|
||||
/**
|
||||
* 按钮
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @param string $btnType
|
||||
* @return $this
|
||||
*/
|
||||
public function button(string $name, string $type = '', string $route = '', array $params = [], string $btnType = 'normal'): self
|
||||
{
|
||||
$params['bath_type'] = $type;
|
||||
$url = route($route, $params);
|
||||
$this->nodes[] = [
|
||||
'nodeName' => 'a-button',
|
||||
'type' => 'secondary',
|
||||
'status' => $btnType,
|
||||
'child' => $name,
|
||||
'vOn:click' => "footer.checkAction('$url', '确定执行$name\操作?')"
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @return $this
|
||||
*/
|
||||
public function select(string $name, string $route = '', array $params = []): self
|
||||
{
|
||||
$url = route($route, $params);
|
||||
$this->select[] = [
|
||||
'nodeName' => 'a-doption',
|
||||
'child' => $name,
|
||||
'vOn:click' => "footer.checkAction('$url' '确定执行$name\操作?')"
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染组件
|
||||
* @return array
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
if ($this->select) {
|
||||
$this->nodes[] = [
|
||||
'nodeName' => 'a-dropdown',
|
||||
'child' => [
|
||||
[
|
||||
'nodeName' => 'a-button',
|
||||
'type' => 'secondary',
|
||||
'child' => '批量操作',
|
||||
],
|
||||
[
|
||||
'vSlot:content' => '',
|
||||
'nodeName' => 'div',
|
||||
'child' => $this->select
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $this->nodes;
|
||||
}
|
||||
|
||||
}
|
||||
467
admin/components/UI/Table/Column.php
Normal file
467
admin/components/UI/Table/Column.php
Normal file
@@ -0,0 +1,467 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use admin\components\UI\Widget\Link;
|
||||
use admin\components\UI\Table;
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* 表格列
|
||||
* Class Column
|
||||
* @method static Column\Hidden hidden()
|
||||
* @method static Column\Progress progress(string $color = 'default')
|
||||
* @method static Column\Status status(array $map, array $color, string $type = 'badge')
|
||||
* @method static Column\Chart chart(int $day = 7, string $has = 'viewsData', string $key = 'pv', string $name = '访问量', string $type = 'area')
|
||||
* @method static Column\Tags tags(array $map, array $color)
|
||||
* @method Column\Toggle toggle(string $field, string $url, array $params = [])
|
||||
* @method static Column\Input input(string $field, $url, array $params = [])
|
||||
* @package backend\components\UI\Table
|
||||
*/
|
||||
class Column
|
||||
{
|
||||
|
||||
protected string $name;
|
||||
protected string $label = '';
|
||||
protected ?\Closure $callback = null;
|
||||
protected array $node = [];
|
||||
protected array $attr = [];
|
||||
protected array $function = [];
|
||||
protected array $children = [];
|
||||
protected $width = '';
|
||||
protected $align = '';
|
||||
protected $fixed = '';
|
||||
protected $class = [];
|
||||
protected $replace = '';
|
||||
protected ?int $colspan = null;
|
||||
protected ?\Closure $show = null;
|
||||
protected ?int $sort = null;
|
||||
protected $sorter = null;
|
||||
protected $layout;
|
||||
protected $relation;
|
||||
protected $model;
|
||||
protected $element;
|
||||
protected $extend;
|
||||
|
||||
/**
|
||||
* Column constructor.
|
||||
* @param string $name
|
||||
* @param string $label
|
||||
* @param null $callback
|
||||
*/
|
||||
public function __construct(string $name = '', string $label = '', $callback = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置父级对象
|
||||
* @param Table $layout
|
||||
*/
|
||||
public function setLayout(Table $layout): void
|
||||
{
|
||||
$this->layout = $layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联数据
|
||||
* @param $relation
|
||||
* @return $this
|
||||
*/
|
||||
public function setRelation($relation): self
|
||||
{
|
||||
$this->relation = $relation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 宽度
|
||||
* @param $width
|
||||
* @return $this
|
||||
*/
|
||||
public function width($width): self
|
||||
{
|
||||
$this->width = $width;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义节点数据
|
||||
* @param $node
|
||||
* @return $this
|
||||
*/
|
||||
public function node($node): self
|
||||
{
|
||||
$this->node = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对齐
|
||||
* @param string $align
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function align(string $align): self
|
||||
{
|
||||
$this->align = $align;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 固定列
|
||||
* @param string $fixed
|
||||
* @return $this
|
||||
*/
|
||||
public function fixed(string $fixed = 'right'): self
|
||||
{
|
||||
$this->fixed = $fixed;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置样式类
|
||||
* @param string $class
|
||||
* @return $this
|
||||
*/
|
||||
public function class(string $class): self
|
||||
{
|
||||
$this->class[] = $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置附加属性
|
||||
* @param string $name
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function attr(string $name, $value): self
|
||||
{
|
||||
$this->attr[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置颜色
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function color(string $name): self
|
||||
{
|
||||
$this->class[] = 'text-' . $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串替换标签(数字字符串处理使用)
|
||||
* @param $replace
|
||||
* @return $this
|
||||
*/
|
||||
public function replace($replace): self
|
||||
{
|
||||
$this->replace = $replace;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加链接
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @param bool $absolute
|
||||
* @return Link
|
||||
*/
|
||||
public function link(string $name, string $route, array $params = [], bool $absolute = false): Link
|
||||
{
|
||||
if (!$this->element) {
|
||||
$this->element = new Table\Column\Link();
|
||||
$this->element->fields($this->layout->fields);
|
||||
}
|
||||
return $this->element->add($name, $route, $params, $absolute);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @return Link
|
||||
*/
|
||||
public function menu(string $name, string $route, array $params = []): Link
|
||||
{
|
||||
if (!$this->element) {
|
||||
$this->element = new Table\Column\Menu();
|
||||
}
|
||||
return $this->element->add($name, $route, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 副标题
|
||||
* @param string $label
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function desc(string $label, callable $callback = null): self
|
||||
{
|
||||
if (!$this->element && !$this->element instanceof Table\Column\RichText) {
|
||||
$this->element = new Table\Column\RichText();
|
||||
$this->element->setRelation($this->relation);
|
||||
}
|
||||
$this->element->desc($label, $callback);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片显示
|
||||
* @param string $label
|
||||
* @param callable|null $callback
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param string $placeholder
|
||||
* @return $this
|
||||
*/
|
||||
public function image(string $label, callable $callback = null, int $width = 10, int $height = 10, string $placeholder = ''): self
|
||||
{
|
||||
if (!$this->element && !$this->element instanceof Table\Column\RichText) {
|
||||
$this->element = new Table\Column\RichText();
|
||||
}
|
||||
$this->element->image($label, $width, $height, $placeholder, $callback);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
* @param $format
|
||||
* @return $this
|
||||
*/
|
||||
public function date($format): self
|
||||
{
|
||||
$this->function[] = [
|
||||
'fun' => 'date',
|
||||
'params' => $format
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示隐藏
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function show(callable $callback): self
|
||||
{
|
||||
$this->show = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列排序
|
||||
* @param int $num
|
||||
* @return $this
|
||||
*/
|
||||
public function sort(int $num): self
|
||||
{
|
||||
$this->sort = $num;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 排序条件
|
||||
*/
|
||||
public function sorter($sorter = true): self
|
||||
{
|
||||
$this->sorter = $sorter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列合并
|
||||
* @param int $num
|
||||
* @return $this
|
||||
*/
|
||||
public function colspan(int $num): self
|
||||
{
|
||||
$this->colspan = $num;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// 分组表格
|
||||
public function children(string $name = '', string $label = '', $callback = null): self
|
||||
{
|
||||
$this->children[] = new Column($name, $label, $callback);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段名
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel(): string
|
||||
{
|
||||
return Tools::converLabel2($this->label, $this->relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列配置
|
||||
*/
|
||||
public function getRender(): array
|
||||
{
|
||||
$render = $this->node;
|
||||
if ($this->node instanceof \Closure) {
|
||||
$render = call_user_func($this->node);
|
||||
}
|
||||
if ($this->element) {
|
||||
$render = $this->element->render($this->getLabel());
|
||||
}
|
||||
|
||||
$node = [
|
||||
'title' => $this->name,
|
||||
'dataIndex' => $this->label,
|
||||
'width' => $this->width,
|
||||
'className' => implode(' ', $this->class),
|
||||
'colSpan' => $this->colspan,
|
||||
'sort' => $this->sort,
|
||||
'align' => $this->align,
|
||||
];
|
||||
|
||||
if ($this->fixed) {
|
||||
$node['fixed'] = $this->fixed;
|
||||
}
|
||||
|
||||
if($this->replace){
|
||||
$node['replace'] = $this->replace;
|
||||
}
|
||||
|
||||
if ($this->children) {
|
||||
$children = [];
|
||||
foreach ($this->children as $item) {
|
||||
$children[] = $item->getRender();
|
||||
}
|
||||
$node['children'] = $children;
|
||||
}
|
||||
|
||||
if ($this->sorter) {
|
||||
$node['vBind:sortable'] = 'colSortable';
|
||||
}
|
||||
|
||||
if ($render) {
|
||||
$node['render:rowData, rowIndex'] = $render;
|
||||
}
|
||||
return array_merge($node, $this->attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 行数据
|
||||
* @param $rowData
|
||||
* @return array
|
||||
*/
|
||||
public function getData($rowData): array
|
||||
{
|
||||
if ($this->relation) {
|
||||
// 解析关联数组
|
||||
$parsingData = Tools::parsingObjData($rowData, $this->relation, $this->label);
|
||||
} else {
|
||||
// 解析普通数组
|
||||
$parsingData = Tools::parsingArrData($rowData, $this->label);
|
||||
}
|
||||
|
||||
// 回调处理
|
||||
if ($this->callback instanceof \Closure) {
|
||||
$callback = call_user_func($this->callback, $parsingData, $rowData);
|
||||
if ($callback) {
|
||||
$parsingData = $callback;
|
||||
}
|
||||
} else {
|
||||
$parsingData = $this->callback ?: $parsingData;
|
||||
}
|
||||
|
||||
// 函数处理
|
||||
if ($this->function) {
|
||||
foreach ($this->function as $vo) {
|
||||
if (function_exists($vo['fun'])) {
|
||||
$parsingData = call_user_func($vo['fun'], $vo['params'], $parsingData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->label) {
|
||||
$data = [
|
||||
$this->getLabel() => $parsingData
|
||||
];
|
||||
} else {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
// 元素数据
|
||||
if ($this->element && method_exists($this->element, 'getData')) {
|
||||
$data = array_merge($data, $this->element->getData($rowData, $this->getLabel(), $parsingData));
|
||||
}
|
||||
|
||||
if ($this->children) {
|
||||
foreach ($this->children as $item) {
|
||||
$data = array_merge($data, $item->getData($rowData));
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列条件
|
||||
* @param $query
|
||||
* @return false|void
|
||||
*/
|
||||
public function execute($query)
|
||||
{
|
||||
$sort = \Yii::$app->request->get('_sort');
|
||||
$value = $sort && $sort[$this->label] ? $sort[$this->label] : null;
|
||||
if (!$this->sorter || $value === null) {
|
||||
return false;
|
||||
}
|
||||
if ($this->sorter instanceof \Closure) {
|
||||
call_user_func($this->sorter, $query, $value);
|
||||
} else if ($this->sorter !== false) {
|
||||
$query->orderBy(is_string($this->sorter) ? $this->sorter : $this->label, $value === 'desc' ? 'desc' : 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行元素处理
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function element(callable $callback){
|
||||
$callback($this->element);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $method
|
||||
* @param $arguments
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
$class = 'backend\\components\\UI\\Table\\Column\\' . ucfirst($method);
|
||||
if (!class_exists($class)) {
|
||||
if (!$this->extend[$method]) {
|
||||
throw new \Exception('There is no form method "' . $method . '"');
|
||||
} else {
|
||||
$class = $this->extend[$method];
|
||||
}
|
||||
}
|
||||
$object = new $class(...$arguments);
|
||||
if (method_exists($object, 'fields')) {
|
||||
$object->fields($this->layout->fields);
|
||||
}
|
||||
$this->element = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
74
admin/components/UI/Table/Column/Chart.php
Normal file
74
admin/components/UI/Table/Column/Chart.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
use admin\components\UI\yii\Arr;
|
||||
use admin\components\UI\yii\Str;
|
||||
|
||||
/**
|
||||
* Class Chart
|
||||
*/
|
||||
class Chart implements Component
|
||||
{
|
||||
|
||||
private int $day;
|
||||
private string $has;
|
||||
private string $key;
|
||||
private string $name;
|
||||
private string $type;
|
||||
|
||||
/**
|
||||
* Chart constructor.
|
||||
* @param int $day
|
||||
* @param string $has
|
||||
* @param string $key
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
*/
|
||||
public function __construct(int $day = 7, string $has = 'viewsData', string $key = 'pv', string $name = '访问量', string $type = 'area')
|
||||
{
|
||||
$this->day = $day;
|
||||
$this->has = $has;
|
||||
$this->key = $key;
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
public function render($value, $data): string
|
||||
{
|
||||
$chartData = $data->{$this->has};
|
||||
$tmpData = [];
|
||||
$chartData->each(function ($item) use (&$tmpData) {
|
||||
$tmpData[$item->date] += $item[$this->key];
|
||||
});
|
||||
$tmpChart = [];
|
||||
foreach ($tmpData as $key => $vo) {
|
||||
$tmpChart[] = [
|
||||
"value" => $vo,
|
||||
"label" => $key,
|
||||
"name" => $this->name
|
||||
];
|
||||
}
|
||||
$viewId = 'chart-chart-' . Str::random(5);
|
||||
|
||||
$chart = (new \backend\components\Util\ApexCharts)->{$this->type}($tmpChart)->type('day', [
|
||||
'start' => date('Y-m-d', strtotime('-' . $this->day . ' day')),
|
||||
])->render($viewId, function ($config) {
|
||||
Arr::set($config, 'chart.height', 35);
|
||||
Arr::set($config, 'chart.sparkline.enabled', true);
|
||||
Arr::set($config, 'chart.animations.enabled', false);
|
||||
Arr::set($config, 'tooltip.enabled', false);
|
||||
return $config;
|
||||
});
|
||||
|
||||
return "<div id='$viewId' class='p-1'></div> $chart";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
13
admin/components/UI/Table/Column/Component.php
Normal file
13
admin/components/UI/Table/Column/Component.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
/**
|
||||
* 组件接口
|
||||
* Class Component
|
||||
* @package backend\components\UI
|
||||
*/
|
||||
interface Component
|
||||
{
|
||||
public function render($label): array;
|
||||
}
|
||||
42
admin/components/UI/Table/Column/Hidden.php
Normal file
42
admin/components/UI/Table/Column/Hidden.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
|
||||
/**
|
||||
* Class Hidden
|
||||
*/
|
||||
class Hidden implements Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$name = $label . '_show';
|
||||
return [
|
||||
'nodeName' => 'div',
|
||||
'child' => [
|
||||
[
|
||||
'nodeName' => 'span',
|
||||
'class' => 'mr-2',
|
||||
'vIf' => "rowData.record['$name']",
|
||||
'child' => "{{rowData.record['$label']}}",
|
||||
],
|
||||
[
|
||||
'nodeName' => 'a-button',
|
||||
'shape' => 'round',
|
||||
'size' => 'mini',
|
||||
'type' => 'outline',
|
||||
'vBind:status' => "rowData.record['$name'] ? 'warning' : ''",
|
||||
'class' => 'mr-2',
|
||||
'vOn:click' => "rowData.record['$name'] = !rowData.record['$name']",
|
||||
'child' => "{{rowData.record['$name'] ? '隐藏' : '显示'}}",
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
49
admin/components/UI/Table/Column/Images.php
Normal file
49
admin/components/UI/Table/Column/Images.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Widget\Badge;
|
||||
|
||||
/**
|
||||
* Class Images
|
||||
*/
|
||||
class Images implements Component
|
||||
{
|
||||
|
||||
private int $size;
|
||||
|
||||
/**
|
||||
* Tags constructor.
|
||||
*/
|
||||
public function __construct(int $size = 3)
|
||||
{
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$node = [
|
||||
'nodeName' => 'div',
|
||||
'vFor' => "item in rowData.record['$label']",
|
||||
'class' => "flex-none bg-cover w-{$this->size} h-{$this->size}",
|
||||
'vBind:style' => "{'background-image': 'url(' + item + ')'}"
|
||||
];
|
||||
|
||||
return [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex gap-2',
|
||||
'child' => $node
|
||||
];
|
||||
}
|
||||
|
||||
public function getData($rowData, $field, $value): array
|
||||
{
|
||||
return [$field => !is_array($value) ? json_decode($value, true) : $value];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
55
admin/components/UI/Table/Column/Input.php
Normal file
55
admin/components/UI/Table/Column/Input.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* Class Input
|
||||
*/
|
||||
class Input implements Component
|
||||
{
|
||||
|
||||
private string $route;
|
||||
private array $params;
|
||||
private string $field;
|
||||
private array $fields;
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(string $field, string $route, array $params = [])
|
||||
{
|
||||
$this->field = $field;
|
||||
$this->params = $params;
|
||||
$this->route = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
* @return $this
|
||||
*/
|
||||
public function fields(array $fields = []): Input
|
||||
{
|
||||
$this->fields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$url = app_route($this->route, $this->params, false, 'rowData.record', $this->fields);
|
||||
return [
|
||||
'nodeName' => 'n-input',
|
||||
'class' => 'shadow-sm',
|
||||
'vModel:value' => "rowData.record['$label']",
|
||||
'vOn:blur' => "editValue($url, {'field': '$this->field', '$this->field': rowData.record['$label']})",
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
80
admin/components/UI/Table/Column/Link.php
Normal file
80
admin/components/UI/Table/Column/Link.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* Class Link
|
||||
*/
|
||||
class Link implements Component
|
||||
{
|
||||
|
||||
private array $link;
|
||||
private array $fields;
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
* @return $this
|
||||
*/
|
||||
public function fields(array $fields = []): Link
|
||||
{
|
||||
$this->fields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加条目
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @param bool $absolute
|
||||
* @return \backend\components\UI\Widget\Link
|
||||
*/
|
||||
public function add(string $name, string $route, array $params = [], bool $absolute = false): \backend\components\UI\Widget\Link
|
||||
{
|
||||
$link = new \backend\components\UI\Widget\Link($name, $route, $params, $absolute);
|
||||
$link->fields($this->fields);
|
||||
$link = $link->model('rowData.record');
|
||||
$this->link[] = $link;
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$link = [];
|
||||
foreach ($this->link as $class) {
|
||||
$type = $class->getType();
|
||||
$data = $class->render();
|
||||
|
||||
if (($type === 'ajax' || $type === 'dialog') && (!isset($data['vBind:before']) || !isset($data['before']))) {
|
||||
$data['vBind:before'] = "() => rowData.record.__loading = true";
|
||||
}
|
||||
|
||||
if (($type === 'ajax' || $type === 'dialog') && (!isset($data['vBind:after']) || !isset($data['after']))) {
|
||||
$data['vBind:after'] = "() => rowData.record.__loading = false";
|
||||
}
|
||||
|
||||
$link[] = [
|
||||
'nodeName' => 'span',
|
||||
'child' => $data
|
||||
];
|
||||
}
|
||||
|
||||
$link = array_filter($link);
|
||||
return [
|
||||
'nodeName' => 'a-spin',
|
||||
'vBind:loading' => 'rowData.record.__loading',
|
||||
'child' => [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'inline-flex gap-2',
|
||||
'child' => $link
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
105
admin/components/UI/Table/Column/Menu.php
Normal file
105
admin/components/UI/Table/Column/Menu.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* Class Menu
|
||||
*/
|
||||
class Menu implements Component
|
||||
{
|
||||
|
||||
private array $link;
|
||||
private array $routes = [];
|
||||
|
||||
/**
|
||||
* 添加条目
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @return \backend\components\UI\Widget\Link
|
||||
*/
|
||||
public function add(string $name, string $route, array $params = []): \backend\components\UI\Widget\Link
|
||||
{
|
||||
$label = $route . '?' . http_build_query($params);
|
||||
$link = new \backend\components\UI\Widget\Link($name, $route, $params);
|
||||
$link = $link->model('rowData');
|
||||
$this->link[] = $link;
|
||||
$this->routes[$label] = [
|
||||
'route' => $route,
|
||||
'params' => $params
|
||||
];
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据
|
||||
* @param $rowData
|
||||
* @return array
|
||||
*/
|
||||
public function getData($rowData): array
|
||||
{
|
||||
$urls = [];
|
||||
foreach ($this->routes as $key => $vo) {
|
||||
$params = [];
|
||||
foreach ($vo['params'] as $k => $v) {
|
||||
$params[$k] = Tools::parsingArrData($rowData, $v, true);
|
||||
}
|
||||
$urls[$key] = route($vo['route'], $params, false);
|
||||
}
|
||||
return $urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$options = [];
|
||||
foreach ($this->link as $key => $class) {
|
||||
$data = $class->render();
|
||||
|
||||
$route = [
|
||||
'nodeName' => 'route',
|
||||
'type' => $data['type'],
|
||||
'title' => $data['title'],
|
||||
'href' => $class->getRoute(),
|
||||
];
|
||||
|
||||
$options[] = [
|
||||
'label' => $data['name'],
|
||||
'key' => $key,
|
||||
'route' =>$route,
|
||||
];
|
||||
}
|
||||
$options = array_filter($options);
|
||||
|
||||
return [
|
||||
'nodeName' => 'n-dropdown',
|
||||
'width' => '80',
|
||||
'placement' => 'right-start',
|
||||
'overlap' => true,
|
||||
'trigger' => 'click',
|
||||
'options' => $options,
|
||||
'render-label:option' => [
|
||||
'nodeName' => 'route',
|
||||
'class' => 'block',
|
||||
'vBind:href' => 'rowData.record[option.route.href]',
|
||||
'vBind:title' => 'option.route.title',
|
||||
'vBind:type' => 'option.route.type',
|
||||
'child' => '{{option.label}}'
|
||||
],
|
||||
'child' => [
|
||||
'nodeName' => 'n-icon',
|
||||
'class' => 'cursor-pointer',
|
||||
'size' => 16,
|
||||
'child' => [
|
||||
'nodeName' => 'dots-vertical-icon'
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
31
admin/components/UI/Table/Column/Progress.php
Normal file
31
admin/components/UI/Table/Column/Progress.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
|
||||
/**
|
||||
* Class Progress
|
||||
*/
|
||||
class Progress implements Component
|
||||
{
|
||||
|
||||
private string $color;
|
||||
|
||||
/**
|
||||
* @param string $color
|
||||
*/
|
||||
public function __construct(string $color = 'default')
|
||||
{
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
return (new \backend\components\UI\Widget\Progress("rowData.record['$label']"))->color($this->color)->render();
|
||||
}
|
||||
|
||||
}
|
||||
153
admin/components/UI/Table/Column/RichText.php
Normal file
153
admin/components/UI/Table/Column/RichText.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* Class RichText
|
||||
*/
|
||||
class RichText implements Component
|
||||
{
|
||||
private array $desc = [];
|
||||
private array $image = [];
|
||||
protected $relation;
|
||||
|
||||
/**
|
||||
* 设置关系
|
||||
* @param $relation
|
||||
* @return $this
|
||||
*/
|
||||
public function setRelation($relation = null): self
|
||||
{
|
||||
$this->relation = $relation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $label
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function desc(string $label, ?callable $callback = null): self
|
||||
{
|
||||
$this->desc[] = ['label' => $label, 'callback' => $callback];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $label
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param string $placeholder
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function image(string $label, int $width = 10, int $height = 10, string $placeholder = '', ?callable $callback = null): self
|
||||
{
|
||||
$this->image[] = [
|
||||
'label' => $label,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'placeholder' => $placeholder,
|
||||
'callback' => $callback
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $rowData
|
||||
* @return array
|
||||
*/
|
||||
public function getData($rowData): array
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->image as $vo) {
|
||||
if ($this->relation) {
|
||||
// 解析关联数组
|
||||
$url = Tools::parsingObjData($rowData, $this->relation, $vo['label']);
|
||||
} else {
|
||||
// 解析普通数组
|
||||
$url = Tools::parsingArrData($rowData, $vo['label'], true);
|
||||
}
|
||||
|
||||
if ($vo['callback'] instanceof \Closure) {
|
||||
$url = call_user_func($vo['callback'], $url, $rowData);
|
||||
}
|
||||
if (filter_var($url, FILTER_VALIDATE_URL) === false) {
|
||||
$url = route('service.image.placeholder', ['w' => 100, 'h' => 100, 't' => $vo['placeholder'] ?: '暂无']);
|
||||
}
|
||||
$data[Tools::converLabel($vo['label'], $this->relation)] = $url;
|
||||
}
|
||||
foreach ($this->desc as $key => $vo) {
|
||||
|
||||
if ($this->relation) {
|
||||
// 解析关联数组
|
||||
$var = Tools::parsingObjData($rowData, $this->relation, $vo['label']);
|
||||
} else {
|
||||
// 解析普通数组
|
||||
$var = Tools::parsingArrData($rowData, $vo['label']);
|
||||
}
|
||||
if ($vo['callback'] instanceof \Closure) {
|
||||
$var = call_user_func($vo['callback'], $var, $rowData);
|
||||
}
|
||||
$data[Tools::converLabel($vo['label'], $this->relation)] = $var;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
|
||||
$imageNode = [];
|
||||
if ($this->image) {
|
||||
foreach ($this->image as $vo) {
|
||||
$itemLabel = Tools::converLabel2($vo['label']);
|
||||
$imageNode[] = [
|
||||
'nodeName' => 'div',
|
||||
'class' => "flex-none bg-cover w-{$vo['width']} h-{$vo['height']}",
|
||||
'vBind:style' => "{'background-image': 'url(' + rowData.record['$itemLabel'] + ')'}"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$descNode = [];
|
||||
if ($this->desc) {
|
||||
foreach ($this->desc as $vo) {
|
||||
$itemLabel = Tools::converLabel2($vo['label']);
|
||||
$descNode[] = [
|
||||
'nodeName' => 'div',
|
||||
'class' => "text-gray-500 overflow-ellipsis max-w-md",
|
||||
'child' => "{{rowData.record['$itemLabel']}}"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex items-center gap-2',
|
||||
'child' => [
|
||||
...$imageNode,
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-grow',
|
||||
'child' => [
|
||||
[//注释是因为图片显示会把url也显示
|
||||
'nodeName' => 'div',
|
||||
'class' => 'overflow-ellipsis max-w-md',
|
||||
'child' => "{{rowData.record['$label']}}"
|
||||
],
|
||||
...$descNode
|
||||
]
|
||||
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
58
admin/components/UI/Table/Column/Status.php
Normal file
58
admin/components/UI/Table/Column/Status.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Widget\Badge;
|
||||
|
||||
/**
|
||||
* Class Status
|
||||
*/
|
||||
class Status implements Component
|
||||
{
|
||||
|
||||
private array $map;
|
||||
private array $color;
|
||||
private string $type;
|
||||
|
||||
/**
|
||||
* @param array $map
|
||||
* @param array $color
|
||||
* @param string $type
|
||||
*/
|
||||
public function __construct(array $map, array $color, string $type = 'badge')
|
||||
{
|
||||
$this->map = $map;
|
||||
$this->color = $color;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$statusArr = [];
|
||||
foreach ($this->map as $key => $vo) {
|
||||
$statusArr[$key]['name'] = $vo;
|
||||
$statusArr[$key]['color'] = $this->color[$key] ?? 'blue';
|
||||
}
|
||||
|
||||
$node = [];
|
||||
foreach ($statusArr as $key => $vo) {
|
||||
if ($this->type === 'badge') {
|
||||
$item = (new Badge($vo['name']))->color($vo['color'])->render();
|
||||
$item['vIf'] = "rowData.record['{$label}'] == " . (is_numeric($key) ? $key : "'$key'");
|
||||
} else {
|
||||
$item = [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'text-' . $vo['color'] . '-900',
|
||||
'child' => $vo['name']
|
||||
];
|
||||
}
|
||||
$node[] = $item;
|
||||
}
|
||||
return $node;
|
||||
}
|
||||
|
||||
}
|
||||
61
admin/components/UI/Table/Column/Tags.php
Normal file
61
admin/components/UI/Table/Column/Tags.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Widget\Badge;
|
||||
|
||||
/**
|
||||
* Class Tags
|
||||
*/
|
||||
class Tags implements Component
|
||||
{
|
||||
|
||||
private array $map;
|
||||
private array $color;
|
||||
|
||||
/**
|
||||
* Tags constructor.
|
||||
* @param array $map
|
||||
* @param array $color
|
||||
*/
|
||||
public function __construct(array $map, array $color)
|
||||
{
|
||||
$this->map = $map;
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return array
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$tagsArr = [];
|
||||
foreach ($this->map as $key => $vo) {
|
||||
$tagsArr[$key]['name'] = $vo;
|
||||
}
|
||||
foreach ($this->color as $key => $vo) {
|
||||
$tagsArr[$key]['color'] = $vo;
|
||||
}
|
||||
|
||||
$node = [];
|
||||
foreach ($tagsArr as $key => $vo) {
|
||||
$item = (new Badge($vo['name']))->color($vo['color'])->render();
|
||||
$item['vIf'] = "~rowData.record['{$label}'].indexOf(". (is_numeric($key) ? $key : "'$key'") .")";
|
||||
$node[] = $item;
|
||||
}
|
||||
|
||||
return [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex gap-2',
|
||||
'child' => $node
|
||||
];
|
||||
}
|
||||
|
||||
public function getData($rowData, $field, $value): array
|
||||
{
|
||||
return [$field => !is_array($value) ? explode(',', $value) : $value];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
71
admin/components/UI/Table/Column/Toggle.php
Normal file
71
admin/components/UI/Table/Column/Toggle.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table\Column;
|
||||
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* Class Toggle
|
||||
*/
|
||||
class Toggle implements Component
|
||||
{
|
||||
|
||||
private string $route;
|
||||
private array $params;
|
||||
private string $field;
|
||||
private array $fields;
|
||||
private $checkedValue = 1;
|
||||
private $uncheckedValue = 0;
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(string $field, string $route, array $params = [])
|
||||
{
|
||||
$this->field = $field;
|
||||
$this->params = $params;
|
||||
$this->route = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置列字段
|
||||
* @param array $fields
|
||||
* @return $this
|
||||
*/
|
||||
public function fields(Array $fields = []): self
|
||||
{
|
||||
$this->fields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开关数据
|
||||
* @param string|number|boolean $checkedValue
|
||||
* @param string|number|boolean $uncheckedValue
|
||||
* @return $this
|
||||
*/
|
||||
public function data($checkedValue,$uncheckedValue){
|
||||
$this->checkedValue = $checkedValue;
|
||||
$this->uncheckedValue = $uncheckedValue;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $label
|
||||
* @return string[]
|
||||
*/
|
||||
public function render($label): array
|
||||
{
|
||||
$url = app_route($this->route, $this->params, false, 'rowData.record', $this->fields);
|
||||
return [
|
||||
'nodeName' => 'a-switch',
|
||||
'vModel:model-value' => "rowData.record['$label']",
|
||||
'vOn:change' => "rowData.record['$label'] = \$event, editValue($url, {'field': '$this->field', '$this->field': rowData.record['$label']})",
|
||||
'checkedValue' => $this->checkedValue,
|
||||
'uncheckedValue' => $this->uncheckedValue
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
87
admin/components/UI/Table/Export.php
Normal file
87
admin/components/UI/Table/Export.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use Closure;
|
||||
use admin\components\Util\Excel;
|
||||
use admin\components\UI\Tools;
|
||||
|
||||
/**
|
||||
* 数据导出
|
||||
* Class Column
|
||||
* @package backend\components\UI\Filter
|
||||
*/
|
||||
class Export
|
||||
{
|
||||
public array $column = [];
|
||||
public string $title = '数据导出';
|
||||
public string $subtitle = '';
|
||||
|
||||
/**
|
||||
* 标题
|
||||
* @param $name
|
||||
* @return $this
|
||||
*/
|
||||
public function title($name): self
|
||||
{
|
||||
$this->title = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 副标题
|
||||
* @param $name
|
||||
* @return $this
|
||||
*/
|
||||
public function subtitle($name): self
|
||||
{
|
||||
$this->subtitle = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列设置
|
||||
* @param string $name
|
||||
* @param string|Closure $value
|
||||
* @param int $width
|
||||
* @return $this
|
||||
*/
|
||||
public function column(string $name, $value, int $width = 10): self
|
||||
{
|
||||
$this->column[] = [
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
'width' => $width
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出表单
|
||||
* @param $data
|
||||
*/
|
||||
public function render($data): void
|
||||
{
|
||||
$header = [];
|
||||
$cellData = [];
|
||||
foreach ($data as $vo) {
|
||||
$tmp = [];
|
||||
foreach ($this->column as $column) {
|
||||
if (is_string($column['value'])) {
|
||||
$tmp[] = Tools::parsingArrData($vo, $column['value']);
|
||||
} else {
|
||||
$tmp[] = call_user_func($column['value'], $vo);
|
||||
}
|
||||
}
|
||||
$cellData[] = $tmp;
|
||||
}
|
||||
foreach ($this->column as $vo) {
|
||||
$header[] = [
|
||||
'name' => $vo['name'],
|
||||
'width' => $vo['width']
|
||||
];
|
||||
}
|
||||
Excel::export($this->title, $this->subtitle, $header, $cellData);
|
||||
}
|
||||
|
||||
}
|
||||
291
admin/components/UI/Table/Filter.php
Normal file
291
admin/components/UI/Table/Filter.php
Normal file
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use admin\components\UI\Form\Cascader;
|
||||
use admin\components\UI\Form\Date;
|
||||
use admin\components\UI\Form\Daterange;
|
||||
use admin\components\UI\Form\Datetime;
|
||||
use admin\components\UI\Form\Select;
|
||||
use admin\components\UI\Form\Text;
|
||||
use admin\components\UI\Table;
|
||||
|
||||
/**
|
||||
* 表格筛选
|
||||
* Class Column
|
||||
* @package backend\components\UI\Filter
|
||||
*/
|
||||
class Filter
|
||||
{
|
||||
|
||||
protected string $name;
|
||||
protected string $field;
|
||||
protected $default;
|
||||
protected $where = true;
|
||||
protected Table $layout;
|
||||
protected string $type = '';
|
||||
protected string $placeholder = '';
|
||||
protected bool $quick = false;
|
||||
protected string $condition = '';
|
||||
protected ?\Closure $callback;
|
||||
protected $data;
|
||||
protected $model;
|
||||
protected $value;
|
||||
protected $filterLayout;//rows
|
||||
|
||||
/**
|
||||
* Filter constructor.
|
||||
* @param string $name
|
||||
* @param string $field
|
||||
* @param bool $where
|
||||
* @param null $default
|
||||
*/
|
||||
public function __construct(string $name, string $field, $where = true, $default = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->field = $field;
|
||||
$this->where = $where;
|
||||
$this->default = $default;
|
||||
$this->value = \Yii::$app->request->get($field, $this->default);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置父级对象
|
||||
* @param Table $layout
|
||||
*/
|
||||
public function setLayout(Table $layout): void
|
||||
{
|
||||
$this->layout = $layout;
|
||||
$this->model = $layout->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* 级联选择
|
||||
* @param callable|array $data
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function cascader($data = [], callable $callback = NULL): self
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->type = 'cascader';
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉框
|
||||
* @param callable|array $data
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function select($data = [], callable $callback = NULL): self
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->type = 'select';
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本库
|
||||
* @param string $placeholder
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function text(string $placeholder = '', callable $callback = NULL): self
|
||||
{
|
||||
$this->placeholder = $placeholder;
|
||||
$this->type = 'text';
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期
|
||||
* @param string $placeholder
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function date(string $placeholder = '', callable $callback = NULL): self
|
||||
{
|
||||
$this->placeholder = $placeholder;
|
||||
$this->type = 'date';
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期时间
|
||||
* @param string $placeholder
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function datetime(string $placeholder = '', callable $callback = NULL): self
|
||||
{
|
||||
$this->placeholder = $placeholder;
|
||||
$this->type = 'datetime';
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期范围
|
||||
* @param string $placeholder
|
||||
* @param callable|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function daterange(string $placeholder = '', callable $callback = NULL): self
|
||||
{
|
||||
$this->placeholder = $placeholder;
|
||||
$this->type = 'daterange';
|
||||
$this->callback = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 快捷筛选
|
||||
* @return $this
|
||||
*/
|
||||
public function quick(): self
|
||||
{
|
||||
$this->quick = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 筛选条件
|
||||
* @param $type
|
||||
* @return $this
|
||||
*/
|
||||
public function condition($type): self
|
||||
{
|
||||
$this->condition = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行筛选
|
||||
* @param $query
|
||||
* @return false
|
||||
*/
|
||||
public function execute($query): bool
|
||||
{
|
||||
if ($this->value === null) {
|
||||
return false;
|
||||
}
|
||||
if (is_array($this->value) && empty($this->value)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->where instanceof \Closure) {
|
||||
call_user_func($this->where, $query, $this->value, $this->data);
|
||||
} elseif ($this->where !== false) {
|
||||
|
||||
$field = is_string($this->where) ? $this->where : $this->field;
|
||||
$condition = '=';
|
||||
$value = $this->value;
|
||||
|
||||
if ($this->condition === 'like') {
|
||||
$condition = 'like';
|
||||
$value = '%' . $value . '%';
|
||||
}
|
||||
|
||||
$query->where($field, $condition, $value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染组件
|
||||
* @return array
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
if (!$this->type) {
|
||||
$this->layout->filterParams($this->field, $this->value);
|
||||
return [];
|
||||
}
|
||||
switch ($this->type) {
|
||||
case 'select':
|
||||
$object = new Select($this->name, $this->field, $this->data);
|
||||
$object->tip(true);
|
||||
break;
|
||||
case 'cascader':
|
||||
$object = new Cascader($this->name, $this->field, $this->data);
|
||||
break;
|
||||
case 'date':
|
||||
$object = new Date($this->name, $this->field);
|
||||
break;
|
||||
case 'datetime':
|
||||
$object = new Datetime($this->name, $this->field);
|
||||
break;
|
||||
case 'daterange':
|
||||
$object = new Daterange($this->name, $this->field);
|
||||
break;
|
||||
case 'text':
|
||||
default:
|
||||
$object = new Text($this->name, $this->field);
|
||||
}
|
||||
|
||||
$object->model('data.filter.');
|
||||
|
||||
|
||||
$this->layout->filterParams($this->field, $this->value);
|
||||
|
||||
if ($this->callback instanceof \Closure) {
|
||||
call_user_func($this->callback, $object);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'status' => $this->value !== null,
|
||||
'quick' => $this->quick,
|
||||
'where' => $this->where,
|
||||
'value' => $this->value,
|
||||
'field' => $this->field,
|
||||
'data' => $this->data,
|
||||
'name' => $this->name
|
||||
];
|
||||
|
||||
if($this->layout->filterLayout=='rows'){
|
||||
$data['render'] = [
|
||||
'nodeName'=>'a-col',
|
||||
"span"=>"6",
|
||||
'child'=>[
|
||||
'nodeName'=>'a-form-item',
|
||||
'field'=>$this->field,
|
||||
'label'=>$this->name,
|
||||
'child' => $object->placeholder($this->placeholder)->getRender()
|
||||
]
|
||||
];
|
||||
return $data;
|
||||
|
||||
}
|
||||
if ($this->quick) {
|
||||
$data['render'] = [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'lg:w-40',
|
||||
'child' => $object->placeholder($this->placeholder)->getRender()
|
||||
];
|
||||
} else {
|
||||
$data['render'] = [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'my-2',
|
||||
'child' => [
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'child' => $this->name,
|
||||
],
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'mt-2',
|
||||
'child' => $object->placeholder($this->placeholder)->getRender()
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
88
admin/components/UI/Table/FilterType.php
Normal file
88
admin/components/UI/Table/FilterType.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use admin\components\UI\Form\Date;
|
||||
use admin\components\UI\Form\Daterange;
|
||||
use admin\components\UI\Form\Datetime;
|
||||
use admin\components\UI\Form\Select;
|
||||
use admin\components\UI\Form\Text;
|
||||
use admin\components\UI\Table;
|
||||
use admin\components\UI\Widget\Icon;
|
||||
|
||||
/**
|
||||
* 类型筛选
|
||||
* Class Column
|
||||
* @package backend\components\UI\Filter
|
||||
*/
|
||||
class FilterType
|
||||
{
|
||||
|
||||
protected string $name;
|
||||
protected ?\Closure $callback;
|
||||
protected ?\Closure $where;
|
||||
protected string $icon = '';
|
||||
protected ?int $num = null;
|
||||
protected ?Table $layout;
|
||||
protected $model;
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param callable|null $where
|
||||
* @param int $value
|
||||
*/
|
||||
public function __construct(string $name, callable $where = null, int $value = 0)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->where = $where;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function setLayout(Table $layout): void
|
||||
{
|
||||
$this->layout = $layout;
|
||||
$this->model = $layout->model();
|
||||
}
|
||||
|
||||
public function num($num = 0): self
|
||||
{
|
||||
$this->num = $num;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function icon($content): self
|
||||
{
|
||||
$this->icon = $content;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function execute($query, $key): void
|
||||
{
|
||||
if ($this->where instanceof \Closure && $this->value == $key) {
|
||||
call_user_func($this->where, $this->model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return array
|
||||
*/
|
||||
public function render($key): array
|
||||
{
|
||||
return [
|
||||
'nodeName' => 'a-radio',
|
||||
'value' => $key,
|
||||
'child' => [
|
||||
$this->icon ? [
|
||||
'nodeName' => $this->icon
|
||||
]: [],
|
||||
[
|
||||
'nodeName' => 'span',
|
||||
'child' => ' ' . $this->name
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
591
admin/components/UI/Table/Node.php
Normal file
591
admin/components/UI/Table/Node.php
Normal file
@@ -0,0 +1,591 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use admin\components\UI\Form\Cascader;
|
||||
use admin\components\UI\Tools;
|
||||
use admin\components\UI\Widget\Icon;
|
||||
|
||||
/**
|
||||
* 表格节点
|
||||
* @package backend\components\UI\Table
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
private string $url;
|
||||
private ?string $key;
|
||||
private ?string $title;
|
||||
private bool $tree = false;
|
||||
private bool $urlBind = true;
|
||||
private string $class = '';
|
||||
private array $params = [];
|
||||
private array $data = ['show'=>[],'filter'=>[]];
|
||||
private array $columns = [];
|
||||
private array $expand = [];
|
||||
private array $filter = [];
|
||||
private array $quickFilter = [];
|
||||
private array $action = [];
|
||||
private array $bath = [];
|
||||
private array $page = ['left'=>[],'right'=>[]];
|
||||
private array $type = [];
|
||||
private array $side = ['left'=>[],'right'=>[]];
|
||||
private array $sideSize = ['left'=>'','right'=>''];
|
||||
private array $header = [];
|
||||
private array $footer = [];
|
||||
private array $script = [];
|
||||
private array $scriptReturn = [];
|
||||
private array $scriptData = [];
|
||||
private ?string $eventName = null;
|
||||
private $filterLayout =null;
|
||||
|
||||
/**
|
||||
* Node constructor.
|
||||
* @param string $url
|
||||
* @param string $key
|
||||
* @param string|null $title
|
||||
*/
|
||||
public function __construct(string $url, string $key, ?string $title = '')
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->key = $key;
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $urlBind
|
||||
* @return $this
|
||||
*/
|
||||
public function urlBind($urlBind): self
|
||||
{
|
||||
$this->urlBind = $urlBind;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @return $this
|
||||
*/
|
||||
public function class($class): self
|
||||
{
|
||||
$this->class .= ' ' . $class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
* @return $this
|
||||
*/
|
||||
public function params($params): self
|
||||
{
|
||||
$this->params = $params;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 附加参数
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function nParams($key,$value){
|
||||
$this->params[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $filter
|
||||
* @return $this
|
||||
*/
|
||||
public function data(array $filter): self
|
||||
{
|
||||
$this->data['filter'] = $filter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $content
|
||||
* @param $return
|
||||
* @return $this
|
||||
*/
|
||||
public function script($content, $return): self
|
||||
{
|
||||
if ($content instanceof \Closure) {
|
||||
$this->script[] = $content();
|
||||
} else {
|
||||
$this->script[] = $content;
|
||||
}
|
||||
$this->scriptReturn[] = $return;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return $this
|
||||
*/
|
||||
public function scriptData($data): self
|
||||
{
|
||||
$this->scriptData = array_merge($this->scriptData, $data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $config
|
||||
* @return $this
|
||||
*/
|
||||
public function tree($config): self
|
||||
{
|
||||
$this->tree = $config;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function columns(array $node): self
|
||||
{
|
||||
$this->columns = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function expand(array $node): self
|
||||
{
|
||||
$this->expand = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function type(array $node): self
|
||||
{
|
||||
$this->type = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(array $node): self
|
||||
{
|
||||
$this->filter = array_values(array_filter($node));
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function filterLayout($l):self{
|
||||
$this->filterLayout =$l;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function quickFilter(array $node): self
|
||||
{
|
||||
if ($node) {
|
||||
$this->quickFilter = $node;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function action(array $node): self
|
||||
{
|
||||
$this->action = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $node
|
||||
* @return $this
|
||||
*/
|
||||
public function bath(array $node): self
|
||||
{
|
||||
$this->bath = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $eventName
|
||||
* @return $this
|
||||
*/
|
||||
public function eventName(?string $eventName): self
|
||||
{
|
||||
$this->eventName = $eventName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $node
|
||||
* @param string $type
|
||||
* @param false $resize
|
||||
* @param string $width
|
||||
* @return $this
|
||||
*/
|
||||
public function side($node, string $type = 'left', bool $resize = false, string $width = '100px'): self
|
||||
{
|
||||
$this->side[$type] = is_callable($node) ? $node() : $node;
|
||||
if ($resize) {
|
||||
$this->sideSize[$type] = $width;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $node
|
||||
* @param string $type
|
||||
* @return $this
|
||||
*/
|
||||
public function page($node, string $type = 'left'): self
|
||||
{
|
||||
$this->page[$type] = is_callable($node) ? $node() : $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $node
|
||||
* @return $this
|
||||
*/
|
||||
public function header($node): self
|
||||
{
|
||||
$this->header = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $node
|
||||
* @return $this
|
||||
*/
|
||||
public function footer($node): self
|
||||
{
|
||||
$this->footer = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
private function headNode(): array
|
||||
{
|
||||
if($this->filterLayout=='rows'){
|
||||
$ret[] = [
|
||||
'nodeName'=>'a-row',
|
||||
'child'=>[
|
||||
[
|
||||
'nodeName'=>'a-col',
|
||||
'child'=>[
|
||||
'nodeName' => 'a-form',
|
||||
"label-align"=>"left",
|
||||
"vBind:label-col-props"=>"{'span':'8'}",
|
||||
"vBind:wrapper-col-props"=>"{'span':'16'}",
|
||||
'child'=>[
|
||||
[
|
||||
'nodeName'=>'a-row',
|
||||
"vBind:gutter"=>"16",
|
||||
'child' => $this->filter
|
||||
],
|
||||
]
|
||||
]
|
||||
],
|
||||
]
|
||||
];
|
||||
if(!empty($this->action)){
|
||||
if(!empty($this->filter)){
|
||||
$ret[] = [
|
||||
'nodeName'=>'a-divider',
|
||||
'style'=>'margin-top: 0',
|
||||
];
|
||||
}
|
||||
$ret[] = [
|
||||
'nodeName'=>'a-row',
|
||||
"style"=>"margin-bottom: 16px",
|
||||
'child'=>[
|
||||
'nodeName' => 'a-col',
|
||||
'vBind:span'=>'16',
|
||||
'child'=>[
|
||||
'nodeName' => 'a-space',
|
||||
'child'=>$this->action
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
if ($this->filter) {
|
||||
$this->quickFilter[] = [
|
||||
'nodeName' => 'a-trigger',
|
||||
'position' => 'br',
|
||||
'trigger' => 'click',
|
||||
'child' => [
|
||||
[
|
||||
'nodeName' => 'a-button',
|
||||
'type' => 'secondary',
|
||||
'child' => [
|
||||
'筛选',
|
||||
[
|
||||
'vSlot:icon' => '',
|
||||
'nodeName' => 'icon-filter',
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'vSlot:content' => '',
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex flex-col rounded shadow bg-white dark:bg-blackgray-1 dark:text-gray-400 p-2 w-56',
|
||||
'child' => $this->filter
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
$header=[];
|
||||
$ret = [];
|
||||
if ($this->type) {
|
||||
$header = [
|
||||
'nodeName' => 'a-radio-group',
|
||||
'name' => 'type',
|
||||
'type' => 'button',
|
||||
'vModel:modelValue' => 'data.filter.type',
|
||||
'child' => $this->type
|
||||
];
|
||||
$ret[] = [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-grow lg:w-10 flex justify-center lg:justify-start',
|
||||
'child' => $header
|
||||
];
|
||||
}
|
||||
$ret[] = [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-none flex gap-2',
|
||||
'child' => array_filter(array_merge($this->quickFilter, $this->action))
|
||||
];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function tableNode(): array
|
||||
{
|
||||
// 指定行key
|
||||
$this->params['row-key'] = $this->key;
|
||||
|
||||
// 设置扩展行
|
||||
if ($this->expand) {
|
||||
$this->params['vChild:expandable'] = $this->expand;
|
||||
}
|
||||
|
||||
// 分组表头线
|
||||
$children = false;
|
||||
foreach ($this->columns as $col) {
|
||||
if (isset($col['children']) && $col['children']) {
|
||||
$children = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($children) {
|
||||
$this->params['bordered'] = [
|
||||
'headerCell' => true
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'nodeName' => 'app-table',
|
||||
'requestEventName' => $this->eventName,
|
||||
'class' => $this->class,
|
||||
'url' => $this->url,
|
||||
'urlBind' => $this->urlBind,
|
||||
'n-params' => $this->params,
|
||||
'columns' => $this->columns,
|
||||
'vBind:filter' => 'data.filter',
|
||||
'select' => (bool)$this->bath,
|
||||
'table-layout-fixed' => true,
|
||||
'child' => [
|
||||
'vSlot:footer' => 'footer',
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex gap-2',
|
||||
'child' => $this->bath
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
|
||||
/*$this->script[] = <<<JS
|
||||
JS;
|
||||
$this->scriptReturn[] = 'dataRef';*/
|
||||
|
||||
$value = [
|
||||
'filter' => $this->data['filter'] ?: [],
|
||||
'show' => $this->data['show'] ?: []
|
||||
];
|
||||
$value = array_merge($this->scriptData, $value);
|
||||
return [
|
||||
'node' => [
|
||||
'nodeName' => 'app-form',
|
||||
'value' => $value,
|
||||
'child' => [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex h-screen',
|
||||
'vSlot' => '{value: data}',
|
||||
'child' => [
|
||||
$this->side['left'] ? [
|
||||
'nodeName' => isset($this->sideSize['left']) ? 'a-resize-box' : 'div',
|
||||
'style' => $this->sideSize['left'] ? 'width:' . $this->sideSize['left'] : '',
|
||||
'directions' => ['right'],
|
||||
'class' => 'border-r border-gray-200 dark:border-gray-700 flex-none bg-white dark:bg-blackgray-4 h-screen',
|
||||
'child' => $this->side['left']
|
||||
] : [],
|
||||
|
||||
[
|
||||
'nodeName' => 'app-layout',
|
||||
'class' => 'flex-grow w-10',
|
||||
'title' => $this->title ?: '列表数据',
|
||||
'child' => [
|
||||
[
|
||||
'vSlot' => '',
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex flex-row items-start gap-4 p-4',
|
||||
'child' => [
|
||||
$this->page['left'] ?: [],
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-grow lg:w-10 p-4 bg-white dark:bg-blackgray-4 rounded shadow',
|
||||
'child' => [
|
||||
$this->header ? [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'pb-4',
|
||||
'child' => $this->header
|
||||
] : [],
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-none flex-row gap-2 items-center pb-4',
|
||||
'child' => $this->headNode()
|
||||
|
||||
],
|
||||
$this->tableNode(),
|
||||
$this->footer ? [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'pb-4',
|
||||
'child' => $this->footer
|
||||
] : [],
|
||||
],
|
||||
],
|
||||
$this->page['right'] ?: [],
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
|
||||
$this->side['right'] ? [
|
||||
'nodeName' => $this->sideSize['right'] ? 'a-resize-box' : 'div',
|
||||
'style' => $this->sideSize['right'] ? 'width:' . $this->sideSize['left'] : '',
|
||||
'directions' => ['left'],
|
||||
'class' => 'border-l border-gray-200 dark:border-gray-700 flex-none bg-white dark:bg-blackgray-4 h-screen',
|
||||
'child' => $this->side['right']
|
||||
] : [],
|
||||
]
|
||||
],
|
||||
],
|
||||
'setupScript' => implode("\n", $this->script) . "\n" . ' return {' . implode(",", $this->scriptReturn) . '}'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染table核心
|
||||
* @return array[]
|
||||
*/
|
||||
public function renderTableCore(): array
|
||||
{
|
||||
$value = [
|
||||
'filter' => $this->data['filter'] ?: [],
|
||||
'show' => $this->data['show'] ?: []
|
||||
];
|
||||
$value = array_merge($this->scriptData, $value);
|
||||
return [
|
||||
'node' => [
|
||||
'nodeName' => 'app-form',
|
||||
'value' => $value,
|
||||
'child' => [
|
||||
'nodeName' => 'app-dialog',
|
||||
'vSlot' => '{value: data}',
|
||||
'title' => $this->title ?: '信息详情',
|
||||
'class' => 'flex-grow',
|
||||
'child' => [
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex',
|
||||
'vSlot' => '{value: data}',
|
||||
'child' => [
|
||||
$this->side['left'] ? [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-none',
|
||||
'child' => $this->side['left']
|
||||
] : [],
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-grow lg:w-10 p-4 bg-white dark:bg-blackgray-4 rounded shadow',
|
||||
'child' => [
|
||||
$this->header ? [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'pb-4',
|
||||
'child' => $this->header
|
||||
] : [],
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-none flex flex-row gap-2 items-center pb-4',
|
||||
'child' => $this->headNode()
|
||||
|
||||
],
|
||||
$this->tableNode(),
|
||||
$this->footer ? [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'pb-4',
|
||||
'child' => $this->footer
|
||||
] : [],
|
||||
],
|
||||
],
|
||||
$this->side['right'] ? [
|
||||
'nodeName' => 'div',
|
||||
'class' => 'flex-none',
|
||||
'child' => $this->side['right']
|
||||
] : []
|
||||
]
|
||||
],
|
||||
[
|
||||
'nodeName' => 'div',
|
||||
'vSlot:footer' => '',
|
||||
'class' => 'arco-modal-footer',
|
||||
'child' => [
|
||||
[
|
||||
'nodeName' => 'route',
|
||||
'type' => 'back',
|
||||
'child' => [
|
||||
'nodeName' => 'a-button',
|
||||
'child' => '关闭'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
99
admin/components/UI/Table/Tree.php
Normal file
99
admin/components/UI/Table/Tree.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace admin\components\UI\Table;
|
||||
|
||||
use admin\components\UI\Widget\Link;
|
||||
|
||||
/**
|
||||
* 树形列表
|
||||
* @package backend\components\UI\Filter
|
||||
*/
|
||||
class Tree
|
||||
{
|
||||
|
||||
protected string $label = '';
|
||||
protected array $node = [];
|
||||
protected array $prefix = [];
|
||||
protected array $suffix = [];
|
||||
protected Column\Link $link;
|
||||
|
||||
/**
|
||||
* @param string $label
|
||||
* @param array $node
|
||||
*/
|
||||
public function __construct(string $label, array $node = [])
|
||||
{
|
||||
$this->label = $label;
|
||||
$this->node = $node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $node
|
||||
* @return $this
|
||||
*/
|
||||
public function prefix($node): self
|
||||
{
|
||||
$this->prefix = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $node
|
||||
* @return $this
|
||||
*/
|
||||
public function suffix($node): self
|
||||
{
|
||||
$this->suffix = $node;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加链接
|
||||
* @param string $name
|
||||
* @param string $route
|
||||
* @param array $params
|
||||
* @return Link
|
||||
*/
|
||||
public function link(string $name, string $route, array $params = []): Link
|
||||
{
|
||||
if (!$this->link) {
|
||||
$this->link = new Column\Link();
|
||||
}
|
||||
return $this->link->add($name, $route, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 渲染组件
|
||||
* @return array
|
||||
*/
|
||||
public function render(): array
|
||||
{
|
||||
$suffix = $this->suffix;
|
||||
if ($this->link) {
|
||||
$suffix = $this->link->render('');
|
||||
}
|
||||
return [
|
||||
'node' => $this->node ?: ['nodeName' => 'div', 'child' => "{{rowData.record['$this->label']}}"],
|
||||
'prefix' => $this->prefix,
|
||||
'suffix' => $suffix
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件行数据
|
||||
* @param $rowData
|
||||
* @return array
|
||||
*/
|
||||
public function getData($rowData): array
|
||||
{
|
||||
$data = [];
|
||||
// 元素数据
|
||||
if ($this->link) {
|
||||
$data = array_merge($data, $this->link->getData($rowData));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user