首页显示优化

This commit is contained in:
mmc
2026-02-26 20:36:28 +08:00
parent d8f7b55868
commit ae34fbd094
3 changed files with 131 additions and 37 deletions

View File

@@ -16,11 +16,16 @@ class ImmersionHeader extends StatelessWidget {
final DeviceEntity device;
const ImmersionHeader({super.key, required this.device});
String _formatName(String name, {int keepLength = 20}) {
if (name.length <= keepLength) return name;
return name.substring(name.length - keepLength);
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: 380,
height: 310,
// 1. 修改这里:去掉 color: Colors.white,改用透明或背景色
decoration: const BoxDecoration(
color: Colors.transparent, // 设为透明,直接透出 Scaffold 的 offWhite
@@ -29,14 +34,14 @@ class ImmersionHeader extends StatelessWidget {
children: [
// 背景文字占位 (SataBot)
Positioned(
top: 140,
top: 130,
left: 0,
right: 0,
child: Text(
'SataBot',
textAlign: TextAlign.center,
style: GoogleFonts.roboto(
fontSize: 100,
fontSize: 80,
fontWeight: FontWeight.w900,
// 2. 既然背景变深了,背景字可以稍微再淡一点点
color: Colors.black.withOpacity(0.08),
@@ -46,11 +51,12 @@ class ImmersionHeader extends StatelessWidget {
// 机器大图
Transform.translate(
offset: const Offset(20, 90), // 正数向右移动(例如 20 像素),负数向左
offset: const Offset(30, 80), // 正数向右移动(例如 20 像素),负数向左
child: Center(
child: Image.asset(
'assets/images/car.png',
width: 380,
width: 330,
height: 190,
fit: BoxFit.contain,
),
),
@@ -73,7 +79,7 @@ class ImmersionHeader extends StatelessWidget {
children: [
// 设备名称和电量
Text(
device.displayName,
_formatName(device.displayName),
style: GoogleFonts.roboto(
fontSize: 22,
fontWeight: FontWeight.w900,

View File

@@ -2,33 +2,122 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
class MachineDetailsPage extends StatelessWidget {
final DeviceEntity? device; // 接收传过来的设备数据
class MachineDetailsPage extends StatefulWidget {
final DeviceEntity? device;
const MachineDetailsPage({super.key, this.device});
@override
Widget build(BuildContext context) {
// 把 device 参数传递给 DeviceDetailPage
return DeviceDetailPage(device: device);
}
State<MachineDetailsPage> createState() => _MachineDetailsPageState();
}
class DeviceDetailPage extends StatelessWidget {
final DeviceEntity? device; // 定义参数接收设备数据
class _MachineDetailsPageState extends State<MachineDetailsPage> {
late TextEditingController _nameController;
late String _deviceName;
// 构造函数接收 device 参数
const DeviceDetailPage({super.key, this.device});
@override
void initState() {
super.initState();
_deviceName = (widget.device?.deviceAlias?.trim().isEmpty ?? true)
? '未知设备'
: widget.device!.deviceAlias!;
_nameController = TextEditingController();
}
@override
void dispose() {
_nameController.dispose();
super.dispose();
}
/// 弹出修改设备名称底部抽屉
void _showEditNameSheet() {
_nameController.text = _deviceName;
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (ctx) {
return Padding(
padding: EdgeInsets.only(
left: 20,
right: 20,
top: 20,
bottom: MediaQuery.of(ctx).viewInsets.bottom + 20,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
"修改设备名称",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w600),
),
const SizedBox(height: 16),
TextField(
controller: _nameController,
autofocus: true,
maxLength: 20,
decoration: const InputDecoration(
hintText: "请输入设备名称",
border: OutlineInputBorder(),
),
),
const SizedBox(height: 10),
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () => Navigator.pop(ctx),
child: const Text("取消"),
),
),
const SizedBox(width: 12),
Expanded(
child: OutlinedButton(
onPressed: () {
final text = _nameController.text.trim();
if (text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("名称不能为空")),
);
return;
}
setState(() {
_deviceName = text;
});
Navigator.pop(ctx);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text("已修改为:$text")));
},
child: const Text("确认"),
),
),
],
),
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
// 空值校验:无设备数据时显示提示
if (device == null) {
if (widget.device == null) {
return const Scaffold(body: Center(child: Text("未获取到设备信息")));
}
// 非空断言:已经校验过 device 非空,放心使用
final currentDevice = device!;
final currentDevice = widget.device!;
return Scaffold(
backgroundColor: const Color(0xFFF5F5F5),
@@ -40,14 +129,14 @@ class DeviceDetailPage extends StatelessWidget {
),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () => Navigator.pop(context), // 正确返回上一页
onPressed: () => Navigator.pop(context),
),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
children: [
_buildDeviceStatusCard(currentDevice), // 传递设备数据
_buildDeviceStatusCard(currentDevice),
const SizedBox(height: 16),
_buildBasicInfoCard(context, currentDevice), // 传递context和设备数据
const SizedBox(height: 16),
@@ -60,7 +149,7 @@ class DeviceDetailPage extends StatelessWidget {
);
}
// 设备状态卡片(接收设备数据参数)
/// 设备状态卡片
Widget _buildDeviceStatusCard(DeviceEntity device) {
return Container(
padding: const EdgeInsets.all(24),
@@ -70,9 +159,8 @@ class DeviceDetailPage extends StatelessWidget {
),
child: Column(
children: [
Image.asset('assets/images/car.png', width: 380, fit: BoxFit.contain),
Image.asset('assets/images/car.png', width: 300, fit: BoxFit.contain),
const SizedBox(height: 12),
// 使用设备真实在线状态
Text(
device.isOnline ? '在线' : '离线',
style: TextStyle(
@@ -95,9 +183,7 @@ class DeviceDetailPage extends StatelessWidget {
: device.deviceAlias!;
// 处理设备ID(空值兜底)
final deviceId = device.deviceName ?? '未知ID';
//print('激活时间:$device'); // 调试输出激活时间
//final activeTime = device.activeTime != null ? device.activeTime : '未知时间';
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
@@ -119,16 +205,18 @@ class DeviceDetailPage extends StatelessWidget {
context: context, // 关键:补上必填的context参数
icon: Icons.info_outline,
label: '设备名称',
trailing: Row(
mainAxisSize: MainAxisSize.min, // 防止Row撑满宽度
trailing: GestureDetector(
onTap: _showEditNameSheet,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// 显示真实设备名称
Text(deviceName),
Text(_deviceName),
const SizedBox(width: 8),
const Icon(Icons.edit, size: 16, color: Color(0xFF007AFF)),
],
),
),
),
const Divider(height: 32, color: Color(0xFFF0F0F0)),
// 设备ID行 - 传递context参数
// 设备ID行 - 传递context参数
@@ -294,7 +382,7 @@ class DeviceDetailPage extends StatelessWidget {
context: context,
builder: (dialogContext) => AlertDialog(
title: const Text('确认解绑'),
content: Text('确定要解绑【${device?.deviceAlias ?? '该设备'}】吗?'),
content: Text('确定要解绑【${_deviceName ?? '该设备'}】吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(dialogContext),

View File

@@ -15,7 +15,7 @@ class MainWrapper extends StatelessWidget {
extendBody: true, // 必须开启,让内容流过导航栏下方
body: navigationShell,
bottomNavigationBar: Container(
margin: const EdgeInsets.fromLTRB(20, 0, 20, 32), // 稍微调高底部间距
margin: const EdgeInsets.fromLTRB(20, 0, 20, 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32),
boxShadow: [