import SwiftUI // MARK: - Text Control struct TextControl: View { let schema: ControlSchema @ObservedObject var engine: BricksEngine var body: some View { let text = displayText Text(text) .font(resolveFont()) .foregroundColor(resolveColor()) .lineLimit(nil) .fixedSize(horizontal: false, vertical: true) } private var displayText: String { let raw = schema.options.otext ?? schema.options.text ?? "" if schema.options.i18n != false { return engine.i18n.t(raw) } return raw } private func resolveFont() -> Font { if let fs = schema.options.cfontsize { return .system(size: CGFloat(fs * 14)) } if let fs = schema.options.fontsize, let size = Double(fs.replacingOccurrences(of: "px", with: "")) { return .system(size: CGFloat(size)) } return .body } private func resolveColor() -> Color { if let color = schema.options.color { return Color.fromCSS(color) } return .primary } } // MARK: - Title Control struct TitleControl: View { let schema: ControlSchema @ObservedObject var engine: BricksEngine let level: Int var body: some View { let text = schema.options.text ?? schema.options.otext ?? "" let translated = (schema.options.i18n != false) ? engine.i18n.t(text) : text Group { switch level { case 1: Text(translated).font(.largeTitle).bold() case 2: Text(translated).font(.title).bold() case 3: Text(translated).font(.title2).bold() case 4: Text(translated).font(.title3).bold() case 5: Text(translated).font(.headline) case 6: Text(translated).font(.subheadline).bold() default: Text(translated).font(.body) } } .foregroundColor(resolveColor()) } private func resolveColor() -> Color { if let color = schema.options.color { return Color.fromCSS(color) } return .primary } } // MARK: - Label Control struct LabelControl: View { let schema: ControlSchema @ObservedObject var engine: BricksEngine var body: some View { let text = schema.options.text ?? schema.options.otext ?? "" let translated = (schema.options.i18n != false) ? engine.i18n.t(text) : text HStack(spacing: 4) { if let icon = schema.options.icon { Text(icon) } Text(translated) .font(.body) .foregroundColor(.secondary) } } } // MARK: - Color Extension extension Color { static func fromCSS(_ css: String) -> Color { let cleaned = css.trimmingCharacters(in: .whitespaces) if cleaned.hasPrefix("#") { return Color(hex: cleaned) } if cleaned.hasPrefix("var(") { // CSS变量 → 使用默认色 return .primary } switch cleaned.lowercased() { case "red": return .red case "blue": return .blue case "green": return .green case "yellow": return .yellow case "orange": return .orange case "purple": return .purple case "pink": return .pink case "white": return .white case "black": return .black case "gray", "grey": return .gray case "transparent": return .clear default: return .primary } } init(hex: String) { var hexStr = hex.trimmingCharacters(in: .whitespacesAndNewlines) if hexStr.hasPrefix("#") { hexStr.removeFirst() } var rgb: UInt64 = 0 Scanner(string: hexStr).scanHexInt64(&rgb) let r = Double((rgb >> 16) & 0xFF) / 255.0 let g = Double((rgb >> 8) & 0xFF) / 255.0 let b = Double(rgb & 0xFF) / 255.0 self.init(red: r, green: g, blue: b) } }