Browse Source

上传移动cmei码显示

newdev_shunjiawei
liwei1dao 7 months ago
parent
commit
6ac8b2a9c3
  1. 4
      lib/data/models/user_Info.dart
  2. 571
      lib/modules/devices/views/devices_view.dart
  3. 0
      preview/yidong.html

4
lib/data/models/user_Info.dart

@ -217,6 +217,7 @@ class UserDevice {
String devicename;
String devicemac;
String license;
String cmei;
UserDevice({
required this.id,
required this.uid,
@ -225,6 +226,7 @@ class UserDevice {
required this.devicename,
required this.devicemac,
required this.license,
this.cmei = '',
});
factory UserDevice.fromJson(Map<String, dynamic> json) => UserDevice(
@ -235,6 +237,7 @@ class UserDevice {
devicename: json['devicename'] as String,
devicemac: json['devicemac'] as String,
license: json['license'] as String,
cmei: json['cmei'] as String? ?? '',
);
toJson() => {
@ -245,5 +248,6 @@ class UserDevice {
'devicename': devicename,
'devicemac': devicemac,
'license': license,
'cmei': cmei,
};
}

571
lib/modules/devices/views/devices_view.dart

@ -1,12 +1,10 @@
import 'dart:ui';
import '../../../routes/app_routes.dart';
import '/modules/devices/controllers/devices_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import '/core/theme/app_colors.dart';
import '/data/models/user_Info.dart';
import '/data/services/ble_manager.dart';
import '../controllers/devices_controller.dart';
// 设备类型枚举
@ -20,7 +18,6 @@ enum DeviceType {
const DeviceType(this.value);
final int value;
// 使用getter获取多语言显示名称
String get displayName {
switch (this) {
case DeviceType.Unknown:
@ -61,112 +58,240 @@ enum DeviceType {
class DevicesView extends GetView<DevicesController> {
const DevicesView({super.key});
bool _isConnected(UserDevice device) {
try {
final bleManager = Get.find<BleManager>();
return bleManager.currentDeviceAddress != null &&
bleManager.currentDeviceAddress == device.devicemac;
} catch (_) {
return false;
}
}
@override
Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
final isDark = Theme.of(context).brightness == Brightness.dark;
final bg = isDark ? const Color(0xFF0A0A0F) : const Color(0xFFF5F6FA);
final topBg = isDark ? const Color(0xFF0F1018) : const Color(0xFFF0F1F6);
return Scaffold(
backgroundColor: isDarkMode ? AppColors.darkBackground : Colors.white,
backgroundColor: bg,
body: Column(
children: [
// 顶部标题栏
Container(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top + 10.h,
left: 20.w,
right: 20.w,
bottom: 20.h,
),
decoration: BoxDecoration(
color: isDarkMode ? Colors.black : Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Row(
children: [
GestureDetector(
onTap: () => Get.back(),
// 顶部区域
_buildTopArea(context, isDark, bg, topBg),
// 设备列表
Expanded(child: _buildDevicesList(isDark, topBg)),
],
),
);
}
Widget _buildTopArea(
BuildContext context, bool isDark, Color bg, Color topBg) {
return Container(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top + 8.h,
left: 20.w,
right: 20.w,
bottom: 24.h,
),
decoration: BoxDecoration(color: bg),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 导航栏
Row(
children: [
GestureDetector(
onTap: () => Get.back(),
child: Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isDark
? Colors.white.withOpacity(0.06)
: Colors.black.withOpacity(0.04),
),
child: Icon(
Icons.arrow_back_ios,
color: isDarkMode ? Colors.white : Colors.black,
size: 24.sp,
Icons.arrow_back_ios_new,
size: 18.sp,
color: isDark ? Colors.white : const Color(0xFF222222),
),
),
SizedBox(width: 16.w),
Text(
"deviceManagement".tr,
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
),
),
SizedBox(width: 16.w),
Text(
"deviceManagement".tr,
style: TextStyle(
fontSize: 26.sp,
fontWeight: FontWeight.w800,
color: isDark ? Colors.white : const Color(0xFF111111),
letterSpacing: -0.5,
),
],
),
),
// 设备列表内容
Expanded(
child: _buildDevicesList(isDarkMode),
),
],
),
SizedBox(height: 20.h),
// 摘要卡片
Obx(() {
final totalDevices = controller.devices.values
.fold<int>(0, (sum, list) => sum + list.length);
final connectedCount = controller.devices.values
.expand((list) => list)
.where((d) => _isConnected(d))
.length;
return Row(
children: [
_buildSummaryCard(
number: totalDevices.toString(),
label: "boundDevices".tr,
isActive: true,
isDark: isDark,
),
SizedBox(width: 12.w),
_buildSummaryCard(
number: connectedCount.toString(),
label: "currentConnection".tr,
isActive: false,
isDark: isDark,
),
],
);
}),
],
),
);
}
Widget _buildDevicesList(bool isDarkMode) {
Widget _buildSummaryCard({
required String number,
required String label,
required bool isActive,
required bool isDark,
}) {
final activeGradient = isDark
? [
const Color(0xFF6366F1).withOpacity(0.15),
const Color(0xFF8B5CF6).withOpacity(0.1),
]
: [const Color(0xFFEEF2FF), const Color(0xFFF5F3FF)];
return Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
gradient: isActive ? LinearGradient(colors: activeGradient) : null,
color: isActive
? null
: (isDark
? Colors.white.withOpacity(0.04)
: Colors.white),
border: Border.all(
color: isActive
? (isDark
? const Color(0xFF6366F1).withOpacity(0.2)
: const Color(0xFF6366F1).withOpacity(0.15))
: (isDark
? Colors.white.withOpacity(0.06)
: Colors.black.withOpacity(0.04)),
),
boxShadow: isDark
? null
: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 4,
offset: const Offset(0, 1),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
number,
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.w700,
color: isActive
? (isDark
? const Color(0xFFA5B4FC)
: const Color(0xFF6366F1))
: (isDark ? Colors.white : const Color(0xFF222222)),
),
),
SizedBox(height: 2.h),
Text(
label,
style: TextStyle(
fontSize: 11.sp,
fontWeight: FontWeight.w500,
color: isActive
? (isDark
? const Color(0xFFA5B4FC).withOpacity(0.6)
: const Color(0xFF818CF8))
: (isDark
? Colors.white.withOpacity(0.35)
: const Color(0xFF999999)),
),
),
],
),
),
);
}
Widget _buildDevicesList(bool isDark, Color topBg) {
return Obx(() {
// 使用控制器的响应式数据,这会触发控制器的实例化
final groupedDevices = controller.devices;
if (groupedDevices.isEmpty) {
return _buildEmptyState(isDarkMode);
return _buildEmptyState(isDark);
}
return ListView(
padding: EdgeInsets.all(20.w),
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
children: [
// 遍历每个设备类型
...groupedDevices.entries.map((entry) {
final deviceTypeValue = entry.key;
final deviceType = DeviceType.fromValue(entry.key);
final deviceList = entry.value;
final deviceType = DeviceType.fromValue(deviceTypeValue);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 设备类型标题
// 分类标题
Padding(
padding: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.only(left: 8.w, bottom: 12.h),
child: Text(
deviceType.displayName,
deviceType.displayName.toUpperCase(),
style: TextStyle(
fontSize: 16.sp,
fontSize: 12.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
color: isDark
? Colors.white.withOpacity(0.25)
: const Color(0xFFAAAAAA),
letterSpacing: 1.5,
),
),
),
// 该类型下的设备列表
...deviceList.map((device) => _buildDeviceCard(
device: device,
deviceType: deviceType,
isDarkMode: isDarkMode,
isDark: isDark,
)),
SizedBox(height: 20.h),
SizedBox(height: 16.h),
],
);
}).toList(),
}),
],
);
});
}
Widget _buildEmptyState(bool isDarkMode) {
Widget _buildEmptyState(bool isDark) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
@ -174,14 +299,14 @@ class DevicesView extends GetView<DevicesController> {
Icon(
Icons.devices_other,
size: 80.sp,
color: isDarkMode ? Colors.white54 : Colors.grey[400],
color: isDark ? Colors.white54 : Colors.grey[400],
),
SizedBox(height: 20.h),
Text(
"noDevicesBound".tr,
style: TextStyle(
fontSize: 16.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
color: isDark ? Colors.white70 : Colors.grey[600],
),
),
SizedBox(height: 12.h),
@ -189,7 +314,7 @@ class DevicesView extends GetView<DevicesController> {
"pleaseBindDeviceFirst".tr,
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.white54 : Colors.grey[500],
color: isDark ? Colors.white54 : Colors.grey[500],
),
),
],
@ -200,121 +325,263 @@ class DevicesView extends GetView<DevicesController> {
Widget _buildDeviceCard({
required UserDevice device,
required DeviceType deviceType,
required bool isDarkMode,
required bool isDark,
}) {
final connected = _isConnected(device);
final connectedColor = const Color(0xFF22C55E);
return GestureDetector(
onTap: () => Get.toNamed(Routes.eqSettings),
child: Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(16.w),
margin: EdgeInsets.only(bottom: 10.h),
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
color: isDarkMode ? AppColors.cardBackground : Colors.white,
borderRadius: BorderRadius.circular(12.r),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
borderRadius: BorderRadius.circular(20.r),
color: isDark
? (connected
? connectedColor.withOpacity(0.04)
: Colors.white.withOpacity(0.03))
: (connected
? connectedColor.withOpacity(0.03)
: Colors.white),
border: Border.all(
color: connected
? connectedColor.withOpacity(0.2)
: (isDark
? Colors.white.withOpacity(0.05)
: Colors.black.withOpacity(0.04)),
),
boxShadow: isDark
? null
: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 12,
offset: const Offset(0, 2),
),
],
),
child: Row(
child: Column(
children: [
// 设备图标
Container(
width: 48.w,
height: 48.w,
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[100],
borderRadius: BorderRadius.circular(12.r),
),
child: Icon(
deviceType.icon,
color: isDarkMode ? Colors.white : Colors.black87,
size: 24.sp,
),
),
SizedBox(width: 16.w),
// 设备信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
device.devicename.isNotEmpty
? device.devicename
: "deviceTypeUnknown".tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black87,
// 上部:图标 + 名称/MAC + 解绑
Row(
children: [
// 设备图标
Container(
width: 46.w,
height: 46.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.r),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: connected
? [connectedColor, const Color(0xFF16A34A)]
: [const Color(0xFF6366F1), const Color(0xFF8B5CF6)],
),
boxShadow: [
BoxShadow(
color: (connected ? connectedColor : const Color(0xFF6366F1))
.withOpacity(0.3),
blurRadius: 16,
offset: const Offset(0, 4),
),
],
),
SizedBox(height: 4.h),
Text(
device.devicemac.isNotEmpty
? device.devicemac
: "noMacAddress".tr,
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.white70 : Colors.grey[600],
),
child: Icon(
deviceType.icon,
color: Colors.white,
size: 22.sp,
),
if (device.license.isNotEmpty) ...[
SizedBox(height: 4.h),
Text(
"${"licenseCode".tr}: ${device.license}",
),
SizedBox(width: 14.w),
// 设备名 + MAC
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
device.devicename.isNotEmpty
? device.devicename
: "deviceTypeUnknown".tr,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w700,
color: isDark
? Colors.white
: const Color(0xFF1A1A2E),
),
),
if (connected) ...[
SizedBox(width: 8.w),
Container(
width: 6.w,
height: 6.w,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: connectedColor,
boxShadow: [
BoxShadow(
color: connectedColor.withOpacity(0.6),
blurRadius: 8,
),
],
),
),
SizedBox(width: 6.w),
Container(
padding: EdgeInsets.symmetric(
horizontal: 8.w, vertical: 3.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: connectedColor.withOpacity(0.1),
),
child: Text(
"connected".tr,
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.w600,
color: connectedColor,
),
),
),
],
],
),
SizedBox(height: 3.h),
Text(
device.devicemac.isNotEmpty
? device.devicemac
: "noMacAddress".tr,
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: isDark
? Colors.white.withOpacity(0.3)
: const Color(0xFF999999),
fontFamily: 'Menlo',
letterSpacing: 0.5,
),
),
],
),
),
// 解绑按钮
GestureDetector(
onTap: () => _showUnbindDialog(device, isDark),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 14.w, vertical: 8.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
border: Border.all(
color: isDark
? Colors.white.withOpacity(0.08)
: Colors.black.withOpacity(0.08),
),
),
child: Text(
"unbind".tr,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.white54 : Colors.grey[500],
fontWeight: FontWeight.w600,
color: isDark
? Colors.white.withOpacity(0.4)
: const Color(0xFF999999),
),
),
],
],
),
),
// 解绑按钮
GestureDetector(
onTap: () => _showUnbindDialog(device, isDarkMode),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 12.w,
vertical: 6.h,
),
),
],
),
// 下部:授权码 / CMEI
if (device.license.isNotEmpty || device.cmei.isNotEmpty) ...[
SizedBox(height: 16.h),
Container(
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(6.r),
border: Border.all(
color: Colors.red.withOpacity(0.3),
width: 1,
),
borderRadius: BorderRadius.circular(12.r),
color: isDark
? Colors.white.withOpacity(0.03)
: const Color(0xFFF7F7FA),
),
child: Text(
"unbind".tr,
style: TextStyle(
fontSize: 12.sp,
color: Colors.red,
fontWeight: FontWeight.w500,
),
child: Column(
children: [
if (device.license.isNotEmpty)
_buildFieldRow(
label: "licenseCode".tr,
value: device.license,
isDark: isDark,
),
if (device.license.isNotEmpty && device.cmei.isNotEmpty)
SizedBox(height: 8.h),
if (device.cmei.isNotEmpty)
_buildFieldRow(
label: "CMEI",
value: device.cmei,
isDark: isDark,
),
],
),
),
),
],
],
),
),
);
}
void _showUnbindDialog(UserDevice device, bool isDarkMode) {
Widget _buildFieldRow({
required String label,
required String value,
required bool isDark,
}) {
return Row(
children: [
SizedBox(
width: 44.w,
child: Text(
label,
style: TextStyle(
fontSize: 10.sp,
fontWeight: FontWeight.w600,
color: isDark
? Colors.white.withOpacity(0.2)
: const Color(0xFFBBBBBB),
letterSpacing: 0.5,
),
),
),
SizedBox(width: 8.w),
Expanded(
child: Text(
value,
style: TextStyle(
fontSize: 11.sp,
fontWeight: FontWeight.w500,
color: isDark
? Colors.white.withOpacity(0.5)
: const Color(0xFF666666),
fontFamily: 'Menlo',
letterSpacing: 0.3,
),
overflow: TextOverflow.ellipsis,
),
),
],
);
}
void _showUnbindDialog(UserDevice device, bool isDark) {
Get.dialog(
AlertDialog(
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
backgroundColor: isDark ? AppColors.cardBackground : Colors.white,
title: Text(
"confirmUnbind".tr,
style: TextStyle(
color: isDarkMode ? Colors.white : Colors.black87,
color: isDark ? Colors.white : Colors.black87,
),
),
content: Text(
@ -322,7 +589,7 @@ class DevicesView extends GetView<DevicesController> {
.tr
.replaceAll('{deviceName}', device.devicename),
style: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.black54,
color: isDark ? Colors.white70 : Colors.black54,
),
),
actions: [
@ -331,7 +598,7 @@ class DevicesView extends GetView<DevicesController> {
child: Text(
"cancel".tr,
style: TextStyle(
color: isDarkMode ? Colors.white70 : Colors.grey[600],
color: isDark ? Colors.white70 : Colors.grey[600],
),
),
),

0
ui/yidong.html → preview/yidong.html

Loading…
Cancel
Save