You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

727 lines
23 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../controllers/home_controller.dart';
import '../../../core/routes/app_pages.dart';
import '../../../core/routes/app_routes.dart';
import '../../../core/widgets/common_bottom_nav.dart';
// 导入枚举
import '../controllers/home_controller.dart' show ConnectionStatus;
// 呼吸光动画组件
class AnimatedPulsing extends StatefulWidget {
@override
_AnimatedPulsingState createState() => _AnimatedPulsingState();
}
class _AnimatedPulsingState extends State<AnimatedPulsing> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
_animation = Tween<double>(begin: 0.5, end: 0.8).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Opacity(
opacity: _animation.value,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
gradient: RadialGradient(
colors: [
Colors.white.withOpacity(0.3),
Colors.transparent,
],
center: Alignment.topRight,
radius: 0.8,
stops: [0.0, 1.0],
),
),
),
);
},
);
}
}
class HomeView extends GetView<HomeController> {
const HomeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFF9FAFC),
appBar: AppBar(
elevation: 0,
backgroundColor: Color(0xFFF9FAFC),
title: Text(
'智能耳机',
style: TextStyle(
color: Colors.black87,
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
),
actions: [
IconButton(
icon: Icon(Icons.settings_outlined, color: Colors.black54),
onPressed: () {
Get.toNamed(Routes.settings);
},
),
],
),
body: SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 顶部图片
Center(
child: _buildEarbudsImage(),
),
SizedBox(height: 20.h),
// 设备状态卡片
_buildDeviceStatusCard(),
SizedBox(height: 20.h),
// 热门AI体验
Row(
children: [
Text(
'热门AI体验',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(width: 8.w),
Icon(
Icons.star,
color: Colors.amber,
size: 20.w,
),
],
),
SizedBox(height: 16.h),
_buildPremiumAILayout(),
],
),
),
),
bottomNavigationBar: const CommonBottomNav(currentIndex: 0),
);
}
// 页面顶部:状态栏和标题
Widget _buildHeader() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
child: Column(
children: [
// 删除状态栏
// 标题区域
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'DeepVoice Pro',
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
),
),
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
color: Colors.grey[200],
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: IconButton(
icon: Icon(Icons.more_horiz, size: 16.sp, color: Colors.grey[600]),
padding: EdgeInsets.zero,
onPressed: () {
// 打开更多选项菜单
},
),
),
],
),
],
),
);
}
// 耳机图片
Widget _buildEarbudsImage() {
return Container(
height: 180.h,
alignment: Alignment.center,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.15),
blurRadius: 15,
offset: const Offset(0, 5),
),
BoxShadow(
color: Colors.blue.withOpacity(0.05),
blurRadius: 20,
offset: const Offset(0, -2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.r),
child: Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
child: Stack(
alignment: Alignment.center,
children: [
// 背景光效
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [
Colors.blue.withOpacity(0.05),
Colors.white,
],
center: Alignment.topRight,
radius: 0.8,
),
),
),
),
// 耳机图片
Image.asset(
'assets/images/headphone_light.png',
height: 150.h,
fit: BoxFit.contain,
),
],
),
),
),
),
);
}
// 设备状态卡片
Widget _buildDeviceStatusCard() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
padding: EdgeInsets.all(16.w),
child: Column(
children: [
// 状态标题行
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'设备状态',
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: Colors.grey[700],
),
),
Obx(() => Row(
children: [
Container(
width: 8.w,
height: 8.w,
decoration: BoxDecoration(
color: controller.getConnectionStatusColor(),
shape: BoxShape.circle,
),
),
SizedBox(width: 4.w),
Text(
controller.getConnectionStatusText(),
style: TextStyle(
fontSize: 12.sp,
color: controller.getConnectionStatusColor(),
),
),
// 添加刷新按钮
SizedBox(width: 8.w),
InkWell(
onTap: controller.refreshDeviceInfo,
child: Icon(
Icons.refresh,
size: 16.sp,
color: Colors.grey[600],
),
),
],
)),
],
),
// 设备信息
SizedBox(height: 12.h),
Obx(() {
// 如果连接失败且有错误信息,显示错误提示
if (controller.connectionStatus == ConnectionStatus.failed &&
controller.connectionErrorMsg.isNotEmpty) {
return Column(
children: [
Container(
padding: EdgeInsets.all(8.w),
decoration: BoxDecoration(
color: Colors.red[50],
borderRadius: BorderRadius.circular(8.r),
border: Border.all(color: Colors.red[200]!),
),
child: Row(
children: [
Icon(
Icons.error_outline,
color: Colors.red,
size: 16.sp,
),
SizedBox(width: 8.w),
Expanded(
child: Text(
controller.connectionErrorMsg,
style: TextStyle(
fontSize: 12.sp,
color: Colors.red[800],
),
),
),
],
),
),
SizedBox(height: 12.h),
// 连接按钮
ElevatedButton(
onPressed: controller.rescanDevices,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
minimumSize: Size(double.infinity, 36.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
child: Text('重新连接'),
),
],
);
}
// 如果正在连接中,显示连接中提示
if (controller.connectionStatus == ConnectionStatus.connecting) {
return Container(
padding: EdgeInsets.symmetric(vertical: 16.h),
child: Center(
child: Column(
children: [
SizedBox(
width: 24.w,
height: 24.w,
child: CircularProgressIndicator(
strokeWidth: 2.w,
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
),
),
SizedBox(height: 8.h),
Text(
'正在连接设备...',
style: TextStyle(
fontSize: 12.sp,
color: Colors.blue,
),
),
],
),
),
);
}
return controller.isConnected
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
'已连接到:${controller.getDeviceName()}',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Colors.grey[700],
),
overflow: TextOverflow.ellipsis,
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 2.h),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(4.r),
),
child: Text(
'信号: ${controller.getSignalStrength()}',
style: TextStyle(
fontSize: 10.sp,
color: Colors.blue[700],
),
),
),
],
),
SizedBox(height: 8.h),
Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
decoration: BoxDecoration(
color: Colors.grey[50],
borderRadius: BorderRadius.circular(8.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'设备ID:${controller.getDeviceId()}',
style: TextStyle(
fontSize: 10.sp,
color: Colors.grey[500],
),
),
SizedBox(height: 4.h),
Text(
'固件版本:${controller.firmwareVersion}',
style: TextStyle(
fontSize: 10.sp,
color: Colors.grey[500],
),
),
],
),
),
],
)
: Container(
padding: EdgeInsets.symmetric(vertical: 8.h),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8.r),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.bluetooth_disabled,
size: 14.sp,
color: Colors.grey[700],
),
SizedBox(width: 4.w),
Text(
'未连接设备,点击下方按钮连接',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[700],
),
),
],
),
);
}),
// 连接按钮(仅在未连接时显示)
SizedBox(height: 12.h),
Obx(() {
if (controller.connectionStatus == ConnectionStatus.disconnected) {
return ElevatedButton(
onPressed: controller.rescanDevices,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
minimumSize: Size(double.infinity, 36.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
),
child: Text('连接设备'),
);
} else {
return SizedBox();
}
}),
],
),
);
}
// 优质AI体验布局(左1右2)
Widget _buildPremiumAILayout() {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 左侧大卡片 - AI助理
Expanded(
flex: 1,
child: Stack(
children: [
// 呼吸光效果
Positioned.fill(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
gradient: RadialGradient(
colors: [
Color(0xFF4ECDC4).withOpacity(0.6),
Colors.transparent,
],
center: Alignment.topRight,
radius: 1.0,
),
),
child: AnimatedPulsing(),
),
),
// 卡片内容
_buildFeatureCard(
title: 'AI全能助手',
description: '24小时专属顾问,解答问题、提供建议',
icon: Icons.smart_toy,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF4ECDC4),
Color(0xFF556270),
],
),
onTap: controller.exploreAIFeatures,
iconOnTop: true,
height: 175.h, // 增加高度
),
],
),
),
SizedBox(width: 16.w),
// 右侧两个卡片
Expanded(
flex: 1,
child: Column(
children: [
// 右上卡片 - 同声翻译
_buildFeatureCard(
title: '同声传译',
description: '80+语言实时翻译,出国无忧',
icon: Icons.translate,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF5E72EB),
Color(0xFF4776E6),
],
),
onTap: controller.openTranslation,
height: 83.h, // 增加高度
),
SizedBox(height: 5.h), // 减少间距
// 右下卡片 - AI女友
_buildFeatureCard(
title: 'AI伴侣',
description: '懂你心意,温暖陪伴',
icon: Icons.favorite,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFFF758C),
Color(0xFFFF7EB3),
],
),
onTap: controller.openAIGirlfriend,
height: 85.h, // 增加高度
),
],
),
),
],
);
}
// 特性卡片构建方法
Widget _buildFeatureCard({
required String title,
required String description,
required IconData icon,
required LinearGradient gradient,
required VoidCallback onTap,
double? height,
bool iconOnTop = false,
}) {
return InkWell(
onTap: onTap,
child: Container(
height: height ?? 175.h,
padding: EdgeInsets.all(14.w),
decoration: BoxDecoration(
gradient: gradient,
borderRadius: BorderRadius.circular(16.r),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 5,
offset: Offset(0, 2),
),
],
),
child: iconOnTop
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 图标靠左而不是居中
Container(
width: 45.w,
height: 45.w,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12.r),
),
child: Icon(
icon,
color: Colors.white,
size: 24.w,
),
),
SizedBox(height: 8.h),
// 标题
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 16.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 4.h),
// 描述
Expanded(
child: Text(
description,
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: 12.sp,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
),
],
)
: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 图标
Container(
width: 34.w,
height: 34.w,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(8.r),
),
child: Icon(
icon,
color: Colors.white,
size: 18.w,
),
),
SizedBox(width: 10.w),
// 文本内容
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
// 标题
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 2.h),
// 描述
Text(
description,
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: 10.sp,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
);
}
}