| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- //
- // HappyEightCompoents.swift
- // LotteryTracker
- //
- // Created by aaa on 2026/1/26.
- //
-
- import SwiftUI
-
- struct HappyEightSection: View {
- @Binding var numbers: String
- @State private var selectedNumbers: [Int] = []
- @State private var selectionType: Happy8Type = .happy8One // 默认为选一
-
- private let columns = Array(repeating: GridItem(.flexible()), count: 10) // 10列网格
-
- var body: some View {
- VStack(alignment: .leading, spacing: 16) {
- // 头部标题
- HStack {
- SectionHeader(title: "选择号码", icon: "number.circle")
-
- Picker(selectionType.string, selection: $selectionType) {
- ForEach(Happy8Type.allCases) { type in // ✅ 使用 ForEach 简化
- Text(type.string).tag(type)
- }
- }
- .pickerStyle(.menu)
- }
-
- // 选号类型选择器
- SelectionTypePicker(selectedType: $selectionType)
-
- // 选择区号码网格(1-80)
- VStack(alignment: .leading, spacing: 12) {
- NumberSelectionGrid(
- lotteryType: .happy8,
- title: "号码区",
- color: .primary,
- range: 1...80,
- maxSelection: selectionType.rawValue,
- selectedNumbers: $selectedNumbers
- )
- }
-
- // 快速操作栏
- QuickActionsBar2(
- maxSelection: 1,
- count: selectedNumbers.count,
- isEmpty: selectedNumbers.isEmpty,
- onRandom: generateRandomNumbers,
- onClear: clearAllNumbers,
- onSmartRandom: generateSmartNumbers
- )
-
- // 已选号码展示
- if !selectedNumbers.isEmpty {
- SelectedNumbersDisplay()
- }
- }
- .onChange(of: selectedNumbers) {
- updateNumbers()
- }
- .onChange(of: selectionType) {
- adjustSelectedNumbers()
- }
- }
-
- // MARK: - 子组件
-
- private func SelectionBadgeView() -> some View {
- HStack(spacing: 6) {
- Image(systemName: "checkmark.circle.fill")
- .font(.caption)
- .foregroundColor(selectedNumbers.count >= 5 ? .green : .orange)
-
- Text("\(selectedNumbers.count)/\(selectionType.rawValue)")
- .font(.system(size: 14, weight: .bold))
- .foregroundColor(selectedNumbers.count == selectionType.rawValue ? .white : .primary)
- }
- .padding(.horizontal, 12)
- .padding(.vertical, 8)
- .background(
- Capsule()
- .fill(selectedNumbers.count == selectionType.rawValue ?
- Color.green.gradient :
- Color(.systemGray6).gradient)
- )
- .overlay(
- Capsule()
- .stroke(selectedNumbers.count == selectionType.rawValue ?
- Color.green.opacity(0.5) :
- Color.gray.opacity(0.3),
- lineWidth: 1)
- )
- .shadow(color: selectedNumbers.count == selectionType.rawValue ?
- Color.green.opacity(0.3) : Color.clear,
- radius: 3, x: 0, y: 2)
- }
-
- private func SelectedNumbersDisplay() -> some View {
- VStack(alignment: .leading, spacing: 12) {
- HStack {
- HStack {
- Text(" 快乐8")
- .font(.subheadline)
- .fontWeight(.semibold)
- .foregroundColor(.primary)
-
- Spacer()
-
- Capsule()
- .fill(Color(.gray).opacity(0.2))
- .frame(width: 48, height: 28)
- .overlay(
- Text(selectionType.string)
- .font(.subheadline)
- .fontWeight(.semibold)
- .foregroundColor(Color(.black))
- )
- }
-
- Spacer()
-
- if selectedNumbers.count == selectionType.rawValue {
- HStack(spacing: 4) {
- Image(systemName: "checkmark.seal.fill")
- .font(.caption)
- .foregroundColor(.green)
-
- Text("已选满")
- .font(.caption)
- .fontWeight(.medium)
- .foregroundColor(.green)
- }
- }
- }
-
- // 号码展示
- LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 5), spacing: 8) {
- ForEach(selectedNumbers.sorted(), id: \.self) { number in
- SelectedNumberPill(number: number)
- }
- }
- }
- .padding(16)
- .background(Color(.systemBackground))
- .cornerRadius(12)
- .overlay(
- RoundedRectangle(cornerRadius: 12)
- .stroke(Color.blue.opacity(0.1), lineWidth: 1)
- )
- }
-
- private func SelectedNumberPill(number: Int) -> some View {
- HStack(spacing: 6) {
- Text(String(format: "%02d", number))
- .font(.system(size: 16, weight: .bold, design: .rounded))
-
- // Button {
- // removeNumber(number)
- // } label: {
- // Image(systemName: "xmark.circle.fill")
- // .font(.caption)
- // .foregroundColor(.red.opacity(0.7))
- // }
- }
- .frame(width: 22, height: 22)
- .padding(.horizontal, 10)
- .padding(.vertical, 10)
- .background(
- LinearGradient(
- colors: [Color.blue, Color.purple],
- startPoint: .topLeading,
- endPoint: .bottomTrailing
- ).opacity(0.15)
- )
- .foregroundColor(.blue)
- .cornerRadius(20)
- .overlay(
- RoundedRectangle(cornerRadius: 20)
- .stroke(Color.blue.opacity(0.3), lineWidth: 1)
- )
- }
-
- // MARK: - 功能方法
-
- // private func removeNumber(_ number: Int) {
- // withAnimation(.spring(response: 0.3)) {
- // selectedNumbers.removeAll { $0 == number }
- // }
- // }
-
- private func generateRandomNumbers() {
- withAnimation(.spring(response: 0.4)) {
- var numbers = Set<Int>()
- while numbers.count < selectionType.rawValue {
- numbers.insert(Int.random(in: 1...80))
- }
- selectedNumbers = Array(numbers).sorted()
- }
-
- // 触觉反馈
- let generator = UIImpactFeedbackGenerator(style: .medium)
- generator.impactOccurred()
- }
-
- private func generateSmartNumbers() {
- // 智能选号:保证奇偶、大小均衡
- var selected = Set<Int>()
-
- // 确保有5个奇数,5个偶数
- let oddNumbers = (1...80).filter { $0 % 2 == 1 }.shuffled()
- let evenNumbers = (1...80).filter { $0 % 2 == 0 }.shuffled()
- let odds = selectionType.rawValue / 2
-
- selected.formUnion(oddNumbers.prefix(odds))
- selected.formUnion(evenNumbers.prefix(selectionType.rawValue - odds))
-
- withAnimation(.spring(response: 0.4)) {
- selectedNumbers = Array(selected).sorted()
- }
- }
-
- private func clearAllNumbers() {
- withAnimation(.spring(response: 0.3)) {
- selectedNumbers.removeAll()
- }
- }
-
- private func updateNumbers() {
- let numberStr = selectedNumbers.sorted().map { String(format: "%02d", $0) }.joined(separator: " ")
- numbers = numberStr
- }
-
- private func adjustSelectedNumbers() {
- clearAllNumbers()
- }
- }
-
-
- // MARK: - 子视图
-
- // 选号类型选择器
- struct SelectionTypePicker: View {
- @Binding var selectedType: Happy8Type
- private let types = Happy8Type.allCases // 使用枚举
-
- var body: some View {
- VStack {
- ScrollView(.horizontal, showsIndicators: false) {
- HStack {
- ForEach(types) { type in
- SelectionTypeButton(
- type: type,
- isSelected: selectedType == type,
- action: { selectedType = type }
- )
- }
- }
- .padding(.horizontal, 2)
- .padding(.vertical, 2)
- }
- }
- .padding(.horizontal, 4)
- }
- }
-
- // 选号类型按钮
- struct SelectionTypeButton: View {
- let type: Happy8Type
- let isSelected: Bool
- let action: () -> Void
-
- var body: some View {
- Button(action: {
- action()
- }) {
- Text(type.string)
- .font(.system(size: 14, weight: .medium))
- .foregroundColor(isSelected ? .blue : .primary)
- .frame(width: 52, height: 36)
- .background(
- Capsule()
- .fill(isSelected ? Color.blue.opacity(0.1) : Color.clear)
- )
- .overlay(
- Capsule()
- .stroke(isSelected ? Color.blue : Color.gray.opacity(0.2), lineWidth: 1)
- )
- }
- .buttonStyle(SelectionTypeButtonStyle())
- }
- }
-
- // 自定义按钮样式
- struct SelectionTypeButtonStyle: ButtonStyle {
- func makeBody(configuration: Configuration) -> some View {
- configuration.label
- .scaleEffect(configuration.isPressed ? 0.95 : 1.0)
- .opacity(configuration.isPressed ? 0.8 : 1.0)
- .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
- }
- }
|