mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2026-06-06 20:18:10 +08:00
style(config): 重整系统配置页布局
将系统配置首页从混合展示存储信息调整为聚焦运行模式与基础参数,移除首页对存储中心上下文的加载,降低配置页渲染耦合。 拆分系统参数表单的入口主题、插件中心、运行参数、安全资源和品牌信息构建逻辑,并加入专用响应式样式,让多列字段在桌面端更紧凑、小屏端自动堆叠。 优化系统与存储概览卡片的栅格展示,更新渲染测试断言,确保配置页不再展示旧存储中心入口,同时保留存储配置独立页面的概览信息。
This commit is contained in:
parent
875c3a16d7
commit
7e87c0d65a
@ -6,6 +6,7 @@ namespace plugin\system\builder;
|
|||||||
|
|
||||||
use think\admin\builder\BuilderLang;
|
use think\admin\builder\BuilderLang;
|
||||||
use think\admin\builder\form\FormBuilder;
|
use think\admin\builder\form\FormBuilder;
|
||||||
|
use think\admin\builder\form\FormNode;
|
||||||
use think\admin\builder\form\module\FormModules;
|
use think\admin\builder\form\module\FormModules;
|
||||||
use think\admin\builder\page\PageBuilder;
|
use think\admin\builder\page\PageBuilder;
|
||||||
use think\admin\builder\page\PageNode;
|
use think\admin\builder\page\PageNode;
|
||||||
@ -23,42 +24,42 @@ class ConfigBuilder
|
|||||||
public static function buildIndexPage(array $context): PageBuilder
|
public static function buildIndexPage(array $context): PageBuilder
|
||||||
{
|
{
|
||||||
$site = is_array($context['site'] ?? null) ? $context['site'] : [];
|
$site = is_array($context['site'] ?? null) ? $context['site'] : [];
|
||||||
$storage = is_array($context['storage'] ?? null) ? $context['storage'] : [];
|
|
||||||
$isSuper = !empty($context['issuper']);
|
$isSuper = !empty($context['issuper']);
|
||||||
$isDebug = !empty($context['appDebug']);
|
$isDebug = !empty($context['appDebug']);
|
||||||
$storageEditable = !empty($context['storageEditable']);
|
|
||||||
$storageDriver = strval($context['storageDriver'] ?? 'local');
|
|
||||||
$storageName = strval($context['storageName'] ?? $storageDriver);
|
|
||||||
$systemInfo = is_array($context['systemInfo'] ?? null) ? $context['systemInfo'] : [];
|
$systemInfo = is_array($context['systemInfo'] ?? null) ? $context['systemInfo'] : [];
|
||||||
$showSystemButton = !empty($context['canEditSystem']);
|
$showSystemButton = !empty($context['canEditSystem']);
|
||||||
$pluginCenter = is_array($context['pluginCenter'] ?? null) ? $context['pluginCenter'] : [];
|
$pluginCenter = is_array($context['pluginCenter'] ?? null) ? $context['pluginCenter'] : [];
|
||||||
|
|
||||||
return PageBuilder::domPage()
|
return PageBuilder::domPage()
|
||||||
->define(function ($page) use ($site, $storage, $isSuper, $isDebug, $storageEditable, $storageDriver, $storageName, $systemInfo, $showSystemButton, $pluginCenter) {
|
->define(function ($page) use ($site, $isSuper, $isDebug, $systemInfo, $showSystemButton, $pluginCenter) {
|
||||||
$page->title('系统参数配置')->contentClass('');
|
$page->title('系统参数配置')->contentClass('');
|
||||||
|
|
||||||
self::buildHeaderButtons($page, $isSuper, $showSystemButton);
|
self::buildHeaderButtons($page, $isSuper, $showSystemButton);
|
||||||
|
|
||||||
PageModules::card($page, ['title' => '系统概览', 'remark' => '统一管理运行模式、存储中心与系统基础参数', 'class' => 'layui-card mb15'], function (PageNode $body) use ($isDebug, $storageName, $site, $pluginCenter) {
|
PageModules::card($page, ['title' => '系统概览', 'remark' => '统一管理运行模式与系统基础参数', 'class' => 'layui-card mb15'], function (PageNode $body) use ($isDebug, $site, $pluginCenter) {
|
||||||
|
$body->html(<<<'HTML'
|
||||||
|
<style>
|
||||||
|
.system-overview-kv{grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
|
||||||
|
.system-overview-kv>.ta-kv-item{min-height:58px;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center}
|
||||||
|
@media screen and (max-width:1400px){.system-overview-kv{grid-template-columns:repeat(3,minmax(0,1fr))}}
|
||||||
|
@media screen and (max-width:900px){.system-overview-kv{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||||
|
@media screen and (max-width:560px){.system-overview-kv{grid-template-columns:1fr}}
|
||||||
|
</style>
|
||||||
|
HTML);
|
||||||
PageModules::paragraphs($body, [
|
PageModules::paragraphs($body, [
|
||||||
'当前后台使用 System 统一维护运行模式、文件存储与系统基础参数。',
|
'当前后台使用 System 统一维护运行模式与系统基础参数。',
|
||||||
], ['class' => 'ta-desc mt0']);
|
], ['class' => 'ta-desc mt0']);
|
||||||
PageModules::kvGrid($body, [
|
PageModules::kvGrid($body, [
|
||||||
['label' => '运行模式', 'value' => $isDebug ? '开发模式' : '生产模式'],
|
['label' => '运行模式', 'value' => $isDebug ? '开发模式' : '生产模式'],
|
||||||
['label' => '默认存储驱动', 'value' => $storageName],
|
|
||||||
['label' => '站点名称', 'value' => strval($site['website_name'] ?? '-')],
|
['label' => '站点名称', 'value' => strval($site['website_name'] ?? '-')],
|
||||||
['label' => '插件中心', 'value' => !empty($pluginCenter['enabled']) ? '已启用' : '已禁用'],
|
['label' => '插件中心', 'value' => !empty($pluginCenter['enabled']) ? '已启用' : '已禁用'],
|
||||||
['label' => '菜单入口策略', 'value' => !empty($pluginCenter['show_menu']) ? '显示插件中心菜单' : '隐藏插件中心菜单'],
|
['label' => '菜单入口策略', 'value' => !empty($pluginCenter['show_menu']) ? '显示插件中心菜单' : '隐藏插件中心菜单'],
|
||||||
]);
|
], ['class' => 'ta-kv system-overview-kv']);
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($isSuper) {
|
if ($isSuper) {
|
||||||
self::buildSummaryPanels($page, [
|
self::buildSummaryPanels($page, [
|
||||||
'isDebug' => $isDebug,
|
'isDebug' => $isDebug,
|
||||||
'storageEditable' => $storageEditable,
|
|
||||||
'storageDriver' => $storageDriver,
|
|
||||||
'storageName' => $storageName,
|
|
||||||
'storage' => $storage,
|
|
||||||
'site' => $site,
|
'site' => $site,
|
||||||
'systemInfo' => $systemInfo,
|
'systemInfo' => $systemInfo,
|
||||||
]);
|
]);
|
||||||
@ -67,6 +68,242 @@ class ConfigBuilder
|
|||||||
->build();
|
->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function buildEntryThemeSection(FormNode $form, string $siteThemeKey, string $siteThemeLabel): void
|
||||||
|
{
|
||||||
|
FormModules::section($form, [
|
||||||
|
'title' => '入口与主题',
|
||||||
|
'description' => '登录入口、登录标题与后台默认主题集中维护,便于统一入口体验。',
|
||||||
|
], function (FormNode $section) use ($siteThemeKey, $siteThemeLabel) {
|
||||||
|
$grid = $section->div()->class('layui-row layui-col-space15 system-config-form-row system-config-cols-3');
|
||||||
|
|
||||||
|
$login = $grid->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$login->fields(function ($fields) {
|
||||||
|
$fields->text('site[login_title]', '登录表单标题', 'Login Title', true, '登录页主标题会显示在登录表单上方。', null, [
|
||||||
|
'placeholder' => '请输入登录页面的表单标题',
|
||||||
|
'vali-name' => '登录标题',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$entry = $grid->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$entry->fields(function ($fields) {
|
||||||
|
$fields->text('site[login_entry]', '后台登录入口', 'Login Entry', true, '由英文字母开头,修改后原地址不能继续访问。', '[A-Za-z][A-Za-z0-9_-]*', [
|
||||||
|
'placeholder' => '例如 system 或 admin',
|
||||||
|
'maxlength' => 32,
|
||||||
|
'vali-name' => '后台登录入口',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$theme = $grid->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
FormModules::pickerField($theme, [
|
||||||
|
'title' => '后台默认配色',
|
||||||
|
'subtitle' => 'Theme Style',
|
||||||
|
'hidden_name' => 'site[theme]',
|
||||||
|
'hidden_value' => $siteThemeKey,
|
||||||
|
'value' => $siteThemeLabel,
|
||||||
|
'attrs' => ['data-open-site-theme' => null],
|
||||||
|
'input_attrs' => ['data-site-theme-text' => null],
|
||||||
|
'help' => '保存后作为后台默认主题,用户个人主题仍可单独切换。',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$host = $section->div()->class('mt15 system-config-single');
|
||||||
|
$host->fields(function ($fields) {
|
||||||
|
$fields->text('site[host]', '站点基础域名', 'Site Host', false, '用于商城 H5、分享链接和外部回调等完整域名场景。', 'url', [
|
||||||
|
'vali-name' => '站点域名',
|
||||||
|
'placeholder' => '例如 https://admin.example.com',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
FormModules::note($host, '建议填写不带结尾斜杠的完整域名,保存时会自动去掉末尾的 /。');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function buildPluginCenterSection(FormNode $form): void
|
||||||
|
{
|
||||||
|
FormModules::section($form, [
|
||||||
|
'title' => '插件中心',
|
||||||
|
'description' => '插件中心已合并进 System,这里只保留启停与菜单展示策略。',
|
||||||
|
], function (FormNode $section) {
|
||||||
|
$grid = $section->div()->class('layui-row layui-col-space15 system-config-form-row system-config-cols-2');
|
||||||
|
|
||||||
|
$status = $grid->div()->class('layui-col-xs6 system-config-form-col');
|
||||||
|
$status->fields(function ($fields) {
|
||||||
|
$fields->radio('plugin_center[enabled]', '插件中心状态', 'Center Status', '', true, [
|
||||||
|
'required-error' => '请选择插件中心状态!',
|
||||||
|
])->options([
|
||||||
|
'1' => '启用',
|
||||||
|
'0' => '禁用',
|
||||||
|
])->defaultValue('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
$menu = $grid->div()->class('layui-col-xs6 system-config-form-col');
|
||||||
|
$menu->fields(function ($fields) {
|
||||||
|
$fields->radio('plugin_center[show_menu]', '菜单显示策略', 'Menu Display', '', true, [
|
||||||
|
'required-error' => '请选择菜单显示策略!',
|
||||||
|
])->options([
|
||||||
|
'1' => '显示菜单节点',
|
||||||
|
'0' => '隐藏菜单节点',
|
||||||
|
])->defaultValue('1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function buildRuntimeSection(FormNode $form): void
|
||||||
|
{
|
||||||
|
FormModules::section($form, [
|
||||||
|
'title' => '运行参数',
|
||||||
|
'description' => '维护队列日志保留时长,避免运行参数散落在其它页面。',
|
||||||
|
], function (FormNode $section) {
|
||||||
|
$section->fields(function ($fields) {
|
||||||
|
$fields->text('runtime[queue_retain_days]', '队列保留天数', 'Queue Days', true, '队列日志默认保留天数,最小值为 1。', null, [
|
||||||
|
'type' => 'number',
|
||||||
|
'min' => 1,
|
||||||
|
'vali-name' => '保留天数',
|
||||||
|
'placeholder' => '请输入队列日志保留天数',
|
||||||
|
])->defaultValue(7);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function buildSecurityResourceSection(FormNode $form): void
|
||||||
|
{
|
||||||
|
FormModules::section($form, [
|
||||||
|
'title' => '安全与登录资源',
|
||||||
|
'description' => 'JWT 密钥与浏览器图标并排维护,登录背景图单独管理。',
|
||||||
|
], function (FormNode $section) {
|
||||||
|
$grid = $section->div()->class('layui-row layui-col-space15 system-config-form-row system-config-cols-2');
|
||||||
|
|
||||||
|
$jwt = $grid->div()->class('layui-col-xs6 system-config-form-col');
|
||||||
|
$jwt->fields(function ($fields) {
|
||||||
|
$field = $fields->password('security[jwt_secret]', 'JWT 接口密钥', 'Jwt Key', false, '保留默认星号表示不修改;点击右侧按钮生成新的 32 位随机密钥。', '.{32}', [
|
||||||
|
'maxlength' => 32,
|
||||||
|
'vali-name' => '接口密钥',
|
||||||
|
'autocomplete' => 'new-password',
|
||||||
|
'placeholder' => '保留默认星号则不修改,点击右侧按钮可生成新密钥',
|
||||||
|
]);
|
||||||
|
$field->inputRightIcon('layui-icon-refresh', ['id' => 'RefreshJwtKey']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$icon = $grid->div()->class('layui-col-xs6 system-config-form-col');
|
||||||
|
$icon->fields(function ($fields) {
|
||||||
|
$field = $fields->text('site[browser_icon]', '浏览器小图标', 'Browser Icon', true, '建议上传 128x128 或 256x256 的 JPG/PNG/JPEG 图片。', 'url', [
|
||||||
|
'vali-name' => '图标文件',
|
||||||
|
'placeholder' => '请上传浏览器图标',
|
||||||
|
'data-tips-image' => null,
|
||||||
|
'data-tips-hover' => null,
|
||||||
|
]);
|
||||||
|
$field->inputRightIcon('layui-icon-upload-drag', [
|
||||||
|
'data-file' => 'btn',
|
||||||
|
'data-type' => 'png,jpg,jpeg',
|
||||||
|
'data-field' => 'site[browser_icon]',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$background = $section->div()->class('system-config-single mt5');
|
||||||
|
$background->fields(function ($fields) {
|
||||||
|
$fields->images('site[login_background_images]', '登录背景图片', 'Background Image', false);
|
||||||
|
});
|
||||||
|
FormModules::note($background, '建议保持 2-4 张横向背景图,风格和当前后台主题尽量统一。');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function buildBrandSection(FormNode $form): void
|
||||||
|
{
|
||||||
|
FormModules::section($form, [
|
||||||
|
'title' => '站点品牌信息',
|
||||||
|
'description' => '浏览器标题、后台品牌位与登录页底部信息分组维护。',
|
||||||
|
], function (FormNode $section) {
|
||||||
|
$main = $section->div()->class('layui-row layui-col-space15 system-config-form-row system-config-cols-3');
|
||||||
|
|
||||||
|
$site = $main->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$site->fields(function ($fields) {
|
||||||
|
$fields->text('site[website_name]', '网站名称', 'Site Name', true, '显示在浏览器标签页和页面标题中。', null, [
|
||||||
|
'placeholder' => '请输入网站名称',
|
||||||
|
'vali-name' => '网站名称',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$app = $main->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$app->fields(function ($fields) {
|
||||||
|
$fields->text('site[application_name]', '后台程序名称', 'App Name', true, '显示在后台左上标题处。', null, [
|
||||||
|
'placeholder' => '请输入程序名称',
|
||||||
|
'vali-name' => '程序名称',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$version = $main->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$version->fields(function ($fields) {
|
||||||
|
$fields->text('site[application_version]', '后台程序版本', 'App Version', false, '用于后台版本标识和发布后的版本核验。', null, [
|
||||||
|
'placeholder' => '请输入程序版本',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$filing = $section->div()->class('layui-row layui-col-space15 system-config-form-row system-config-cols-3');
|
||||||
|
|
||||||
|
$police = $filing->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$police->fields(function ($fields) {
|
||||||
|
$fields->text('site[public_security_filing]', '公安备案号', 'Beian', false, '', null, [
|
||||||
|
'placeholder' => '请输入公安备案号',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$miit = $filing->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$miit->fields(function ($fields) {
|
||||||
|
$fields->text('site[miit_filing]', '网站备案号', 'Miitbeian', false, '', null, [
|
||||||
|
'placeholder' => '请输入网站备案号',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$copyright = $filing->div()->class('layui-col-xs4 system-config-form-col');
|
||||||
|
$copyright->fields(function ($fields) {
|
||||||
|
$fields->text('site[copyright]', '网站版权信息', 'Copyright', true, '上线时建议同步补齐备案与版权信息。', null, [
|
||||||
|
'placeholder' => '请输入版权信息',
|
||||||
|
'vali-name' => '版权信息',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function renderSystemFormStyle(): string
|
||||||
|
{
|
||||||
|
return <<<'STYLE'
|
||||||
|
.system-config-form .system-config-form-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.system-config-form .system-config-cols-2 > .system-config-form-col {
|
||||||
|
width: 50% !important;
|
||||||
|
max-width: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.system-config-form .system-config-cols-3 > .system-config-form-col {
|
||||||
|
width: 33.333333% !important;
|
||||||
|
max-width: 33.333333%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.system-config-form .system-config-form-col .layui-form-item {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
.system-config-form .system-config-single .layui-form-item {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.system-config-form .system-config-form-col .help-label,
|
||||||
|
.system-config-form .system-config-form-col .help-block {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.system-config-form .system-config-cols-2 > .system-config-form-col,
|
||||||
|
.system-config-form .system-config-cols-3 > .system-config-form-col {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STYLE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $context
|
* @param array<string, mixed> $context
|
||||||
*/
|
*/
|
||||||
@ -87,7 +324,15 @@ class ConfigBuilder
|
|||||||
->open('返回系统配置', sysuri('system/config/index'));
|
->open('返回系统配置', sysuri('system/config/index'));
|
||||||
});
|
});
|
||||||
|
|
||||||
PageModules::card($page, ['title' => '存储概览', 'remark' => '统一管理文件上传、命名策略与外链输出', 'class' => 'layui-card mb15'], function (PageNode $body) use ($driverName, $storage, $files) {
|
PageModules::card($page, ['title' => '存储概览', 'remark' => '统一管理文件上传、命名策略与外链输出', 'class' => 'layui-card mb15'], function (PageNode $body) use ($driverName, $storage) {
|
||||||
|
$body->html(<<<'HTML'
|
||||||
|
<style>
|
||||||
|
.storage-overview-kv{grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
|
||||||
|
.storage-overview-kv>.ta-kv-item{min-height:58px;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center}
|
||||||
|
@media screen and (max-width:900px){.storage-overview-kv{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
||||||
|
@media screen and (max-width:560px){.storage-overview-kv{grid-template-columns:1fr}}
|
||||||
|
</style>
|
||||||
|
HTML);
|
||||||
PageModules::paragraphs($body, [
|
PageModules::paragraphs($body, [
|
||||||
'系统所有上传驱动共享一套全局策略,切换默认驱动后,上传入口、命名方式和链接输出会同步生效。',
|
'系统所有上传驱动共享一套全局策略,切换默认驱动后,上传入口、命名方式和链接输出会同步生效。',
|
||||||
], ['class' => 'ta-desc mt0']);
|
], ['class' => 'ta-desc mt0']);
|
||||||
@ -95,8 +340,7 @@ class ConfigBuilder
|
|||||||
['label' => '当前默认驱动', 'value' => $driverName],
|
['label' => '当前默认驱动', 'value' => $driverName],
|
||||||
['label' => '命名策略', 'value' => strval($storage['naming_rule'] ?? 'xmd5')],
|
['label' => '命名策略', 'value' => strval($storage['naming_rule'] ?? 'xmd5')],
|
||||||
['label' => '链接策略', 'value' => strval($storage['link_mode'] ?? 'none')],
|
['label' => '链接策略', 'value' => strval($storage['link_mode'] ?? 'none')],
|
||||||
['label' => '可用驱动数量', 'value' => strval(count($files))],
|
], ['class' => 'ta-kv storage-overview-kv']);
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
PageModules::card($page, ['title' => '存储引擎', 'remark' => '系统默认文件存储方式,可按驱动分别配置', 'class' => 'layui-card mb15'], function (PageNode $body) use ($files, $driver, $canEdit, $allowedExtensionsText) {
|
PageModules::card($page, ['title' => '存储引擎', 'remark' => '系统默认文件存储方式,可按驱动分别配置', 'class' => 'layui-card mb15'], function (PageNode $body) use ($files, $driver, $canEdit, $allowedExtensionsText) {
|
||||||
@ -134,147 +378,13 @@ class ConfigBuilder
|
|||||||
->class('system-config-form')
|
->class('system-config-form')
|
||||||
->data('auto', 'true')
|
->data('auto', 'true')
|
||||||
->action(sysuri());
|
->action(sysuri());
|
||||||
|
$form->html('<style id="SystemConfigFormStyle">' . self::renderSystemFormStyle() . '</style>');
|
||||||
|
|
||||||
FormModules::section($form, [
|
self::buildEntryThemeSection($form, $siteThemeKey, $siteThemeLabel);
|
||||||
'title' => '入口与主题',
|
self::buildPluginCenterSection($form);
|
||||||
'description' => '登录入口由插件注册前缀决定,这里负责维护登录页标题和后台默认主题。',
|
self::buildRuntimeSection($form);
|
||||||
], function ($section) use ($siteThemeKey, $siteThemeLabel) {
|
self::buildSecurityResourceSection($form);
|
||||||
$grid = $section->div()->class('layui-row layui-col-space15');
|
self::buildBrandSection($form);
|
||||||
|
|
||||||
$col = $grid->div()->class('layui-col-xs12 layui-col-md4');
|
|
||||||
$col->fields(function ($fields) {
|
|
||||||
$fields->text('site[login_title]', '登录表单标题', 'Login Title', true, '登录页主标题会显示在登录表单上方。', null, [
|
|
||||||
'placeholder' => '请输入登录页面的表单标题',
|
|
||||||
'vali-name' => '登录标题',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
$entry = $grid->div()->class('layui-col-xs12 layui-col-md4');
|
|
||||||
$entry->fields(function ($fields) {
|
|
||||||
$fields->text('site[login_entry]', '后台登录入口', 'Login Entry', true, '后台登录入口是由英文字母开头,且不能有相同名称的模块,设置之后原地址不能继续访问,请谨慎配置 ~', '[A-Za-z][A-Za-z0-9_-]*', [
|
|
||||||
'placeholder' => '例如 system 或 admin',
|
|
||||||
'maxlength' => 32,
|
|
||||||
'vali-name' => '后台登录入口',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
$theme = $grid->div()->class('layui-col-xs12 layui-col-md4');
|
|
||||||
FormModules::pickerField($theme, [
|
|
||||||
'title' => '后台默认配色',
|
|
||||||
'subtitle' => 'Theme Style',
|
|
||||||
'hidden_name' => 'site[theme]',
|
|
||||||
'hidden_value' => $siteThemeKey,
|
|
||||||
'value' => $siteThemeLabel,
|
|
||||||
'attrs' => ['data-open-site-theme' => null],
|
|
||||||
'input_attrs' => ['data-site-theme-text' => null],
|
|
||||||
'help' => '保存后会作为后台默认主题,用户个人主题仍可单独切换。',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$host = $section->div()->class('mt15');
|
|
||||||
$host->fields(function ($fields) {
|
|
||||||
$fields->text('site[host]', '站点基础域名', 'Site Host', false, '可选。用于商城 H5、分享链接和外部回调等需要完整域名的业务场景。', 'url', [
|
|
||||||
'vali-name' => '站点域名',
|
|
||||||
'placeholder' => '例如 https://admin.example.com',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
FormModules::note($host, '建议填写不带结尾斜杠的完整域名,保存时会自动去掉末尾的 /。');
|
|
||||||
});
|
|
||||||
|
|
||||||
FormModules::section($form, [
|
|
||||||
'title' => '插件中心',
|
|
||||||
'description' => '插件中心已经合并进 System,这里只保留启停和菜单展示策略两个全局开关。',
|
|
||||||
], function ($section) {
|
|
||||||
$section->fields(function ($fields) {
|
|
||||||
$fields->radio('plugin_center[enabled]', '插件中心状态', 'Center Status', '', true, [
|
|
||||||
'required-error' => '请选择插件中心状态!',
|
|
||||||
])->options([
|
|
||||||
'1' => '启用',
|
|
||||||
'0' => '禁用',
|
|
||||||
])->defaultValue('1')->radio('plugin_center[show_menu]', '菜单显示策略', 'Menu Display', '', true, [
|
|
||||||
'required-error' => '请选择菜单显示策略!',
|
|
||||||
])->options([
|
|
||||||
'1' => '显示菜单节点',
|
|
||||||
'0' => '隐藏菜单节点',
|
|
||||||
])->defaultValue('1');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
FormModules::section($form, [
|
|
||||||
'title' => '运行参数',
|
|
||||||
'description' => '维护队列日志保留时长,避免运行参数散落在其它页面。',
|
|
||||||
], function ($section) {
|
|
||||||
$section->fields(function ($fields) {
|
|
||||||
$fields->text('runtime[queue_retain_days]', '队列保留天数', 'Queue Days', true, '队列日志的默认保留天数,最小值为 1。', null, [
|
|
||||||
'type' => 'number',
|
|
||||||
'min' => 1,
|
|
||||||
'vali-name' => '保留天数',
|
|
||||||
'placeholder' => '请输入队列日志保留天数',
|
|
||||||
])->defaultValue(7);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
FormModules::section($form, [
|
|
||||||
'title' => '安全与登录资源',
|
|
||||||
'description' => '统一维护 JWT 密钥、浏览器图标以及登录背景图片。',
|
|
||||||
], function ($section) {
|
|
||||||
$grid = $section->div()->class('layui-row layui-col-space15');
|
|
||||||
|
|
||||||
$col1 = $grid->div()->class('layui-col-xs12 layui-col-md6');
|
|
||||||
$col1->fields(function ($fields) {
|
|
||||||
$field = $fields->password('security[jwt_secret]', 'JWT 接口密钥', 'Jwt Key', false, '保留默认星号表示不修改当前密钥,点击右侧按钮可生成新的 32 位随机密钥。', '.{32}', [
|
|
||||||
'maxlength' => 32,
|
|
||||||
'vali-name' => '接口密钥',
|
|
||||||
'autocomplete' => 'new-password',
|
|
||||||
'placeholder' => '保留默认星号则不修改,点击右侧按钮可生成新密钥',
|
|
||||||
]);
|
|
||||||
$field->inputRightIcon('layui-icon-refresh', ['id' => 'RefreshJwtKey']);
|
|
||||||
});
|
|
||||||
|
|
||||||
$col2 = $grid->div()->class('layui-col-xs12 layui-col-md6');
|
|
||||||
$col2->fields(function ($fields) {
|
|
||||||
$field = $fields->text('site[browser_icon]', '浏览器小图标', 'Browser Icon', true, '建议上传 128x128 或 256x256 的 JPG/PNG/JPEG 图片。', 'url', [
|
|
||||||
'vali-name' => '图标文件',
|
|
||||||
'placeholder' => '请上传浏览器图标',
|
|
||||||
'data-tips-image' => null,
|
|
||||||
'data-tips-hover' => null,
|
|
||||||
]);
|
|
||||||
$field->inputRightIcon('layui-icon-upload-drag', [
|
|
||||||
'data-file' => 'btn',
|
|
||||||
'data-type' => 'png,jpg,jpeg',
|
|
||||||
'data-field' => 'site[browser_icon]',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
$col3 = $grid->div()->class('layui-col-xs12');
|
|
||||||
$col3->fields(function ($fields) {
|
|
||||||
$fields->images('site[login_background_images]', '登录背景图片', 'Background Image', false);
|
|
||||||
});
|
|
||||||
FormModules::note($col3, '建议保持 2-4 张横向背景图,风格和当前后台主题尽量统一。');
|
|
||||||
});
|
|
||||||
|
|
||||||
FormModules::section($form, [
|
|
||||||
'title' => '站点品牌信息',
|
|
||||||
'description' => '这部分字段会出现在浏览器标题、后台品牌位和登录页底部。',
|
|
||||||
], function ($section) {
|
|
||||||
$section->fields(function ($fields) {
|
|
||||||
$fields->text('site[website_name]', '网站名称', 'Site Name', true, '网站名称将显示在浏览器标签页和页面标题中。', null, [
|
|
||||||
'placeholder' => '请输入网站名称',
|
|
||||||
'vali-name' => '网站名称',
|
|
||||||
])->text('site[application_name]', '后台程序名称', 'App Name', true, '管理程序名称显示在后台左上标题处。', null, [
|
|
||||||
'placeholder' => '请输入程序名称',
|
|
||||||
'vali-name' => '程序名称',
|
|
||||||
])->text('site[application_version]', '后台程序版本', 'App Version', false, '用于后台版本标识和发布后的版本核验。', null, [
|
|
||||||
'placeholder' => '请输入程序版本',
|
|
||||||
])->text('site[public_security_filing]', '公安备案号', 'Beian', false, '', null, [
|
|
||||||
'placeholder' => '请输入公安备案号',
|
|
||||||
])->text('site[miit_filing]', '网站备案号', 'Miitbeian', false, '', null, [
|
|
||||||
'placeholder' => '请输入网站备案号',
|
|
||||||
])->text('site[copyright]', '网站版权信息', 'Copyright', true, '网站上线时建议同步补齐备案与版权信息。', null, [
|
|
||||||
'placeholder' => '请输入版权信息',
|
|
||||||
'vali-name' => '版权信息',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$form->actions(function ($actions) {
|
$form->actions(function ($actions) {
|
||||||
$actions->submit('保存修改')->cancel('取消修改', '确定要取消修改吗?');
|
$actions->submit('保存修改')->cancel('取消修改', '确定要取消修改吗?');
|
||||||
@ -414,7 +524,6 @@ SCRIPT, json_encode(strval(lang('选择后台默认配色')), JSON_UNESCAPED_UNI
|
|||||||
$right = $grid->div()->class('layui-col-xs12 layui-col-md6');
|
$right = $grid->div()->class('layui-col-xs12 layui-col-md6');
|
||||||
|
|
||||||
self::buildRuntimeCard($left, $context);
|
self::buildRuntimeCard($left, $context);
|
||||||
self::buildStorageCard($left, $context);
|
|
||||||
if (!empty($context['isDebug'])) {
|
if (!empty($context['isDebug'])) {
|
||||||
self::buildSystemInfoCard($left, $context);
|
self::buildSystemInfoCard($left, $context);
|
||||||
}
|
}
|
||||||
@ -443,40 +552,6 @@ SCRIPT, json_encode(strval(lang('选择后台默认配色')), JSON_UNESCAPED_UNI
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $context
|
|
||||||
*/
|
|
||||||
private static function buildStorageCard(PageNode $parent, array $context): void
|
|
||||||
{
|
|
||||||
$storage = is_array($context['storage'] ?? null) ? $context['storage'] : [];
|
|
||||||
$storageName = strval($context['storageName'] ?? 'local');
|
|
||||||
$storageDriver = strval($context['storageDriver'] ?? 'local');
|
|
||||||
$storageEditable = !empty($context['storageEditable']);
|
|
||||||
|
|
||||||
PageModules::card($parent, ['title' => '存储中心', 'class' => 'layui-card mb15'], function (PageNode $body) use ($storage, $storageName, $storageDriver, $storageEditable) {
|
|
||||||
if ($storageEditable) {
|
|
||||||
PageModules::buttonGroup($body, [
|
|
||||||
['label' => '进入存储中心', 'url' => sysuri('system/config/storage'), 'data_key' => 'data-open', 'class' => 'layui-btn layui-btn-sm layui-btn-active'],
|
|
||||||
['label' => "配置当前驱动", 'url' => sysuri('system/config/storage') . '?type=' . $storageDriver, 'data_key' => 'data-open', 'class' => 'layui-btn layui-btn-sm layui-btn-primary'],
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
PageModules::buttonGroup($body, [
|
|
||||||
['label' => BuilderLang::format('当前驱动:%s', [BuilderLang::text($storageName)]), 'class' => 'layui-btn layui-btn-sm layui-btn-active'],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageModules::kvGrid($body, [
|
|
||||||
['label' => '当前默认驱动', 'value' => $storageName],
|
|
||||||
['label' => '命名策略', 'value' => strval($storage['naming_rule'] ?? 'xmd5')],
|
|
||||||
['label' => '链接策略', 'value' => strval($storage['link_mode'] ?? 'none')],
|
|
||||||
['label' => '允许类型', 'value' => strval($storage['allowed_extensions_text'] ?? '-')],
|
|
||||||
]);
|
|
||||||
PageModules::paragraphs($body, [
|
|
||||||
'上传驱动、命名规则、外链输出与文件管理统一由 System 收口。',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $context
|
* @param array<string, mixed> $context
|
||||||
*/
|
*/
|
||||||
@ -507,6 +582,14 @@ SCRIPT, json_encode(strval(lang('选择后台默认配色')), JSON_UNESCAPED_UNI
|
|||||||
$site = is_array($context['site'] ?? null) ? $context['site'] : [];
|
$site = is_array($context['site'] ?? null) ? $context['site'] : [];
|
||||||
|
|
||||||
PageModules::card($parent, ['title' => '系统参数', 'class' => 'layui-card mb15'], function (PageNode $body) use ($site) {
|
PageModules::card($parent, ['title' => '系统参数', 'class' => 'layui-card mb15'], function (PageNode $body) use ($site) {
|
||||||
|
$body->html(<<<'HTML'
|
||||||
|
<style>
|
||||||
|
.system-site-fields{display:flex;flex-wrap:wrap}
|
||||||
|
.system-site-fields>.system-site-field{width:33.333333%;max-width:33.333333%;box-sizing:border-box}
|
||||||
|
@media screen and (max-width:900px){.system-site-fields>.system-site-field{width:50%;max-width:50%}}
|
||||||
|
@media screen and (max-width:560px){.system-site-fields>.system-site-field{width:100%;max-width:100%}}
|
||||||
|
</style>
|
||||||
|
HTML);
|
||||||
PageModules::readonlyFields($body, [
|
PageModules::readonlyFields($body, [
|
||||||
[
|
[
|
||||||
'label' => '网站名称',
|
'label' => '网站名称',
|
||||||
@ -550,7 +633,7 @@ SCRIPT, json_encode(strval(lang('选择后台默认配色')), JSON_UNESCAPED_UNI
|
|||||||
'copy' => strval($site['copyright'] ?? ''),
|
'copy' => strval($site['copyright'] ?? ''),
|
||||||
'help' => '显示在登录页底部,通常用于版权声明和品牌主体信息。',
|
'help' => '显示在登录页底部,通常用于版权声明和品牌主体信息。',
|
||||||
],
|
],
|
||||||
]);
|
], ['class' => 'layui-row layui-col-space15 system-site-fields', 'item_class' => 'layui-col-xs4 system-site-field']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,15 +26,9 @@ class ConfigService extends Service
|
|||||||
*/
|
*/
|
||||||
public static function buildIndexContext(array $themes = []): array
|
public static function buildIndexContext(array $themes = []): array
|
||||||
{
|
{
|
||||||
StorageConfig::initialize();
|
|
||||||
|
|
||||||
$site = self::getSiteConfig($themes);
|
$site = self::getSiteConfig($themes);
|
||||||
$security = self::getSecurityConfig();
|
$security = self::getSecurityConfig();
|
||||||
$runtime = self::getRuntimeConfig();
|
$runtime = self::getRuntimeConfig();
|
||||||
$storage = self::maskStorageViewData(StorageConfig::viewData());
|
|
||||||
$files = Storage::types();
|
|
||||||
$storageDriver = strtolower((string)StorageConfig::global('default_driver', 'local'));
|
|
||||||
$storageName = strval($files[$storageDriver] ?? $storageDriver);
|
|
||||||
$framework = AppService::getPluginLibrarys('topthink/framework');
|
$framework = AppService::getPluginLibrarys('topthink/framework');
|
||||||
$thinkadmin = AppService::getPluginLibrarys('zoujingli/think-library');
|
$thinkadmin = AppService::getPluginLibrarys('zoujingli/think-library');
|
||||||
$showErrorMessage = '';
|
$showErrorMessage = '';
|
||||||
@ -59,11 +53,6 @@ class ConfigService extends Service
|
|||||||
'site' => $site,
|
'site' => $site,
|
||||||
'security' => $security,
|
'security' => $security,
|
||||||
'runtime' => $runtime,
|
'runtime' => $runtime,
|
||||||
'storage' => $storage,
|
|
||||||
'files' => $files,
|
|
||||||
'storageDriver' => $storageDriver,
|
|
||||||
'storageName' => $storageName,
|
|
||||||
'storageEditable' => self::canManageStorage(),
|
|
||||||
'pluginCenter' => $pluginCenter,
|
'pluginCenter' => $pluginCenter,
|
||||||
'issuper' => AuthService::isSuper(),
|
'issuper' => AuthService::isSuper(),
|
||||||
'appDebug' => app()->isDebug(),
|
'appDebug' => app()->isDebug(),
|
||||||
|
|||||||
@ -43,14 +43,19 @@ class ConfigPageRenderTest extends SqliteIntegrationTestCase
|
|||||||
|
|
||||||
$html = $this->callPageHtml('index');
|
$html = $this->callPageHtml('index');
|
||||||
|
|
||||||
$this->assertStringContainsString('统一管理运行模式、存储中心与系统基础参数', $html);
|
$this->assertStringContainsString('统一管理运行模式与系统基础参数', $html);
|
||||||
$this->assertStringContainsString('站点名称', $html);
|
$this->assertStringContainsString('站点名称', $html);
|
||||||
$this->assertStringContainsString('插件中心', $html);
|
$this->assertStringContainsString('插件中心', $html);
|
||||||
$this->assertStringContainsString('菜单入口策略', $html);
|
$this->assertStringContainsString('菜单入口策略', $html);
|
||||||
|
$this->assertStringContainsString('system-site-fields', $html);
|
||||||
$this->assertStringContainsString('page-builder-schema', $html);
|
$this->assertStringContainsString('page-builder-schema', $html);
|
||||||
$this->assertStringContainsString('系统参数配置', $html);
|
$this->assertStringContainsString('系统参数配置', $html);
|
||||||
$this->assertStringNotContainsString('插件应用', $html);
|
$this->assertStringNotContainsString('插件应用', $html);
|
||||||
$this->assertStringNotContainsString('插件标识', $html);
|
$this->assertStringNotContainsString('插件标识', $html);
|
||||||
|
$this->assertStringNotContainsString('默认存储驱动', $html);
|
||||||
|
$this->assertStringNotContainsString('存储中心', $html);
|
||||||
|
$this->assertStringNotContainsString('进入存储中心', $html);
|
||||||
|
$this->assertStringNotContainsString('配置当前驱动', $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSystemRendersGroupedConfigurationSections(): void
|
public function testSystemRendersGroupedConfigurationSections(): void
|
||||||
@ -64,6 +69,9 @@ class ConfigPageRenderTest extends SqliteIntegrationTestCase
|
|||||||
$this->assertStringContainsString('保存修改', $html);
|
$this->assertStringContainsString('保存修改', $html);
|
||||||
$this->assertStringContainsString('取消修改', $html);
|
$this->assertStringContainsString('取消修改', $html);
|
||||||
$this->assertStringContainsString('class="system-config-form layui-form"', $html);
|
$this->assertStringContainsString('class="system-config-form layui-form"', $html);
|
||||||
|
$this->assertStringContainsString('SystemConfigFormStyle', $html);
|
||||||
|
$this->assertStringContainsString('system-config-cols-2', $html);
|
||||||
|
$this->assertStringContainsString('system-config-cols-3', $html);
|
||||||
$this->assertStringContainsString('data-builder-scope="page"', $html);
|
$this->assertStringContainsString('data-builder-scope="page"', $html);
|
||||||
$this->assertStringContainsString('站点品牌信息', $html);
|
$this->assertStringContainsString('站点品牌信息', $html);
|
||||||
$this->assertStringContainsString('data-target-submit', $html);
|
$this->assertStringContainsString('data-target-submit', $html);
|
||||||
@ -92,6 +100,7 @@ class ConfigPageRenderTest extends SqliteIntegrationTestCase
|
|||||||
$this->assertStringContainsString('存储引擎', $html);
|
$this->assertStringContainsString('存储引擎', $html);
|
||||||
$this->assertStringContainsString('page-builder-schema', $html);
|
$this->assertStringContainsString('page-builder-schema', $html);
|
||||||
$this->assertStringContainsString('当前默认驱动', $html);
|
$this->assertStringContainsString('当前默认驱动', $html);
|
||||||
|
$this->assertStringContainsString('storage-overview-kv', $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStorageDriverFormRendersWithBuilder(): void
|
public function testStorageDriverFormRendersWithBuilder(): void
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user