Catalog · How the catalog works
unigui-admin
Zero-code admin framework built on Delphi 12 Athens + UniGUI, inspired by Django Admin. Plugin-based, config-driven CRUD.
- ★ 6 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
UniAdmin
A zero-code admin framework built on Delphi 12 Athens + UniGUI, inspired by Django Admin.
基于 Delphi 12 Athens + UniGUI 的零代码后台管理框架,借鉴 Django Admin 设计理念。插件化核心、设计时配置、运行时驱动——通过配置声明即可生成完整 CRUD,无需编写重复代码。
特性
- 插件化架构 — 动态加载、注册、依赖解析的业务模块扩展
- 声明式 Admin 引擎 — 一个
TModelAdmin记录即可声明list_display/search_fields/ 权限前缀,引擎自动派生网格列、参数化查询、菜单与权限(Django Admin 风格) - 元数据驱动 — 自动发现数据库 Schema,元数据缓存驱动网格列生成
- RBAC 权限 — 用户-角色-权限三级模型,声明式引擎按前缀自动派生
view/add/edit/delete - 任务调度 — Cron 表达式驱动的定时任务,内置健康检查、日志清理、数据库备份
- 日志审计 — 登录日志、操作日志、数据变更日志,支持 Excel/CSV/JSON/XML 导出
- 数据驱动 MDI — 菜单路由零代码,Frame 缓存保状态,新增模块不改主框架
技术栈
| 组件 | 版本/技术 |
|---|---|
| 语言 | Delphi 12 Athens |
| Web 框架 | UniGUI 1.6+ |
| 数据访问 | FireDAC |
| 数据库 | SQL Server |
| 测试 | DUnitX |
快速开始
环境要求
- Embarcadero RAD Studio 12 Athens
- Visual Studio 2022 BuildTools(MSBuild)
- VS Code + DelphiLSP 扩展(可选)
构建
VS Code 中按 Ctrl+Shift+B,或终端执行:
.vscode/CompileOmniPascalServerProject.bat build构建并运行
VS Code 中运行 test 任务,或终端执行:
.vscode/CompileOmniPascalServerProject.bat test清理
clean.bat项目结构
src/
????????? Core/ ????????????
??? ????????? Admin/ ??????????????????TModelAdmin????????????????????????????????????
??? ????????? Auth/ ????????????
??? ????????? Config/ ????????????
??? ????????? Context/ ???????????????
??? ????????? Data/ ???????????????
??? ????????? Main/ ?????????/?????????
??? ????????? Menu/ ????????????
??? ????????? Metadata/ ???????????????
??? ????????? Permission/ ????????????
??? ????????? Plugin/ ????????????
??? ????????? Scheduler/ ????????????
??? ????????? Services/ ???????????????
??? ????????? Session/ ????????????
??? ????????? UI/ UI ?????????BaseCrudFrame???AutoCrudFrame???MainFrame???MdiRouter????????????
????????? Modules/ ????????????
??? ????????? User/ ????????????
??? ????????? Role/ ????????????
??? ????????? Menu/ ????????????
??? ????????? Dictionary/ ????????????
??? ????????? Config/ ????????????
??? ????????? Log/ ????????????
??? ????????? Scheduler/ ????????????
????????? Plugins/ ????????????
????????? Dictionary/ ??????????????????模块完成度
| 模块 | 状态 | 说明 |
|---|---|---|
| 核心框架 | ✅ 完成 | 插件系统、认证授权、元数据缓存、服务定位器 |
| 用户管理 | ✅ 完成 | CRUD、密码管理、操作日志集成 |
| 角色管理 | ✅ 完成 | 角色定义、权限分配、数据范围 |
| 菜单管理 | ✅ 完成 | 动态树形菜单、路径更新、权限过滤 |
| 数据字典 | ✅ 完成 | 字典类型/项管理、缓存机制 |
| 系统配置 | ✅ 完成 | 分类管理、多类型值、缓存 |
| 日志审计 | ✅ 完成 | 三类日志 + Excel/CSV/JSON/XML 导出 |
| 定时任务 | ✅ 完成 | Cron 调度、日志清理、数据库备份、健康检查 |
| 插件系统 | ✅ 完成 | 生命周期管理、依赖解析、循环检测、示例插件 |
| UI 模板 | ✅ 完成 | 9 个模板(表单、对话框、网格、向导等) |
| 辅助工具 | ✅ 完成 | 10 个工具(代码生成、性能分析、日志查看等) |
MDI 架构(数据驱动路由)
主界面采用数据驱动的 MDI 路由:菜单项的 RoutePath 字段直接存储目标 Frame/Form 类名,TUniAdminMdiRouter 在运行时通过 FindClass 动态加载,每个模块作为可关闭标签页(TUniPageControl)打开;切换菜单时标签页状态完整保留(筛选/分页/滚动)。
新增一个业务模块,主框架零修改——只需 3 步:
- 编写
TUniFrame子类,并在单元initialization段注册类:initialization RegisterClass(TMyListFrame); - 在
UniAdmin_Menus表中,将该菜单的RoutePath设为'TMyListFrame' - 完成!点击菜单即自动路由打开
核心机制:
| 机制 | 说明 |
|---|---|
| 数据驱动路由 | RoutePath(类名)→ FindClass 动态实例化,告别 if-else 硬编码 |
| 多标签缓存 | 每模块一个可关闭标签页(TUniPageControl),切换保留状态 |
| 打开方式推导 | 类名以 Form 结尾 → 模态窗口;否则 → 嵌入内容区 |
| 开闭原则 | 新增模块对扩展开放,对 MainFrame 修改封闭(SOLID-O) |
📐 设计参考:FSThemeCrystal(Falcon Sistemas 出品的 uniGUI + UniFalcon 水晶主题 Demo),借鉴其
FindClass动态加载与 Panel 缓存模式。 完整方案详见 MDI 架构设计方案。
声明式 Admin 引擎(Django Admin 风格)
在 MDI 路由之上,本项目实现了 Django Admin 风格的声明式 CRUD:业务模块只需在单元 initialization 段向 TModelAdminRegistry 注册一份声明(表名、列表字段、搜索字段、权限前缀),引擎自动派生网格列、参数化查询、菜单项和权限码,无需手写 SQL、无需手写网格列定义。
一个完整声明(UserListFrame 落地示例):
initialization
TModelAdminRegistry.CreateInstance.Register(
TModelAdmin.Create('user', 'UniAdmin_Users', '用户管理')
.WithFrame('TUserListFrame')
.WithListDisplay([
TAdminFieldConfig.Create('UserID', 'ID', 50),
TAdminFieldConfig.Create('UserName', '用户名', 100),
TAdminFieldConfig.Create('Email', '邮箱', 150),
TAdminFieldConfig.Create('Status', '状态', 60)
])
.WithSearchFields(['UserName', 'RealName', 'Email'])
.WithFilterFields(['Status'])
.WithPermissionPrefix('user')
.WithSortOrder(110)
.WithParentMenuCode('system')
);
RegisterClass(TUserListFrame);核心单元:
| 单元 | 职责 |
|---|---|
Core/Admin/UniModelAdmin.Intf.pas |
TModelAdmin 声明记录 + fluent 链式 API + IModelAdminRegistry 接口 |
Core/Admin/UniModelAdmin.pas |
进程级注册中心单例(双检锁惰性创建,initialization 段注册、finalization 段清理) |
Core/Admin/UniQueryBuilder.pas |
通用参数化 SELECT/WHERE 生成器,标识符白名单防 SQL 注入 |
Core/UI/AutoCrudFrame.pas |
零样板的声明式 CRUD Frame,BindAdmin(AdminID) 即用 |
Core/UI/BaseCrudFrame.pas |
基类新增 AutoGridFromMeta 开关,从元数据缓存派生网格列(默认关闭,向后兼容) |
Core/Menu/SystemMenuSetup.pas |
BuildMenusFromRegistry / BuildPermissionsFromRegistry 从声明自动派生菜单与权限 |
自动派生能力(声明 → 运行时):
| 声明字段 | 自动产出 |
|---|---|
TableName + 元数据缓存 |
网格列(跳过 Password / 审计字段) |
SearchFields |
LIKE-OR 参数化搜索(共享单参数,去重) |
FilterFields |
等值参数化筛选 |
PermissionPrefix |
prefix:view/add/edit/delete 四件套权限 + 按钮可见性 |
ParentMenuCode + SortOrder + FrameClassName |
菜单项(RoutePath 指向类名,MdiRouter 解析) |
快速开始(端到端开发一个声明式模块)
以"商品管理"为例,从零到菜单自动出现,完整 5 步。主框架、菜单表、权限表零手改。
第 1 步:建数据库表
在 Database/Schema/ 加建表 SQL,或直接在 DB 执行。表名 Products:
CREATE TABLE Products (
ProductID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
SKU TEXT,
Price NUMERIC(10,2),
Status INTEGER NOT NULL DEFAULT 1,
CreatedDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);第 2 步:编写 Frame 单元(.pas)
新建 src/Modules/Product/ProductListFrame.pas。继承 TAutoCrudFrame,搜索框/网格/数据源已内置,只需声明字段配置:
unit ProductListFrame;
interface
uses
System.SysUtils, System.Classes,
Data.DB, FireDAC.Comp.Client,
uniGUIBaseClasses, uniGUIClasses, uniEdit, uniButton,
uniBasicGrid, uniDBGrid, uniPanel, uniGUIFrame,
BaseCrudFrame, UniModelAdmin.Intf;
type
TProductListFrame = class(TAutoCrudFrame)
public
constructor Create(AOwner: TComponent); override;
end;
implementation
uses
UniModelAdmin;
{$R *.dfm}
constructor TProductListFrame.Create(AOwner: TComponent);
begin
inherited;
BindAdmin('product'); // 一行绑定:读注册中心声明,开启网格/查询/权限派生
end;
initialization
// 声明:菜单/权限由 DatabaseInitializer.SeedFromRegistry 幂等写入 DB
TModelAdminRegistry.CreateInstance.Register(
TModelAdmin.Create('product', 'Products', '商品管理')
.WithFrame('TProductListFrame')
.WithListDisplay([
TAdminFieldConfig.Create('ProductID', 'ID', 50),
TAdminFieldConfig.Create('Name', '商品名', 150),
TAdminFieldConfig.Create('SKU', 'SKU', 100),
TAdminFieldConfig.Create('Price', '价格', 80),
TAdminFieldConfig.Create('Status', '状态', 60)
])
.WithSearchFields(['Name', 'SKU'])
.WithFilterFields(['Status'])
.WithPermissionPrefix('product')
.WithSortOrder(200)
.WithParentMenuCode('system')
);
RegisterClass(TProductListFrame); // MdiRouter 路由必需
end.第 3 步:编写 Frame DFM(.dfm)
新建 src/Modules/Product/ProductListFrame.dfm。继承内置工具栏与网格,中文用 #编码 转义、不加引号(见 AGENTS.md 规则 9/10):
inherited ProductListFrame: TProductListFrame
Width = 800
Height = 600
end
TAutoCrudFrame的工具栏、搜索框、网格、数据源都在基类 DFM 里,子类通常无需新增控件。
第 4 步:加入项目(dpr)
在 src/UniAdmin.dpr 的 uses 子句追加一行:
ProductListFrame in 'Modules\Product\ProductListFrame.pas' {ProductListFrame: TUniFrame};第 5 步:构建并运行
.vscode/CompileOmniPascalServerProject.bat test启动后用 admin / admin123 登录。"商品管理"菜单自动出现,点击即路由到 Frame:
| 自动产出 | 来源 |
|---|---|
| 菜单项"商品管理" | SeedFromRegistry 写入 UniAdmin_Menus(MenuCode='system:product') |
product:view/add/edit/delete 权限 |
写入 UniAdmin_Permissions,admin 角色自动获得 |
| 网格列(ID/商品名/SKU/价格/状态) | ListDisplay 声明(MSSQL 下也可走元数据派生) |
| 搜索框 LIKE 查询 | SearchFields 声明 → TQueryClauseBuilder |
| 增删改按钮可见性 | PermissionPrefix='product' → 按角色权限过滤 |
💡 SQLite 开发环境提示:若用 SQLite 且未声明
ListDisplay,网格列会派生失败(SQLite 不支持INFORMATION_SCHEMA,BuildGridFromMetadata静默降级为空网格)。声明ListDisplay可绕过此限制。生产用 MSSQL 则无此问题。
进阶:自定义查询逻辑
继承 TBaseCrudFrame(而非 TAutoCrudFrame)可获得完全控制权,仍享受元数据派生网格列 + 权限挂钩:
procedure TProductListFrame.DoInitialize;
begin
AutoGridFromMeta := True; // 从 Products 元数据自动建列
ModelTableName := 'Products';
inherited; // 触发 BuildGridFromMetadata
UniDataSource.DataSet := FQuery;
end;📐 设计理念:Django 的
admin.site.register(Model, ModelAdmin)单一真值源——本项目用TModelAdminRegistry实现同样的声明即配置,菜单/权限/查询从声明派生而非各自硬编码。 完整设计与 TDD 落地步骤详见 声明式 Admin 引擎实现计划。
数据库
数据库 Schema 位于 Database/ 目录:
Database/
????????? Schema/
??? ????????? 01_CreatePluginTables.sql ???????????????
??? ????????? 02_CreateCoreTables.sql ????????????????????????????????????????????????
??? ????????? 03_CreateSystemTables.sql ????????????????????????????????????????????????
????????? Seed/
????????? 01_InitialPluginData.sql ??????????????????
????????? 02_InitialCoreData.sql ??????????????????
????????? 03_SystemPermissions.sql ??????????????????测试
cd tests && UniAdminTests.exe当前测试覆盖:插件系统、配置服务、字典服务、声明式引擎(ModelAdmin 注册中心、查询生成器注入防护)。
文档
- 开发指南 | 中文版
- 架构设计 | 中文版
- CRUD 框架 | 中文版
- API 文档 | 中文版
- 部署指南 | 中文版
- 安全指南 | 中文版
- MDI 架构设计 — 数据驱动路由与多标签缓存方案
- 声明式 Admin 引擎实现计划 — Django Admin 风格声明式 CRUD 的 TDD 落地全过程
- UniFalcon 接入评估 — 30 控件 + 11 主题,UI 质感升级方案
扩展资料:UniGUI 组件参考手册、开发者手册
贡献
欢迎提交 Issue 和 Pull Request!提 PR 前请先阅读 贡献指南。
如果这个项目对你有帮助,欢迎 ⭐ Star 支持一下!
许可证
本项目基于 MIT License 开源。
Copyright © 2026 jianfeihua

