From cff16f671fd4b84597d91cf08e60fb18b1f91019 Mon Sep 17 00:00:00 2001 From: liyi Date: Wed, 3 Sep 2025 14:44:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E4=B8=BB=E9=A1=B5?= =?UTF-8?q?=E3=80=81=E6=B6=88=E6=81=AF=E9=A1=B5=E3=80=81=E6=88=91=E7=9A=84?= =?UTF-8?q?=E9=A1=B5=E4=B8=89=E4=B8=AA=E6=A8=A1=E5=9D=97=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/icon/icon_menu.png | Bin 0 -> 3724 bytes assets/icon/icon_vip.png | Bin 0 -> 918 bytes assets/images/default_avatar.png | Bin 0 -> 1544 bytes lib/common/constant/app_images.dart | 2 + lib/views/home/home_view.dart | 37 ++-- lib/views/mine/mine_view.dart | 312 +++++++++++++++++++++++++++- 6 files changed, 330 insertions(+), 21 deletions(-) create mode 100644 assets/icon/icon_menu.png create mode 100644 assets/icon/icon_vip.png create mode 100644 assets/images/default_avatar.png diff --git a/assets/icon/icon_menu.png b/assets/icon/icon_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..393beef8998366c765c39d55d03a5b9a5c60f33d GIT binary patch literal 3724 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 literal 0 HcmV?d00001 diff --git a/lib/common/constant/app_images.dart b/lib/common/constant/app_images.dart index 2a9e24e..6bca120 100644 --- a/lib/common/constant/app_images.dart +++ b/lib/common/constant/app_images.dart @@ -52,6 +52,8 @@ class AppImages{ static const String iconTeamQrcode = 'assets/icon/team_qrcode.png'; static const String iconDeviceManagement = 'assets/icon/device_management.png'; static const String iconTableMenu = 'assets/icon/icon_table_menu.png'; + static const String iconVip = 'assets/icon/icon_vip.png'; + static const String defaultAvatar = 'assets/images/default_avatar.png'; // 底部导航栏图标 static const String iconHome = 'assets/icon/bar/home.png'; diff --git a/lib/views/home/home_view.dart b/lib/views/home/home_view.dart index d013fa2..32b699f 100644 --- a/lib/views/home/home_view.dart +++ b/lib/views/home/home_view.dart @@ -40,8 +40,13 @@ class HomeView extends GetView { children: [ // 固定的上半部分 _buildPageHead(context), - SizedBox( - height: 10.h, + Obx( + () => Visibility( + visible: controller.isOpenNotificationPermission.value, + child: SizedBox( + height: 10.h, + ), + ), ), _buildSystemNotificationPermissionRow(), @@ -160,23 +165,29 @@ class HomeView extends GetView { return RefreshIndicator( onRefresh: _onRefresh, // 基础样式配置 - color: const Color(0xFF4A90E2), // 刷新指示器颜色 - backgroundColor: Colors.white, // 背景颜色 - + color: const Color(0xFF4A90E2), + // 刷新指示器颜色 + backgroundColor: Colors.white, + // 背景颜色 + // 控制下拉触发距离的关键属性 - displacement: 60.0, // 刷新指示器距离顶部的距离 - edgeOffset: 0.0, // 边缘偏移量 - + displacement: 60.0, + // 刷新指示器距离顶部的距离 + edgeOffset: 0.0, + // 边缘偏移量 + // 控制下拉幅度的关键属性 - triggerMode: RefreshIndicatorTriggerMode.onEdge, // 触发模式 - + triggerMode: RefreshIndicatorTriggerMode.onEdge, + // 触发模式 + // 描边宽度 - strokeWidth: 2.5, // 刷新指示器的描边宽度 - + strokeWidth: 2.5, + // 刷新指示器的描边宽度 + // 语义标签(用于无障碍功能) semanticsLabel: '下拉刷新首页内容', semanticsValue: '刷新中...', - + child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics( // 添加弹性滚动效果 diff --git a/lib/views/mine/mine_view.dart b/lib/views/mine/mine_view.dart index 56a913a..6e87d06 100644 --- a/lib/views/mine/mine_view.dart +++ b/lib/views/mine/mine_view.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:starwork_flutter/common/constant/app_images.dart'; import 'mine_controller.dart'; @@ -9,16 +12,309 @@ class MineView extends GetView { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('MineView'), - centerTitle: true, - ), - body: const Center( - child: Text( - 'MineView is working', - style: TextStyle(fontSize: 20), + backgroundColor: const Color(0xFFF6F7FB), + body: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 4.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildHeader(), + SizedBox(height: 10.h), + _buildUserProfile(), + SizedBox(height: 10.h), + _buildMenuItems(), + SizedBox(height: 10.h), + _buildBottomButtons(), + ], + ), + ), ), ), ); } + + // 页面顶部标题栏 + Widget _buildHeader() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '我的', + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w500, + color: Colors.black87, + ), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + Row( + children: [ + Stack( + children: [ + Icon( + Icons.settings, + size: 22.sp, + ), + Positioned( + right: 0, + top: 0, + child: Container( + width: 8.w, + height: 8.h, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + ), + ], + ), + ], + ), + ], + ); + } + + // 用户信息区域 + Widget _buildUserProfile() { + return Row( + children: [ + CircleAvatar( + radius: 30.r, + backgroundColor: Colors.grey[200], + child: ClipOval( + child: Image( + image: const AssetImage(AppImages.defaultAvatar), + width: 56.w, + height: 56.w, + fit: BoxFit.cover, + gaplessPlayback: true, + // 防止闪烁 + filterQuality: FilterQuality.medium, + // 优化过滤质量 + errorBuilder: (context, error, stackTrace) { + return Icon( + Icons.person, + size: 30.sp, + color: Colors.grey[400], + ); + }, + ), + ), + ), + SizedBox(width: 16.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'HikMall_30013234', + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + SizedBox(height: 4.h), + Row( + children: [ + Image( + image: AssetImage(AppImages.iconVip), + width: 20.w, + height: 20.w, + fit: BoxFit.contain, + gaplessPlayback: true, + // 防止闪烁 + filterQuality: FilterQuality.medium, + // 优化过滤质量 + errorBuilder: (context, error, stackTrace) { + return Icon( + Icons.image_not_supported, + size: 26.sp, + color: Colors.grey, + ); + }, + ), + SizedBox(width: 4.w), + Text( + '用户', + style: TextStyle( + fontSize: 14.sp, + color: Colors.grey, + ), + ), + ], + ), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 4.h), + decoration: BoxDecoration( + color: const Color(0xFFEBEFFF), + borderRadius: BorderRadius.circular(6.r), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.group, + size: 14.sp, + color: Colors.blue, + ), + SizedBox(width: 4.w), + Text( + '我的团队', + style: TextStyle( + fontSize: 12.sp, + color: Colors.black, + fontWeight: FontWeight.w500), + ), + ], + ), + ), + ], + ); + } + + + // 菜单项区域 + Widget _buildMenuItems() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.r), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + children: [ + _buildMenuItem( + title: '帮助中心', + onTap: () {}, + ), + Divider(height: 1.h, color: Colors.grey[200]), + _buildMenuItem( + title: '线下体验', + onTap: () {}, + ), + Divider(height: 1.h, color: Colors.grey[200]), + _buildMenuItem( + title: '分享海康互联', + onTap: () {}, + ), + ], + ), + ); + } + + // 底部按钮区域 + Widget _buildBottomButtons() { + return Container( + padding: EdgeInsets.all(16.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8.r), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildBottomButton( + icon: Icons.receipt_long, + title: '我的订单', + onTap: () {}, + ), + Container( + width: 1.w, + height: 40.h, + color: Colors.grey[200], + ), + _buildBottomButton( + icon: Icons.receipt, + title: '发票管理', + onTap: () {}, + ), + ], + ), + ); + } + + // 菜单项组件 + Widget _buildMenuItem({ + required String title, + required VoidCallback onTap, + }) { + return InkWell( + onTap: onTap, + child: Container( + padding: EdgeInsets.symmetric( vertical: 10.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + style: TextStyle( + fontSize: 16.sp, + color: Colors.black87, + ), + ), + Icon( + Icons.arrow_forward_ios, + size: 16.sp, + color: Colors.grey[400], + ), + ], + ), + ), + ); + } + + // 底部按钮组件 + Widget _buildBottomButton({ + required IconData icon, + required String title, + required VoidCallback onTap, + }) { + return GestureDetector( + onTap: onTap, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + icon, + size: 20.sp, + color: Colors.grey[600], + ), + SizedBox(width: 8.w), + Text( + title, + style: TextStyle( + fontSize: 14.sp, + color: Colors.grey[600], + ), + ), + ], + ), + ); + } }