Files
xk-api-yii/admin/components/UI/Form/Node.php
2024-09-19 11:32:39 +08:00

265 lines
7.6 KiB
PHP

<?php
namespace admin\components\UI\Form;
/**
* 表单节点
* @package backend\components\UI\Form
*/
class Node
{
private string $url;
private string $method;
private ?string $title;
private bool $back = false;
private bool $dialog = false;
private bool $vertical = false;
private array $element = [];
private array $data = [];
private array $side = ['left'=>[],'right'=>[]];
private array $script = [];
private array $scriptReturn = [];
/**
* Node constructor.
* @param string $action
* @param string $method
* @param string|null $title
*/
public function __construct(string $action, string $method, ?string $title = '')
{
$this->url = $action;
$this->method = $method;
$this->title = $title;
}
/**
* @param bool $bool
*/
public function back(bool $bool): void
{
$this->back = $bool;
}
/**
* @param Closure|string $content
* @param string $return
* @return $this
*/
public function script($content, string $return): self
{
if ($content instanceof \Closure) {
$this->script[] = $content();
} else {
$this->script[] = $content;
}
$this->scriptReturn[] = $return;
return $this;
}
/**
* @param bool $bool
* @return $this
*/
public function dialog(bool $bool): self
{
$this->dialog = $bool;
$this->vertical = true;
return $this;
}
/**
* @param bool $bool
* @return $this
*/
public function vertical(bool $bool): self
{
$this->vertical = $bool;
return $this;
}
/**
* @param array $node
* @return $this
*/
public function element(array $node): self
{
$this->element = $node;
return $this;
}
/**
* @param Closure|array $node
* @param string $type
* @return $this
*/
public function side($node, string $type = 'left'): self
{
$this->side[$type] = is_callable($node) ? $node() : $node;
return $this;
}
/**
* @param $data
* @return $this
*/
public function data($data): self
{
$this->data = $data;
return $this;
}
/**
* 渲染页面
* @return array[]
*/
private function renderPage(): array
{
return [
$this->side['left'] ? [
'nodeName' => 'div',
'class' => 'flex-none flex h-screen flex-col',
'child' => $this->side['left']
] : [],
[
'nodeName' => 'app-layout',
'class' => 'flex-grow w-10',
'title' => $this->title ?: '信息详情',
'form' => true,
'back' => $this->back,
'vBind:formLoading' => 'loading',
'child' => [
[
'nodeName' => 'div',
'class' => 'p-4',
'child' => [
[
'nodeName' => 'div',
'child' => $this->element
],
[
'nodeName' => 'div',
'class' => 'flex items-center justify-end gap-2 flex-row ',
'child' => [
$this->back ? [
'nodeName' => 'route',
'type' => 'back',
'child' => [
'type' => "outline",
'nodeName' => 'a-button',
'child' => '返回',
]
] : [],
[
'nodeName' => 'a-button',
'html-type' => 'submit',
'vBind:loading' => "loading",
'type' => 'primary',
'child' => $this->back ? '提交' : '保存',
],
]
],
],
],
],
],
$this->side['right']? [
'nodeName' => 'div',
'class' => 'flex-none flex h-screen flex-col',
'child' => $this->side['right']
] : [],
];
}
/**
* 渲染弹窗
* @return array
*/
private function renderDialog(): array
{
return [
'nodeName' => 'app-dialog',
'title' => $this->title ?: '信息详情',
'class' => 'flex-grow',
'child' => [
[
'nodeName' => 'div',
'vSlot:default' => '',
'class' => 'flex',
'child' => [
$this->side['left'] ? [
'nodeName' => 'div',
'class' => 'flex-none',
'child' => $this->side['left']
] : [],
[
'nodeName' => 'div',
'class' => 'flex-grow p-5 pb-0',
'child' => $this->element
],
$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' => '取消'
]
],
[
'nodeName' => 'a-button',
'type' => 'primary',
'html-type' => 'submit',
'vBind:loading' => "loading",
'child' => '提交'
],
]
]
]
];
}
/**
* 渲染布局
* @return array
*/
public function render(): array
{
return [
'node' => [
'nodeName' => 'app-form',
'url' => $this->url,
'method' => $this->method,
'value' => $this->data,
'layout' => $this->vertical ? 'vertical' : 'horizontal',
'back' => $this->back,
'child' => [
'nodeName' => 'div',
'class' => 'flex',
'vSlot' => '{value: data, submitStatus: loading}',
'child' => $this->dialog ? $this->renderDialog() : $this->renderPage()
]
],
'setupScript' => implode("\n", $this->script) . "\n" . ' return {' . implode(",", $this->scriptReturn) . '}'
];
}
}