- Core: Schema (Codable), Store, EventBus, RPC, Engine, I18n - Controls: Text, Title1-6, Label, Input, Textarea, Number, Date, Button, Select VBox, HBox, ScrollPanel, DynamicColumn, Tabular, Form, InlineForm, TabView, Menu, PopupWindow, Html, Image, UrlWidget - Renderer: BricksView (main entry), ControlRenderer (recursive dispatch) - 30+ widget types, 9 bind actiontypes - Form validation (required/minlength/maxlength/min/max/email/number/pattern) - i18n with multi-language JSON files - 18 tests covering schema parsing, store, i18n, events
118 lines
3.2 KiB
Swift
118 lines
3.2 KiB
Swift
import Foundation
|
||
import Combine
|
||
import SwiftUI
|
||
|
||
/// 数据存储 — Bricks binds系统的数据层
|
||
/// 存储widget的值,提供双向绑定
|
||
@MainActor
|
||
public final class BricksStore: ObservableObject {
|
||
/// widget值存储: widgetId → value
|
||
@Published public var values: [String: Any] = [:]
|
||
|
||
/// 表单字段值: formId → {fieldName: value}
|
||
@Published public var formValues: [String: [String: String]] = [:]
|
||
|
||
/// Tabular数据: tabularId → rows
|
||
@Published public var tableData: [String: [[String: Any]]] = [:]
|
||
|
||
/// Tabular选中行: tabularId → selectedIndex
|
||
@Published public var selectedRows: [String: Int] = [:]
|
||
|
||
/// 弹出窗口状态
|
||
@Published public var popups: [String: PopupState] = [:]
|
||
|
||
/// 侧边栏折叠状态
|
||
@Published public var collapsedMenus: Set<String> = []
|
||
|
||
private var cancellables = Set<AnyCancellable>()
|
||
|
||
public init() {}
|
||
|
||
// MARK: - 通用值存取
|
||
|
||
public func getValue(id: String) -> Any? {
|
||
values[id]
|
||
}
|
||
|
||
public func setValue(id: String, value: Any?) {
|
||
if let value {
|
||
values[id] = value
|
||
} else {
|
||
values.removeValue(forKey: id)
|
||
}
|
||
}
|
||
|
||
// MARK: - 表单字段
|
||
|
||
public func getFormField(formId: String, field: String) -> String {
|
||
formValues[formId]?[field] ?? ""
|
||
}
|
||
|
||
public func setFormField(formId: String, field: String, value: String) {
|
||
if formValues[formId] == nil {
|
||
formValues[formId] = [:]
|
||
}
|
||
formValues[formId]?[field] = value
|
||
}
|
||
|
||
public func getFormValues(formId: String) -> [String: String] {
|
||
formValues[formId] ?? [:]
|
||
}
|
||
|
||
public func setFormValues(formId: String, data: [String: String]) {
|
||
formValues[formId] = data
|
||
}
|
||
|
||
public func clearForm(formId: String) {
|
||
formValues[formId]?.keys.forEach { key in
|
||
formValues[formId]?[key] = ""
|
||
}
|
||
}
|
||
|
||
// MARK: - 表格数据
|
||
|
||
public func setTableData(id: String, rows: [[String: Any]]) {
|
||
tableData[id] = rows
|
||
}
|
||
|
||
public func getTableData(id: String) -> [[String: Any]] {
|
||
tableData[id] ?? []
|
||
}
|
||
|
||
public func selectRow(tabularId: String, index: Int) {
|
||
selectedRows[tabularId] = index
|
||
}
|
||
|
||
public func getSelectedRow(tabularId: String) -> Int? {
|
||
selectedRows[tabularId]
|
||
}
|
||
|
||
public func getSelectedRowData(tabularId: String) -> [String: Any]? {
|
||
guard let idx = selectedRows[tabularId],
|
||
let rows = tableData[tabularId],
|
||
idx >= 0, idx < rows.count else { return nil }
|
||
return rows[idx]
|
||
}
|
||
|
||
// MARK: - 弹窗
|
||
|
||
public func openPopup(id: String, schema: ControlSchema, options: PopupOptions) {
|
||
popups[id] = PopupState(schema: schema, options: options, isOpen: true)
|
||
}
|
||
|
||
public func closePopup(id: String) {
|
||
popups.removeValue(forKey: id)
|
||
}
|
||
|
||
public func isPopupOpen(id: String) -> Bool {
|
||
popups[id]?.isOpen ?? false
|
||
}
|
||
}
|
||
|
||
/// 弹窗状态
|
||
public struct PopupState {
|
||
public let schema: ControlSchema
|
||
public let options: PopupOptions
|
||
public var isOpen: Bool
|
||
}
|