外观
客户功能与模块配置
最终口径
Beta 客户配置只有两个来源:
- 模块代码中的 Schema 默认值。
config/sites/{active}中由可视化页面维护的客户差异 JSON。
运行时始终用“代码默认值 + 客户差异”得到有效值。数据库、n_set、根 .env 和遗留 temp/diff_files 不再作为 Feature/模块配置的现场覆盖层;n_set 只继续承载主题等原有系统数据。
config/site-schema-lock.json 是第三类文件,但它不提供运行时配置值。它只锁定当前 Schema 的默认值、类型、改名信息和遗留来源映射,用来阻止代码默认值或导入关系被无意修改。
身份字段只有一个主键口径:active 是部署配置的唯一标识,同时也是目录名和运行时选择键;dw_biaozhi 只是老系统业务标识,允许多个 active 重复使用,不能拿它定位配置。
文件结构
text
config/sites/
└── shanghaipudong/
├── site.json
├── features.json # 可选,仅保存 Feature 差异
└── modules/
└── filemanagement.json # 可选,仅保存该模块差异site.json 只包含站点身份:
json
{
"schema_version": 1,
"active": "shanghaipudong",
"dw_biaozhi": "lims3.0",
"customer_name": "实验室信息管理系统"
}文件管理客户差异示例:
json
{
"category.export_subclass.enabled": true
}配置值等于代码默认值时不会写入 JSON;一个模块没有任何差异时,对应文件会被删除。因此不再保存 generated_at、源路径、哈希、告警或 value_sources 等同步过程信息。
开发新增配置
Feature 与模块设置定义都跟随业务模块,例如:
text
app/Modules/FileManagement/config/
├── features.php
└── settings.phpfeatures.php 声明模块 key 和可独立启停的业务能力,settings.php 声明展示、规则和兼容配置。 FeatureRegistry 和 ModuleSettingsRegistry 会自动发现这些文件;不要把业务 Schema 重新添加到 config/features.php 或 config/module-settings.php。
模块文件中的 Feature 使用短 key,注册中心自动组合成全系统唯一的 模块 key.Feature key。例如 FileManagement 模块声明 module => filemanagement 和 key => controlled-file,运行时完整 key 为 filemanagement.controlled-file。同模块依赖可以 使用短 key,跨模块依赖必须写完整 key;运行时不得根据调用位置猜测当前模块。
功能开启状态统一通过以下入口判断:
- Blade:
@feature('filemanagement.controlled-file') ... @endfeature - PHP:
app('feature')->isEnabled('filemanagement.controlled-file') - 路由:
feature.enabled:filemanagement.controlled-file
feature 是 FeatureStateService 的容器别名,跨模块调用和构造函数注入读取的是同一个单例。
新增一个字段只需在模块 settings 数组中注册:
php
[
'key' => 'category.download_by_type.enabled',
'name' => '按类型下载',
'type' => 'boolean',
'default' => false,
'default_policy' => 'stable',
'description' => '是否显示按文件类型打包下载入口。',
'group' => '分类与下载',
'feature' => 'filemanagement.core',
],页面会根据 type 自动生成控件。当前支持:
boolean:开关。enum:下拉选项,必须声明options。string:文本输入,可用rules声明 Laravel 校验规则。string_list:逐行输入,页面不要求管理员手写 JSON。
业务代码通过 ModuleSettingsService 读取有效值,不直接解析客户 JSON。
如果新字段对应老系统已有配置,应在同一个 Feature 或模块 Schema 中声明 legacy_source,不要再把一对一关系写进同步命令:
php
'legacy_source' => [
'source' => 'global',
'path' => 'filemanagement.enable_controlled_file',
'cast' => 'boolean',
],支持的来源为 env、global、vars 和 trade_global。每个新配置最多声明一个真实存在的老来源, 不提供来源优先级或多来源覆盖。Feature 必须转换成 boolean,模块设置只支持与字段类型相符的 boolean、string、array 转换。
一个老字段对应多个新字段、按客户标识推导值等复杂转换继续放在 app/Foundation/Deployment/Mappers 的专用 Mapper 中。一对一关系禁止在那里重复维护, 同步器会报告重复绑定和类型转换失败。遗留来源只用于初始化导入, 可视化保存不会反向修改老 PHP 配置。
default_policy 支持三种纪律:
stable:默认策略。允许客户继承,但默认值受 Schema 锁保护,修改时必须评估受影响客户。customer_required:对应功能启用时,每个客户必须在 JSON 中单独配置该字段。inherited:允许默认值跟随代码演进,仅适合确认可以全局同步变化的低风险展示项。
字段改名时不要直接删旧 key。新定义先声明迁移别名:
php
[
'key' => 'preview.use_legacy_pdf_viewer',
'renamed_from' => ['preview.legacy_viewer'],
// 其余定义……
]运行时会临时兼容旧 key,校验命令会列出仍需迁移的客户;新旧 key 同时存在会直接报错。客户 JSON 全部迁移后,再在后续版本移除 renamed_from。
日常配置流程
- 超级管理员打开
/feature-configuration。 - 选择目标客户和模块。
- 修改字段;未定制字段保持“跟随系统默认”。
- 保存后页面直接原子写入目标 JSON。
- 开发或实施人员检查
git diff,人工提交并随代码发布。
页面保存使用文件哈希做并发保护。如果文件在页面打开后被其他人修改,本次保存返回 409,不会覆盖新内容。 页面默认只读。只有总部维护环境设置 SITE_CONFIG_EDITABLE=true 后才能保存;客户现场保持默认值 false,即使超级管理员构造请求,后端也会拒绝写入。
提交前校验与横向查看
每次修改模块 Schema 或客户 JSON 后执行:
bash
php artisan lims:site-config-validate
php artisan lims:site-config-validate --strict
php artisan lims:site-config-validate --site=nanning_zls命令会校验全部客户的 JSON 格式、未知/旧 key、字段类型、Feature 依赖、customer_required 字段以及 Schema 锁。--strict 会把待迁移旧 key 等警告也视为失败。
横向回答“哪些客户开了某功能”或“关键字段各客户有什么差异”:
bash
php artisan lims:site-config-status --all --feature=filemanagement.controlled-file
php artisan lims:site-config-status --all \
--feature=filemanagement.controlled-file \
--setting=filemanagement:preview.use_legacy_pdf_viewer
php artisan lims:site-config-status --all --json矩阵同时显示有效值及来源:客户值 表示客户 JSON、继承 表示代码默认、旧 key 表示兼容读取、无效 表示客户值不合法且运行时已回退默认。
修改默认值的安全流程
“只存差异”不等于可以随意改默认值。stable 字段的默认值变更会影响所有未显式覆盖的客户,必须按以下顺序处理:
- 修改 Schema 默认值,但先不要刷新锁。
- 执行
php artisan lims:site-config-validate,查看schema_default_changed列出的继承客户。 - 对必须保持旧行为的客户,通过页面写入旧值;必要时用状态矩阵复核。
- 再次校验,确认剩余受影响客户确实应随新默认变化。
- 执行
php artisan lims:site-config-validate --refresh-schema-lock,把审核过的新基线写入锁文件。 - 将 Schema、客户 JSON 和锁文件放在同一次代码评审中提交。
刷新锁前如仍存在非 Schema 类配置错误,命令会拒绝写锁,避免用“更新基线”掩盖客户配置问题。
遗留配置初始化
遗留文件只用于首次/过渡导入:
bash
php artisan lims:sync-site-config
php artisan lims:sync-site-config --only=nanning_zls
php artisan lims:sync-site-config --dry-run
php artisan lims:sync-site-config --strict不带 --only 会先解析全部站点,全部成功后再切换整个 config/sites 目录,避免只生成一半。该命令以遗留配置重新生成客户 JSON,会覆盖可视化页面已经保存的差异,因此不应作为日常部署时的自动步骤。 只要目标 active(或全量目标目录)已经存在,命令就会拒绝写入;确认需要重新导入时必须加 --force。--dry-run 和 --validate-only 永远不要求 --force,也不会写文件。
安全与版本管理
- 仅超级管理员能查看页面;保存还必须由
SITE_CONFIG_EDITABLE=true开启。 - active 和 module key 均经过白名单格式校验,不能构造目录穿越路径。
- 值必须通过模块 Schema 类型与
rules校验。 - JSON 采用稳定字段顺序、Unicode 明文和统一缩进,便于 Git 审核。
- 写入使用同目录临时文件和
rename,避免进程中断留下半个 JSON。 - 页面本身不执行
git add、commit或push,仍由人工检查客户差异后提交。 config/site-schema-lock.json必须随代码提交;CI/发布检查应执行lims:site-config-validate --strict。