mirror of
http://180.163.74.83:13000/zhangzhenghao/MPVN_Android.git
synced 2025-12-13 15:44:29 +00:00
调整细节
This commit is contained in:
parent
8c21431bcc
commit
238958f3d2
@ -9,6 +9,8 @@ import androidx.compose.foundation.border
|
|||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
@ -72,7 +74,7 @@ fun LoginScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
// 登录方式:phone=手机号登录,wechat=微信扫码登录
|
// 登录方式:phone=手机号登录,wechat=微信扫码登录
|
||||||
var loginMethod by remember { mutableStateOf("phone") }
|
var loginMethod by remember { mutableStateOf("wechat") }
|
||||||
|
|
||||||
// 扫码状态(微信登录用)
|
// 扫码状态(微信登录用)
|
||||||
var scanStatus by remember { mutableStateOf(ScanStatus.WAITING) }
|
var scanStatus by remember { mutableStateOf(ScanStatus.WAITING) }
|
||||||
@ -335,7 +337,8 @@ fun WeChatLoginCard(
|
|||||||
),
|
),
|
||||||
shape = RoundedCornerShape(28.dp)
|
shape = RoundedCornerShape(28.dp)
|
||||||
)
|
)
|
||||||
.padding(32.dp)
|
.padding(24.dp)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
@ -354,12 +357,12 @@ fun WeChatLoginCard(
|
|||||||
modifier = Modifier.padding(top = 4.dp)
|
modifier = Modifier.padding(top = 4.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
// 二维码区域
|
// 二维码区域
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(200.dp)
|
.size(160.dp)
|
||||||
.clip(RoundedCornerShape(16.dp))
|
.clip(RoundedCornerShape(16.dp))
|
||||||
.background(Color.White)
|
.background(Color.White)
|
||||||
.padding(12.dp),
|
.padding(12.dp),
|
||||||
@ -458,15 +461,15 @@ fun WeChatLoginCard(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
// 模拟登录按钮(仅在模拟模式下显示)
|
// 模拟登录按钮(仅在模拟模式下显示)- 放在显眼位置
|
||||||
if (LoginConfig.USE_MOCK) {
|
if (LoginConfig.USE_MOCK) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(48.dp)
|
.height(52.dp)
|
||||||
.clip(RoundedCornerShape(12.dp))
|
.clip(RoundedCornerShape(14.dp))
|
||||||
.background(
|
.background(
|
||||||
Brush.horizontalGradient(
|
Brush.horizontalGradient(
|
||||||
listOf(Color(0xFF07C160), Color(0xFF06AD56))
|
listOf(Color(0xFF07C160), Color(0xFF06AD56))
|
||||||
@ -479,17 +482,17 @@ fun WeChatLoginCard(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = "💬", fontSize = 18.sp)
|
Text(text = "<EFBFBD>", fontSize = 20.sp)
|
||||||
Text(
|
Text(
|
||||||
text = tr("login_simulate"),
|
text = "点击模拟扫码登录",
|
||||||
fontSize = 15.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Bold,
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新二维码
|
// 刷新二维码
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import androidx.compose.ui.platform.LocalDensity
|
|||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import android.view.SoundEffectConstants
|
import android.view.SoundEffectConstants
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
||||||
@ -139,7 +140,11 @@ fun RoomContent(selectedRoom: Int, roomName: String) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun OverviewRoomContent() {
|
fun OverviewRoomContent() {
|
||||||
Column(modifier = Modifier.fillMaxSize()) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||||
AirConditionerCard(modifier = Modifier.weight(1f), roomName = tr("room_all"))
|
AirConditionerCard(modifier = Modifier.weight(1f), roomName = tr("room_all"))
|
||||||
UsageStatusChart(modifier = Modifier.weight(1f), roomName = tr("room_all"))
|
UsageStatusChart(modifier = Modifier.weight(1f), roomName = tr("room_all"))
|
||||||
@ -157,13 +162,17 @@ fun OverviewRoomContent() {
|
|||||||
color = Color.White,
|
color = Color.White,
|
||||||
modifier = Modifier.padding(bottom = 12.dp)
|
modifier = Modifier.padding(bottom = 12.dp)
|
||||||
)
|
)
|
||||||
AllDevicesOverview(modifier = Modifier.fillMaxSize())
|
AllDevicesOverview(modifier = Modifier.fillMaxWidth())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SpecificRoomContent(selectedRoom: Int, roomName: String) {
|
fun SpecificRoomContent(selectedRoom: Int, roomName: String) {
|
||||||
Column(modifier = Modifier.fillMaxSize()) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||||
AirConditionerCard(modifier = Modifier.weight(1f), roomName = roomName)
|
AirConditionerCard(modifier = Modifier.weight(1f), roomName = roomName)
|
||||||
UsageStatusChart(modifier = Modifier.weight(1f), roomName = roomName)
|
UsageStatusChart(modifier = Modifier.weight(1f), roomName = roomName)
|
||||||
@ -179,7 +188,7 @@ fun SpecificRoomContent(selectedRoom: Int, roomName: String) {
|
|||||||
color = Color.White,
|
color = Color.White,
|
||||||
modifier = Modifier.padding(bottom = 12.dp)
|
modifier = Modifier.padding(bottom = 12.dp)
|
||||||
)
|
)
|
||||||
MyDevicesGrid(selectedRoom = selectedRoom, modifier = Modifier.fillMaxSize())
|
MyDevicesGrid(selectedRoom = selectedRoom, modifier = Modifier.fillMaxWidth())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,13 +202,11 @@ fun AllDevicesOverview(modifier: Modifier = Modifier) {
|
|||||||
Device("影音室电视", "运行中", R.drawable.ic_media, true),
|
Device("影音室电视", "运行中", R.drawable.ic_media, true),
|
||||||
Device("游戏房主机", "待机中", R.drawable.ic_media, false)
|
Device("游戏房主机", "待机中", R.drawable.ic_media, false)
|
||||||
)
|
)
|
||||||
LazyVerticalGrid(
|
Column(
|
||||||
columns = GridCells.Adaptive(minSize = 140.dp),
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
||||||
) {
|
) {
|
||||||
items(allDevices) { d -> DeviceCard(d) }
|
allDevices.forEach { d -> DeviceCard(d) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,29 +446,105 @@ fun DeviceGrid() {
|
|||||||
data class Device(val name: String, val sub: String, val icon: Int, val on: Boolean)
|
data class Device(val name: String, val sub: String, val icon: Int, val on: Boolean)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DeviceCard(d: Device) {
|
fun DeviceCard(d: Device, roomName: String = "") {
|
||||||
var active by remember { mutableStateOf(d.on) }
|
var active by remember { mutableStateOf(d.on) }
|
||||||
|
val accentColor = if (active) Color(0xFFFFB74D) else Color(0xFF5A5A6E)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(Color(0x40121212))
|
||||||
|
.padding(12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
// 左侧图标
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(120.dp)
|
.size(48.dp)
|
||||||
.clip(RoundedCornerShape(24.dp))
|
.clip(RoundedCornerShape(12.dp))
|
||||||
.background(Color(0x50121212))
|
.background(accentColor.copy(alpha = if (active) 0.3f else 0.15f)),
|
||||||
.padding(16.dp)
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
Image(
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
painter = painterResource(id = d.icon),
|
||||||
Image(painter = painterResource(id = d.icon), contentDescription = null, modifier = Modifier.size(40.dp))
|
contentDescription = null,
|
||||||
Column {
|
modifier = Modifier.size(28.dp),
|
||||||
Text(text = d.name, fontWeight = FontWeight.SemiBold)
|
colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
if (active) accentColor else Color(0xFF9AA0A6)
|
||||||
Box(modifier = Modifier.size(8.dp).clip(RoundedCornerShape(4.dp)).background(if (active) Color(0xFF00E676) else Color(0xFF9AA0A6)))
|
)
|
||||||
Text(text = d.sub, color = Color(0xFF9AA0A6))
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 中间文字
|
||||||
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
Text(
|
||||||
|
text = if (roomName.isNotEmpty()) "$roomName ${d.name}" else d.name,
|
||||||
|
fontWeight = FontWeight.SemiBold,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 15.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = d.sub,
|
||||||
|
color = if (active) Color(0xFF00E676) else Color(0xFF9AA0A6),
|
||||||
|
fontSize = 13.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧控制 - 根据设备类型显示不同控制方式
|
||||||
|
val isLight = d.icon == R.drawable.ic_light || d.name.contains("灯")
|
||||||
|
val isAC = d.icon == R.drawable.ic_ac || d.name.contains("空调")
|
||||||
|
val isCurtain = d.icon == R.drawable.ic_curtain || d.name.contains("窗帘")
|
||||||
|
|
||||||
|
when {
|
||||||
|
isLight -> {
|
||||||
|
// 灯光:亮度调节点
|
||||||
|
Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||||
|
val brightnessLevel = d.sub.replace("%", "").toIntOrNull()?.let { it / 20 } ?: 4
|
||||||
|
repeat(6) { index ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(10.dp)
|
||||||
|
.clip(RoundedCornerShape(5.dp))
|
||||||
|
.background(
|
||||||
|
if (active && index < brightnessLevel) Color(0xFF00D1FF)
|
||||||
|
else Color(0xFF00D1FF).copy(alpha = 0.3f)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
isAC -> {
|
||||||
Text(text = if (active) "运行中" else "待机中", color = if (active) Color(0xFF00E676) else Color(0xFF9AA0A6))
|
// 空调:显示温度
|
||||||
Toggle(active) { active = it }
|
Text(
|
||||||
|
text = d.sub,
|
||||||
|
color = if (active) Color(0xFF00D1FF) else Color(0xFF9AA0A6),
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
isCurtain -> {
|
||||||
|
// 窗帘:开关状态图标
|
||||||
|
Text(
|
||||||
|
text = if (active) "▼" else "▲",
|
||||||
|
color = if (active) Color(0xFF00E676) else Color(0xFF9AA0A6),
|
||||||
|
fontSize = 18.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// 其他设备:开关按钮
|
||||||
|
Switch(
|
||||||
|
checked = active,
|
||||||
|
onCheckedChange = { active = it },
|
||||||
|
colors = SwitchDefaults.colors(
|
||||||
|
checkedThumbColor = Color.White,
|
||||||
|
checkedTrackColor = Color(0xFF00D1FF),
|
||||||
|
uncheckedThumbColor = Color.Gray,
|
||||||
|
uncheckedTrackColor = Color(0xFF3A3A4E)
|
||||||
|
),
|
||||||
|
modifier = Modifier.scale(0.8f)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -949,29 +1032,71 @@ fun MyDevicesGrid(selectedRoom: Int, modifier: Modifier = Modifier) {
|
|||||||
)
|
)
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
LazyVerticalGrid(
|
Column(
|
||||||
columns = GridCells.Adaptive(minSize = 140.dp),
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
||||||
) {
|
) {
|
||||||
items(devices) { d -> DeviceCard(d) }
|
devices.forEach { d -> DeviceCard(d) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 各房间的固定能耗数据 (用电量kWh, 运行时长h, 设备数, 趋势, 趋势百分比, 费用, 峰值功率W)
|
||||||
|
private val roomEnergyData = mapOf(
|
||||||
|
"客厅" to RoomEnergy(3.2, 8, 6, "↑", 8, 1.8, 320),
|
||||||
|
"厨房" to RoomEnergy(2.1, 4, 4, "↓", 12, 1.2, 1800),
|
||||||
|
"卧室" to RoomEnergy(1.5, 6, 5, "↓", 5, 0.9, 180),
|
||||||
|
"影音室" to RoomEnergy(2.8, 5, 6, "↑", 15, 1.6, 450),
|
||||||
|
"游戏房" to RoomEnergy(3.5, 7, 5, "↑", 18, 2.0, 380)
|
||||||
|
)
|
||||||
|
|
||||||
|
private data class RoomEnergy(
|
||||||
|
val power: Double, // 今日用电量 kWh
|
||||||
|
val hours: Int, // 今日运行时长 h
|
||||||
|
val devices: Int, // 活跃设备数
|
||||||
|
val trend: String, // 趋势方向
|
||||||
|
val trendPercent: Int, // 趋势百分比
|
||||||
|
val cost: Double, // 今日费用 元
|
||||||
|
val peakWatt: Int // 峰值功率 W
|
||||||
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UsageStatusChart(modifier: Modifier = Modifier, roomName: String = "房间") {
|
fun UsageStatusChart(modifier: Modifier = Modifier, roomName: String = "房间") {
|
||||||
// 根据房间生成不同的数据
|
// 判断是否为总览
|
||||||
|
val isOverview = roomName == tr("room_all") || roomName == "总览" || roomName == "全部"
|
||||||
|
|
||||||
|
// 根据房间获取数据,总览时汇总所有房间
|
||||||
|
val roomData = if (isOverview) {
|
||||||
|
// 汇总所有房间数据
|
||||||
|
val allRooms = roomEnergyData.values.toList()
|
||||||
|
RoomEnergy(
|
||||||
|
power = allRooms.sumOf { it.power },
|
||||||
|
hours = allRooms.maxOf { it.hours }, // 取最长运行时间(今日已过时间)
|
||||||
|
devices = allRooms.sumOf { it.devices },
|
||||||
|
trend = if (allRooms.count { it.trend == "↑" } > allRooms.size / 2) "↑" else "↓",
|
||||||
|
trendPercent = allRooms.map { it.trendPercent }.average().toInt(),
|
||||||
|
cost = allRooms.sumOf { it.cost },
|
||||||
|
peakWatt = allRooms.maxOf { it.peakWatt } // 取最大峰值
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
roomEnergyData[roomName] ?: RoomEnergy(2.0, 5, 4, "↓", 8, 1.2, 200)
|
||||||
|
}
|
||||||
|
|
||||||
val values = remember(roomName) {
|
val values = remember(roomName) {
|
||||||
|
if (isOverview) {
|
||||||
|
// 总览:生成更高的数值
|
||||||
|
List(12) { (40..90).random().toFloat() }
|
||||||
|
} else {
|
||||||
List(12) { (15..45).random().toFloat() }
|
List(12) { (15..45).random().toFloat() }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
val maxValue = remember(values) { values.maxOrNull() ?: 45f }
|
val maxValue = remember(values) { values.maxOrNull() ?: 45f }
|
||||||
val totalPower = remember(roomName) { (15.0 + Math.random() * 30).toString().take(4) }
|
val totalPower = String.format("%.1f", roomData.power)
|
||||||
val totalHours = remember(roomName) { (10 + (Math.random() * 40).toInt()) }
|
val totalHours = roomData.hours
|
||||||
val activeDevices = remember(roomName) { (3 + (Math.random() * 8).toInt()) }
|
val activeDevices = roomData.devices
|
||||||
val trend = remember(roomName) { if (Math.random() > 0.5) "↑" else "↓" }
|
val trend = roomData.trend
|
||||||
val trendPercent = remember(roomName) { (5 + (Math.random() * 15).toInt()) }
|
val trendPercent = roomData.trendPercent
|
||||||
val costToday = remember(roomName) { String.format("%.1f", 2 + Math.random() * 8) }
|
val costToday = String.format("%.1f", roomData.cost)
|
||||||
|
val peakWatt = roomData.peakWatt
|
||||||
|
|
||||||
// 主题色
|
// 主题色
|
||||||
val accentColor = Color(0xFF00D1FF)
|
val accentColor = Color(0xFF00D1FF)
|
||||||
@ -1139,7 +1264,7 @@ fun UsageStatusChart(modifier: Modifier = Modifier, roomName: String = "房间")
|
|||||||
// 峰值功率
|
// 峰值功率
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Text(
|
Text(
|
||||||
text = "${(800 + (Math.random() * 400).toInt())}",
|
text = "$peakWatt",
|
||||||
color = Color(0xFFFFB74D),
|
color = Color(0xFFFFB74D),
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
@ -1623,12 +1748,8 @@ enum class Mode { HOME, AWAY, FUN }
|
|||||||
@Composable
|
@Composable
|
||||||
fun ModeButtonsRow(onModeSelected: (Mode) -> Unit) {
|
fun ModeButtonsRow(onModeSelected: (Mode) -> Unit) {
|
||||||
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
|
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
|
||||||
val density = LocalDensity.current
|
// 固定高度,确保在滚动前完全显示
|
||||||
val buttonHeight = when {
|
val buttonHeight = 100.dp
|
||||||
maxWidth >= 1024.dp -> with(density) { 500f.toDp() }
|
|
||||||
maxWidth >= 600.dp -> with(density) { 460f.toDp() }
|
|
||||||
else -> with(density) { 160f.toDp() }
|
|
||||||
}
|
|
||||||
|
|
||||||
var selected by remember { mutableStateOf<Mode?>(null) }
|
var selected by remember { mutableStateOf<Mode?>(null) }
|
||||||
|
|
||||||
@ -1876,7 +1997,7 @@ fun LightRow(modifier: Modifier = Modifier, roomName: String = "房间") {
|
|||||||
fun LightCard(name: String, percent: Float, modifier: Modifier = Modifier) {
|
fun LightCard(name: String, percent: Float, modifier: Modifier = Modifier) {
|
||||||
var brightness by remember { mutableStateOf(percent) }
|
var brightness by remember { mutableStateOf(percent) }
|
||||||
|
|
||||||
Box(modifier = modifier.height(100.dp).clip(RoundedCornerShape(16.dp)).background(Color(0x50121212)).padding(12.dp)) {
|
Box(modifier = modifier.height(72.dp).clip(RoundedCornerShape(16.dp)).background(Color(0x50121212)).padding(horizontal = 12.dp, vertical = 8.dp)) {
|
||||||
Row(horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
|
Row(horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
|
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
// 灯光图标 - 带发光效果
|
// 灯光图标 - 带发光效果
|
||||||
@ -2080,7 +2201,13 @@ fun AddRoomDialog(
|
|||||||
onConfirm: (String) -> Unit
|
onConfirm: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
var roomName by remember { mutableStateOf("") }
|
var roomName by remember { mutableStateOf("") }
|
||||||
|
var selectedIcon by remember { mutableStateOf(0) }
|
||||||
|
|
||||||
|
// 预设房间图标
|
||||||
|
val roomIcons = listOf("🛋️", "🍳", "🛏️", "🎬", "🎮", "📚", "🛁", "🌿")
|
||||||
|
val roomSuggestions = listOf("书房", "阳台", "浴室", "储物间", "健身房", "儿童房")
|
||||||
|
|
||||||
|
// 背景遮罩(点击关闭)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@ -2090,94 +2217,282 @@ fun AddRoomDialog(
|
|||||||
) { onDismiss() },
|
) { onDismiss() },
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
|
// 对话框主体
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(400.dp)
|
.width(420.dp)
|
||||||
.clip(RoundedCornerShape(24.dp))
|
.clip(RoundedCornerShape(28.dp))
|
||||||
.background(Color(0xFF1E1E1E))
|
.background(
|
||||||
|
Brush.verticalGradient(
|
||||||
|
listOf(
|
||||||
|
Color(0xFF2A2A3E),
|
||||||
|
Color(0xFF1A1A2E)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
brush = Brush.linearGradient(
|
||||||
|
listOf(Color(0xFF00D1FF).copy(alpha = 0.3f), Color(0xFFB89CFF).copy(alpha = 0.3f))
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(28.dp)
|
||||||
|
)
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
) { /* 阻止点击穿透 */ }
|
) { /* 阻止点击穿透 */ }
|
||||||
.padding(24.dp)
|
.padding(28.dp)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(20.dp)
|
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||||
) {
|
) {
|
||||||
|
// 标题区域
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
// 图标
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(44.dp)
|
||||||
|
.clip(RoundedCornerShape(12.dp))
|
||||||
|
.background(
|
||||||
|
Brush.linearGradient(
|
||||||
|
listOf(Color(0xFF00D1FF).copy(alpha = 0.3f), Color(0xFFB89CFF).copy(alpha = 0.3f))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "🏠", fontSize = 22.sp)
|
||||||
|
}
|
||||||
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = "添加房间",
|
text = "添加新房间",
|
||||||
fontSize = 20.sp,
|
fontSize = 20.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = Color.White
|
color = Color.White
|
||||||
)
|
)
|
||||||
|
Text(
|
||||||
|
text = "创建一个新的智能空间",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = Color(0xFF9AA0A6)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(32.dp)
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(Color(0x33FFFFFF))
|
||||||
|
.clickable { onDismiss() },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = "✕", color = Color(0xFF9AA0A6), fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 房间名称输入
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "房间名称",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color(0xFFB0B0B0)
|
||||||
|
)
|
||||||
androidx.compose.material3.TextField(
|
androidx.compose.material3.TextField(
|
||||||
value = roomName,
|
value = roomName,
|
||||||
onValueChange = { roomName = it },
|
onValueChange = { roomName = it },
|
||||||
placeholder = { Text("请输入房间名称", color = Color(0xFF9AA0A6)) },
|
placeholder = { Text("例如:书房、阳台...", color = Color(0xFF6A6A7A)) },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(56.dp),
|
||||||
colors = androidx.compose.material3.TextFieldDefaults.colors(
|
colors = androidx.compose.material3.TextFieldDefaults.colors(
|
||||||
focusedContainerColor = Color(0x55FFFFFF),
|
focusedContainerColor = Color(0xFF1A1A2E),
|
||||||
unfocusedContainerColor = Color(0x55FFFFFF),
|
unfocusedContainerColor = Color(0xFF1A1A2E),
|
||||||
focusedTextColor = Color.White,
|
focusedTextColor = Color.White,
|
||||||
unfocusedTextColor = Color.White,
|
unfocusedTextColor = Color.White,
|
||||||
cursorColor = Color(0xFFA9F0FF),
|
cursorColor = Color(0xFF00D1FF),
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
),
|
),
|
||||||
shape = RoundedCornerShape(12.dp),
|
shape = RoundedCornerShape(14.dp),
|
||||||
singleLine = true
|
singleLine = true,
|
||||||
|
textStyle = androidx.compose.ui.text.TextStyle(fontSize = 16.sp)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 快速选择建议
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "快速选择",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color(0xFFB0B0B0)
|
||||||
|
)
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
roomSuggestions.take(3).forEach { suggestion ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(20.dp))
|
||||||
|
.background(
|
||||||
|
if (roomName == suggestion) Color(0xFF00D1FF).copy(alpha = 0.3f)
|
||||||
|
else Color(0xFF1A1A2E)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = if (roomName == suggestion) Color(0xFF00D1FF) else Color(0xFF3A3A4E),
|
||||||
|
shape = RoundedCornerShape(20.dp)
|
||||||
|
)
|
||||||
|
.clickable { roomName = suggestion }
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = suggestion,
|
||||||
|
color = if (roomName == suggestion) Color.White else Color(0xFF9AA0A6),
|
||||||
|
fontSize = 13.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
roomSuggestions.drop(3).forEach { suggestion ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(20.dp))
|
||||||
|
.background(
|
||||||
|
if (roomName == suggestion) Color(0xFF00D1FF).copy(alpha = 0.3f)
|
||||||
|
else Color(0xFF1A1A2E)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = if (roomName == suggestion) Color(0xFF00D1FF) else Color(0xFF3A3A4E),
|
||||||
|
shape = RoundedCornerShape(20.dp)
|
||||||
|
)
|
||||||
|
.clickable { roomName = suggestion }
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = suggestion,
|
||||||
|
color = if (roomName == suggestion) Color.White else Color(0xFF9AA0A6),
|
||||||
|
fontSize = 13.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择图标
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "选择图标",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = Color(0xFFB0B0B0)
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
|
) {
|
||||||
|
roomIcons.forEachIndexed { index, icon ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(44.dp)
|
||||||
|
.clip(RoundedCornerShape(12.dp))
|
||||||
|
.then(
|
||||||
|
if (selectedIcon == index)
|
||||||
|
Modifier.background(Brush.linearGradient(listOf(Color(0xFF00D1FF), Color(0xFFB89CFF))))
|
||||||
|
else Modifier.background(Color(0xFF1A1A2E))
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = if (selectedIcon == index) 0.dp else 1.dp,
|
||||||
|
color = Color(0xFF3A3A4E),
|
||||||
|
shape = RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
.clickable { selectedIcon = index },
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(text = icon, fontSize = 20.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按钮区域
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
|
// 取消按钮
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(48.dp)
|
.height(52.dp)
|
||||||
.clip(RoundedCornerShape(12.dp))
|
.clip(RoundedCornerShape(14.dp))
|
||||||
.background(Color(0x55FFFFFF))
|
.background(Color(0xFF1A1A2E))
|
||||||
.clickable(
|
.border(
|
||||||
indication = null,
|
width = 1.dp,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
color = Color(0xFF3A3A4E),
|
||||||
) { onDismiss() },
|
shape = RoundedCornerShape(14.dp)
|
||||||
|
)
|
||||||
|
.clickable { onDismiss() },
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "取消",
|
text = "取消",
|
||||||
color = Color(0xFFB0B0B0),
|
color = Color(0xFFB0B0B0),
|
||||||
fontWeight = FontWeight.Medium
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确定按钮
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(48.dp)
|
.height(52.dp)
|
||||||
.clip(RoundedCornerShape(12.dp))
|
.clip(RoundedCornerShape(14.dp))
|
||||||
.background(
|
.background(
|
||||||
Brush.linearGradient(
|
if (roomName.isNotBlank())
|
||||||
listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))
|
Brush.linearGradient(listOf(Color(0xFF00D1FF), Color(0xFFB89CFF)))
|
||||||
|
else
|
||||||
|
Brush.linearGradient(listOf(Color(0xFF3A3A4E), Color(0xFF3A3A4E)))
|
||||||
)
|
)
|
||||||
)
|
.clickable(enabled = roomName.isNotBlank()) {
|
||||||
.clickable(
|
|
||||||
indication = null,
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
enabled = roomName.isNotBlank()
|
|
||||||
) {
|
|
||||||
if (roomName.isNotBlank()) {
|
if (roomName.isNotBlank()) {
|
||||||
onConfirm(roomName.trim())
|
onConfirm(roomName.trim())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
.alpha(if (roomName.isNotBlank()) 1f else 0.5f),
|
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "确定",
|
text = "✓",
|
||||||
color = Color.Black,
|
color = if (roomName.isNotBlank()) Color.White else Color(0xFF6A6A7A),
|
||||||
fontWeight = FontWeight.Bold
|
fontSize = 16.sp
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "添加房间",
|
||||||
|
color = if (roomName.isNotBlank()) Color.White else Color(0xFF6A6A7A),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 15.sp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2185,3 +2500,4 @@ fun AddRoomDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user