mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2026-06-06 20:18:10 +08:00
feat(form): 增加表单栅格布局模块
新增 FormModules::grid 与 gridColumn,用统一方法生成 1 到 4 列的标准表单栅格,避免各业务表单重复拼接 layui 栅格类名。 在表单渲染壳层中注入标准样式,统一栅格列宽、字段间距、单行说明省略和自动补全下拉层样式,保证弹窗与页面模式展示一致。 补充 FormBuilderTest 覆盖可复用栅格布局、nowrap 说明文案和标准样式输出,防止后续表单布局能力回退。
This commit is contained in:
parent
217b1c9ea9
commit
875c3a16d7
@ -13,6 +13,48 @@ use think\admin\builder\form\FormNode;
|
|||||||
*/
|
*/
|
||||||
class FormModules
|
class FormModules
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 标准表单栅格容器.
|
||||||
|
*/
|
||||||
|
public static function grid(FormNode $parent, int $columns = 2, string|array $class = '', int $space = 15): FormNode
|
||||||
|
{
|
||||||
|
$columns = self::normalizeGridColumns($columns);
|
||||||
|
$space = max(0, min(30, $space));
|
||||||
|
$node = $parent->div()->class([
|
||||||
|
'layui-row',
|
||||||
|
"layui-col-space{$space}",
|
||||||
|
'ta-form-grid',
|
||||||
|
"ta-form-grid-{$columns}",
|
||||||
|
]);
|
||||||
|
if ($class !== '' && $class !== []) {
|
||||||
|
$node->class($class);
|
||||||
|
}
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标准表单栅格列.
|
||||||
|
*/
|
||||||
|
public static function gridColumn(FormNode $parent, int $columns = 2, string|array $class = ''): FormNode
|
||||||
|
{
|
||||||
|
$columns = self::normalizeGridColumns($columns);
|
||||||
|
$span = match ($columns) {
|
||||||
|
1 => 12,
|
||||||
|
2 => 6,
|
||||||
|
3 => 4,
|
||||||
|
default => 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
$node = $parent->div()->class([
|
||||||
|
"layui-col-xs{$span}",
|
||||||
|
'ta-form-grid-col',
|
||||||
|
]);
|
||||||
|
if ($class !== '' && $class !== []) {
|
||||||
|
$node->class($class);
|
||||||
|
}
|
||||||
|
return $node;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $config
|
* @param array<string, mixed> $config
|
||||||
*/
|
*/
|
||||||
@ -84,4 +126,9 @@ class FormModules
|
|||||||
{
|
{
|
||||||
return htmlentities($content, ENT_QUOTES, 'UTF-8');
|
return htmlentities($content, ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function normalizeGridColumns(int $columns): int
|
||||||
|
{
|
||||||
|
return max(1, min(4, $columns));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ class FormShellRenderer
|
|||||||
|
|
||||||
$html = sprintf('<form %s>', $context->attrs($attrs));
|
$html = sprintf('<form %s>', $context->attrs($attrs));
|
||||||
$html .= "\n\t" . sprintf('<div %s>', $context->attrs($bodyAttrs));
|
$html .= "\n\t" . sprintf('<div %s>', $context->attrs($bodyAttrs));
|
||||||
|
$html .= "\n\t\t" . $this->renderStandardStyle();
|
||||||
|
|
||||||
if (count($content) > 0) {
|
if (count($content) > 0) {
|
||||||
$html .= $context->renderChildren($content);
|
$html .= $context->renderChildren($content);
|
||||||
@ -76,6 +77,7 @@ class FormShellRenderer
|
|||||||
$header = (new PageHeaderRenderer())->render(strval($schema['title'] ?? ''), $headerButtons);
|
$header = (new PageHeaderRenderer())->render(strval($schema['title'] ?? ''), $headerButtons);
|
||||||
$form = sprintf('<form %s>', $context->attrs($attrs));
|
$form = sprintf('<form %s>', $context->attrs($attrs));
|
||||||
$form .= "\n\t\t\t\t" . sprintf('<div %s>', $context->attrs($bodyAttrs));
|
$form .= "\n\t\t\t\t" . sprintf('<div %s>', $context->attrs($bodyAttrs));
|
||||||
|
$form .= "\n\t\t\t\t\t" . $this->renderStandardStyle();
|
||||||
|
|
||||||
if (count($content) > 0) {
|
if (count($content) > 0) {
|
||||||
$form .= "\n\t\t\t\t\t" . $context->renderChildren($content);
|
$form .= "\n\t\t\t\t\t" . $context->renderChildren($content);
|
||||||
@ -116,4 +118,30 @@ class FormShellRenderer
|
|||||||
$html .= "\n\t" . '</div>';
|
$html .= "\n\t" . '</div>';
|
||||||
return $html . "\n</div>";
|
return $html . "\n</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function renderStandardStyle(): string
|
||||||
|
{
|
||||||
|
return <<<'HTML'
|
||||||
|
<style data-form-builder-standard-style>
|
||||||
|
.ta-form-grid{display:flex;flex-wrap:wrap;align-items:flex-start}
|
||||||
|
.ta-form-grid>.ta-form-grid-col{box-sizing:border-box}
|
||||||
|
.ta-form-grid-1>.ta-form-grid-col{width:100%!important;max-width:100%}
|
||||||
|
.ta-form-grid-2>.ta-form-grid-col{width:50%!important;max-width:50%}
|
||||||
|
.ta-form-grid-3>.ta-form-grid-col{width:33.333333%!important;max-width:33.333333%}
|
||||||
|
.ta-form-grid-4>.ta-form-grid-col{width:25%!important;max-width:25%}
|
||||||
|
.ta-form-grid>.ta-form-grid-col .layui-form-item{margin-bottom:14px}
|
||||||
|
.ta-form-grid-compact>.ta-form-grid-col{padding-top:4px!important;padding-bottom:4px!important}
|
||||||
|
.ta-form-grid-compact>.ta-form-grid-col .layui-form-item{margin-bottom:6px}
|
||||||
|
.ta-form-grid-compact>.ta-form-grid-col .help-block{margin-top:2px;line-height:1.4}
|
||||||
|
.ta-form-nowrap section>div:first-child p,
|
||||||
|
.ta-form-nowrap .ta-form-grid-col .help-label,
|
||||||
|
.ta-form-nowrap .ta-form-grid-col .help-block,
|
||||||
|
.ta-form-grid.ta-form-nowrap .help-label,
|
||||||
|
.ta-form-grid.ta-form-nowrap .help-block{display:block;max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
|
||||||
|
.ta-form-autocompleter{top:58px;z-index:19892000;min-width:100%;border-radius:0 0 6px 6px;box-shadow:0 8px 24px rgba(15,23,42,.14)}
|
||||||
|
.ta-form-autocompleter .autocompleter-list{max-height:220px;overflow-y:auto;background:#fff}
|
||||||
|
.ta-form-autocompleter .autocompleter-item{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
|
||||||
|
</style>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ use think\admin\Controller;
|
|||||||
use think\admin\builder\form\FormBuilder;
|
use think\admin\builder\form\FormBuilder;
|
||||||
use think\admin\builder\form\FormComponents;
|
use think\admin\builder\form\FormComponents;
|
||||||
use think\admin\builder\form\FormChoiceField;
|
use think\admin\builder\form\FormChoiceField;
|
||||||
|
use think\admin\builder\form\module\FormModules;
|
||||||
use think\admin\builder\form\FormSelectField;
|
use think\admin\builder\form\FormSelectField;
|
||||||
use think\admin\builder\form\FormTextField;
|
use think\admin\builder\form\FormTextField;
|
||||||
use think\admin\builder\form\FormUploadField;
|
use think\admin\builder\form\FormUploadField;
|
||||||
@ -348,6 +349,38 @@ class FormBuilderTest extends TestCase
|
|||||||
$this->assertStringContainsString('data-builder-modules=', $html);
|
$this->assertStringContainsString('data-builder-modules=', $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFormModulesCanRenderReusableGridLayout(): void
|
||||||
|
{
|
||||||
|
$builder = $this->newBuilder();
|
||||||
|
$builder->define(function ($form) {
|
||||||
|
$form->class('ta-form-nowrap');
|
||||||
|
FormModules::section($form, [
|
||||||
|
'title' => '布局',
|
||||||
|
'description' => '描述信息保持单行显示。',
|
||||||
|
], function ($section) {
|
||||||
|
$grid = FormModules::grid($section, 3, 'profile-grid');
|
||||||
|
FormModules::gridColumn($grid, 3)->fields(function ($fields) {
|
||||||
|
$fields->text('nickname', '用户名称', 'Nickname', true, '单行说明');
|
||||||
|
});
|
||||||
|
FormModules::gridColumn($grid, 3)->fields(function ($fields) {
|
||||||
|
$fields->text('email', '联系邮箱', 'Email');
|
||||||
|
});
|
||||||
|
FormModules::gridColumn($grid, 3)->fields(function ($fields) {
|
||||||
|
$fields->text('phone', '联系电话', 'Phone');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})->build();
|
||||||
|
|
||||||
|
$html = $this->invokePrivate($builder, '_buildFormModal');
|
||||||
|
|
||||||
|
$this->assertStringContainsString('data-form-builder-standard-style', $html);
|
||||||
|
$this->assertStringContainsString('ta-form-nowrap', $html);
|
||||||
|
$this->assertStringContainsString('layui-row layui-col-space15 ta-form-grid ta-form-grid-3 profile-grid', $html);
|
||||||
|
$this->assertStringContainsString('layui-col-xs4 ta-form-grid-col', $html);
|
||||||
|
$this->assertStringContainsString('width:33.333333%!important', $html);
|
||||||
|
$this->assertStringContainsString('white-space:nowrap', $html);
|
||||||
|
}
|
||||||
|
|
||||||
public function testPageModeCanRenderTitleAndDefaultPadding(): void
|
public function testPageModeCanRenderTitleAndDefaultPadding(): void
|
||||||
{
|
{
|
||||||
$builder = $this->newBuilder('form', 'page');
|
$builder = $this->newBuilder('form', 'page');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user