Skip to content

Commit 9de1726

Browse files
committed
删除 JavaGeneratorTest.ktUIComponents.kt 测试文件;更新 GradleSettings 默认版本至 8.10;引入 UI 组件工具库(UIUtils.ktGroupCard.kt);优化表单组件以提升界面布局与交互体验;补充 Gradle 和语言选项的关联逻辑,支持动态更新生成配置。
1 parent 82b5c63 commit 9de1726

File tree

14 files changed

+567
-337
lines changed

14 files changed

+567
-337
lines changed

composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/gen/view/UIComponents.kt renamed to composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/components/EnhancedTextField.kt

Lines changed: 13 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1-
package love.forte.simbot.codegen.gen.view
1+
package love.forte.simbot.codegen.components
22

3-
import androidx.compose.animation.animateColor
43
import androidx.compose.animation.animateColorAsState
54
import androidx.compose.animation.animateContentSize
6-
import androidx.compose.animation.core.*
5+
import androidx.compose.animation.core.Spring
6+
import androidx.compose.animation.core.spring
7+
import androidx.compose.animation.core.tween
78
import androidx.compose.foundation.interaction.MutableInteractionSource
89
import androidx.compose.foundation.interaction.collectIsFocusedAsState
910
import androidx.compose.foundation.layout.fillMaxWidth
10-
import androidx.compose.foundation.layout.size
1111
import androidx.compose.foundation.shape.RoundedCornerShape
12-
import androidx.compose.material.icons.Icons
13-
import androidx.compose.material.icons.outlined.Search
14-
import androidx.compose.material3.*
15-
import androidx.compose.runtime.*
12+
import androidx.compose.material3.MaterialTheme
13+
import androidx.compose.material3.OutlinedTextField
14+
import androidx.compose.material3.OutlinedTextFieldDefaults
15+
import androidx.compose.material3.Text
16+
import androidx.compose.runtime.Composable
17+
import androidx.compose.runtime.getValue
18+
import androidx.compose.runtime.remember
1619
import androidx.compose.ui.Modifier
17-
import androidx.compose.ui.graphics.Color
1820
import androidx.compose.ui.text.font.FontWeight
1921
import androidx.compose.ui.unit.dp
2022
import androidx.compose.ui.unit.sp
21-
import kotlinx.browser.window
23+
2224

2325
/**
2426
* 定制化的输入框组件,提供统一的样式和交互体验
@@ -53,7 +55,7 @@ fun EnhancedTextField(
5355

5456
val backgroundColor by animateColorAsState(
5557
targetValue = when {
56-
isFocused -> MaterialTheme.colorScheme.surfaceVariant // .copy(alpha = 0.3f)
58+
isFocused -> MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f)
5759
else -> MaterialTheme.colorScheme.surface
5860
},
5961
animationSpec = tween(durationMillis = 200),
@@ -114,80 +116,3 @@ fun EnhancedTextField(
114116
),
115117
)
116118
}
117-
118-
/**
119-
* 带动画效果的搜索图标组件
120-
*/
121-
@Composable
122-
fun SearchingIcon(
123-
initialColor: Color = LocalContentColor.current,
124-
targetColor: Color = LocalContentColor.current.copy(alpha = .2f),
125-
animationSpec: InfiniteRepeatableSpec<Color> = infiniteRepeatable(
126-
tween(durationMillis = 600, delayMillis = 200),
127-
repeatMode = RepeatMode.Reverse
128-
),
129-
label: String = "SearchIconColorAnimation"
130-
) {
131-
val infiniteTransition = rememberInfiniteTransition(label = "SearchIconTransition")
132-
val color by infiniteTransition.animateColor(
133-
initialValue = initialColor,
134-
targetValue = targetColor,
135-
animationSpec = animationSpec,
136-
label = label
137-
)
138-
val size by infiniteTransition.animateFloat(
139-
initialValue = 24f,
140-
targetValue = 28f,
141-
animationSpec = infiniteRepeatable(
142-
tween(durationMillis = 800, delayMillis = 100),
143-
repeatMode = RepeatMode.Reverse
144-
),
145-
label = "IconSizeAnimation"
146-
)
147-
148-
Icon(
149-
Icons.Outlined.Search,
150-
"Searching",
151-
tint = color,
152-
modifier = Modifier.size(size.dp)
153-
)
154-
}
155-
156-
/**
157-
* 记住当前窗口大小的 Composable 函数
158-
*/
159-
@Composable
160-
fun rememberWindowSize(): WindowSize {
161-
var windowSize by remember { mutableStateOf(WindowSize.Desktop) }
162-
163-
DisposableEffect(Unit) {
164-
val resizeListener: (Any?) -> Unit = {
165-
val width = window.innerWidth
166-
windowSize = when {
167-
width < 600 -> WindowSize.Mobile
168-
width < 840 -> WindowSize.Tablet
169-
else -> WindowSize.Desktop
170-
}
171-
}
172-
173-
// 初始化窗口大小
174-
resizeListener(null)
175-
176-
// 添加窗口调整大小的监听器
177-
window.addEventListener("resize", resizeListener)
178-
179-
// 清理监听器
180-
onDispose {
181-
window.removeEventListener("resize", resizeListener)
182-
}
183-
}
184-
185-
return windowSize
186-
}
187-
188-
/**
189-
* 窗口大小枚举类
190-
*/
191-
enum class WindowSize {
192-
Mobile, Tablet, Desktop
193-
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package love.forte.simbot.codegen.components
2+
3+
import androidx.compose.animation.animateColorAsState
4+
import androidx.compose.animation.core.animateDpAsState
5+
import androidx.compose.foundation.BorderStroke
6+
import androidx.compose.foundation.hoverable
7+
import androidx.compose.foundation.interaction.MutableInteractionSource
8+
import androidx.compose.foundation.interaction.collectIsHoveredAsState
9+
import androidx.compose.foundation.layout.*
10+
import androidx.compose.foundation.shape.RoundedCornerShape
11+
import androidx.compose.material3.*
12+
import androidx.compose.runtime.*
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.text.font.FontWeight
15+
import androidx.compose.ui.unit.dp
16+
17+
/**
18+
* 统一的分组卡片组件,用于将表单内容按功能分组展示
19+
* 提供现代化的卡片样式,支持标题和内容区域
20+
*
21+
* @param title 分组标题
22+
* @param modifier 修饰符
23+
* @param subtitle 可选的副标题
24+
* @param content 分组内容
25+
*/
26+
@Composable
27+
fun GroupCard(
28+
title: String,
29+
modifier: Modifier = Modifier,
30+
subtitle: String? = null,
31+
content: @Composable ColumnScope.() -> Unit
32+
) {
33+
val interactionSource = remember { MutableInteractionSource() }
34+
val isHovered by interactionSource.collectIsHoveredAsState()
35+
36+
val cardBorderColor by animateColorAsState(
37+
targetValue = if (isHovered) {
38+
MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)
39+
} else {
40+
MaterialTheme.colorScheme.outline.copy(alpha = 0.1f)
41+
},
42+
label = "borderColor"
43+
)
44+
45+
val cardContainerColor by animateColorAsState(
46+
targetValue = if (isHovered) {
47+
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.15f)
48+
} else {
49+
MaterialTheme.colorScheme.surface
50+
},
51+
label = "cardContainerColor"
52+
)
53+
54+
val cardElevationValue by animateDpAsState(
55+
targetValue = if (isHovered) 2.dp else 0.dp,
56+
label = "cardElevation"
57+
)
58+
OutlinedCard(
59+
modifier = modifier
60+
.fillMaxWidth()
61+
.hoverable(interactionSource),
62+
shape = RoundedCornerShape(16.dp), // 稍微增大圆角以获得更现代的外观
63+
border = BorderStroke(
64+
width = 1.dp,
65+
color = cardBorderColor
66+
),
67+
colors = CardDefaults.outlinedCardColors(
68+
containerColor = cardContainerColor
69+
),
70+
elevation = CardDefaults.outlinedCardElevation(
71+
defaultElevation = cardElevationValue
72+
)
73+
) {
74+
Column(
75+
modifier = Modifier
76+
.fillMaxWidth()
77+
.padding(20.dp), // 增加内边距以获得更现代的外观
78+
verticalArrangement = Arrangement.spacedBy(16.dp)
79+
) {
80+
// 标题区域
81+
Column(
82+
verticalArrangement = Arrangement.spacedBy(4.dp)
83+
) {
84+
Text(
85+
text = title,
86+
style = MaterialTheme.typography.titleLarge,
87+
fontWeight = FontWeight.Bold,
88+
color = MaterialTheme.colorScheme.primary
89+
)
90+
91+
subtitle?.let {
92+
Text(
93+
text = it,
94+
style = MaterialTheme.typography.bodyMedium,
95+
color = MaterialTheme.colorScheme.onSurfaceVariant
96+
)
97+
}
98+
}
99+
100+
// 内容区域
101+
Column(
102+
modifier = Modifier.fillMaxWidth(),
103+
verticalArrangement = Arrangement.spacedBy(12.dp),
104+
content = content
105+
)
106+
}
107+
}
108+
}
109+
110+
/**
111+
* 轻量级的分组容器,用于不需要卡片样式的简单分组
112+
*
113+
* @param title 分组标题
114+
* @param modifier 修饰符
115+
* @param subtitle 可选的副标题
116+
* @param content 分组内容
117+
*/
118+
@Composable
119+
fun GroupContainer(
120+
title: String,
121+
modifier: Modifier = Modifier,
122+
subtitle: String? = null,
123+
content: @Composable ColumnScope.() -> Unit
124+
) {
125+
Column(
126+
modifier = modifier.fillMaxWidth(),
127+
verticalArrangement = Arrangement.spacedBy(16.dp)
128+
) {
129+
// 标题区域
130+
Column(
131+
verticalArrangement = Arrangement.spacedBy(4.dp)
132+
) {
133+
Text(
134+
text = title,
135+
style = MaterialTheme.typography.titleLarge,
136+
fontWeight = FontWeight.Bold,
137+
color = MaterialTheme.colorScheme.primary
138+
)
139+
140+
subtitle?.let {
141+
Text(
142+
text = it,
143+
style = MaterialTheme.typography.bodyMedium,
144+
color = MaterialTheme.colorScheme.onSurfaceVariant
145+
)
146+
}
147+
}
148+
149+
// 内容区域
150+
Column(
151+
modifier = Modifier.fillMaxWidth(),
152+
verticalArrangement = Arrangement.spacedBy(12.dp),
153+
content = content
154+
)
155+
}
156+
}
157+
158+
/**
159+
* 响应式的分组网格,用于在不同屏幕尺寸下展示分组
160+
*
161+
* @param modifier 修饰符
162+
* @param windowSize 窗口尺寸
163+
* @param content 分组内容
164+
*/
165+
@Composable
166+
fun GroupGrid(
167+
modifier: Modifier = Modifier,
168+
windowSize: WindowSize,
169+
content: @Composable ColumnScope.() -> Unit
170+
) {
171+
Column(
172+
modifier = modifier.fillMaxWidth(),
173+
verticalArrangement = Arrangement.spacedBy(
174+
when (windowSize) {
175+
WindowSize.Mobile -> 16.dp
176+
WindowSize.Tablet -> 20.dp
177+
WindowSize.Desktop -> 24.dp
178+
}
179+
),
180+
content = content
181+
)
182+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package love.forte.simbot.codegen.components
2+
3+
import androidx.compose.animation.animateColor
4+
import androidx.compose.animation.core.InfiniteRepeatableSpec
5+
import androidx.compose.animation.core.RepeatMode
6+
import androidx.compose.animation.core.animateFloat
7+
import androidx.compose.animation.core.infiniteRepeatable
8+
import androidx.compose.animation.core.rememberInfiniteTransition
9+
import androidx.compose.animation.core.tween
10+
import androidx.compose.foundation.layout.size
11+
import androidx.compose.material.icons.Icons
12+
import androidx.compose.material.icons.outlined.Search
13+
import androidx.compose.material3.Icon
14+
import androidx.compose.material3.LocalContentColor
15+
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.getValue
17+
import androidx.compose.ui.Modifier
18+
import androidx.compose.ui.graphics.Color
19+
import androidx.compose.ui.unit.dp
20+
21+
22+
/**
23+
* 带动画效果的搜索图标组件
24+
*/
25+
@Composable
26+
fun SearchingIcon(
27+
initialColor: Color = LocalContentColor.current,
28+
targetColor: Color = LocalContentColor.current.copy(alpha = .2f),
29+
animationSpec: InfiniteRepeatableSpec<Color> = infiniteRepeatable(
30+
tween(durationMillis = 600, delayMillis = 200),
31+
repeatMode = RepeatMode.Reverse
32+
),
33+
label: String = "SearchIconColorAnimation"
34+
) {
35+
val infiniteTransition = rememberInfiniteTransition(label = "SearchIconTransition")
36+
val color by infiniteTransition.animateColor(
37+
initialValue = initialColor,
38+
targetValue = targetColor,
39+
animationSpec = animationSpec,
40+
label = label
41+
)
42+
val size by infiniteTransition.animateFloat(
43+
initialValue = 24f,
44+
targetValue = 28f,
45+
animationSpec = infiniteRepeatable(
46+
tween(durationMillis = 800, delayMillis = 100),
47+
repeatMode = RepeatMode.Reverse
48+
),
49+
label = "IconSizeAnimation"
50+
)
51+
52+
Icon(
53+
Icons.Outlined.Search,
54+
"Searching",
55+
tint = color,
56+
modifier = Modifier.size(size.dp)
57+
)
58+
}

0 commit comments

Comments
 (0)