mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2026-06-07 04:28:11 +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
|
||||
{
|
||||
/**
|
||||
* 标准表单栅格容器.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@ -84,4 +126,9 @@ class FormModules
|
||||
{
|
||||
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 .= "\n\t" . sprintf('<div %s>', $context->attrs($bodyAttrs));
|
||||
$html .= "\n\t\t" . $this->renderStandardStyle();
|
||||
|
||||
if (count($content) > 0) {
|
||||
$html .= $context->renderChildren($content);
|
||||
@ -76,6 +77,7 @@ class FormShellRenderer
|
||||
$header = (new PageHeaderRenderer())->render(strval($schema['title'] ?? ''), $headerButtons);
|
||||
$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\t" . $this->renderStandardStyle();
|
||||
|
||||
if (count($content) > 0) {
|
||||
$form .= "\n\t\t\t\t\t" . $context->renderChildren($content);
|
||||
@ -116,4 +118,30 @@ class FormShellRenderer
|
||||
$html .= "\n\t" . '</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\FormComponents;
|
||||
use think\admin\builder\form\FormChoiceField;
|
||||
use think\admin\builder\form\module\FormModules;
|
||||
use think\admin\builder\form\FormSelectField;
|
||||
use think\admin\builder\form\FormTextField;
|
||||
use think\admin\builder\form\FormUploadField;
|
||||
@ -348,6 +349,38 @@ class FormBuilderTest extends TestCase
|
||||
$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
|
||||
{
|
||||
$builder = $this->newBuilder('form', 'page');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user