+```
+
+### 拖拽状态样式
+不同拖拽状态对应不同的视觉效果:
+
+| 状态 | 样式变化 | 说明 |
+|------|---------|------|
+| 开始拖拽 | `opacity: 0.8`, `z-index: 9999` | 降低透明度,提升层级 |
+| 拖拽经过 | `box-shadow: 0 8px 24px rgba(0,0,0,0.15)` | 添加阴影效果 |
+| 选中状态 | 边框高亮,显示操作图标 | 显示删除、复制等操作按钮 |
+| 动画进行中 | `transition: transform 0.25s cubic-bezier(0.2, 0, 0.2, 1)` | 平滑动画效果 |
+
+**本节来源**
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [ComponentDesignStateSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PropertySchemas/ComponentDesignStateSchema.cs)
+
+## 位置判断与JavaScript工具函数
+
+拖拽过程中的位置判断依赖于JavaScript工具函数`elementUtils.js`,通过Blazor的JS互操作实现高性能的位置计算。
+
+### elementUtils.js功能
+`elementUtils.js`提供了以下核心功能:
+
+```javascript
+window.elementUtils = {
+ // 获取元素尺寸信息(包含margin)
+ getDimensions: function (element) {
+ if (!element) return null;
+
+ const rect = element.getBoundingClientRect();
+ const computedStyle = window.getComputedStyle(element);
+ const containerWidth = element.parentElement ? element.parentElement.getBoundingClientRect().width : 0;
+
+ const margin = {
+ top: parseFloat(computedStyle.marginTop),
+ right: parseFloat(computedStyle.marginRight),
+ bottom: parseFloat(computedStyle.marginBottom),
+ left: parseFloat(computedStyle.marginLeft)
+ };
+
+ return {
+ width: rect.width,
+ height: rect.height,
+ actualWidth: rect.width + margin.left + margin.right,
+ actualHeight: rect.height + margin.top + margin.bottom,
+ containerWidth: containerWidth,
+ margin: margin,
+ offsetTop: rect.top,
+ offsetLeft: rect.left
+ };
+ },
+
+ // 获取容器信息
+ getContainerInfo: function (element) {
+ if (!element || !element.parentElement) return null;
+
+ const container = element.parentElement;
+ const containerRect = container.getBoundingClientRect();
+ const computedStyle = window.getComputedStyle(container);
+
+ return {
+ width: containerRect.width,
+ height: containerRect.height,
+ padding: {
+ top: parseFloat(computedStyle.paddingTop),
+ right: parseFloat(computedStyle.paddingRight),
+ bottom: parseFloat(computedStyle.paddingBottom),
+ left: parseFloat(computedStyle.paddingLeft)
+ }
+ };
+ },
+
+ // 设置元素的transform属性(优化性能)
+ setTransform: function (element, transform) {
+ if (!element) return;
+ element.style.transform = transform;
+ element.style.willChange = 'transform';
+ },
+
+ // 节流函数,用于优化拖拽性能
+ throttle: function (func, limit) {
+ let inThrottle;
+ return function() {
+ const args = arguments;
+ const context = this;
+ if (!inThrottle) {
+ func.apply(context, args);
+ inThrottle = true;
+ setTimeout(() => inThrottle = false, limit);
+ }
+ }
+ }
+};
+```
+
+### Blazor中的调用
+在`DraggableItem.razor`中通过`IJSRuntime`调用JavaScript函数:
+
+```csharp
+protected override async Task OnAfterRenderAsync(bool firstRender)
+{
+ if (firstRender)
+ {
+ await JSRuntime.InvokeAsync
("import", "./_content/H.LowCode.DesignEngineBase/js/elementUtils.js");
+ await UpdateDimensions();
+ }
+}
+
+private async Task UpdateDimensions()
+{
+ try
+ {
+ dimensions = await JSRuntime.InvokeAsync("elementUtils.getDimensions", itemRef);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error getting element dimensions: {ex.Message}");
+ }
+}
+```
+
+### 防抖机制
+为了提升性能,拖拽过程中的位置更新采用了防抖机制:
+
+```csharp
+private void OnDragOver(DragEventArgs dragEventArgs)
+{
+ var now = DateTime.Now;
+ if ((now - lastUpdateTime).TotalMilliseconds < UPDATE_INTERVAL_MS)
+ return;
+
+ lastUpdateTime = now;
+ // 处理拖拽逻辑
+}
+```
+
+**本节来源**
+- [elementUtils.js](file://src/DesignEngine/H.LowCode.DesignEngineBase/wwwroot/js/elementUtils.js)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+
+## 页面元数据生成
+
+当用户在画布上释放拖拽的组件时,系统会生成相应的页面元数据并更新应用模式。
+
+### 组件数据结构
+`ComponentPartsSchema`是组件的核心数据结构,包含设计时和运行时所需的所有信息:
+
+```csharp
+public class ComponentPartsSchema : ComponentSchemaBase
+{
+ [JsonPropertyName("partsId")]
+ public string PartsId { get; set; };
+
+ [JsonPropertyName("libid")]
+ public string LibraryId { get; set; }
+
+ [JsonPropertyName("cn")]
+ public string ComponentName { get; set; }
+
+ [JsonPropertyName("ct")]
+ public int ComponentType { get; set; }
+
+ [JsonPropertyName("frag")]
+ public ComponentPartsFragmentSchema Fragment { get; set; }
+
+ [JsonPropertyName("ds")]
+ public ComponentPartsDataSourceSchema DataSource { get; set; } = new();
+
+ [JsonPropertyName("attrdefgroups")]
+ public IEnumerable AttributeDefineGroups { get; set; } = [];
+
+ [JsonPropertyName("childs")]
+ public IList Childrens { get; set; } = [];
+
+ [JsonIgnore]
+ public ComponentDesignStateSchema DesignState { get; set; } = new();
+
+ [JsonIgnore]
+ public Action Refresh { get; set; }
+
+ public ComponentPartsSchema DeepClone()
+ {
+ // 深拷贝实现
+ }
+}
+```
+
+### 深拷贝机制
+新添加的组件通过`DeepClone`方法创建副本,确保每个实例都有唯一的ID:
+
+```csharp
+public ComponentPartsSchema DeepClone()
+{
+ ComponentPartsSchema newComponent = ObjectExtension.DeepClone(this);
+ newComponent.Id = ShortIdGenerator.Generate();
+ newComponent.ParentId = string.Empty;
+ newComponent.Name = $"{newComponent.ComponentName}_{Random.Shared.Next(100, 999)}";
+ newComponent.DesignState.IsSelected = false;
+ newComponent.Refresh = Refresh;
+ DeepCloneRecursive(newComponent, this);
+ return newComponent;
+}
+```
+
+### 元数据更新流程
+1. 创建组件副本
+2. 设置父级ID
+3. 添加到目标容器的子组件列表
+4. 更新UI状态
+
+```csharp
+private void DragItem_Add(ComponentPartsSchema containerComponent, ComponentPartsSchema currentDragComponent, ComponentPartsSchema dragOverComponent, bool isSelected = false)
+{
+ currentDragComponent.ParentId = containerComponent.Id;
+ currentDragComponent.DesignState.IsDroppedFromComponentPanel = false;
+
+ if (isSelected)
+ {
+ currentDragComponent.DesignState.IsSelected = isSelected;
+ DragDropStateService.SetLastSelectedComponent(PageCascading.AppId, PageCascading.PageId, currentDragComponent);
+ }
+ currentDragComponent.Refresh = StateHasChanged;
+
+ if (dragOverComponent != null)
+ {
+ containerComponent.Childrens.InsertBefore(dragOverComponent, currentDragComponent);
+ }
+ else
+ {
+ containerComponent.Childrens.Add(currentDragComponent);
+ }
+}
+```
+
+**本节来源**
+- [ComponentPartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/ComponentPartsSchema.cs)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+
+## 错误处理机制
+
+系统在拖拽交互过程中实现了多层次的错误处理机制,确保用户体验的稳定性和数据的完整性。
+
+### 空值检查
+在关键操作前进行空值检查,防止空引用异常:
+
+```csharp
+private void Init()
+{
+ if (Component == null)
+ throw new NullReferenceException(nameof(Component));
+}
+
+private void LoadRootComponent()
+{
+ var rootComponent = DragDropStateService.GetRootComponent(PageCascading.AppId, PageCascading.PageId);
+ if (rootComponent == null)
+ {
+ rootComponent = new ComponentPartsSchema();
+ rootComponent.Name = "root";
+ rootComponent.Refresh = StateHasChanged;
+ }
+ return rootComponent;
+}
+```
+
+### JavaScript互操作异常处理
+在调用JavaScript函数时捕获异常,避免前端崩溃:
+
+```csharp
+private async Task UpdateDimensions()
+{
+ try
+ {
+ dimensions = await JSRuntime.InvokeAsync("elementUtils.getDimensions", itemRef);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error getting element dimensions: {ex.Message}");
+ }
+}
+```
+
+### 状态重置机制
+提供专门的状态重置方法,确保异常情况下的状态一致性:
+
+```csharp
+public void ResetDragStyle(string appId, string pageId)
+{
+ var stateSchema = GetStateSchema(appId, pageId);
+ if (stateSchema == null) return;
+
+ if (stateSchema.CurrentDragComponent != null)
+ {
+ stateSchema.CurrentDragComponent.DesignState.AnimationTransform = string.Empty;
+ stateSchema.CurrentDragComponent.DesignState.IsAnimating = false;
+ }
+
+ if (stateSchema.LastSelectedComponent != null)
+ {
+ stateSchema.LastSelectedComponent.DesignState.IsSelected = false;
+ stateSchema.LastSelectedComponent.RefreshState();
+ }
+
+ if (stateSchema.LastDragOverComponent != null)
+ {
+ stateSchema.LastDragOverComponent.DesignState.DragEffectStyle = string.Empty;
+ stateSchema.LastDragOverComponent.DesignState.AnimationTransform = string.Empty;
+ stateSchema.LastDragOverComponent.DesignState.IsAnimating = false;
+ }
+}
+```
+
+### 事件订阅管理
+实现`IAsyncDisposable`接口,确保事件订阅的正确清理:
+
+```csharp
+public async ValueTask DisposeAsync()
+{
+ if (IsInRootContainer)
+ {
+ BlazorEventDispatcher.Unsubscribe("designengine.pagesetting.pagelayout.onchange", OnPageLayoutChange);
+ }
+}
+```
+
+**本节来源**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+
+## 关键代码片段
+
+### 拖拽开始处理
+```csharp
+private void OnDragStart(DragEventArgs dragEventArgs)
+{
+ isDragging = true;
+ initialX = dragEventArgs.ClientX;
+ initialY = dragEventArgs.ClientY;
+ lastDragX = initialX;
+ lastDragY = initialY;
+ lastUpdateTime = DateTime.Now;
+
+ Component.DesignState.DragEffectStyle = "box-shadow: 0 8px 24px rgba(0,0,0,0.15); transform-origin: center;";
+ DragDropStateService.SetCurrentDragComponent(PageCascading.AppId, PageCascading.PageId, Component);
+ ResetAllAnimationStates();
+}
+```
+
+### 拖拽释放处理
+```csharp
+private void OnDrop()
+{
+ var currentDragComponent = DragDropStateService.GetCurrentDragComponent(PageCascading.AppId, PageCascading.PageId);
+ DragDropHandler(currentDragComponent);
+ DragDropStateService.ResetDragStyle(PageCascading.AppId, PageCascading.PageId);
+ ResetAllAnimationStates();
+}
+```
+
+### 拖拽处理核心逻辑
+```csharp
+private void DragDropHandler(ComponentPartsSchema currentDragComponent)
+{
+ var dragOverComponent = DragDropStateService.GetLastDragOverComponent(PageCascading.AppId, PageCascading.PageId);
+
+ if (currentDragComponent.DesignState.IsDroppedFromComponentPanel)
+ {
+ DragItem_Add(ContainerComponent, currentDragComponent, dragOverComponent);
+ }
+ else
+ {
+ bool isInnerContainer = ContainerComponent.Childrens.Any(t => t.Id == currentDragComponent.Id);
+ if (isInnerContainer)
+ {
+ DraggableItem_Sorting(ContainerComponent, currentDragComponent, dragOverComponent);
+ }
+ else
+ {
+ DragItem_Move(ContainerComponent, currentDragComponent, dragOverComponent);
+ }
+ }
+
+ StateHasChanged();
+ DragDropStateService.SetLastDragOverComponent(PageCascading.AppId, PageCascading.PageId, null);
+}
+```
+
+### 组件添加逻辑
+```csharp
+private void DragItem_Add(ComponentPartsSchema containerComponent, ComponentPartsSchema currentDragComponent, ComponentPartsSchema dragOverComponent, bool isSelected = false)
+{
+ currentDragComponent.ParentId = containerComponent.Id;
+ currentDragComponent.DesignState.IsDroppedFromComponentPanel = false;
+
+ if (isSelected)
+ {
+ currentDragComponent.DesignState.IsSelected = isSelected;
+ DragDropStateService.SetLastSelectedComponent(PageCascading.AppId, PageCascading.PageId, currentDragComponent);
+ }
+ currentDragComponent.Refresh = StateHasChanged;
+
+ if (dragOverComponent != null)
+ {
+ containerComponent.Childrens.InsertBefore(dragOverComponent, currentDragComponent);
+ }
+ else
+ {
+ containerComponent.Childrens.Add(currentDragComponent);
+ }
+}
+```
+
+**本节来源**
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs)
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\346\213\226\346\213\275\347\212\266\346\200\201\347\256\241\347\220\206\346\234\215\345\212\241.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\346\213\226\346\213\275\347\212\266\346\200\201\347\256\241\347\220\206\346\234\215\345\212\241.md"
new file mode 100644
index 0000000000000000000000000000000000000000..6c33645d4e6982a54efb9d10fa2565015ee9e207
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\346\213\226\346\213\275\347\212\266\346\200\201\347\256\241\347\220\206\346\234\215\345\212\241.md"
@@ -0,0 +1,249 @@
+# 拖拽状态管理服务
+
+
+**本文档引用的文件**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+- [DesignPage.razor](file://src/DesignEngine/H.LowCode.DesignEngine/Pages/DesignPage.razor)
+- [DesignPanel.razor](file://src/DesignEngine/H.LowCode.DesignEngine/DesignPanel/DesignPanel.razor)
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor)
+
+
+## 目录
+1. [引言](#引言)
+2. [核心属性与状态管理](#核心属性与状态管理)
+3. [服务初始化与依赖注入](#服务初始化与依赖注入)
+4. [拖拽事件处理流程](#拖拽事件处理流程)
+5. [状态变更通知机制](#状态变更通知机制)
+6. [状态重置与异常恢复](#状态重置与异常恢复)
+7. [并发操作处理](#并发操作处理)
+8. [最佳实践与代码示例](#最佳实践与代码示例)
+
+## 引言
+拖拽状态管理服务(DragDropStateService)是Blazor低代码设计器中的核心全局状态容器,负责在多个可拖拽组件之间协调和共享拖拽相关的状态信息。该服务通过依赖注入机制被所有相关的UI组件(如DraggableItem、DraggableContainer等)所使用,确保了跨组件状态的一致性和同步性。本文档将深入解析该服务的设计与实现,详细说明其如何管理拖拽状态、处理事件以及与其他组件协同工作。
+
+## 核心属性与状态管理
+
+### DragDropStateSchema 核心属性
+`DragDropStateSchema` 类是拖拽状态服务的数据模型,定义了所有需要在应用中共享的核心状态属性。
+
+```mermaid
+classDiagram
+class DragDropStateSchema {
++ComponentPartsSchema RootComponent
++PagePartsSchema Page
++ComponentPartsSchema LastSelectedComponent
++ComponentPartsSchema CurrentDragComponent
++ComponentPartsSchema LastDragOverComponent
++ComponentPartsSchema LastDropComponent
++DateTime LastDragOverTime
+}
+```
+
+**Diagram sources**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs#L203-L237)
+
+**Section sources**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs#L203-L237)
+
+#### 属性详解
+- **RootComponent**: 存储当前页面的根组件对象,作为所有可拖拽组件的父容器,是构建组件树结构的基础。
+- **Page**: 存储当前页面的元数据信息,如页面ID、名称和布局等。
+- **LastSelectedComponent**: 记录最后一次被选中的组件,即使该组件失去焦点,此属性仍保留其引用,用于实现“最后选中”逻辑。
+- **CurrentDragComponent**: 标识当前正在被拖拽的组件对象,是拖拽操作的核心状态。
+- **LastDragOverComponent**: 记录鼠标指针最后一次悬停在其上方的组件,用于实现放置时的视觉反馈和逻辑判断。
+- **LastDropComponent**: 记录最后一次成功放置的组件,可用于撤销操作或日志记录。
+- **LastDragOverTime**: 记录最后一次拖拽到某个组件上方的时间戳,可用于处理拖拽延迟或防抖逻辑。
+
+## 服务初始化与依赖注入
+
+### 服务注册与生命周期
+`DragDropStateService` 是一个通过依赖注入(DI)容器管理的单例服务。它在应用启动时被注册,确保在整个应用生命周期内只有一个实例存在,从而保证了状态的全局唯一性。
+
+### 组件初始化流程
+多个关键组件在初始化时会与 `DragDropStateService` 进行交互,建立其状态上下文。
+
+```mermaid
+sequenceDiagram
+participant DesignPage as DesignPage.razor
+participant DesignPanel as DesignPanel.razor
+participant StateService as DragDropStateService
+participant ComponentPanel as ComponentPanel.razor
+DesignPage->>StateService : SetPage(AppId, pageSchema)
+DesignPage->>DesignPanel : 传递 Components 列表
+DesignPanel->>StateService : GetRootComponent(AppId, PageId)
+DesignPanel->>StateService : SetRootComponent(AppId, PageId, rootComponent)
+ComponentPanel->>StateService : SetCurrentDragComponent(AppId, PageId, component)
+```
+
+**Diagram sources**
+- [DesignPage.razor](file://src/DesignEngine/H.LowCode.DesignEngine/Pages/DesignPage.razor#L79-L84)
+- [DesignPanel.razor](file://src/DesignEngine/H.LowCode.DesignEngine/DesignPanel/DesignPanel.razor#L30-L35)
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor#L42)
+
+**Section sources**
+- [DesignPage.razor](file://src/DesignEngine/H.LowCode.DesignEngine/Pages/DesignPage.razor#L79-L84)
+- [DesignPanel.razor](file://src/DesignEngine/H.LowCode.DesignEngine/DesignPanel/DesignPanel.razor#L30-L35)
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor#L42)
+
+#### 初始化步骤
+1. **页面加载 (DesignPage)**: 当 `DesignPage` 组件初始化时,它会从后端服务加载页面元数据 (`PagePartsSchema`),然后调用 `DragDropStateService.SetPage()` 将页面信息存储到全局状态中。
+2. **面板构建 (DesignPanel)**: `DesignPanel` 组件在初始化时,首先尝试从 `DragDropStateService` 获取根组件。如果不存在,则创建一个新的根组件,并通过 `SetRootComponent()` 方法将其注册到全局状态。这确保了所有拖拽操作都基于同一个组件树。
+3. **拖拽开始 (ComponentPanel)**: 当用户从组件面板 (`ComponentPanel`) 拖拽一个新组件时,`DragItem` 组件会创建该组件的深拷贝,并立即通过 `SetCurrentDragComponent()` 方法将其设置为当前拖拽对象,从而启动拖拽流程。
+
+## 拖拽事件处理流程
+
+### 事件处理器集成
+`DragDropStateService` 与 `DraggableItem` 和 `DraggableContainer` 组件的原生拖拽事件(`OnDragStart`, `OnDragOver`, `OnDrop`)紧密集成。
+
+```mermaid
+flowchart TD
+A[OnDragStart] --> B[设置 CurrentDragComponent]
+B --> C[添加拖拽视觉反馈]
+C --> D[OnDragOver]
+D --> E{是否悬停在新组件上?}
+E --> |是| F[更新 LastDragOverComponent]
+E --> |否| G[触发兄弟组件让位动画]
+F --> G
+G --> H[OnDrop]
+H --> I[执行 DragDropHandler]
+I --> J[重置全局状态]
+```
+
+**Diagram sources**
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor#L178-L185)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor#L70-L74)
+
+**Section sources**
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor#L178-L185)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor#L70-L74)
+
+#### 详细流程
+1. **OnDragStart**: 在 `DraggableItem` 的 `OnDragStart` 事件中,服务被调用以设置 `CurrentDragComponent`。这标志着拖拽操作的开始,并为被拖拽的组件添加了阴影等视觉反馈。
+2. **OnDragOver**: 在 `DraggableContainer` 的 `OnDragOver` 事件中,服务被用来获取 `CurrentDragComponent` 和 `LastDragOverComponent`。通过比较,可以判断鼠标是否悬停在了一个新的目标容器上。如果是,则更新 `LastDragOverComponent` 并触发兄弟组件的“让位”动画,为放置腾出空间。
+3. **OnDrop**: 当在 `DraggableContainer` 上释放时,`OnDrop` 事件被触发。`DragDropHandler` 方法会根据 `CurrentDragComponent` 的来源(是来自组件面板还是页面内部)执行不同的逻辑(新增、排序或移动),并在操作完成后调用 `ResetDragStyle()` 来清理状态。
+
+## 状态变更通知机制
+
+### SetStateSchema 方法
+服务内部通过 `SetStateSchema` 方法来安全地修改状态,这是实现状态变更通知的核心。
+
+```csharp
+private void SetStateSchema(string appId, string pageId, Action action)
+{
+ string key = $"{appId}-{pageId}";
+
+ if (schemaStates.TryGetValue(key, out DragDropStateSchema stateSchema))
+ action(stateSchema);
+ else
+ {
+ stateSchema = new();
+ action(stateSchema);
+ schemaStates[key] = stateSchema;
+ }
+}
+```
+
+**Section sources**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs#L110-L128)
+
+#### 机制分析
+- **键值存储**: 状态以字典 `schemaStates` 的形式存储,键由 `appId` 和 `pageId` 拼接而成,实现了多页面、多应用的隔离。
+- **原子性操作**: `SetStateSchema` 接收一个 `Action` 委托。如果指定键的状态已存在,则直接在现有对象上执行操作;否则,创建一个新对象,执行操作后存入字典。这种方式确保了状态修改的原子性。
+- **直接引用修改**: 由于 `DragDropStateSchema` 是引用类型,`SetStateSchema` 内部对 `stateSchema` 对象的修改会直接反映到字典中存储的实例上。当其他组件通过 `GetCurrentDragComponent()` 等方法获取该对象时,它们拿到的是同一个引用,因此能立即看到最新的状态变化,实现了“通知”效果。
+
+## 状态重置与异常恢复
+
+### 重置方法
+服务提供了两个关键的重置方法,用于清理状态和恢复UI。
+
+```mermaid
+classDiagram
+class DragDropStateService {
++void ResetComponent(string appId, string pageId)
++void ResetDragStyle(string appId, string pageId)
+}
+```
+
+**Diagram sources**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs#L148-L185)
+
+**Section sources**
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs#L148-L185)
+
+#### 方法详解
+- **ResetComponent**: 此方法将 `LastSelectedComponent`、`CurrentDragComponent` 和 `LastDragOverComponent` 三个核心引用属性重置为 `default`(即 `null`)。这通常在组件销毁或页面切换时调用,用于彻底清除特定页面的拖拽上下文。
+- **ResetDragStyle**: 这是一个更精细的重置方法,专门用于UI清理。它会:
+ 1. 清除 `CurrentDragComponent` 的 `AnimationTransform` 和 `IsAnimating` 状态。
+ 2. 如果 `LastSelectedComponent` 存在,则将其 `IsSelected` 设为 `false` 并刷新其状态。
+ 3. 清除 `LastDragOverComponent` 的 `DragEffectStyle` 和动画状态。
+ 4. 遍历根组件下的所有子组件,重置它们的动画状态。
+ 该方法在 `OnDragEnd` 和 `OnDrop` 事件的末尾被调用,确保拖拽操作结束后,所有相关的视觉反馈都被清除。
+
+## 并发操作处理
+
+### 线程安全考量
+在Blazor WebAssembly应用中,所有代码通常在单个UI线程上执行,因此 `DragDropStateService` 的字典操作(`TryGetValue`, `Add`)在默认情况下是线程安全的,无需额外的锁机制。
+
+### 防抖与性能优化
+虽然服务本身不直接处理并发,但与之集成的UI组件实现了防抖机制来优化性能。
+
+```csharp
+private const int UPDATE_INTERVAL_MS = 16; // 约60fps的更新频率
+private DateTime lastUpdateTime = DateTime.MinValue;
+
+private void OnDragOver(DragEventArgs dragEventArgs)
+{
+ var now = DateTime.Now;
+ if ((now - lastUpdateTime).TotalMilliseconds < UPDATE_INTERVAL_MS)
+ return;
+ lastUpdateTime = now;
+ // ... 处理逻辑
+}
+```
+
+**Section sources**
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor#L199-L205)
+
+此代码片段展示了 `DraggableItem` 组件如何通过限制 `OnDragOver` 事件的处理频率(约每16毫秒一次)来防止因鼠标快速移动而产生的过多状态更新,从而避免了不必要的UI重渲染。
+
+## 最佳实践与代码示例
+
+### 状态重置最佳实践
+在组件的 `Dispose` 方法中调用 `ResetComponent` 是一个良好的实践,可以防止内存泄漏。
+
+```csharp
+public void Dispose()
+{
+ DragDropStateService.ResetComponent(PageCascading.AppId, PageCascading.PageId);
+}
+```
+
+**Section sources**
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor#L254)
+
+### 异常恢复代码示例
+以下是一个在 `OnDragEnd` 事件中进行异常恢复的完整示例,它确保了无论拖拽过程是否正常结束,UI状态都能被正确清理。
+
+```csharp
+private void OnDragEnd(DragEventArgs e)
+{
+ isDragging = false;
+ // ... 重置本地变量
+
+ // 清理所有拖动相关的样式和状态
+ Component.DesignState.DragEffectStyle = string.Empty;
+ Component.DesignState.AnimationTransform = string.Empty;
+ Component.DesignState.IsAnimating = false;
+
+ // 重置所有组件的动画状态
+ ResetAllAnimationStates();
+
+ // 使用DragDropStateService的重置方法确保状态一致性
+ DragDropStateService.ResetDragStyle(PageCascading.AppId, PageCascading.PageId);
+}
+```
+
+**Section sources**
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor#L220-L237)
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\346\213\226\346\213\275\351\241\271\350\247\206\350\247\211\350\256\276\350\256\241.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\346\213\226\346\213\275\351\241\271\350\247\206\350\247\211\350\256\276\350\256\241.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f024aad315aa2edcdff23e76ec7dfd59af944ffc
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\346\213\226\346\213\275\351\241\271\350\247\206\350\247\211\350\256\276\350\256\241.md"
@@ -0,0 +1,208 @@
+# 拖拽项视觉设计
+
+
+**本文档中引用的文件**
+- [DragItem.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor.css)
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor)
+- [DraggableItem.razor.css](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor.css)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+- [ComponentItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/ComponentItem.razor)
+- [ComponentPartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/ComponentPartsSchema.cs)
+
+
+## 目录
+1. [引言](#引言)
+2. [项目结构分析](#项目结构分析)
+3. [核心组件分析](#核心组件分析)
+4. [DragItem.razor.css 样式详解](#dragitemrazorcss-样式详解)
+5. [DraggableItem 组件实现机制](#draggableitem-组件实现机制)
+6. [组件绑定与数据模型](#组件绑定与数据模型)
+7. [拖拽交互逻辑分析](#拖拽交互逻辑分析)
+8. [响应式设计与高分辨率适配](#响应式设计与高分辨率适配)
+9. [结论](#结论)
+
+## 引言
+本文档详细说明了在低代码设计引擎中,`DragItem.razor.css` 文件定义的 CSS 类如何控制组件面板中可拖拽项的外观与布局。通过深入分析样式规则对边框、阴影、过渡动画、悬停效果的实现机制,并结合 Blazor 组件模板分析其与 `DraggableItem` 组件的绑定关系,全面阐述了拖拽项的视觉设计体系。文档还提供了实际样式应用示例,展示了不同组件类型在拖拽面板中的视觉差异化呈现,并探讨了响应式设计考量及在高分辨率屏幕下的适配策略。
+
+## 项目结构分析
+项目采用分层架构设计,主要分为 `Common`、`DesignEngine` 和 `RenderEngine` 三大模块。`DesignEngine` 模块负责设计时的用户界面和交互逻辑,其中 `H.LowCode.DesignEngine` 和 `H.LowCode.PartsDesignEngine` 子模块分别处理主设计面板和部件设计面板的可拖拽项。`DragItem.razor.css` 文件位于 `ComponentPanel` 目录下,是控制组件面板中可拖拽项视觉表现的核心样式文件。
+
+```mermaid
+graph TB
+subgraph "DesignEngine"
+DP[DesignEngine]
+PDE[PartsDesignEngine]
+DEB[DesignEngineBase]
+end
+subgraph "Common"
+CM[MetaSchema.DesignEngine]
+CB[ComponentBase]
+end
+DP --> DEB
+PDE --> DEB
+DEB --> CM
+DEB --> CB
+```
+
+**Diagram sources**
+- [DragItem.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor.css)
+- [ComponentPartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/ComponentPartsSchema.cs)
+
+## 核心组件分析
+系统中的核心可拖拽组件包括 `DragItem`、`DraggableItem` 和 `DraggableContainer`。`DragItem` 是组件面板中的可拖拽项,用于将组件添加到设计面板;`DraggableItem` 是设计面板中已放置的可拖拽组件实例;`DraggableContainer` 是用于容纳其他组件的容器。这些组件通过 `DragDropStateService` 服务进行状态管理和事件通信,形成了完整的拖拽交互体系。
+
+**Section sources**
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+
+## DragItem.razor.css 样式详解
+`DragItem.razor.css` 文件定义了 `.dragitem` 类,该类控制了组件面板中可拖拽项的基本外观和交互效果。
+
+### 基础布局与外观
+`.dragitem` 类通过以下属性定义了可拖拽项的基础样式:
+- **浮动布局**:`float: left` 使多个可拖拽项在面板中水平排列。
+- **尺寸控制**:`width: 6.8rem; height: 2.2rem` 定义了项的固定尺寸,确保视觉一致性。
+- **居中对齐**:`display: flex; justify-content: center; align-items: center` 实现了内容在项内的水平和垂直居中。
+- **视觉样式**:`color: #333; background-color: #f5f7fa` 定义了默认的文字颜色和背景色,提供清晰的视觉层次。
+
+### 悬停效果
+`.dragitem:hover` 选择器定义了鼠标悬停时的视觉反馈:
+- **边框变化**:`border: #409eff dashed 1px` 将边框变为蓝色虚线,明确指示该项可交互。
+- **文字变色**:`color: #409eff` 将文字颜色变为蓝色,增强视觉反馈,提升用户体验。
+
+```mermaid
+classDiagram
+class DragItemStyle {
++float : left
++width : 6.8rem
++height : 2.2rem
++margin : 4px
++cursor : pointer
++display : flex
++justify-content : center
++align-items : center
++color : #333
++background-color : #f5f7fa
+}
+class DragItemHoverStyle {
++border : #409eff dashed 1px
++color : #409eff
+}
+DragItemStyle <|-- DragItemHoverStyle : "hover"
+```
+
+**Diagram sources**
+- [DragItem.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor.css)
+
+## DraggableItem 组件实现机制
+`DraggableItem` 组件是设计面板中可拖拽项的核心实现,其样式和行为由 `DraggableItem.razor.css` 文件定义。
+
+### 外层容器样式
+`.draggableitem-box` 类定义了外层容器的样式:
+- **固定高度**:`height: 85px` 为容器提供统一的高度基准。
+- **边框与过渡**:`border: #f0f2f5 solid 2px` 定义了浅灰色边框,`transition: all 0.25s cubic-bezier(0.2, 0, 0.2, 1)` 为所有属性变化添加平滑的过渡动画。
+- **3D 变换优化**:`backface-visibility: hidden; transform-style: preserve-3d` 优化了 3D 变换的性能。
+
+### 内层项样式
+`.draggableitem` 类定义了内层可拖拽项的样式:
+- **相对定位**:`position: relative` 允许内部元素进行绝对定位。
+- **光标样式**:`cursor: grab` 在鼠标悬停时显示抓取光标,直观地提示用户可以拖拽。
+- **过渡效果**:`transition: all 0.2s ease-out` 为状态变化提供流畅的动画。
+
+### 交互状态样式
+组件定义了多种交互状态的样式类:
+- **选中状态**:`.draggableitem-selected` 添加蓝色实线轮廓和阴影,明确指示当前选中项。
+- **拖拽中状态**:`.draggableitem-dragging` 提升 `z-index` 至 9999,确保拖拽项位于最上层,并增加阴影深度。
+- **拖拽目标状态**:`.draggableitem-drag-over` 改变背景色和边框样式,清晰地指示可放置区域。
+- **让位动画状态**:`.draggableitem-moving` 降低透明度,视觉上表示该组件正在为拖拽项让位。
+
+```mermaid
+stateDiagram-v2
+[*] --> Normal
+Normal --> Selected : "点击"
+Selected --> Dragging : "开始拖拽"
+Dragging --> DragOver : "拖拽到目标上"
+DragOver --> Normal : "拖拽结束"
+Dragging --> Moving : "触发让位动画"
+Moving --> Normal : "动画结束"
+class Normal draggableitem
+class Selected draggableitem-selected
+class Dragging draggableitem-dragging
+class DragOver draggableitem-drag-over
+class Moving draggableitem-moving
+```
+
+**Diagram sources**
+- [DraggableItem.razor.css](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor.css)
+
+## 组件绑定与数据模型
+`DragItem` 和 `DraggableItem` 组件通过 `ComponentPartsSchema` 数据模型与后端逻辑进行绑定。
+
+### 数据模型结构
+`ComponentPartsSchema` 类是可拖拽项的核心数据模型,其关键属性包括:
+- **标识信息**:`ComponentId`、`ComponentName`、`Label` 用于唯一标识和显示组件。
+- **类型信息**:`ComponentType` 区分原子组件和组合组件,`IsContainer` 标记是否为容器。
+- **设计状态**:`DesignState` 属性(`[JsonIgnore]`)存储设计时的临时状态,如 `IsSelected`、`IsAnimating` 等,这些状态不持久化。
+
+### 组件绑定机制
+在 `DragItem.razor` 中,通过 `[Parameter] public ComponentPartsSchema Component { get; set; }` 将数据模型注入组件。组件的显示内容 `@Component.Label` 直接绑定到模型的 `Label` 属性。当用户点击或拖拽时,组件会调用 `DragDropStateService` 服务,将 `Component` 的深拷贝(通过 `DeepClone()` 方法)传递给设计面板,实现了数据的解耦和安全传递。
+
+**Section sources**
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [ComponentPartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/ComponentPartsSchema.cs)
+
+## 拖拽交互逻辑分析
+系统的拖拽交互逻辑通过 Blazor 事件和 `DragDropStateService` 服务协同实现。
+
+### 事件流分析
+```mermaid
+sequenceDiagram
+participant User as "用户"
+participant DragItem as "DragItem"
+participant Service as "DragDropStateService"
+participant DraggableItem as "DraggableItem"
+participant Container as "DraggableContainer"
+User->>DragItem : 点击或拖拽
+DragItem->>Service : SetCurrentDragComponent()
+Service-->>DragItem : 设置当前拖拽组件
+User->>DraggableItem : 拖拽到目标区域
+DraggableItem->>Service : SetLastDragOverComponent()
+Service-->>DraggableItem : 记录最后拖拽到的组件
+User->>Container : 释放拖拽
+Container->>Service : OnDrop()
+Service->>Container : 执行 DragDropHandler
+Container->>Container : 添加或移动组件
+Container->>Service : ResetDragStyle()
+Service-->>Container : 重置所有状态
+```
+
+**Diagram sources**
+- [DragItem.razor](file://src/DesignEngine/H.LowCode.DesignEngine/ComponentPanel/DragItem.razor)
+- [DraggableItem.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableItem.razor)
+- [DraggableContainer.razor](file://src/DesignEngine/H.LowCode.DesignEngineBase/DraggableComponents/DraggableContainer.razor)
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs)
+
+### 实际应用示例
+不同类型的组件在拖拽面板中通过 `ComponentItem` 组件进行差异化呈现:
+- **表单组件**:显示为带有输入框图标的项,背景色为浅蓝色。
+- **容器组件**:显示为带有网格图标的项,背景色为浅灰色,尺寸更大。
+- **按钮组件**:显示为带有手形图标的项,背景色为浅绿色。
+
+这种视觉差异化帮助用户快速识别组件类型,提升设计效率。
+
+## 响应式设计与高分辨率适配
+系统通过多种机制实现响应式设计和高分辨率适配。
+
+### 响应式布局
+`DraggableItem` 组件的宽度通过计算动态设置:`width: @((Component.Style.ItemWidth > 4 ? Component.Style.ItemWidth : (IsInRootContainer ? 24/PageCascading.PageLayout : 24)) /24 * 100)%`。该表达式根据 `PageLayout`(如 12 或 24 列)动态计算宽度百分比,确保在不同屏幕尺寸下都能合理布局。
+
+### 高分辨率适配
+- **GPU 加速**:大量使用 `transform: translate3d()` 和 `backface-visibility: hidden`,触发 GPU 硬件加速,确保在高分辨率屏幕上动画流畅。
+- **防抖机制**:在 `OnDragOver` 事件中使用 `UPDATE_INTERVAL_MS` 常量(约 16ms)限制更新频率,防止在高刷新率屏幕上产生性能瓶颈。
+- **清晰的视觉反馈**:使用 `box-shadow` 和 `rgba` 颜色值,在高 PPI 屏幕上提供细腻的视觉层次。
+
+## 结论
+本文档全面分析了低代码平台中拖拽项的视觉设计体系。`DragItem.razor.css` 通过简洁的 CSS 规则定义了组件面板中可拖拽项的基础样式和悬停效果。`DraggableItem` 组件利用丰富的 CSS 类和 Blazor 事件,实现了复杂的拖拽交互、动画效果和状态管理。通过 `ComponentPartsSchema` 数据模型,实现了组件与数据的紧密绑定。整个系统采用响应式设计,并通过 GPU 加速等技术确保在高分辨率屏幕上的流畅体验。这一设计模式为构建直观、高效的低代码设计界面提供了坚实的基础。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\351\241\265\351\235\242\345\261\236\346\200\247\350\256\276\347\275\256\347\225\214\351\235\242.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\351\241\265\351\235\242\345\261\236\346\200\247\350\256\276\347\275\256\347\225\214\351\235\242.md"
new file mode 100644
index 0000000000000000000000000000000000000000..bbe17b1c05f5ba8baedc796c1d3592d413afa46e
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/UI\347\273\204\344\273\266\344\270\216\344\272\244\344\272\222/\351\241\265\351\235\242\345\261\236\346\200\247\350\256\276\347\275\256\347\225\214\351\235\242.md"
@@ -0,0 +1,234 @@
+# 页面属性设置界面
+
+
+**本文档引用的文件**
+- [PageSetting.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor.css)
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PagePropertySchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/PagePropertySchema.cs)
+- [PageDataSourceSchema.cs](file://src/Common/H.LowCode.MetaSchema/DataSourceSchemas/PageDataSourceSchema.cs)
+- [PageTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/PageTypeEnum.cs)
+- [EventSchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/EventSchema.cs)
+- [EventTargetTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/EventTargetTypeEnum.cs)
+- [PagePartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PagePartsSchema.cs)
+- [designengine.css](file://src/DesignEngine/H.LowCode.DesignEngine/wwwroot/designengine.css)
+
+
+## 目录
+1. [简介](#简介)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构概览](#架构概览)
+5. [详细组件分析](#详细组件分析)
+6. [依赖分析](#依赖分析)
+7. [性能考量](#性能考量)
+8. [故障排除指南](#故障排除指南)
+9. [结论](#结论)
+
+## 简介
+本文档深入解析 `PageSetting.razor.css` 在页面属性配置面板中的作用,说明其定义的布局结构、表单控件样式、标签对齐方式及响应式断点设置。结合 `SettingPanel` 组件分析 CSS 类如何与 Blazor 的 `EditForm`、`InputText` 等组件协同工作,实现动态属性编辑界面。展示页面背景色、尺寸、边距等配置项的 UI 呈现逻辑,并解释主题变量的使用方式以支持未来主题扩展。
+
+## 项目结构
+项目采用模块化分层架构,主要分为 `meta`(元数据)、`src`(源码)和工具模块。`src` 目录下包含 `Common`(通用组件)、`DesignEngine`(设计引擎)、`RenderEngine`(渲染引擎)等核心模块。页面属性设置功能位于 `DesignEngine` 模块的 `SettingPanel` 组件中,通过 `PageSetting.razor` 和 `PageSetting.razor.css` 实现。
+
+```mermaid
+graph TB
+subgraph "DesignEngine"
+PageSetting[PageSetting.razor]
+PageSettingCSS[PageSetting.razor.css]
+designengineCSS[designengine.css]
+end
+subgraph "Common"
+PagePropertySchema[PagePropertySchema.cs]
+PageDataSourceSchema[PageDataSourceSchema.cs]
+PageTypeEnum[PageTypeEnum.cs]
+EventSchema[EventSchema.cs]
+EventTargetTypeEnum[EventTargetTypeEnum.cs]
+PagePartsSchema[PagePartsSchema.cs]
+end
+PageSetting --> PageSettingCSS
+PageSetting --> designengineCSS
+PageSetting --> PagePropertySchema
+PageSetting --> PageDataSourceSchema
+PageSetting --> PageTypeEnum
+PageSetting --> EventSchema
+PageSetting --> PagePartsSchema
+```
+
+**图示来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PageSetting.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor.css)
+- [designengine.css](file://src/DesignEngine/H.LowCode.DesignEngine/wwwroot/designengine.css)
+- [PagePropertySchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/PagePropertySchema.cs)
+- [PageDataSourceSchema.cs](file://src/Common/H.LowCode.MetaSchema/DataSourceSchemas/PageDataSourceSchema.cs)
+- [PageTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/PageTypeEnum.cs)
+- [EventSchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/EventSchema.cs)
+- [EventTargetTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/EventTargetTypeEnum.cs)
+- [PagePartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PagePartsSchema.cs)
+
+**本节来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PageSetting.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor.css)
+
+## 核心组件
+`PageSetting.razor` 是页面属性配置面板的核心组件,它使用 Blazor 框架构建,通过绑定 `PagePartsSchema` 模型实现对页面属性的动态编辑。其对应的 CSS 文件 `PageSetting.razor.css` 定义了 `.pagesetting-item` 类,用于统一配置项的外边距,确保 UI 布局的一致性。
+
+**本节来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PageSetting.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor.css)
+
+## 架构概览
+系统采用前后端分离架构,`DesignEngine` 负责可视化设计,`RenderEngine` 负责运行时渲染。`PageSetting` 组件作为 `DesignEngine` 的一部分,通过 `DragDropStateService` 获取当前编辑的 `PagePartsSchema` 实例,并利用 Blazor 的数据绑定机制 (`@bind-Value`) 将 UI 操作实时同步到模型中。
+
+```mermaid
+sequenceDiagram
+participant UI as "UI (PageSetting.razor)"
+participant Component as "PageSetting 组件"
+participant Service as "DragDropStateService"
+participant Model as "PagePartsSchema"
+UI->>Component : 用户更改布局
+Component->>Model : 更新 Page.PageProperty.PageLayout
+Component->>Service : 发布 "designengine.pagesetting.pagelayout.onchange" 事件
+Service->>Model : 通知其他组件布局已更改
+Model-->>Component : 返回新布局
+Component-->>UI : 重新渲染界面
+```
+
+**图示来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [DragDropStateService.cs](file://src/DesignEngine/H.LowCode.DesignEngineBase/Services/DragDropStateService.cs)
+- [PagePartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PagePartsSchema.cs)
+
+## 详细组件分析
+
+### PageSetting 组件分析
+`PageSetting` 组件根据 `Page` 模型的状态动态渲染不同的配置项。其核心功能包括布局选择、数据源配置、自定义样式编辑和事件管理。
+
+#### 布局与样式结构
+组件使用 `div` 容器和 `label` 标签构建表单项,通过 `pagesetting-item` CSS 类控制外边距。Ant Design Blazor 的 `RadioGroup`、`Input`、`TextArea` 等组件用于提供用户交互。
+
+```mermaid
+classDiagram
+class PageSetting {
++Page : PagePartsSchema
++OnLayoutChange(pageLayout : int) : void
++OnStyleChange(customStyle : string) : void
++ShowEventModal() : void
++OnEventConfirm() : void
+}
+class PagePartsSchema {
++PageProperty : PagePropertySchema
++DataSource : PageDataSourceSchema
++PageType : PageTypeEnum
++Events : IList~EventSchema~
++SupportEvents : string[]
+}
+class PagePropertySchema {
++PageLayout : int
++TitleWidth : string
++DefaultStyle : string
++CustomStyle : string
+}
+class PageDataSourceSchema {
++DataSourceType : PageDataSourceTypeEnum
++DataSourceValue : string
+}
+class EventSchema {
++EventName : string
++EventHandlerType : EventTargetTypeEnum
++EventCustomScript : string
+}
+PageSetting --> PagePartsSchema : "使用"
+PagePartsSchema --> PagePropertySchema : "包含"
+PagePartsSchema --> PageDataSourceSchema : "包含"
+PagePartsSchema --> EventSchema : "包含"
+```
+
+**图示来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PagePartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PagePartsSchema.cs)
+- [PagePropertySchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/PagePropertySchema.cs)
+- [PageDataSourceSchema.cs](file://src/Common/H.LowCode.MetaSchema/DataSourceSchemas/PageDataSourceSchema.cs)
+- [EventSchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/EventSchema.cs)
+
+#### 条件渲染逻辑
+组件使用 Razor 语法进行条件渲染。当 `Page.PageType` 为 `Form` 时,显示数据源配置区域。根据 `DataSourceType` 的不同,动态显示“表”或“API”输入框。
+
+```mermaid
+flowchart TD
+Start([开始]) --> CheckPage{"Page != null?"}
+CheckPage --> |是| CheckForm{"Page.PageType == Form?"}
+CheckForm --> |是| ShowDataSource["显示数据源配置"]
+CheckForm --> |否| SkipDataSource["跳过"]
+ShowDataSource --> CheckDB{"DataSourceType == DB?"}
+CheckDB --> |是| ShowTableInput["显示表输入框"]
+CheckDB --> |否| CheckAPI{"DataSourceType == API?"}
+CheckAPI --> |是| ShowAPISection["显示API配置"]
+CheckAPI --> |否| End
+SkipDataSource --> ShowOther["显示其他配置"]
+ShowTableInput --> ShowOther
+ShowAPISection --> ShowOther
+ShowOther --> ShowEvent["显示事件配置"]
+ShowEvent --> End([结束])
+```
+
+**图示来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PageTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/PageTypeEnum.cs)
+
+**本节来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PagePartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PagePartsSchema.cs)
+- [PagePropertySchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/PagePropertySchema.cs)
+- [PageDataSourceSchema.cs](file://src/Common/H.LowCode.MetaSchema/DataSourceSchemas/PageDataSourceSchema.cs)
+- [PageTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/PageTypeEnum.cs)
+- [EventSchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/EventSchema.cs)
+
+## 依赖分析
+`PageSetting` 组件依赖于多个核心模型和样式文件。`PagePartsSchema` 作为数据模型,聚合了页面的所有配置信息。`PagePropertySchema` 和 `PageDataSourceSchema` 提供了具体的属性定义。`designengine.css` 提供了全局样式覆盖,确保组件在 `settingpanel` 容器中正确显示。
+
+```mermaid
+graph TD
+PageSettingCSS --> designengineCSS
+PageSetting --> PageSettingCSS
+PageSetting --> designengineCSS
+PageSetting --> PagePartsSchema
+PagePartsSchema --> PagePropertySchema
+PagePartsSchema --> PageDataSourceSchema
+PagePartsSchema --> EventSchema
+PagePartsSchema --> PageTypeEnum
+```
+
+**图示来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PageSetting.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor.css)
+- [designengine.css](file://src/DesignEngine/H.LowCode.DesignEngine/wwwroot/designengine.css)
+- [PagePartsSchema.cs](file://src/Common/H.LowCode.MetaSchema.DesignEngine/PagePartsSchema.cs)
+- [PagePropertySchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/PagePropertySchema.cs)
+- [PageDataSourceSchema.cs](file://src/Common/H.LowCode.MetaSchema/DataSourceSchemas/PageDataSourceSchema.cs)
+- [EventSchema.cs](file://src/Common/H.LowCode.MetaSchema/PropertySchemas/EventSchema.cs)
+- [PageTypeEnum.cs](file://src/Common/H.LowCode.MetaSchema/Enums/PageTypeEnum.cs)
+
+**本节来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+- [PageSetting.razor.css](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor.css)
+- [designengine.css](file://src/DesignEngine/H.LowCode.DesignEngine/wwwroot/designengine.css)
+
+## 性能考量
+组件的性能主要受数据绑定和事件发布的影响。`OnLayoutChange` 方法通过 `BlazorEventDispatcher` 发布事件,避免了直接操作 DOM,保证了响应式更新的效率。`TextArea` 的 `OnChange` 事件在用户输入时触发,应考虑防抖处理以优化性能。
+
+## 故障排除指南
+- **问题:配置项未保存**
+ - 检查 `@bind-Value` 是否正确绑定到 `Page` 模型的属性。
+ - 确认 `Page` 模型是否为引用类型且在父组件中正确传递。
+- **问题:UI 样式错乱**
+ - 检查 `designengine.css` 是否被正确加载。
+ - 确认 `settingpanel` 容器的高度是否设置为 100%。
+- **问题:事件配置模态框不显示**
+ - 检查 `_eventVisible` 变量的绑定是否正确。
+ - 确认 `Modal` 组件的 `Width` 属性是否设置合理。
+
+**本节来源**
+- [PageSetting.razor](file://src/DesignEngine/H.LowCode.DesignEngine/SettingPanel/PageSetting.razor)
+
+## 结论
+`PageSetting.razor.css` 通过定义 `.pagesetting-item` 类,为页面属性配置面板提供了统一的布局间距。`PageSetting.razor` 组件巧妙地结合 Blazor 的数据绑定和条件渲染,实现了动态、响应式的属性编辑界面。通过 `PagePropertySchema` 和 `PageDataSourceSchema` 等模型,系统将复杂的页面配置逻辑抽象为清晰的数据结构,为未来的主题扩展和功能迭代奠定了坚实的基础。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/Entity Framework Core\344\273\223\345\202\250\345\256\236\347\216\260.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/Entity Framework Core\344\273\223\345\202\250\345\256\236\347\216\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..80096483c4eaf89ee5f430758745f004167cbf51
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/Entity Framework Core\344\273\223\345\202\250\345\256\236\347\216\260.md"
@@ -0,0 +1,294 @@
+# Entity Framework Core仓储实现
+
+
+**本文档引用的文件**
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+- [TableDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/TableDataRepository.cs)
+- [EntityTypeManager.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityManager/EntityTypeManager.cs)
+- [ReadOnlySaveChangesInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/ReadOnlySaveChangesInterceptor.cs)
+- [QueryWithNoLockDbCommandInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/QueryWithNoLockDbCommandInterceptor.cs)
+- [IFormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/DataRepositories/IFormDataRepository.cs)
+- [EntityBase.cs](file://src/Common/H.LowCode.Entity/Base/EntityBase.cs)
+
+
+## 目录
+1. [引言](#引言)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构概述](#架构概述)
+5. [详细组件分析](#详细组件分析)
+6. [依赖分析](#依赖分析)
+7. [性能考量](#性能考量)
+8. [故障排除指南](#故障排除指南)
+9. [结论](#结论)
+
+## 引言
+本文档详细解析基于Entity Framework Core的数据库仓储实现,重点阐述`FormDataRepository`和`TableDataRepository`如何通过`DesignEngineDbContext`访问关系型数据库,实现表单与表格数据的增删改查(CRUD)操作。文档将深入分析`DbContext`的实体映射配置、查询优化策略(如使用`NoLock`提示)以及通过`EntityTypeManager`动态管理实体类型的机制。同时,将探讨`ReadOnlySaveChangesInterceptor`等扩展组件在保障数据一致性方面的作用。最后,对比JSON文件存储,说明EF Core在事务支持、并发控制和复杂查询方面的优势,以及相应的配置与迁移管理方法。
+
+## 项目结构
+本项目采用分层架构,主要分为`Common`、`DesignEngine`和`RenderEngine`三大模块。`Common`模块存放跨领域共享的实体、配置和基础类。`DesignEngine`和`RenderEngine`分别负责设计时和运行时的功能,两者都实现了基于EF Core的数据访问层。`DesignEngine.EntityFrameworkCore`项目是分析的核心,它包含了`DesignEngineDbContext`、仓储实现、实体类型管理器和EF Core拦截器等关键组件。
+
+**Section sources**
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+
+## 核心组件
+核心组件包括`DesignEngineDbContext`、`FormDataRepository`、`TableDataRepository`、`EntityTypeManager`以及`ReadOnlySaveChangesInterceptor`和`QueryWithNoLockDbCommandInterceptor`两个拦截器。`DesignEngineDbContext`是EF Core的数据库上下文,负责管理实体的生命周期和数据库连接。`FormDataRepository`和`TableDataRepository`是具体的仓储实现,为上层业务逻辑提供数据访问接口。`EntityTypeManager`负责在运行时动态创建和管理实体类型。拦截器则用于在数据保存和查询执行前进行干预,以实现特定的业务规则和性能优化。
+
+**Section sources**
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+- [TableDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/TableDataRepository.cs)
+- [EntityTypeManager.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityManager/EntityTypeManager.cs)
+- [ReadOnlySaveChangesInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/ReadOnlySaveChangesInterceptor.cs)
+- [QueryWithNoLockDbCommandInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/QueryWithNoLockDbCommandInterceptor.cs)
+
+## 架构概述
+系统采用经典的领域驱动设计(DDD)分层架构,分为表现层、应用层、领域层和基础设施层。在基础设施层,`DesignEngineDbContext`作为EF Core的入口,通过仓储模式(Repository Pattern)为领域层提供数据访问服务。`EntityTypeManager`利用反射和动态程序集技术,在运行时根据元数据配置动态生成实体类,实现了高度的灵活性。EF Core拦截器则提供了非侵入式的横切关注点(如只读保护和查询优化)实现方式。
+
+```mermaid
+graph TB
+subgraph "表现层"
+UI[用户界面]
+end
+subgraph "应用层"
+AppService[应用服务]
+end
+subgraph "领域层"
+DomainService[领域服务]
+Repository[仓储接口]
+end
+subgraph "基础设施层"
+EFCore[Entity Framework Core]
+DbContext[DesignEngineDbContext]
+RepositoryImpl[仓储实现]
+EntityTypeManager[EntityTypeManager]
+Interceptors[拦截器]
+end
+UI --> AppService
+AppService --> DomainService
+DomainService --> Repository
+Repository --> RepositoryImpl
+RepositoryImpl --> DbContext
+DbContext --> EFCore
+DbContext --> EntityTypeManager
+DbContext --> Interceptors
+```
+
+**Diagram sources**
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+- [EntityTypeManager.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityManager/EntityTypeManager.cs)
+
+## 详细组件分析
+
+### DesignEngineDbContext 分析
+`DesignEngineDbContext`是整个数据访问层的核心。它继承自`DbContext`,并重写了`OnModelCreating`和`OnConfiguring`方法。
+
+#### OnModelCreating 方法
+该方法在模型创建时被调用,负责配置实体与数据库表的映射关系。其核心逻辑是通过`EntityTypeManager`加载所有动态实体(`LoadDynamicEntities`),然后为每个实体执行以下配置:
+1. **表映射**:使用`ToTable`方法将实体类型映射到指定的表名。
+2. **属性映射**:调用`ConfigureProperties`方法,根据`DynamicEntityInfo`中的字段信息,为每个属性配置数据类型、长度、精度、是否可空、默认值和注释。
+3. **主键配置**:使用`HasKey`方法指定主键字段。
+4. **查询过滤器**:如果实体启用了软删除(`EnableSoftDelete`),则添加一个查询过滤器`HasQueryFilter`,自动在所有查询中添加`IsDeleted = 0`的条件,实现逻辑删除。
+
+```mermaid
+classDiagram
+class DesignEngineDbContext {
++string AppId
++Task AddAsync(FormEntity formEntity)
++Task UpdateAsync(FormEntity formEntity)
++Task GetAsync(string tableName, string id)
++int SaveChangesAsync(FormEntity formEntity)
++Type GetEntityType(string tableName)
+-void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+-void OnModelCreating(ModelBuilder modelBuilder)
+-void ConfigureProperties(EntityTypeBuilder entityBuilder, DynamicEntityInfo dynamicEntity, Type entityType)
+-LambdaExpression SoftDeleteQueryFilterExpression(Type entityClrType)
+}
+class DbContext {
+<>
+}
+class DynamicEntityInfo {
++string EntityName
++Type EntityType
++string PrimaryKey
++bool EnableSoftDelete
++IReadOnlyList Fields
+}
+class DynamicEntityField {
++string Name
++Type ClrType
++bool IsNullable
++int? MaxLength
++int? Precision
++int? Scale
++object DefaultValue
++string Comment
+}
+DesignEngineDbContext --|> DbContext : 继承
+DesignEngineDbContext --> DynamicEntityInfo : 使用
+DesignEngineDbContext --> DynamicEntityField : 使用
+```
+
+**Diagram sources**
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+
+#### OnConfiguring 方法
+该方法在上下文配置时被调用,用于设置数据库连接和注册服务。关键配置包括:
+1. **注册拦截器**:添加了`ReadOnlySaveChangesInterceptor`和`QueryWithNoLockDbCommandInterceptor`。
+2. **替换验证服务**:使用`CustomizeRelationalModelValidator`来处理可能的表重复注册问题。
+
+### FormDataRepository 分析
+`FormDataRepository`实现了`IFormDataRepository`接口,是`FormEntity`数据访问的具体实现。
+
+#### 接口契约
+`IFormDataRepository`定义了对表单数据的基本CRUD操作:
+- `Task AddAsync(FormEntity entity)`:异步添加新实体。
+- `Task UpdateAsync(FormEntity entity)`:异步更新现有实体。
+- `Task GetAsync(string entityName, string id)`:根据实体名和ID异步获取实体。
+- `Task DeleteAsync(string entityName, string id)`:根据实体名和ID异步删除实体。
+
+#### 实现分析
+`FormDataRepository`的实现非常简洁,它通过依赖注入获取`DesignEngineDbContext`实例,并将大部分操作委托给`DbContext`。
+- `AddAsync`和`GetAsync`方法直接调用了`DbContext`中对应的`AddAsync`和`GetAsync`方法。
+- `UpdateAsync`和`DeleteAsync`方法尚未实现(`NotImplementedException`),这表明该功能可能仍在开发中或由其他机制处理。
+
+```mermaid
+classDiagram
+class FormDataRepository {
+-DesignEngineDbContext _dbContext
++bool? IsChangeTrackingEnabled
++FormDataRepository(DesignEngineDbContext dbContext)
++Task AddAsync(FormEntity entity)
++Task GetAsync(string tableName, string id)
++Task UpdateAsync(FormEntity entity)
++Task DeleteAsync(string entityName, string id)
+}
+class IFormDataRepository {
+<>
++Task AddAsync(FormEntity entity)
++Task UpdateAsync(FormEntity entity)
++Task GetAsync(string entityName, string id)
++Task DeleteAsync(string entityName, string id)
+}
+class FormEntity {
++string Name
++List Fields
+}
+class FormFieldEntity {
++string Name
++string TypeName
++object Value
+}
+FormDataRepository --> IFormDataRepository : 实现
+FormDataRepository --> DesignEngineDbContext : 依赖
+FormDataRepository --> FormEntity : 使用
+FormDataRepository --> FormFieldEntity : 使用
+```
+
+**Diagram sources**
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+- [IFormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/DataRepositories/IFormDataRepository.cs)
+
+### EntityTypeManager 分析
+`EntityTypeManager`是实现动态实体的关键组件。它在运行时根据元数据(如JSON配置文件)动态创建.NET类型。
+
+#### 工作流程
+1. **初始化程序集**:`InitDynamicAssembly`方法创建一个名为`H.LowCode.DynamicEntity`的动态程序集和模块,所有动态生成的实体类都将定义于此。
+2. **加载元数据**:通过`IDataSourceDomainService`从`caseapp`应用中获取所有实体的元数据(字段、主键、是否启用软删除等)。
+3. **创建实体类型**:对于每个元数据实体,调用`EntityFactory.CreateEntityType`方法,在动态模块中创建一个新的`Type`。该方法会为每个字段定义属性。
+4. **缓存信息**:将创建的`Type`和元数据信息封装成`DynamicEntityInfo`对象,并缓存起来,避免重复创建。
+
+#### 与DbContext的集成
+`DesignEngineDbContext`在`OnModelCreating`方法中调用`_entityTypeManager.LoadDynamicEntities()`来获取所有动态实体信息,并据此配置EF Core模型。这使得EF Core能够识别并映射这些在编译时不存在的实体。
+
+**Section sources**
+- [EntityTypeManager.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityManager/EntityTypeManager.cs)
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+
+### 扩展组件分析
+
+#### ReadOnlySaveChangesInterceptor
+该拦截器实现了`SaveChangesInterceptor`,用于在数据保存前进行检查。
+
+##### 作用
+防止被标记为“只读”的实体被修改、删除或添加。它通过检查实体的元数据(`Metadata.FindAnnotation`)中是否存在名为`Custom:ReadOnly`且值为`true`的注解来判断实体是否为只读。
+
+##### 工作流程
+- 在`SavingChanges`和`SavingChangesAsync`方法中,遍历`ChangeTracker`中所有状态为`Added`、`Modified`或`Deleted`的实体条目。
+- 对于每个条目,调用`IsReadOnly`方法检查其是否为只读。
+- 如果发现任何只读实体被修改,则抛出`InvalidOperationException`异常,阻止保存操作。
+
+```mermaid
+flowchart TD
+Start([开始保存更改]) --> CheckEntries["遍历所有变更条目"]
+CheckEntries --> IsReadOnly{"条目是否为只读?"}
+IsReadOnly --> |是| ThrowError["抛出 InvalidOperationException"]
+IsReadOnly --> |否| Continue["继续检查下一个条目"]
+Continue --> CheckNext["检查下一个条目"]
+CheckNext --> AllChecked{"所有条目检查完毕?"}
+AllChecked --> |是| Proceed["继续保存流程"]
+AllChecked --> |否| CheckEntries
+ThrowError --> End([保存失败])
+Proceed --> End2([保存成功])
+```
+
+**Diagram sources**
+- [ReadOnlySaveChangesInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/ReadOnlySaveChangesInterceptor.cs)
+
+#### QueryWithNoLockDbCommandInterceptor
+该拦截器实现了`DbCommandInterceptor`,用于在SQL命令执行前修改其文本。
+
+##### 作用
+实现查询优化,通过在`SELECT`语句的`FROM`和`JOIN`子句后自动添加`WITH (NOLOCK)`提示,来减少锁争用,提高查询性能。`WITH (NOLOCK)`提示允许查询读取未提交的数据(脏读),适用于对数据一致性要求不高的场景。
+
+##### 工作流程
+- 在`ReaderExecuting`方法中,拦截即将执行的`DbCommand`。
+- 使用正则表达式`TableAliasRegex`匹配SQL语句中所有`FROM [TableName] AS [Alias]`或`JOIN [TableName] AS [Alias]`的模式,但不包含`WITH (NOLOCK)`的。
+- 将匹配到的模式替换为`$& WITH (NOLOCK)`,其中`$&`代表整个匹配的字符串。
+- 修改后的SQL命令将包含`WITH (NOLOCK)`提示,然后被发送到数据库执行。
+
+**Section sources**
+- [QueryWithNoLockDbCommandInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/QueryWithNoLockDbCommandInterceptor.cs)
+
+## 依赖分析
+系统各组件之间存在清晰的依赖关系。`FormDataRepository`和`TableDataRepository`直接依赖`DesignEngineDbContext`。`DesignEngineDbContext`依赖`EntityTypeManager`来获取实体模型信息,并通过构造函数注入。`EntityTypeManager`依赖`IDataSourceDomainService`来获取元数据。`DbContext`在配置时注册了`ReadOnlySaveChangesInterceptor`和`QueryWithNoLockDbCommandInterceptor`,形成了对这些拦截器的依赖。这种依赖注入的设计使得组件之间松耦合,易于测试和维护。
+
+```mermaid
+graph TD
+FormDataRepository --> DesignEngineDbContext
+TableDataRepository --> DesignEngineDbContext
+DesignEngineDbContext --> EntityTypeManager
+DesignEngineDbContext --> ReadOnlySaveChangesInterceptor
+DesignEngineDbContext --> QueryWithNoLockDbCommandInterceptor
+EntityTypeManager --> IDataSourceDomainService
+```
+
+**Diagram sources**
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+- [TableDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/TableDataRepository.cs)
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs)
+- [EntityTypeManager.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityManager/EntityTypeManager.cs)
+
+## 性能考量
+本实现通过多种方式优化性能:
+1. **动态实体缓存**:`EntityTypeManager`缓存了已创建的动态实体类型,避免了重复的类型生成开销。
+2. **查询优化**:`QueryWithNoLockDbCommandInterceptor`通过减少锁争用,显著提升了高并发读取场景下的查询性能。
+3. **延迟加载与变更跟踪**:EF Core内置的变更跟踪机制可以精确地生成更新SQL,避免了全表更新。
+4. **潜在优化点**:`FormDataRepository`中的`GetAsync`方法返回的是`FormEntity`对象,这涉及到从数据库实体到`FormEntity`的转换。对于大数据量的查询,可以考虑提供直接返回`IQueryable`的方法,以支持更灵活的分页和过滤。
+
+## 故障排除指南
+- **实体类型找不到**:如果`GetEntityType`方法抛出`ArgumentException`,请检查`EntityTypeManager`加载的元数据是否正确,确保`dynamicEntities`列表中包含该实体。
+- **保存更改失败**:如果保存操作抛出`InvalidOperationException`并提示“Entity is marked as read-only”,请检查相关实体的元数据或注解,确认其是否被错误地标记为只读。
+- **查询未使用NOLOCK**:如果生成的SQL没有包含`WITH (NOLOCK)`,请检查`QueryWithNoLockDbCommandInterceptor`是否已正确注册到`DbContextOptionsBuilder`中。
+- **动态实体创建失败**:如果`EntityFactory.CreateEntityType`失败,请检查传入的字段定义(如类型、名称)是否符合.NET类型创建的规范。
+
+**Section sources**
+- [DesignEngineDbContext.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/DesignEngineDbContext.cs#L190-L199)
+- [ReadOnlySaveChangesInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/ReadOnlySaveChangesInterceptor.cs#L10-L15)
+- [QueryWithNoLockDbCommandInterceptor.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/EntityFrameworkCore/Extensions/QueryWithNoLockDbCommandInterceptor.cs#L25-L30)
+
+## 结论
+本文档详细解析了基于Entity Framework Core的动态仓储实现。该设计通过`EntityTypeManager`实现了高度的灵活性,能够根据运行时元数据动态映射数据库表。`DesignEngineDbContext`作为核心,不仅管理实体映射和数据访问,还通过拦截器机制优雅地实现了只读保护和查询优化等横切关注点。尽管`FormDataRepository`的部分方法尚未实现,但其整体架构清晰,遵循了良好的设计原则。相较于JSON文件存储,该EF Core实现提供了强大的事务支持、并发控制能力和复杂的LINQ查询功能,更适合构建企业级应用。通过合理的配置和迁移管理,可以确保数据库模式与应用逻辑的同步演进。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/JSON\346\226\207\344\273\266\344\273\223\345\202\250\345\256\236\347\216\260.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/JSON\346\226\207\344\273\266\344\273\223\345\202\250\345\256\236\347\216\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b755941c43a3ab15a1328c0f51bb934e87dbcd2f
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/JSON\346\226\207\344\273\266\344\273\223\345\202\250\345\256\236\347\216\260.md"
@@ -0,0 +1,336 @@
+# JSON文件仓储实现
+
+
+**本文档引用的文件**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [PageFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/PageFileRepository.cs)
+- [MenuFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/MenuFileRepository.cs)
+- [DataSourceFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/DataSourceFileRepository.cs)
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+- [MetaOption.cs](file://src/Common/H.LowCode.Configuration/Options/MetaOption.cs)
+- [caseapp.json](file://meta/apps/caseapp/caseapp.json)
+- [0lgu6xpop.json](file://meta/apps/caseapp/page/0lgu6xpop.json)
+- [5omcgxevf.json](file://meta/apps/caseapp/menu/5omcgxevf.json)
+- [iumn5yg5t.json](file://meta/apps/caseapp/datasource/iumn5yg5t.json)
+
+
+## 目录
+1. [简介](#简介)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构概述](#架构概述)
+5. [详细组件分析](#详细组件分析)
+6. [依赖分析](#依赖分析)
+7. [性能考量](#性能考量)
+8. [故障排除指南](#故障排除指南)
+9. [结论](#结论)
+
+## 简介
+本文档深入分析基于JSON文件的仓储实现机制,重点阐述`FileRepositoryBase`作为所有文件仓储基类的设计原理,包括元数据序列化、反序列化、文件路径管理与读写异常处理。详细说明`AppFileRepository`如何实现`IAppRepository`接口,完成应用元数据在`meta/apps`目录下的持久化存储与加载流程。解释`PageFileRepository`、`MenuFileRepository`和`DataSourceFileRepository`对各自领域对象的文件操作逻辑,以及如何通过约定的文件命名规则(如GUID.json)维护数据一致性。提供JSON仓储的性能瓶颈分析、并发访问控制策略及适用场景建议。
+
+## 项目结构
+项目采用分层架构设计,将设计引擎(DesignEngine)与渲染引擎(RenderEngine)分离,各自拥有独立的JSON文件仓储实现。核心元数据模型定义在`H.LowCode.MetaSchema`中,而仓储逻辑位于`H.LowCode.DesignEngine.Repository.JsonFile`和`H.LowCode.RenderEngine.Repository.JsonFile`模块中。元数据以JSON格式存储在`meta/apps`目录下,按应用ID组织为子目录,并进一步按类型(page、menu、datasource)分类存储。
+
+```mermaid
+graph TB
+subgraph "源代码"
+DesignEngine[DesignEngine模块]
+RenderEngine[RenderEngine模块]
+Common[Common模块]
+end
+subgraph "元数据存储"
+AppsFolder[meta/apps]
+AppDir[应用目录]
+PageDir[page/]
+MenuDir[menu/]
+DataSourceDir[datasource/]
+end
+DesignEngine --> AppsFolder
+RenderEngine --> AppsFolder
+Common --> DesignEngine
+Common --> RenderEngine
+AppsFolder --> AppDir
+AppDir --> PageDir
+AppDir --> MenuDir
+AppDir --> DataSourceDir
+```
+
+**图示来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [meta/apps](file://meta/apps)
+
+## 核心组件
+核心组件包括`FileRepositoryBase`基类、`AppFileRepository`、`PageFileRepository`、`MenuFileRepository`和`DataSourceFileRepository`。这些类共同构成了基于文件系统的元数据持久化层,通过统一的接口契约(如`IAppRepository`)与上层业务逻辑解耦。
+
+**本节来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+
+## 架构概述
+系统采用模块化设计,仓储层位于领域层(Domain)与基础设施层(Infrastructure)之间。`FileRepositoryBase`提供基础文件操作,具体仓储类实现领域接口,完成特定实体的CRUD操作。元数据配置通过`MetaOption`注入,确保路径可配置。
+
+```mermaid
+classDiagram
+class FileRepositoryBase {
++bool? IsChangeTrackingEnabled
+-static string _metaBaseDir
++FileRepositoryBase(IOptions~MetaOption~ metaOption)
+-static string ReadAllText(string fileName)
+}
+class AppFileRepository {
+-static string appFileName_Format
++Task~IList~AppPartsSchema~~ GetListAsync()
++Task~AppPartsSchema~ GetAsync(string appId)
++Task SaveAsync(AppPartsSchema appSchema)
+}
+class PageFileRepository {
+-static string pageFileName_Format
++Task~PageListModel[]~ GetListAsync(string appId)
++Task~PagePartsSchema~ GetAsync(string appId, string pageId)
++Task SaveAsync(PagePartsSchema pageSchema)
++Task DeleteAsync(string appId, string pageId)
+}
+class MenuFileRepository {
+-static string menuFileName_Format
++Task~MenuSchema~ GetAsync(string appId, string menuId)
++Task~IList~MenuSchema~~ GetListAsync(string appId)
++Task SaveAsync(MenuSchema menuSchema)
++Task DeleteAsync(string appId, string menuId)
+-static IList~MenuSchema~ BuildTreeMenus(IList~MenuSchema~ menus)
+}
+class DataSourceFileRepository {
+-static string dataSourceName_Format
++Task~IList~DataSourceSchema~~ GetListAsync(string appId)
++Task~DataSourceSchema~ GetAsync(string appId, string id)
++Task SaveAsync(string appId, DataSourceSchema dataSourceSchema)
++Task DeleteAsync(string appId, string id)
+}
+class IAppRepository {
+<>
++Task~IList~AppPartsSchema~~ GetListAsync()
++Task~AppPartsSchema~ GetAsync(string appId)
++Task SaveAsync(AppPartsSchema appSchema)
+}
+FileRepositoryBase <|-- AppFileRepository
+FileRepositoryBase <|-- PageFileRepository
+FileRepositoryBase <|-- MenuFileRepository
+FileRepositoryBase <|-- DataSourceFileRepository
+IAppRepository <|.. AppFileRepository
+```
+
+**图示来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [PageFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/PageFileRepository.cs)
+- [MenuFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/MenuFileRepository.cs)
+- [DataSourceFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/DataSourceFileRepository.cs)
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+
+## 详细组件分析
+### FileRepositoryBase 分析
+`FileRepositoryBase`是所有文件仓储的抽象基类,负责管理元数据文件的基础路径和提供通用文件读取方法。
+
+#### 设计原理
+该类通过依赖注入接收`MetaOption`,初始化`_metaBaseDir`为`AppsFilePath`,确保所有子类共享统一的根路径。`ReadAllText`方法封装了文件存在性检查和UTF-8编码的文本读取,若文件不存在则抛出`FileNotFoundException`。
+
+```csharp
+public abstract class FileRepositoryBase
+{
+ protected static string _metaBaseDir;
+
+ public FileRepositoryBase(IOptions metaOption)
+ {
+ _metaBaseDir = metaOption.Value.AppsFilePath;
+ IsChangeTrackingEnabled = false;
+ }
+
+ protected static string ReadAllText(string fileName)
+ {
+ if (!File.Exists(fileName))
+ throw new FileNotFoundException(fileName);
+
+ return File.ReadAllText(fileName, Encoding.UTF8);
+ }
+}
+```
+
+**本节来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+
+### AppFileRepository 分析
+`AppFileRepository`实现了`IAppRepository`接口,负责应用元数据的持久化。
+
+#### 持久化存储与加载流程
+- **加载列表**:遍历`_metaBaseDir`下的所有子目录,将每个目录下与目录名同名的`.json`文件(如`caseapp/caseapp.json`)反序列化为`AppPartsSchema`对象并返回列表。
+- **加载单个**:根据`appId`构造文件路径并读取JSON内容,反序列化为`AppPartsSchema`。
+- **保存**:将`AppPartsSchema`的`ModifiedTime`更新为当前UTC时间,根据`appId`构造文件路径,确保目录存在后,将对象序列化为JSON并写入文件。
+
+```csharp
+public class AppFileRepository : FileRepositoryBase, IAppRepository
+{
+ private static string appFileName_Format = @"{0}\{1}\{2}.json";
+
+ public async Task SaveAsync(AppPartsSchema appSchema)
+ {
+ ArgumentNullException.ThrowIfNull(appSchema);
+ ArgumentException.ThrowIfNullOrEmpty(appSchema.Id);
+
+ appSchema.ModifiedTime = DateTime.UtcNow;
+
+ string fileName = string.Format(appFileName_Format, _metaBaseDir, appSchema.Id, appSchema.Id);
+
+ string fileDirectory = Path.GetDirectoryName(fileName);
+ if (!Directory.Exists(fileDirectory))
+ Directory.CreateDirectory(fileDirectory);
+
+ File.WriteAllText(fileName, appSchema.ToJson(), Encoding.UTF8);
+ await Task.CompletedTask;
+ }
+}
+```
+
+**本节来源**
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+
+### PageFileRepository 分析
+`PageFileRepository`负责页面元数据的文件操作。
+
+#### 文件操作逻辑
+- **获取列表**:读取指定应用`page`目录下的所有JSON文件,构建`PageListModel`列表并按`Order`排序。
+- **获取单个**:根据`appId`和`pageId`构造路径,读取并反序列化`PagePartsSchema`。
+- **保存与删除**:与`AppFileRepository`类似,保存时更新时间戳并写入文件;删除时检查文件存在性后直接删除。
+
+```csharp
+public class PageFileRepository : FileRepositoryBase, IPageRepository
+{
+ private static string pageFileName_Format = @"{0}\{1}\page\{2}.json";
+
+ public Task SaveAsync(PagePartsSchema pageSchema)
+ {
+ // ... 更新 ModifiedTime, 确保目录存在, 写入文件
+ }
+
+ public Task DeleteAsync(string appId, string pageId)
+ {
+ string fileName = string.Format(pageFileName_Format, _metaBaseDir, appId, pageId);
+ if (!File.Exists(fileName))
+ return Task.CompletedTask;
+
+ File.Delete(fileName);
+ return Task.CompletedTask;
+ }
+}
+```
+
+**本节来源**
+- [PageFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/PageFileRepository.cs)
+
+### MenuFileRepository 分析
+`MenuFileRepository`处理菜单元数据,其特色在于支持树形结构。
+
+#### 树形结构构建
+`GetListAsync`方法读取所有菜单文件后,调用`BuildTreeMenus`将扁平列表转换为树形结构。它使用字典缓存所有菜单,遍历列表时将`ParentId`为空的菜单作为根节点,非空的则查找其父节点并添加到`Childrens`集合中,最后按`Order`排序。
+
+```csharp
+private static IList BuildTreeMenus(IList menus)
+{
+ var treeMenus = new List();
+ var menuDic = new Dictionary();
+
+ foreach (var m in menus) menuDic[m.Id] = m;
+
+ foreach (var menu in menus)
+ {
+ if (menu.ParentId.IsNullOrEmpty())
+ treeMenus.Add(menu);
+ else
+ {
+ if (menuDic.TryGetValue(menu.ParentId, out var parentMenu))
+ {
+ parentMenu.Childrens.Add(menu);
+ parentMenu.Childrens = parentMenu.Childrens.OrderBy(t => t.Order).ToList();
+ }
+ else
+ throw new KeyNotFoundException($"ParentId not found: {menu.ParentId}");
+ }
+ }
+
+ return treeMenus.OrderBy(t => t.Order).ToList();
+}
+```
+
+**本节来源**
+- [MenuFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/MenuFileRepository.cs)
+
+### DataSourceFileRepository 分析
+`DataSourceFileRepository`管理数据源元数据。
+
+#### 文件操作逻辑
+其逻辑与其他仓储类似,`GetListAsync`读取`datasource`目录下所有文件并按`Order`排序。`SaveAsync`和`DeleteAsync`方法实现标准的增删改查。
+
+```csharp
+public class DataSourceFileRepository : FileRepositoryBase, IDataSourceRepository
+{
+ private static string dataSourceName_Format = @"{0}\{1}\datasource\{2}.json";
+
+ public async Task SaveAsync(string appId, DataSourceSchema dataSourceSchema)
+ {
+ // ... 更新 ModifiedTime, 确保目录存在, 写入文件
+ }
+}
+```
+
+**本节来源**
+- [DataSourceFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/DataSourceFileRepository.cs)
+
+## 依赖分析
+### 依赖关系图
+```mermaid
+graph TD
+MetaOption --> FileRepositoryBase : "注入"
+FileRepositoryBase --> AppFileRepository : "继承"
+FileRepositoryBase --> PageFileRepository : "继承"
+FileRepositoryBase --> MenuFileRepository : "继承"
+FileRepositoryBase --> DataSourceFileRepository : "继承"
+IAppRepository --> AppFileRepository : "实现"
+IPageRepository --> PageFileRepository : "实现"
+IMenuRepository --> MenuFileRepository : "实现"
+IDataSourceRepository --> DataSourceFileRepository : "实现"
+AppFileRepository --> "meta/apps/[appId]/[appId].json" : "读写"
+PageFileRepository --> "meta/apps/[appId]/page/[pageId].json" : "读写"
+MenuFileRepository --> "meta/apps/[appId]/menu/[menuId].json" : "读写"
+DataSourceFileRepository --> "meta/apps/[appId]/datasource/[dsId].json" : "读写"
+```
+
+**图示来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [MetaOption.cs](file://src/Common/H.LowCode.Configuration/Options/MetaOption.cs)
+
+## 性能考量
+### 性能瓶颈分析
+- **文件I/O开销**:每次操作都涉及磁盘读写,频繁操作可能导致性能下降。
+- **全量读取**:`GetListAsync`方法需读取目录下所有文件,当文件数量庞大时,内存和I/O压力显著增加。
+- **序列化开销**:JSON序列化/反序列化在大数据量时消耗CPU资源。
+
+### 并发访问控制
+当前实现未内置显式并发控制(如文件锁)。在多进程或高并发场景下,同时写入同一文件可能导致数据损坏。建议通过外部机制(如分布式锁)或升级到数据库仓储来解决。
+
+### 适用场景建议
+- **适用**:低频更新、小型应用、开发/测试环境、配置存储。
+- **不适用**:高并发、大数据量、需要复杂查询或事务支持的生产环境。
+
+## 故障排除指南
+### 常见问题
+- **文件找不到**:确保`MetaOption.AppsFilePath`配置正确,且目标文件存在。
+- **JSON解析错误**:检查文件内容是否符合对应Schema的JSON结构。
+- **权限不足**:确保应用对`meta`目录有读写权限。
+- **数据不一致**:避免手动编辑JSON文件,应通过API操作以保证`ModifiedTime`等字段正确更新。
+
+**本节来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+
+## 结论
+基于JSON文件的仓储实现提供了一种简单、直观的元数据持久化方案,特别适合低代码平台的元数据管理。`FileRepositoryBase`通过统一基类封装了基础文件操作,各具体仓储类遵循约定的文件命名规则(`{appId}/{type}/{id}.json`),实现了清晰的职责分离。尽管存在性能和并发瓶颈,但其轻量级和易调试的特性使其在特定场景下极具价值。未来可考虑引入缓存层或支持多种仓储实现(如数据库)以提升灵活性和性能。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202.md"
new file mode 100644
index 0000000000000000000000000000000000000000..7e80fc6b1e28bd9dc4378b43f3faa4d5add345e8
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202.md"
@@ -0,0 +1,234 @@
+# 仓储实现层
+
+
+**本文档引用文件**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+- [IFormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/DataRepositories/IFormDataRepository.cs)
+- [FileRepositoryBase.cs](file://src/RenderEngine/H.LowCode.RenderEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/RenderEngine/H.LowCode.RenderEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+
+
+## 目录
+1. [引言](#引言)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构概览](#架构概览)
+5. [详细组件分析](#详细组件分析)
+6. [依赖分析](#依赖分析)
+7. [性能考量](#性能考量)
+8. [结论](#结论)
+
+## 引言
+本文档旨在深入分析低代码平台中设计引擎与渲染引擎的仓储层(Repository Layer)设计,重点阐述其多后端支持机制。通过分析 `FileRepositoryBase`、`AppFileRepository`、`FormDataRepository` 等关键类,揭示系统如何通过接口抽象与依赖注入实现存储策略的灵活切换,支持文件系统、数据库和远程服务等多种持久化方式。
+
+## 项目结构
+本项目采用分层架构,核心模块包括 `DesignEngine`(设计引擎)和 `RenderEngine`(渲染引擎),两者共享元数据定义(`MetaSchema`),但拥有独立的仓储实现。元数据以 JSON 文件形式存储在 `meta` 目录下,结构清晰,按应用(apps)和部件(parts)组织。
+
+```mermaid
+graph TB
+subgraph "核心模块"
+DesignEngine["DesignEngine (设计引擎)"]
+RenderEngine["RenderEngine (渲染引擎)"]
+end
+subgraph "共享组件"
+MetaSchema["MetaSchema (元数据模型)"]
+Configuration["Configuration (配置)"]
+end
+subgraph "数据存储"
+MetaDir["meta/ (JSON文件)"]
+Database["数据库 (Entity Framework Core)"]
+end
+DesignEngine --> MetaSchema
+RenderEngine --> MetaSchema
+DesignEngine --> Configuration
+RenderEngine --> Configuration
+DesignEngine --> MetaDir
+DesignEngine --> Database
+RenderEngine --> MetaDir
+```
+
+**图示来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs)
+
+## 核心组件
+系统的核心在于其仓储层的设计,通过定义统一的接口(如 `IAppRepository`)和提供多种实现(文件、数据库、远程服务),实现了数据访问的解耦。`FileRepositoryBase` 作为文件存储的基类,封装了文件读写的基础逻辑,而 `AppFileRepository` 则是其具体实现,负责应用元数据的序列化与持久化。
+
+**中文来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs#L1-L30)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs#L1-L70)
+
+## 架构概览
+系统的架构遵循领域驱动设计(DDD)原则,将数据访问逻辑封装在仓储层。设计引擎和渲染引擎通过各自的 `Domain` 模块定义仓储接口,并在 `EntityFrameworkCore` 和 `Repository.JsonFile` 模块中提供具体实现。这种设计使得上层业务逻辑无需关心底层数据存储细节。
+
+```mermaid
+classDiagram
+class IAppRepository {
+<>
++GetListAsync() Task~IList~>
++GetAsync(appId) Task~AppSchema~>
++SaveAsync(appSchema) Task
+}
+class AppFileRepository {
+-_metaBaseDir string
+-appFileName_Format string
++GetListAsync() Task~IList~>
++GetAsync(appId) Task~AppSchema~>
++SaveAsync(appSchema) Task
+}
+class FormDataRepository {
+-_dbContext DesignEngineDbContext
++AddAsync(entity) Task~bool~>
++GetAsync(entityName, id) Task~FormEntity~>
++UpdateAsync(entity) Task~bool~>
++DeleteAsync(entityName, id) Task~bool~>
+}
+class FileRepositoryBase {
+#_metaBaseDir string
++IsChangeTrackingEnabled bool?
++ReadAllText(fileName) string
+}
+IAppRepository <|.. AppFileRepository
+AppFileRepository --|> FileRepositoryBase
+IFormDataRepository <|.. FormDataRepository
+```
+
+**图示来源**
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs#L1-L14)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs#L1-L70)
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs#L1-L30)
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs#L1-L40)
+- [IFormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/DataRepositories/IFormDataRepository.cs#L1-L21)
+
+## 详细组件分析
+
+### 文件仓储基类分析
+`FileRepositoryBase` 是所有基于文件的仓储实现的基类,它提供了跨平台的文件操作基础。
+
+#### 类图分析
+```mermaid
+classDiagram
+class FileRepositoryBase {
++IsChangeTrackingEnabled bool?
+#_metaBaseDir string
++FileRepositoryBase(metaOption)
+#ReadAllText(fileName) string
+}
+```
+
+**图示来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs#L1-L30)
+
+#### 实现细节
+- **构造函数注入**:通过 `IOptions` 注入配置,获取元数据根目录 `_metaBaseDir`。
+- **静态字段**:`_metaBaseDir` 被声明为 `static`,确保所有继承类共享同一个元数据路径。
+- **文件读取**:`ReadAllText` 方法封装了文件存在性检查和 UTF-8 编码的读取,是安全读取 JSON 文件的基础。
+
+**中文来源**
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs#L1-L30)
+
+### 应用文件仓储分析
+`AppFileRepository` 实现了 `IAppRepository` 接口,负责应用元数据的 CRUD 操作。
+
+#### 类图分析
+```mermaid
+classDiagram
+class AppFileRepository {
+-appFileName_Format string
++GetListAsync() Task~IList~>
++GetAsync(appId) Task~AppSchema~>
++SaveAsync(appSchema) Task
+}
+```
+
+**图示来源**
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs#L1-L70)
+
+#### 实现细节
+- **文件路径格式**:使用 `appFileName_Format` 常量定义文件路径模板 `{0}\{1}\{2}.json`,其中 `{0}` 是元数据根目录,`{1}` 是应用ID,`{2}` 是文件名。
+- **获取应用列表**:`GetListAsync` 方法遍历 `_metaBaseDir` 下的所有子目录,为每个目录尝试读取同名的 `.json` 文件,并反序列化为 `AppPartsSchema` 对象。
+- **获取单个应用**:`GetAsync` 方法根据 `appId` 构造文件路径,直接读取并反序列化。
+- **保存应用**:`SaveAsync` 方法在保存前会更新 `ModifiedTime` 字段,并确保目标目录存在,然后将对象序列化为 JSON 并写入文件。
+
+**中文来源**
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs#L1-L70)
+
+### 数据库仓储分析
+`FormDataRepository` 展示了基于 Entity Framework Core 的数据库访问模式。
+
+#### 类图分析
+```mermaid
+classDiagram
+class FormDataRepository {
+-_dbContext DesignEngineDbContext
++AddAsync(entity) Task~bool~>
++GetAsync(entityName, id) Task~FormEntity~>
++UpdateAsync(entity) Task~bool~>
++DeleteAsync(entityName, id) Task~bool~>
+}
+```
+
+**图示来源**
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs#L1-L40)
+
+#### 实现细节
+- **依赖注入**:通过构造函数注入 `DesignEngineDbContext`,这是 EF Core 的核心上下文。
+- **数据操作**:`AddAsync` 和 `GetAsync` 方法直接调用 `_dbContext` 的对应方法,体现了典型的 ORM 模式。
+- **未实现方法**:`UpdateAsync` 和 `DeleteAsync` 方法抛出 `NotImplementedException`,表明该实现可能不完整或仅用于演示。
+
+**中文来源**
+- [FormDataRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DataRepositories/FormDataRepository.cs#L1-L40)
+
+### 仓储接口与解耦机制
+`IAppRepository` 接口定义了应用元数据访问的标准契约。
+
+#### 接口定义
+```csharp
+public interface IAppRepository
+{
+ Task> GetListAsync();
+ Task GetAsync(string appId);
+ Task SaveAsync(AppPartsSchema appSchema);
+}
+```
+
+#### 解耦机制
+- **接口抽象**:上层业务逻辑(如 `AppDomainService`)仅依赖 `IAppRepository` 接口,不关心具体实现。
+- **依赖注入**:在应用启动时,通过 DI 容器将 `IAppRepository` 接口绑定到具体的实现类(如 `AppFileRepository` 或 `AppRemoteServiceRepository`)。
+- **动态切换**:通过修改配置或 DI 注册,可以轻松地在文件存储、数据库存储和远程服务之间切换,而无需修改业务逻辑代码。
+
+**中文来源**
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs#L1-L14)
+
+## 依赖分析
+系统通过模块化设计实现了良好的依赖管理。
+
+```mermaid
+graph TD
+A[IAppRepository] --> B[AppFileRepository]
+A --> C[AppRemoteServiceRepository]
+A --> D[FormDataRepository]
+B --> E[FileRepositoryBase]
+C --> F[RemoteServiceRepositoryBase]
+D --> G[DesignEngineDbContext]
+E --> H[MetaOption]
+F --> H
+G --> H
+```
+
+**图示来源**
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs#L1-L14)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs#L1-L70)
+- [FileRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Base/FileRepositoryBase.cs#L1-L30)
+
+## 性能考量
+- **文件存储**:适用于小型应用或开发环境,简单直接,但并发读写和性能扩展性较差。
+- **数据库存储**:适用于生产环境,支持事务、并发和复杂查询,性能更优,但增加了系统复杂性。
+- **远程服务**:适用于微服务架构,实现了存储与应用的完全解耦,但引入了网络延迟和可靠性问题。
+
+## 结论
+该低代码平台的仓储层设计体现了高度的灵活性和可扩展性。通过 `FileRepositoryBase` 提供统一的文件操作基础,`AppFileRepository` 实现了元数据的文件持久化,而 `FormDataRepository` 则展示了与数据库集成的模式。`IAppRepository` 接口与依赖注入机制的结合,使得系统能够轻松支持多种存储后端,为未来的功能扩展(如远程服务)奠定了坚实的基础。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\344\273\223\345\202\250\346\216\245\345\217\243\344\270\216\344\276\235\350\265\226\346\263\250\345\205\245.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\344\273\223\345\202\250\346\216\245\345\217\243\344\270\216\344\276\235\350\265\226\346\263\250\345\205\245.md"
new file mode 100644
index 0000000000000000000000000000000000000000..542274ea2e0c90b24b7f52014630d7061f36ab24
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\344\273\223\345\202\250\346\216\245\345\217\243\344\270\216\344\276\235\350\265\226\346\263\250\345\205\245.md"
@@ -0,0 +1,260 @@
+# 仓储接口与依赖注入
+
+
+**本文档引用的文件**
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+- [DesignEngineJsonFileRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/DesignEngineJsonFileRepositoryModule.cs)
+- [DesignEngineRemoteServiceRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/DesignEngineRemoteServiceRepositoryModule.cs)
+- [DesignEngineEntityFrameworkCoreModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DesignEngineEntityFrameworkCoreModule.cs)
+- [AppFileRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [AppRemoteServiceRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Repositories/AppRemoteServiceRepository.cs)
+- [AppFileRepository.cs](file://src/RenderEngine/H.LowCode.RenderEngine.Repository.JsonFile/Repositories/AppFileRepository.cs)
+- [AppRemoteServiceRepository.cs](file://src/RenderEngine/H.LowCode.RenderEngine.Repository.RemoteService/Repositories/AppRemoteServiceRepository.cs)
+- [MetaOption.cs](file://src/Common/H.LowCode.Configuration/Options/MetaOption.cs)
+
+
+## 目录
+1. [引言](#引言)
+2. [项目结构分析](#项目结构分析)
+3. [仓储接口抽象设计](#仓储接口抽象设计)
+4. [仓储实现模块注册机制](#仓储实现模块注册机制)
+5. [运行时存储策略动态切换](#运行时存储策略动态切换)
+6. [多仓储共存与优先级配置](#多仓储共存与优先级配置)
+7. [最佳实践与扩展建议](#最佳实践与扩展建议)
+
+## 引言
+本文件系统阐述低代码平台中仓储模式的接口抽象设计与依赖注入机制。重点分析 `IAppRepository` 等接口如何定义统一的数据访问契约,实现领域层与基础设施层的解耦。详细说明 `DesignEngineJsonFileRepositoryModule`、`DesignEngineRemoteServiceRepositoryModule` 和 `DesignEngineEntityFrameworkCoreModule` 三个模块如何通过依赖注入容器注册不同的仓储实现,并解释在运行时如何根据配置动态切换 JSON 文件、数据库或远程服务等存储策略。
+
+## 项目结构分析
+项目采用分层架构设计,核心模块包括 `DesignEngine`(设计引擎)和 `RenderEngine`(渲染引擎),两者共享 `Common` 基础组件。数据访问层通过仓储模式(Repository Pattern)实现,具体实现分散在不同的模块中。
+
+```mermaid
+graph TB
+subgraph "src"
+subgraph "DesignEngine"
+DJson[DesignEngineJsonFileRepositoryModule]
+DRemote[DesignEngineRemoteServiceRepositoryModule]
+DEfCore[DesignEngineEntityFrameworkCoreModule]
+DDomain[DesignEngine.Domain]
+end
+subgraph "RenderEngine"
+RJson[RenderEngineJsonFileRepositoryModule]
+RRemote[RenderEngineRemoteServiceRepositoryModule]
+REfCore[RenderEngineEntityFrameworkCoreModule]
+RDomain[RenderEngine.Domain]
+end
+Common[Common]
+end
+DDomain --> DJson
+DDomain --> DRemote
+DDomain --> DEfCore
+RDomain --> RJson
+RDomain --> RRemote
+RDomain --> REfCore
+Common --> DDomain
+Common --> RDomain
+style DJson fill:#f9f,stroke:#333
+style DRemote fill:#f9f,stroke:#333
+style DEfCore fill:#f9f,stroke:#333
+style RJson fill:#f9f,stroke:#333
+style RRemote fill:#f9f,stroke:#333
+style REfCore fill:#f9f,stroke:#333
+```
+
+**图示来源**
+- [DesignEngineJsonFileRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/DesignEngineJsonFileRepositoryModule.cs)
+- [DesignEngineRemoteServiceRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/DesignEngineRemoteServiceRepositoryModule.cs)
+- [DesignEngineEntityFrameworkCoreModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DesignEngineEntityFrameworkCoreModule.cs)
+
+## 仓储接口抽象设计
+仓储接口定义在 `DesignEngine.Domain` 和 `RenderEngine.Domain` 模块的 `MetaRepositories` 目录下,为元数据(应用、页面、菜单等)提供统一的数据访问契约。
+
+### 核心仓储接口
+```mermaid
+classDiagram
+class IAppRepository {
++Task GetAsync(string appId)
++Task> GetAllAsync()
++Task SaveAsync(AppSchemaBase app)
++Task DeleteAsync(string appId)
+}
+class IPageRepository {
++Task GetAsync(string pageId)
++Task> GetByAppIdAsync(string appId)
++Task SaveAsync(PageSchemaBase page)
++Task DeleteAsync(string pageId)
+}
+class IMenuRepository {
++Task GetAsync(string menuId)
++Task> GetByAppIdAsync(string appId)
++Task SaveAsync(MenuSchema menu)
++Task DeleteAsync(string menuId)
+}
+class IDataSourceRepository {
++Task GetAsync(string dsId)
++Task> GetByAppIdAsync(string appId)
++Task SaveAsync(DataSourceSchema ds)
++Task DeleteAsync(string dsId)
+}
+IAppRepository <|-- AppFileRepository : "实现"
+IAppRepository <|-- AppRemoteServiceRepository : "实现"
+IAppRepository <|-- AppEfCoreRepository : "实现"
+IPageRepository <|-- PageFileRepository : "实现"
+IPageRepository <|-- PageRemoteServiceRepository : "实现"
+IPageRepository <|-- PageEfCoreRepository : "实现"
+IMenuRepository <|-- MenuFileRepository : "实现"
+IMenuRepository <|-- MenuRemoteServiceRepository : "实现"
+IMenuRepository <|-- MenuEfCoreRepository : "实现"
+IDataSourceRepository <|-- DataSourceFileRepository : "实现"
+IDataSourceRepository <|-- DataSourceRemoteServiceRepository : "实现"
+IDataSourceRepository <|-- DataSourceEfCoreRepository : "实现"
+```
+
+**图示来源**
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+- [IPageRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IPageRepository.cs)
+- [IMenuRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IMenuRepository.cs)
+- [IDataSourceRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IDataSourceRepository.cs)
+
+**本节来源**
+- [IAppRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/MetaRepositories/IAppRepository.cs)
+
+## 仓储实现模块注册机制
+系统通过模块化的方式注册不同的仓储实现,每个实现模块负责将其具体的仓储类注册到依赖注入容器中。
+
+### JSON 文件仓储模块
+`DesignEngineJsonFileRepositoryModule` 负责注册基于 JSON 文件的仓储实现。
+
+```csharp
+public class DesignEngineJsonFileRepositoryModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ }
+}
+```
+
+**本节来源**
+- [DesignEngineJsonFileRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/DesignEngineJsonFileRepositoryModule.cs)
+
+### 远程服务仓储模块
+`DesignEngineRemoteServiceRepositoryModule` 负责注册基于远程 API 调用的仓储实现。
+
+```csharp
+public class DesignEngineRemoteServiceRepositoryModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ context.Services.AddTransient();
+ }
+}
+```
+
+**本节来源**
+- [DesignEngineRemoteServiceRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/DesignEngineRemoteServiceRepositoryModule.cs)
+
+### Entity Framework Core 仓储模块
+`DesignEngineEntityFrameworkCoreModule` 负责注册基于数据库的仓储实现。
+
+```csharp
+public class DesignEngineEntityFrameworkCoreModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAbpDbContext(options =>
+ {
+ options.AddDefaultRepositories();
+ options.AddDefaultRepositories();
+ options.AddDefaultRepositories();
+ options.AddDefaultRepositories();
+ });
+ }
+}
+```
+
+**本节来源**
+- [DesignEngineEntityFrameworkCoreModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DesignEngineEntityFrameworkCoreModule.cs)
+
+## 运行时存储策略动态切换
+系统通过配置文件 `MetaOption` 中的 `StorageType` 配置项来决定运行时使用哪种仓储实现。
+
+### 配置驱动的仓储选择
+```csharp
+public class MetaOption
+{
+ public StorageType StorageType { get; set; } = StorageType.JsonFile;
+
+ public string? RemoteServiceUrl { get; set; }
+ public string? ConnectionString { get; set; }
+}
+
+public enum StorageType
+{
+ JsonFile,
+ RemoteService,
+ Database
+}
+```
+
+在应用启动时,根据 `appsettings.json` 中的配置,动态决定加载哪个仓储模块:
+
+```json
+{
+ "MetaOption": {
+ "StorageType": "Database",
+ "ConnectionString": "Server=localhost;Database=LowCode;Trusted_Connection=true;"
+ }
+}
+```
+
+**本节来源**
+- [MetaOption.cs](file://src/Common/H.LowCode.Configuration/Options/MetaOption.cs)
+
+## 多仓储共存与优先级配置
+虽然系统设计上支持多种仓储实现,但在实际运行时,通常通过条件注册确保只激活一种策略,避免冲突。
+
+### 条件注册示例
+```csharp
+public override void ConfigureServices(ServiceConfigurationContext context)
+{
+ var configuration = context.Services.GetConfiguration();
+ var storageType = configuration.GetValue("MetaOption:StorageType");
+
+ switch (storageType)
+ {
+ case StorageType.JsonFile:
+ context.Services.AddTransient();
+ break;
+ case StorageType.RemoteService:
+ context.Services.AddTransient();
+ break;
+ case StorageType.Database:
+ context.Services.AddAbpDbContext(options =>
+ options.AddDefaultRepository());
+ break;
+ }
+}
+```
+
+### 优先级与覆盖规则
+1. **配置优先**:`appsettings.json` 中的 `StorageType` 决定最终使用的仓储。
+2. **后注册覆盖**:如果多个模块注册了同一接口,后注册的实现会覆盖先注册的(取决于 DI 容器行为)。
+3. **显式条件控制**:推荐使用 `if` 或 `switch` 语句进行显式条件判断,确保单一实现被注册。
+
+## 最佳实践与扩展建议
+为确保系统的灵活性与可扩展性,建议遵循以下最佳实践:
+
+1. **接口隔离**:保持仓储接口的职责单一,避免臃肿接口。
+2. **配置驱动**:所有存储策略的选择都应通过配置文件控制,无需重新编译。
+3. **模块化注册**:将不同存储实现封装在独立模块中,便于启用/禁用。
+4. **运行时验证**:在应用启动时验证所选存储类型的配置项是否完整(如数据库连接字符串、远程服务地址)。
+5. **扩展性设计**:新增存储类型(如 Redis、MongoDB)时,只需实现对应仓储接口并创建新模块,无需修改现有代码。
+
+通过上述设计,系统实现了领域逻辑与数据访问的完全解耦,支持在不同环境(开发、测试、生产)中灵活切换数据存储策略,极大提升了系统的可维护性和部署灵活性。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\350\277\234\347\250\213\346\234\215\345\212\241\344\273\223\345\202\250\345\256\236\347\216\260.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\350\277\234\347\250\213\346\234\215\345\212\241\344\273\223\345\202\250\345\256\236\347\216\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f207b28258856460603ec3783089a1fc84d92f0e
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\344\273\223\345\202\250\345\256\236\347\216\260\345\261\202/\350\277\234\347\250\213\346\234\215\345\212\241\344\273\223\345\202\250\345\256\236\347\216\260.md"
@@ -0,0 +1,173 @@
+# 远程服务仓储实现
+
+
+**本文档引用文件**
+- [RemoteServiceRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Base/RemoteServiceRepositoryBase.cs)
+- [AppRemoteServiceRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Repositories/AppRemoteServiceRepository.cs)
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+- [appsettings.json](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/wwwroot/appsettings.json)
+- [IAppApplicationService.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Application.Contracts/AppServices/IAppApplicationService.cs)
+
+
+## 目录
+1. [引言](#引言)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构概述](#架构概述)
+5. [详细组件分析](#详细组件分析)
+6. [依赖分析](#依赖分析)
+7. [性能考虑](#性能考虑)
+8. [故障排除指南](#故障排除指南)
+9. [结论](#结论)
+
+## 引言
+本文档全面解析远程服务仓储模式,重点描述`RemoteServiceRepositoryBase`如何封装HTTP客户端调用,处理认证、重试、超时等横切关注点。详细说明`AppRemoteServiceRepository`等具体实现类如何通过RESTful API与远程元数据服务通信,完成应用、页面、菜单和数据源的远程读写操作。分析请求序列化、响应反序列化、错误码映射及缓存策略的实现细节。阐述该模式在微服务架构中的集成方式、网络延迟影响及容错机制,提供服务地址配置、API版本管理和安全认证的实践指南。
+
+## 项目结构
+本项目采用模块化分层架构,主要分为`meta`元数据目录和`src`源代码目录。`meta`目录存放应用、菜单、页面等JSON格式的元数据文件。`src`目录包含多个子系统,包括设计引擎、渲染引擎和工具模块。设计引擎和渲染引擎各自拥有独立的远程服务仓储实现,通过`RemoteServiceRepositoryBase`基类提供统一的远程调用抽象。
+
+```mermaid
+graph TB
+subgraph "元数据"
+meta[meta目录]
+apps[apps子目录]
+parts[parts子目录]
+end
+subgraph "源代码"
+src[src目录]
+DesignEngine[DesignEngine模块]
+RenderEngine[RenderEngine模块]
+Tools[Tools模块]
+end
+meta --> DesignEngine
+meta --> RenderEngine
+DesignEngine --> RemoteService[远程服务仓储]
+RenderEngine --> RemoteService
+```
+
+**Diagram sources**
+- [meta目录](file://meta)
+- [src目录](file://src)
+
+## 核心组件
+远程服务仓储模式的核心组件包括`RemoteServiceRepositoryBase`基类、具体仓储实现类(如`AppRemoteServiceRepository`)、HTTP客户端配置和动态API代理。这些组件共同协作,为上层应用提供透明的远程数据访问能力。
+
+**Section sources**
+- [RemoteServiceRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Base/RemoteServiceRepositoryBase.cs)
+- [AppRemoteServiceRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Repositories/AppRemoteServiceRepository.cs)
+
+## 架构概述
+系统采用分层架构,客户端通过依赖注入获取仓储实例,仓储层通过动态生成的HTTP代理调用远程API服务。ABP框架的`AddHttpClientProxies`方法根据应用服务契约自动生成强类型的HTTP客户端,实现了服务接口的远程调用。
+
+```mermaid
+graph LR
+A[客户端] --> B[仓储接口]
+B --> C[远程服务仓储]
+C --> D[动态HTTP代理]
+D --> E[远程API服务]
+E --> F[数据库]
+style A fill:#f9f,stroke:#333
+style F fill:#bbf,stroke:#333
+```
+
+**Diagram sources**
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+- [IAppApplicationService.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Application.Contracts/AppServices/IAppApplicationService.cs)
+
+## 详细组件分析
+
+### 远程服务仓储基类分析
+`RemoteServiceRepositoryBase`作为抽象基类,为所有远程仓储提供统一的基础。虽然当前实现为空,但其设计意图是封装HTTP客户端、认证、重试、超时等跨切面功能。
+
+```mermaid
+classDiagram
+class RemoteServiceRepositoryBase {
+<>
+}
+class AppRemoteServiceRepository {
++IOptions metaOption
++GetAsync(string appId) Task
++GetListAsync() Task>
++SaveAsync(AppPartsSchema appSchema) Task
+}
+class IAppRepository {
+<>
++GetAsync(string appId) Task
++GetListAsync() Task>
++SaveAsync(AppPartsSchema appSchema) Task
+}
+RemoteServiceRepositoryBase <|-- AppRemoteServiceRepository
+AppRemoteServiceRepository ..|> IAppRepository
+```
+
+**Diagram sources**
+- [RemoteServiceRepositoryBase.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Base/RemoteServiceRepositoryBase.cs)
+- [AppRemoteServiceRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Repositories/AppRemoteServiceRepository.cs)
+
+### 应用远程服务仓储分析
+`AppRemoteServiceRepository`实现了`IAppRepository`接口,通过依赖注入获取`MetaOption`配置。该类目前的方法实现为`NotImplementedException`,表明其设计为通过动态代理调用远程服务。
+
+```mermaid
+sequenceDiagram
+participant Client as 客户端
+participant Repo as AppRemoteServiceRepository
+participant Proxy as 动态HTTP代理
+participant API as 远程API服务
+Client->>Repo : GetAsync(appId)
+Repo->>Proxy : 调用远程服务
+Proxy->>API : HTTP GET请求
+API-->>Proxy : 返回JSON数据
+Proxy-->>Repo : 反序列化为对象
+Repo-->>Client : 返回AppPartsSchema
+```
+
+**Diagram sources**
+- [AppRemoteServiceRepository.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.RemoteService/Repositories/AppRemoteServiceRepository.cs)
+- [IAppApplicationService.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Application.Contracts/AppServices/IAppApplicationService.cs)
+
+### HTTP客户端配置分析
+`DesignEngineHostClientModule`模块负责配置HTTP客户端和动态代理。`ConfigureHttpClient`方法设置基础地址,`ConfigureHttpClientProxies`方法根据服务契约生成强类型代理。
+
+```mermaid
+flowchart TD
+Start([模块初始化]) --> ConfigureDI["配置依赖注入"]
+ConfigureDI --> SetupHttpClient["设置HTTP客户端"]
+SetupHttpClient --> SetBaseAddress["设置基础地址"]
+SetBaseAddress --> CreateProxy["创建动态代理"]
+CreateProxy --> RegisterServices["注册仓储服务"]
+RegisterServices --> End([配置完成])
+```
+
+**Diagram sources**
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+
+## 依赖分析
+系统依赖ABP框架的HTTP客户端模块实现动态代理,通过`AbpHttpClientModule`和`AddHttpClientProxies`方法生成服务代理。仓储层依赖`MetaOption`配置获取服务地址,客户端依赖`appsettings.json`中的`RemoteServices`配置。
+
+```mermaid
+graph TD
+A[AppRemoteServiceRepository] --> B[MetaOption]
+A --> C[IAppApplicationService]
+C --> D[AbpHttpClientModule]
+D --> E[HttpClient]
+E --> F[appsettings.json]
+style A fill:#f96,stroke:#333
+style F fill:#6f9,stroke:#333
+```
+
+**Diagram sources**
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+- [appsettings.json](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/wwwroot/appsettings.json)
+
+## 性能考虑
+远程服务调用的主要性能瓶颈在于网络延迟。建议实施客户端缓存策略,对不频繁变更的元数据进行缓存。同时,合理配置HTTP客户端的超时和重试策略,避免因网络波动导致的服务不可用。
+
+## 故障排除指南
+当远程服务调用失败时,首先检查`appsettings.json`中的`BaseUrl`配置是否正确。其次确认远程API服务是否正常运行。可通过浏览器直接访问API端点验证服务状态。最后检查网络连接和防火墙设置。
+
+**Section sources**
+- [appsettings.json](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/wwwroot/appsettings.json)
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+
+## 结论
+远程服务仓储模式通过抽象基类和动态代理机制,实现了本地数据访问与远程服务调用的统一接口。该模式提高了代码的可维护性和可测试性,同时利用ABP框架的强大功能简化了分布式系统的开发复杂度。未来可在此基础上扩展缓存、熔断、监控等企业级功能。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\345\256\277\344\270\273\351\205\215\347\275\256\344\270\216\345\220\257\345\212\250\346\265\201\347\250\213.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\345\256\277\344\270\273\351\205\215\347\275\256\344\270\216\345\220\257\345\212\250\346\265\201\347\250\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f9cf4074a2f97dea4fd6097bf2a5379846561729
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\345\256\277\344\270\273\351\205\215\347\275\256\344\270\216\345\220\257\345\212\250\346\265\201\347\250\213.md"
@@ -0,0 +1,380 @@
+# 宿主配置与启动流程
+
+
+**本文档引用的文件**
+- [Program.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/Program.cs)
+- [appsettings.json](file://src/DesignEngine/H.LowCode.DesignEngine.Host/appsettings.json)
+- [DesignEngineHostModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/DesignEngineHostModule.cs)
+- [Program.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/Program.cs)
+- [LowCodeGlobalVariables.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/LowCodeGlobalVariables.cs)
+- [DesignEngineApplicationModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Application/DesignEngineApplicationModule.cs)
+- [DesignEngineDomainModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/DesignEngineDomainModule.cs)
+- [DesignEngineJsonFileRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/DesignEngineJsonFileRepositoryModule.cs)
+- [DesignEngineEntityFrameworkCoreModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DesignEngineEntityFrameworkCoreModule.cs)
+- [LowCodeComponentBaseModule.cs](file://src/Common/H.LowCode.ComponentBase/LowCodeComponentBaseModule.cs)
+- [LowCodeDefaultComponentModule.cs](file://src/Common/H.LowCode.Components.Defaults/LowCodeDefaultComponentModule.cs)
+- [LowCodeWorkbenchModule.cs](file://src/DesignEngine/H.LowCode.Workbench/LowCodeWorkbenchModule.cs)
+- [DesignEngineModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine/DesignEngineModule.cs)
+- [PartsDesignEngineModule.cs](file://src/DesignEngine/H.LowCode.PartsDesignEngine/PartsDesignEngineModule.cs)
+- [MyAppModule.cs](file://src/DesignEngine/H.LowCode.MyApp/MyAppModule.cs)
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+
+
+## 目录
+1. [简介](#简介)
+2. [项目结构](#项目结构)
+3. [核心组件](#核心组件)
+4. [架构概览](#架构概览)
+5. [详细组件分析](#详细组件分析)
+6. [依赖分析](#依赖分析)
+7. [性能考虑](#性能考虑)
+8. [故障排除指南](#故障排除指南)
+9. [结论](#结论)
+
+## 简介
+本文档详细描述了低代码平台中设计引擎的宿主应用(Host)配置与系统启动流程。重点分析了服务注册、模块依赖、配置加载及客户端启动逻辑,旨在为开发者提供清晰的系统初始化路径和扩展指导。
+
+## 项目结构
+设计引擎宿主应用采用模块化分层架构,主要分为服务端(Host)与客户端(Client)两部分,通过ABP框架实现依赖注入与模块协调。
+
+```mermaid
+graph TB
+subgraph "服务端"
+Program[Program.cs]
+HostModule[DesignEngineHostModule]
+AppSettings[appsettings.json]
+end
+subgraph "客户端"
+ClientProgram[Client/Program.cs]
+ClientModule[DesignEngineHostClientModule]
+GlobalVars[LowCodeGlobalVariables]
+end
+subgraph "共享模块"
+Application[Application]
+Domain[Domain]
+Repository[Repository]
+ComponentBase[ComponentBase]
+end
+Program --> HostModule
+HostModule --> Application
+HostModule --> Domain
+HostModule --> Repository
+ClientProgram --> ClientModule
+ClientModule --> Application
+ClientModule --> ComponentBase
+GlobalVars --> ClientProgram
+```
+
+**图示来源**
+- [Program.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/Program.cs)
+- [DesignEngineHostModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/DesignEngineHostModule.cs)
+- [Program.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/Program.cs)
+
+## 核心组件
+
+### 服务端启动流程
+服务端通过`Program.cs`启动,使用ABP框架的`AddApplicationAsync`方法加载`DesignEngineHostModule`,完成模块化服务注册。
+
+**关键步骤:**
+1. 创建WebApplicationBuilder
+2. 注册Razor组件与控制器
+3. 配置响应压缩
+4. 使用Autofac作为DI容器
+5. 加载`DesignEngineHostModule`
+6. 构建应用并运行
+
+```csharp
+var builder = WebApplication.CreateBuilder(args);
+builder.Host.UseAutofac();
+await builder.AddApplicationAsync();
+var app = builder.Build();
+await app.InitializeApplicationAsync();
+await app.RunAsync();
+```
+
+**中文标签:**
+- **builder**: Web应用构建器
+- **AddApplicationAsync**: 异步添加ABP应用模块
+- **InitializeApplicationAsync**: 初始化应用服务
+
+**中文注释:**
+- 启用Autofac以支持更灵活的依赖注入
+- `InitializeApplicationAsync`触发模块的`OnApplicationInitialization`方法
+
+**宿主配置与启动流程**
+- [Program.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/Program.cs#L1-L77)
+
+### 客户端启动流程
+客户端为Blazor WebAssembly应用,其`Program.cs`通过`WebAssemblyHostBuilder`创建宿主,并加载`DesignEngineHostClientModule`。
+
+```csharp
+var builder = WebAssemblyHostBuilder.CreateDefault(args);
+var application = await builder.AddApplicationAsync(options =>
+{
+ options.UseAutofac();
+});
+var host = builder.Build();
+await application.InitializeApplicationAsync(host.Services);
+await host.RunAsync();
+```
+
+该流程确保了客户端模块的依赖注入与服务初始化。
+
+**宿主配置与启动流程**
+- [Program.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/Program.cs#L1-L20)
+
+## 架构概览
+系统采用ABP模块化架构,通过`[DependsOn]`特性声明模块依赖,实现分层解耦。
+
+```mermaid
+classDiagram
+class DesignEngineHostModule {
++ConfigureServices()
+}
+class DesignEngineApplicationModule {
++ConfigureServices()
+}
+class DesignEngineDomainModule {
++ConfigureServices()
+}
+class DesignEngineJsonFileRepositoryModule {
++ConfigureServices()
+}
+class DesignEngineEntityFrameworkCoreModule {
++ConfigureServices()
+}
+DesignEngineHostModule --> DesignEngineApplicationModule : 依赖
+DesignEngineHostModule --> DesignEngineDomainModule : 依赖
+DesignEngineHostModule --> DesignEngineJsonFileRepositoryModule : 依赖
+DesignEngineHostModule --> DesignEngineEntityFrameworkCoreModule : 依赖
+DesignEngineApplicationModule --> DesignEngineDomainModule : 依赖
+DesignEngineJsonFileRepositoryModule --> DesignEngineDomainModule : 依赖
+```
+
+**图示来源**
+- [DesignEngineHostModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/DesignEngineHostModule.cs)
+- [DesignEngineApplicationModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Application/DesignEngineApplicationModule.cs)
+- [DesignEngineDomainModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Domain/DesignEngineDomainModule.cs)
+
+## 详细组件分析
+
+### DesignEngineHostModule 分析
+`DesignEngineHostModule`是服务端核心模块,协调所有子模块的依赖注入。
+
+```csharp
+[DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(AbpAspNetCoreMvcModule),
+ typeof(DesignEngineApplicationModule),
+ typeof(DesignEngineEntityFrameworkCoreModule),
+ typeof(DesignEngineJsonFileRepositoryModule),
+ typeof(LowCodeWorkbenchModule),
+ typeof(DesignEngineModule),
+ typeof(MyAppModule),
+ typeof(PartsDesignEngineModule),
+ typeof(LowCodeDefaultComponentModule),
+ typeof(LowCodeComponentBaseModule)
+)]
+public class DesignEngineHostModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ ConfigureAutoApiControllers();
+ context.Services.AddSingleton(new LowCodeAppState(true));
+ }
+
+ private void ConfigureAutoApiControllers()
+ {
+ Configure(options =>
+ {
+ options.ConventionalControllers.Create(typeof(DesignEngineApplicationModule).Assembly);
+ });
+ }
+}
+```
+
+**功能说明:**
+- **自动API控制器**:扫描`DesignEngineApplicationModule`程序集,自动生成REST API端点
+- **应用状态**:注册`LowCodeAppState`为单例,用于全局状态管理
+
+**宿主配置与启动流程**
+- [DesignEngineHostModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/DesignEngineHostModule.cs#L1-L54)
+
+### 配置文件分析 (appsettings.json)
+`appsettings.json`定义了系统关键配置:
+
+```json
+{
+ "ConnectionStrings": {
+ "Default": "Server=(localdb)\\MSSQLLocalDB;Database=H_LowCode;Trusted_Connection=True;TrustServerCertificate=True"
+ },
+ "Meta": {
+ "appsFilePath": "../../../meta/apps",
+ "partsFilePath": "../../../meta/parts"
+ },
+ "RemoteServices": {
+ "Default": {
+ "BaseUrl": "https://localhost:5181"
+ }
+ },
+ "Sites": [
+ {
+ "AppId": "caseapp",
+ "SiteUrl": "https://localhost:5191"
+ }
+ ]
+}
+```
+
+**配置项说明:**
+- **ConnectionStrings::Default**: 数据库连接字符串,使用LocalDB
+- **Meta::appsFilePath**: 元数据应用文件存储路径
+- **Meta::partsFilePath**: 元数据部件文件存储路径
+- **RemoteServices::Default::BaseUrl**: 远程服务基础地址,用于API调用
+- **Sites**: 多站点配置,定义应用ID与访问URL
+
+这些配置在模块中通过`context.Services.GetConfiguration()`读取并注入服务。
+
+**宿主配置与启动流程**
+- [appsettings.json](file://src/DesignEngine/H.LowCode.DesignEngine.Host/appsettings.json#L1-L32)
+
+### 仓储模块分析
+系统支持多种仓储实现,通过模块配置切换。
+
+#### JSON文件仓储
+`DesignEngineJsonFileRepositoryModule`注册基于JSON文件的仓储实现:
+
+```csharp
+context.Services.AddScoped();
+context.Services.AddScoped();
+// ... 其他仓储
+context.Services.Configure(configuration.GetSection(MetaOption.SectionName));
+```
+
+**特点:**
+- 无数据库依赖
+- 元数据存储于`meta`目录下的JSON文件
+- 适用于开发与轻量级部署
+
+**宿主配置与启动流程**
+- [DesignEngineJsonFileRepositoryModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Repository.JsonFile/DesignEngineJsonFileRepositoryModule.cs#L8-L24)
+
+#### Entity Framework Core 仓储
+`DesignEngineEntityFrameworkCoreModule`注册基于EF Core的仓储:
+
+```csharp
+context.Services.AddScoped();
+context.Services.AddDbContext(options =>
+{
+ var connectionString = context.Services.GetConfiguration().GetConnectionString("Default");
+ options.UseSqlServer(connectionString);
+});
+```
+
+**特点:**
+- 使用SQL Server持久化数据
+- 支持复杂查询与事务
+- 适用于生产环境
+
+**宿主配置与启动流程**
+- [DesignEngineEntityFrameworkCoreModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.EntityFrameworkCore/DesignEngineEntityFrameworkCoreModule.cs#L10-L25)
+
+### 客户端模块分析
+`DesignEngineHostClientModule`配置客户端服务:
+
+```csharp
+[DependsOn(
+ typeof(AbpAutofacWebAssemblyModule),
+ typeof(AbpHttpClientModule),
+ typeof(DesignEngineApplicationContractsModule),
+ // ... 其他模块
+)]
+public class DesignEngineHostClientModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ ConfigureHttpClient(context, environment);
+ ConfigureHttpClientProxies(context);
+ context.Services.AddSingleton(new LowCodeAppState(true));
+ }
+
+ private void ConfigureHttpClientProxies(ServiceConfigurationContext context)
+ {
+ context.Services.AddHttpClientProxies(
+ typeof(DesignEngineApplicationContractsModule).Assembly,
+ RemoteServiceName
+ );
+ }
+}
+```
+
+**功能:**
+- **HttpClient代理**:自动生成API代理类,简化远程调用
+- **单例应用状态**:与服务端共享`LowCodeAppState`
+
+**宿主配置与启动流程**
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs#L13-L62)
+
+### 全局变量分析
+`LowCodeGlobalVariables`提供客户端全局运行时变量:
+
+```csharp
+public static class LowCodeGlobalVariables
+{
+ public static readonly Type LowCodeDefaultLayout = typeof(DesignEngineBase.DesignEngineNavLayout);
+
+ public static readonly Assembly[] AdditionalAssemblies =
+ [
+ typeof(Workbench._Imports).Assembly,
+ typeof(DesignEngine._Imports).Assembly,
+ typeof(PartsDesignEngine._Imports).Assembly,
+ typeof(MyApp._Imports).Assembly
+ ];
+}
+```
+
+**用途:**
+- **LowCodeDefaultLayout**: 指定默认布局组件
+- **AdditionalAssemblies**: 在Razor组件映射中包含额外程序集,支持跨模块组件渲染
+
+**宿主配置与启动流程**
+- [LowCodeGlobalVariables.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/LowCodeGlobalVariables.cs#L1-L17)
+
+## 依赖分析
+系统依赖关系清晰,采用分层架构。
+
+```mermaid
+graph TD
+A[DesignEngineHostModule] --> B[DesignEngineApplicationModule]
+A --> C[DesignEngineDomainModule]
+A --> D[DesignEngineJsonFileRepositoryModule]
+A --> E[DesignEngineEntityFrameworkCoreModule]
+B --> C
+D --> C
+E --> C
+F[DesignEngineHostClientModule] --> G[DesignEngineApplicationContractsModule]
+F --> C
+G --> B
+```
+
+**图示来源**
+- [DesignEngineHostModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/DesignEngineHostModule.cs)
+- [DesignEngineHostClientModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host.Client/DesignEngineHostClientModule.cs)
+
+## 性能考虑
+- **响应压缩**:启用Brotli压缩,减少网络传输量
+- **静态文件缓存**:设置`Cache-Control: public,max-age=600`,提升前端性能
+- **数据库连接**:EF Core使用连接池,优化数据库访问
+
+## 故障排除指南
+- **API 404错误**:检查`DesignEngineHostModule`中`ConfigureAutoApiControllers`是否正确执行
+- **依赖注入失败**:确认模块的`[DependsOn]`特性包含所需模块
+- **元数据加载失败**:检查`appsettings.json`中`Meta::appsFilePath`路径是否正确
+- **客户端代理调用失败**:验证`RemoteServices::Default::BaseUrl`是否可达
+
+**宿主配置与启动流程**
+- [DesignEngineHostModule.cs](file://src/DesignEngine/H.LowCode.DesignEngine.Host/DesignEngineHostModule.cs#L1-L54)
+- [appsettings.json](file://src/DesignEngine/H.LowCode.DesignEngine.Host/appsettings.json#L1-L32)
+
+## 结论
+设计引擎的宿主应用通过ABP模块化架构实现了高度解耦与灵活配置。服务端`Program.cs`启动流程清晰,`DesignEngineHostModule`有效协调了应用、领域、仓储各层。`appsettings.json`集中管理关键配置,支持数据库与存储模式切换。客户端通过`LowCodeGlobalVariables`提供全局变量,支持多模块集成。该架构为系统扩展与维护提供了坚实基础。
\ No newline at end of file
diff --git "a/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\345\272\224\347\224\250\346\234\215\345\212\241\345\261\202/\345\272\224\347\224\250\346\234\215\345\212\241\345\261\202.md" "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\345\272\224\347\224\250\346\234\215\345\212\241\345\261\202/\345\272\224\347\224\250\346\234\215\345\212\241\345\261\202.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e5b0149ebf92e92da05f54bc373101ebe6a7471e
--- /dev/null
+++ "b/.qoder/repowiki/zh/content/\350\256\276\350\256\241\345\274\225\346\223\216/\345\272\224\347\224\250\346\234\215\345\212\241\345\261\202/\345\272\224\347\224\250\346\234\215\345\212\241\345\261\202.md"
@@ -0,0 +1,285 @@
+# 应用服务层
+
+
+**本文档中引用的文件**
+- [AppApplicationService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\AppApplicationService.cs)
+- [IAppApplicationService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IAppApplicationService.cs)
+- [PageAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\PageAppService.cs)
+- [IPageAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IPageAppService.cs)
+- [MenuAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\MenuAppService.cs)
+- [IMenuAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IMenuAppService.cs)
+- [DataSourceAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\DataSourceAppService.cs)
+- [IDataSourceAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IDataSourceAppService.cs)
+- [APIDataSourceSchema.cs](file://src\Common\H.LowCode.MetaSchema\DataSourceSchemas\APIDataSourceSchema.cs)
+- [SQLDataSourceSchema.cs](file://src\Common\H.LowCode.MetaSchema\DataSourceSchemas\SQLDataSourceSchema.cs)
+- [ComponentDataSourceTypeEnum.cs](file://src\Common\H.LowCode.MetaSchema\Enums\ComponentDataSourceTypeEnum.cs)
+
+
+## 目录
+1. [引言](#引言)
+2. [应用服务层架构概览](#应用服务层架构概览)
+3. [核心服务实现分析](#核心服务实现分析)
+4. [服务间调用与依赖关系](#服务间调用与依赖关系)
+5. [数据转换与AutoMapper应用](#数据转换与automapper应用)
+6. [典型API调用流程示例](#典型api调用流程示例)
+7. [异常处理机制](#异常处理机制)
+8. [总结](#总结)
+
+## 引言
+
+应用服务层是低代码设计引擎的核心协调层,位于前端用户界面与后端领域层之间。它负责接收用户请求,协调领域服务执行业务逻辑,管理事务边界,并将领域实体转换为前端可消费的数据传输对象(DTO)。本文档深入解析 `AppApplicationService`、`PageAppService`、`MenuAppService` 和 `DataSourceAppService` 四个核心应用服务的实现逻辑与职责划分,阐明其作为系统“指挥官”的关键作用。
+
+## 应用服务层架构概览
+
+应用服务层遵循典型的分层架构模式,其核心职责是作为领域层(Domain Layer)与表现层(Presentation Layer)之间的桥梁。该层的实现位于 `src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices` 目录下,每个服务都遵循“接口+实现”的契约设计模式。
+
+```mermaid
+graph TB
+subgraph "表现层"
+Frontend[前端界面]
+end
+subgraph "应用服务层"
+AppService[AppApplicationService]
+PageService[PageAppService]
+MenuService[MenuAppService]
+DataSourceService[DataSourceAppService]
+end
+subgraph "领域层"
+AppDomain[AppDomainService]
+PageDomain[PageDomainService]
+MenuDomain[MenuDomainService]
+DataSourceDomain[DataSourceDomainService]
+end
+subgraph "基础设施层"
+Repository[Repository]
+Database[(数据库/文件系统)]
+end
+Frontend --> AppService
+Frontend --> PageService
+Frontend --> MenuService
+Frontend --> DataSourceService
+AppService --> AppDomain
+PageService --> PageDomain
+MenuService --> MenuDomain
+DataSourceService --> DataSourceDomain
+AppDomain --> Repository
+PageDomain --> Repository
+MenuDomain --> Repository
+DataSourceDomain --> Repository
+Repository --> Database
+style AppService fill:#f9f,stroke:#333
+style PageService fill:#f9f,stroke:#333
+style MenuService fill:#f9f,stroke:#333
+style DataSourceService fill:#f9f,stroke:#333
+```
+
+**图示来源**
+- [AppApplicationService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\AppApplicationService.cs)
+- [PageAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\PageAppService.cs)
+- [MenuAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\MenuAppService.cs)
+- [DataSourceAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\DataSourceAppService.cs)
+
+## 核心服务实现分析
+
+### AppApplicationService:应用管理服务
+
+`AppApplicationService` 是管理低代码应用(App)的核心服务,实现了 `IAppApplicationService` 接口。它主要负责应用的查询、保存等操作。
+
+**服务契约 (IAppApplicationService)**
+```csharp
+public interface IAppApplicationService : IApplicationService
+{
+ Task> GetAppsAsync();
+ Task> GetListAsync();
+ Task GetByIdAsync(string appId);
+ Task SaveAsync(AppPartsSchema appSchema);
+}
+```
+
+**实现逻辑分析**
+- **依赖注入**:通过 `LazyServiceProvider` 获取 `IAppDomainService` 和站点配置 `SiteOption`。
+- **获取应用列表**:`GetAppsAsync` 方法调用领域服务获取所有应用的 Schema,然后将其映射为包含站点 URL 的 `AppListModel` 列表。
+- **保存应用**:`SaveAsync` 方法对输入参数进行空值校验后,委托给领域服务执行持久化操作。
+
+**Section sources**
+- [AppApplicationService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\AppApplicationService.cs#L1-L53)
+- [IAppApplicationService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IAppApplicationService.cs#L1-L16)
+
+### PageAppService:页面管理服务
+
+`PageAppService` 负责管理应用内的页面(Page),其功能最为复杂,体现了服务层协调多个领域对象的能力。
+
+**服务契约 (IPageAppService)**
+```csharp
+public interface IPageAppService : IApplicationService
+{
+ Task> GetListAsync(string appId);
+ Task GetByIdAsync(string appId, string pageId);
+ Task GetByIdWithDefineAsync(string appId, string pageId);
+ Task SaveAsync(PagePartsSchema pageSchema);
+ Task DeleteAsync(string appId, string pageId);
+ Task GetPageComponentAsync(string appId, string pageId, string componentId);
+}
+```
+
+**实现逻辑分析**
+- **依赖注入**:除了 `IPageDomainService`,还依赖 `IComponentPartsAppService`,体现了服务间的协作。
+- **获取页面并合并组件定义**:`GetByIdWithDefineAsync` 是其核心方法。它不仅从领域层获取页面 Schema,还通过 `MergeComponentPartsDefineRecursive` 方法递归地将页面中每个组件的实例与最新的组件定义(Component Parts Define)进行合并。这确保了即使组件定义已更新,旧的页面实例也能继承新特性。
+- **获取特定组件**:`GetPageComponentAsync` 方法允许前端精确获取页面中的某个组件实例,并同样执行组件定义的合并。
+
+```mermaid
+sequenceDiagram
+participant Frontend as 前端
+participant PageService as PageAppService
+participant DomainService as PageDomainService
+participant CompService as ComponentPartsAppService
+Frontend->>PageService : GetByIdWithDefineAsync(appId, pageId)
+PageService->>DomainService : GetByIdAsync(appId, pageId)
+DomainService-->>PageService : 返回 PageSchema
+loop 遍历每个组件
+PageService->>CompService : GetByIdAsync(libraryId, componentId)
+CompService-->>PageService : 返回 ComponentPartsDefine
+PageService->>PageService : 合并组件实例与定义
+loop 遍历子组件
+PageService->>CompService : 递归调用
+end
+end
+PageService-->>Frontend : 返回合并后的 PageSchema
+```
+
+**Diagram sources**
+- [PageAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\PageAppService.cs#L1-L111)
+
+**Section sources**
+- [PageAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\PageAppService.cs#L1-L111)
+- [IPageAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IPageAppService.cs#L1-L20)
+
+### MenuAppService:菜单管理服务
+
+`MenuAppService` 负责管理应用的菜单结构,其实现相对直接。
+
+**服务契约 (IMenuAppService)**
+```csharp
+public interface IMenuAppService : IApplicationService
+{
+ Task> GetListAsync(string appId);
+ Task GetByIdAsync(string appId, string menuId);
+ Task SaveAsync(MenuSchema menuSchema);
+ Task DeleteAsync(string appId, string menuId);
+}
+```
+
+**实现逻辑分析**
+- **CRUD操作**:该服务提供了对菜单项的完整增删改查(CRUD)支持。
+- **参数校验**:在 `SaveAsync` 方法中,使用 `ArgumentNullException.ThrowIfNull` 和 `ArgumentException.ThrowIfNullOrEmpty` 对输入参数进行严格校验,体现了良好的防御性编程实践。
+- **委托模式**:所有业务逻辑均委托给 `IMenuDomainService` 执行,保持了应用服务层的轻量级。
+
+**Section sources**
+- [MenuAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application\AppServices\MenuAppService.cs#L1-L43)
+- [IMenuAppService.cs](file://src\DesignEngine\H.LowCode.DesignEngine.Application.Contracts\AppServices\IMenuAppService.cs#L1-L15)
+
+### DataSourceAppService:数据源管理服务
+
+`DataSourceAppService` 负责管理页面组件所依赖的数据源,其特点是需要对数据进行筛选和转换。
+
+**服务契约 (IDataSourceAppService)**
+```csharp
+public interface IDataSourceAppService : IApplicationService
+{
+ Task> GetListAsync(string appId, DataSourceInput input);
+ Task GetByIdAsync(string appId, string id);
+ Task SaveAsync(string appId, DataSourceSchema dataSourceSchema);
+ Task