2026/1/1 6:31:07
网站建设
项目流程
制作一个网站都需要学什么,棋牌小程序制作开发,做公司网站的费用,wordpress 小论坛小程序前言#xff1a;本文章是我在看到其他人的文章后的学习笔记#xff0c;我参照的文章链接在下面#xff1a;
【学习打卡】day03基于flutter实现鸿蒙应用开发之gitcode口袋工具箱完善版本-CSDN博客https://blog.csdn.net/laoren1998/article/details/155579537?fromshareblo…前言本文章是我在看到其他人的文章后的学习笔记我参照的文章链接在下面【学习打卡】day03基于flutter实现鸿蒙应用开发之gitcode口袋工具箱完善版本-CSDN博客https://blog.csdn.net/laoren1998/article/details/155579537?fromshareblogdetailsharetypeblogdetailsharerId155579537sharereferPCsharesourcejhp0108sharefromfrom_link一、项目核心定位GitCode口袋工具是基于Flutter开发、适配DevEco Studio的轻量化GitCode平台客户端核心亮点的是毛玻璃二次元视觉风格功能覆盖登录验证、动态查看、仓库管理、个人信息展示整体架构模块化便于维护与扩展。二、前期准备开发环境配置 - 开发工具DevEco Studio需适配Flutter开发插件 - 技术依赖在项目 pubspec.yaml 中添加核心依赖支撑网络请求、本地存储等功能 yaml dependencies: flutter: sdk: flutter dio: ^5.7.0 # 网络请求核心库 shared_preferences: ^2.3.0 # 本地存储令牌管理 flutter_easyloading: ^3.0.5 # 加载状态提示可选优化 - 权限配置确保项目开启网络权限满足GitCode API请求需求。项目结构规划采用模块化拆分思路明确各目录职责降低代码耦合度结构如下plaintextlib/├── main.dart # 应用入口初始化主题与根组件├── constants/ # 常量集中管理API地址、存储键等└── app_constants.dart # 核心常量定义├── themes/ # 主题配置专属目录└── app_theme.dart # 毛玻璃二次元主题核心配置├── services/ # 网络服务层└── gitcode_service.dart # GitCode API请求封装单例模式├── screens/ # 页面组件目录核心功能页├── login_screen.dart # 令牌登录页├── main_screen.dart # 底部导航主页面├── home_screen.dart # 首页动态展示├── repo_screen.dart # 热门/个人仓库页└── profile_screen.dart # 个人中心页└── widgets/ # 自定义复用组件├── glass_card.dart # 毛玻璃卡片全局复用核心组件└── activity_card.dart # 动态列表卡片组件三、核心模块实现步骤常量定义constants/app_constants.dart 集中管理API基础地址、令牌存储键、历史记录限制等常量避免硬编码便于统一修改class AppConstants { // GitCode API基础地址 static const String apiBaseUrl https://api.gitcode.com/api/v5; // 当前令牌本地存储键 static const String tokenStorageKey gitcode_token; // 历史令牌存储键新增 static const String tokenHistoryKey gitcode_token_history; // 历史令牌最大存储数量新增 static const int maxHistoryCount 5; }毛玻璃二次元主题核心配置themes/app_theme.dart 主题是风格落地核心统一管控颜色、字体、组件样式重点实现二次元视觉与毛玻璃适配import package:flutter/material.dart; // SPDX-License-Identifier: Apache-2.0 import package:flutter/material.dart; /// 毛玻璃二次元主题配置 class AppTheme { /// 字体大小超大 static const double fontSizeXXLarge 24; /// 字体大小大 static const double fontSizeXLarge 18; /// 字体大小中 static const double fontSizeLarge 16; /// 字体大小中 static const double fontSizeMedium 14; /// 字体大小小 static const double fontSizeSmall 12; /// 主色调二次元粉紫色 static const Color primaryColor Color(0xFF8B5CF6); /// 次要色调天空蓝 static const Color secondaryColor Color(0xFF38BDF8); /// 强调色樱花粉 static const Color accentColor Color(0xFFEC4899); /// 背景色浅紫灰 static const Color backgroundColor Color(0xFFF5F3FF); /// 卡片背景色半透明白 static const Color cardBackgroundColor Color(0xC8FFFFFF); /// 文字主色 static const Color primaryTextColor Color(0xFF1E1B4B); /// 文字次要色 static const Color secondaryTextColor Color(0xFF64748B); /// 边框颜色 static const Color borderColor Color.fromARGB(50, 139, 92, 246); /// 阴影效果 static const BoxShadow cardShadow BoxShadow( color: Color.fromRGBO(139, 92, 246, 0.1), // 主题色阴影 blurRadius: 12, // 模糊半径 offset: Offset(0, 4), // 偏移量 ); /// 圆角大小 static const BorderRadius cardBorderRadius BorderRadius.all(Radius.circular(16)); /// 构建Material主题 static ThemeData get themeData ThemeData( // 主色调 primaryColor: primaryColor, // 画布背景色 scaffoldBackgroundColor: backgroundColor, // 卡片主题 cardTheme: CardTheme( color: cardBackgroundColor, elevation: 0, shape: RoundedRectangleBorder(borderRadius: cardBorderRadius), shadowColor: cardShadow.color, ), // AppBar主题 appBarTheme: const AppBarTheme( backgroundColor: Colors.transparent, // 透明背景配合毛玻璃 foregroundColor: primaryTextColor, // 文字颜色 elevation: 0, // 无阴影 centerTitle: true, // 标题居中 ), // 底部导航栏主题 bottomNavigationBarTheme: BottomNavigationBarThemeData( backgroundColor: cardBackgroundColor, // 半透明背景 selectedItemColor: primaryColor, // 选中颜色 unselectedItemColor: secondaryTextColor, // 未选中颜色 elevation: 8, // 阴影 type: BottomNavigationBarType.fixed, // 固定类型 ), // 文字主题 textTheme: const TextTheme( bodyLarge: TextStyle(color: primaryTextColor), bodyMedium: TextStyle(color: secondaryTextColor), titleLarge: TextStyle( fontWeight: FontWeight.bold, color: primaryTextColor, ), ), // 按钮主题 elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: primaryColor, // 按钮背景色 foregroundColor: Colors.white, // 按钮文字色 shape: RoundedRectangleBorder(borderRadius: cardBorderRadius), // 圆角 padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), // 内边距 ), ), // 输入框主题 inputDecorationTheme: InputDecorationTheme( filled: true, // 填充背景 fillColor: cardBackgroundColor, // 填充色 border: OutlineInputBorder( borderRadius: cardBorderRadius, // 圆角 borderSide: BorderSide(color: borderColor), // 边框色 ), enabledBorder: OutlineInputBorder( borderRadius: cardBorderRadius, borderSide: BorderSide(color: borderColor), ), focusedBorder: OutlineInputBorder( borderRadius: cardBorderRadius, borderSide: BorderSide(color: primaryColor, width: 2), // 聚焦边框色 ), ), ); }毛玻璃卡片组件封装widgets/glass_card.dart 全局复用核心组件通过 BackdropFilter ImageFilter.blur 实现毛玻璃效果适配各页面// SPDX-License-Identifier: Apache-2.0 import package:flutter/material.dart; import dart:ui; // 用于ImageFilter毛玻璃 import ../themes/app_theme.dart; /// 毛玻璃卡片组件 class GlassCard extends StatelessWidget { /// 卡片子组件 final Widget child; /// 内边距 final EdgeInsets padding; /// 外边距 final EdgeInsets margin; const GlassCard({ Key? key, required this.child, this.padding const EdgeInsets.all(16), this.margin const EdgeInsets.only(bottom: 16), }) : super(key: key); override Widget build(BuildContext context) { return Container( margin: margin, //毛玻璃效果核心BackdropFilter ImageFilter.blur child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), // 模糊程度 child: Container( padding: padding, decoration: BoxDecoration( color: AppTheme.cardBackgroundColor, // 半透明背景 borderRadius: AppTheme.cardBorderRadius, // 圆角 boxShadow: [AppTheme.cardShadow], // 阴影 border: Border.all( color: Colors.white.withOpacity(0.2), // 白色描边增强玻璃感 width: 1, ), ), child: child, ), ), ); } }网络服务层封装services/gitcode_service.dart 采用单例模式封装GitCode API请求统一处理令牌添加、错误拦截支撑核心功能// SPDX-License-Identifier: Apache-2.0 import package:dio/dio.dart; import ../constants/app_constants.dart; /// GitCode API服务类 class GitCodeService { // 单例模式确保全局只有一个实例 static final GitCodeService _instance GitCodeService._internal(); factory GitCodeService() _instance; late Dio dio; // Dio实例用于网络请求 // 内部构造函数 GitCodeService._internal() { // 初始化Dio dio Dio( BaseOptions( baseUrl: AppConstants.apiBaseUrl, // API基础地址 connectTimeout: const Duration(seconds: 15), // 连接超时 receiveTimeout: const Duration(seconds: 15), // 接收超时 responseType: ResponseType.json, // 响应类型 contentType: application/json; charsetutf-8, // 请求类型 headers: { Accept: application/json, // 接受JSON格式 }, ), ); // 添加拦截器日志、错误处理 dio.interceptors.add( InterceptorsWrapper( // 请求拦截 onRequest: (options, handler) { // 如果有令牌添加到请求头 String? token _accessToken; if (token ! null token.isNotEmpty) { options.headers[Authorization] Bearer $token; } print( 请求: ${options.method} ${options.uri}); handler.next(options); // 继续请求 }, // 响应拦截 onResponse: (response, handler) { print(✅ 响应: ${response.statusCode} ${response.requestOptions.uri}); handler.next(response); // 继续处理响应 }, // 错误拦截 onError: (DioException e, handler) { print(❌ 错误: ${e.message}); print(❌ 响应状态: ${e.response?.statusCode}); print(❌ 响应体: ${e.response?.data}); // 统一错误信息 String errorMsg 网络请求失败; if (e.response?.statusCode 404) { errorMsg API端点不存在; } else if (e.response?.statusCode 401) { errorMsg 无效的访问令牌; } else if (e.type DioExceptionType.connectionTimeout) { errorMsg 网络超时请检查网络连接; } // 包装错误 e DioException( requestOptions: e.requestOptions, type: e.type, error: errorMsg, response: e.response, ); handler.next(e); // 继续处理错误 }, ), ); } // 令牌存储全局变量实际项目建议使用本地存储 static String? _accessToken; /// 设置访问令牌 void setToken(String token) { _accessToken token; } /// 清除访问令牌 void clearToken() { _accessToken null; } /// 获取当前用户信息 FutureMapString, dynamic fetchUserInfo() async { try { final response await dio.get(/user); // 请求用户信息 return response.data as MapString, dynamic; // 返回数据 } on DioException catch (e) { throw Exception(e.error ?? 获取用户信息失败); // 抛出异常 } } /// 获取用户仓库列表 FutureListdynamic fetchMyRepositories() async { try { final response await dio.get( /user/repos, queryParameters: { visibility: all, // 所有可见性 affiliation: owner, // 仅自己的仓库 page: 1, // 页码 per_page: 20, // 每页数量 }, ); return response.data as Listdynamic; // 返回仓库列表 } on DioException catch (e) { throw Exception(e.error ?? 获取我的仓库失败); // 抛出异常 } } /// 获取动态列表 FutureListdynamic fetchActivities() async { try { final response await dio.get( /events, queryParameters: {page: 1, per_page: 20}, // 分页参数 ); return response.data as Listdynamic; // 返回动态列表 } catch (e) { print(⚠️ 动态API调用失败返回模拟数据: $e); // 返回模拟数据防止API不可用导致崩溃 return [ { id: 1, type: PushEvent, actor: {login: user1, avatar_url: https://placehold.co/40x40/8B5CF6/ffffff?textU1}, repo: {name: user1/repo1}, created_at: DateTime.now().subtract(const Duration(hours: 1)).toIso8601String() }, { id: 2, type: WatchEvent, actor: {login: user2, avatar_url: https://placehold.co/40x40/38BDF8/ffffff?textU2}, repo: {name: user2/repo2}, created_at: DateTime.now().subtract(const Duration(hours: 2)).toIso8601String() }, ]; } } /// 获取热门仓库 FutureListdynamic fetchHotRepositories() async { try { final response await dio.get( /search/repositories, queryParameters: { q: stars:100, // 搜索条件星数100 sort: stars, // 按星数排序 order: desc, // 降序 page: 1, // 页码 per_page: 10, // 每页数量 }, ); final data response.data as MapString, dynamic; return data[items] as Listdynamic; // 返回热门仓库列表 } catch (e) { print(⚠️ 热门仓库API调用失败返回模拟数据: $e); // 返回模拟数据 return [ { id: 101, name: flutter-kit, full_name: google/flutter-kit, description: Flutter 开发工具包, language: Dart, stargazers_count: 5000, forks_count: 1200, html_url: https://gitcode.com/google/flutter-kit }, ]; } } }核心页面实现screens目录 1登录页login_screen.dart 令牌验证入口采用毛玻璃卡片承载表单适配主题风格验证通过跳转主页面// SPDX-License-Identifier: Apache-2.0 import package:flutter/material.dart; import ../services/gitcode_service.dart; import ../themes/app_theme.dart; import ../widgets/glass_card.dart; import ./main_screen.dart; /// 登录页面 class LoginScreen extends StatefulWidget { const LoginScreen({Key? key}) : super(key: key); override StateLoginScreen createState() _LoginScreenState(); } class _LoginScreenState extends StateLoginScreen { /// 令牌输入控制器 final TextEditingController _tokenController TextEditingController(); /// 加载状态 bool _isLoading false; /// 错误信息 String? _errorMessage; /// 登录处理函数 void _handleLogin() async { setState(() { _isLoading true; // 显示加载中 _errorMessage null; // 清空错误信息 }); final token _tokenController.text.trim(); // 获取输入的令牌 if (token.isEmpty) { setState(() { _isLoading false; _errorMessage 请输入访问令牌; // 空令牌提示 }); return; } try { // 初始化服务并设置令牌 final service GitCodeService(); service.setToken(token); // 验证令牌是否有效调用用户信息API await service.fetchUserInfo(); // 登录成功跳转到主页面 if (mounted) { Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) const MainScreen()), ); } } catch (e) { setState(() { _isLoading false; _errorMessage e.toString(); // 显示错误信息 }); } } override Widget build(BuildContext context) { return Scaffold( // 背景渐变增强二次元风格 body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFFF5F3FF), // 浅紫灰 Color(0xFFE0E7FF), // 浅蓝紫 ], ), ), child: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.all(32.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: Widget[ // Logo区域 GlassCard( margin: const EdgeInsets.only(bottom: 32), padding: const EdgeInsets.all(24), child: Column( children: [ // Logo图标 Container( width: 100, height: 100, decoration: BoxDecoration( color: AppTheme.primaryColor, borderRadius: BorderRadius.circular(20), boxShadow: [AppTheme.cardShadow], ), child: const Icon( Icons.code, size: 60, color: Colors.white, ), ), const SizedBox(height: 16), // 应用标题 const Text( GitCode 客户端, style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: AppTheme.primaryTextColor, ), ), const SizedBox(height: 8), // 副标题 const Text( 使用访问令牌登录, style: TextStyle( fontSize: 16, color: AppTheme.secondaryTextColor, ), ), ], ), ), // 登录表单 GlassCard( child: Column( children: [ // 令牌输入框 TextField( controller: _tokenController, obscureText: true, // 密码模式隐藏令牌 decoration: InputDecoration( labelText: 访问令牌, hintText: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, hintStyle: const TextStyle(color: AppTheme.secondaryTextColor), errorText: _errorMessage, // 错误提示 prefixIcon: const Icon(Icons.security, color: AppTheme.primaryColor), suffixIcon: IconButton( icon: const Icon(Icons.clear, color: AppTheme.secondaryTextColor), onPressed: () _tokenController.clear(), // 清空输入 ), ), maxLines: 1, textInputAction: TextInputAction.done, onSubmitted: (_) _handleLogin(), // 回车登录 ), const SizedBox(height: 16), // 帮助链接 Align( alignment: Alignment.centerRight, child: TextButton( onPressed: () { // 打开获取令牌的帮助页面预留 print(打开获取令牌帮助); }, child: const Text( 如何获取令牌, style: TextStyle(color: AppTheme.primaryColor), ), ), ), const SizedBox(height: 24), // 登录按钮 SizedBox( width: double.infinity, height: 50, child: ElevatedButton.icon( onPressed: _isLoading ? null : _handleLogin, // 加载中禁用 icon: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2), ) : const Icon(Icons.login), label: const Text( 登录, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ), ), ], ), ), ], ), ), ), ), ), ); } }2主页面main_screen.dart 底部导航核心页切换首页、仓库、个人中心导航栏适配毛玻璃效果import dart:ui; import package:flutter/material.dart; import ./home_screen.dart; import ./repo_screen.dart; import ./profile_screen.dart; import ../themes/app_theme.dart; class MainScreen extends StatefulWidget { const MainScreen({Key? key}) : super(key: key); override StateMainScreen createState() _MainScreenState(); } class _MainScreenState extends StateMainScreen { int _selectedIndex 0; // 当前选中页面索引 static const ListWidget _widgetOptions [HomeScreen(), RepoScreen(), ProfileScreen()]; // 页面列表 // 导航栏点击切换 void _onItemTapped(int index) setState(() _selectedIndex index); override Widget build(BuildContext context) { return Scaffold( // 背景渐变与登录页一致风格统一 body: Container( decoration: const BoxDecoration( gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFF5F3FF), Color(0xFFE0E7FF)]), ), child: _widgetOptions.elementAt(_selectedIndex), ), // 毛玻璃底部导航栏 bottomNavigationBar: Container( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: BottomNavigationBar( items: const [ BottomNavigationBarItem(icon: Icon(Icons.home_outlined), activeIcon: Icon(Icons.home), label: 首页), BottomNavigationBarItem(icon: Icon(Icons.code_outlined), activeIcon: Icon(Icons.code), label: 仓库), BottomNavigationBarItem(icon: Icon(Icons.person_outlined), activeIcon: Icon(Icons.person), label: 我的), ], currentIndex: _selectedIndex, onTap: _onItemTapped, backgroundColor: AppTheme.cardBackgroundColor, selectedItemColor: AppTheme.primaryColor, unselectedItemColor: AppTheme.secondaryTextColor, elevation: 8, type: BottomNavigationBarType.fixed, ), ), ), ); } }3首页动态/仓库/个人中心页 均基于 GlassCard 组件复用毛玻璃风格核心逻辑为请求接口数据→展示加载/错误/空状态→渲染列表/详情以个人中心为例展示用户信息登出功能import ./login_screen.dart; import package:flutter/material.dart; import ../services/gitcode_service.dart; import ../themes/app_theme.dart; import ../widgets/glass_card.dart; class ProfileScreen extends StatefulWidget { const ProfileScreen({Key? key}) : super(key: key); override StateProfileScreen createState() _ProfileScreenState(); } class _ProfileScreenState extends StateProfileScreen { final GitCodeService _service GitCodeService(); MapString, dynamic? _userInfo; // 用户信息 bool _isLoading true; // 加载状态 String? _errorMessage; // 错误提示 override void initState() {super.initState(); _fetchUserInfo();} // 获取用户信息 Futurevoid _fetchUserInfo() async { setState(() {_isLoading true; _errorMessage null;}); try { final userInfo await _service.fetchUserInfo(); setState(() _userInfo userInfo); } catch (e) { setState(() _errorMessage e.toString()); } finally { setState(() _isLoading false); } } // 格式化日期YYYY年MM月DD日 String _formatDate(String? dateStr) dateStr null ? : DateTime.parse(dateStr).toString().split( )[0].replaceAll(-, 年) 日; // 构建统计项仓库/关注者/关注中 Widget _buildStatItem(String label, int count, IconData icon) Column( children: [ Container(width: 56, height: 56, decoration: BoxDecoration(borderRadius: BorderRadius.circular(16), color: AppTheme.primaryColor.withOpacity(0.1)), child: Icon(icon, size: 28, color: AppTheme.primaryColor)), const SizedBox(height: 8), Text(count.toString(), style: const TextStyle(fontSize: 24, fontWeight: bold, color: AppTheme.primaryTextColor)), const SizedBox(height: 4), Text(label, style: TextStyle(fontSize: AppTheme.fontSizeSmall, color: AppTheme.secondaryTextColor)), ], ); override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(我的), backgroundColor: Colors.transparent, actions: [IconButton(icon: const Icon(Icons.settings_outlined), onPressed: () print(打开设置))]), body: RefreshIndicator( onRefresh: _fetchUserInfo, // 下拉刷新 color: AppTheme.primaryColor, backgroundColor: AppTheme.cardBackgroundColor, child: _isLoading ? const Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [CircularProgressIndicator(color: AppTheme.primaryColor), SizedBox(height: 16), Text(加载中...)])) : _errorMessage ! null ? Center( child: GlassCard( child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 64, color: Colors.red), const SizedBox(height: 16), Text(_errorMessage!, textAlign: TextAlign.center, style: const TextStyle(color: AppTheme.secondaryTextColor)), const SizedBox(height: 16), ElevatedButton(onPressed: () {_service.clearToken(); Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) const LoginScreen()));}, child: const Text(重新登录)), ]), ), ) : _userInfo null ? const Center(child: Text(未能获取用户信息)) : SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ // 用户信息卡片 GlassCard( margin: const EdgeInsets.only(bottom: 24), padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ CircleAvatar(radius: 60, backgroundImage: NetworkImage(_userInfo![avatar_url] ?? ), backgroundColor: AppTheme.secondaryColor.withOpacity(0.1)), const SizedBox(height: 16), Text(_userInfo![name] ?? _userInfo![login] ?? 匿名用户, style: const TextStyle(fontSize: AppTheme.fontSizeXXLarge, fontWeight: bold, color: AppTheme.primaryTextColor)), Text(${_userInfo![login]}, style: TextStyle(fontSize: AppTheme.fontSizeLarge, color: AppTheme.secondaryTextColor)), const SizedBox(height: 16), if (_userInfo![bio] ! null) Text(_userInfo![bio] ?? , textAlign: TextAlign.center, style: TextStyle(fontSize: AppTheme.fontSizeMedium, color: AppTheme.secondaryTextColor)), ], ), ), // 统计卡片 GlassCard( margin: const EdgeInsets.only(bottom: 24), padding: const EdgeInsets.all(24), child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildStatItem(仓库, _userInfo![public_repos] ?? 0, Icons.code_outlined), _buildStatItem(关注者, _userInfo![followers] ?? 0, Icons.people_outlined), _buildStatItem(关注中, _userInfo![following] ?? 0, Icons.person_add_outlined), ]), ), // 登出按钮红色主题区分常规按钮 SizedBox( width: double.infinity, height: 50, child: ElevatedButton.icon( onPressed: () {_service.clearToken(); Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) const LoginScreen()));}, icon: const Icon(Icons.logout), label: const Text(登出), style: ElevatedButton.styleFrom(backgroundColor: Colors.redAccent, foregroundColor: Colors.white), ), ), ], ), ), ), ); } }应用入口main.dart初始化应用绑定主题配置设置初始页面为登录页// SPDX-License-Identifier: Apache-2.0 import package:flutter/material.dart; import ./screens/login_screen.dart; import ./themes/app_theme.dart; /// 应用入口函数 void main() { runApp(const MyApp()); // 启动应用 } /// 根组件 class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); override Widget build(BuildContext context) { return MaterialApp( title: GitCode 客户端, // 应用标题 theme: AppTheme.themeData, // 应用主题 home: const LoginScreen(), // 初始页面登录页 debugShowCheckedModeBanner: false, // 隐藏调试横幅 ); } }四、毛玻璃二次元风格核心要点1. 背景基础全局使用 LinearGradient 浅紫灰→浅蓝紫渐变奠定柔和二次元基调避免纯色单调。2. 毛玻璃核心通过 BackdropFilter ImageFilter.blur(sigmaX:10, sigmaY:10) 实现模糊效果配合半透明白卡片 Color.fromARGB(200, 255, 255, 255) 强化玻璃质感。3. 视觉细节- 圆角全局统一16px圆角弱化尖锐感契合二次元柔和风格- 配色以粉紫为主色天蓝、樱花粉为辅文字区分主次色视觉统一- 阴影使用主题色淡阴影 opacity:0.1 增加组件层次感不突兀。4. 组件复用封装 GlassCard 组件全局页面复用确保风格一致性减少重复代码。五、运行测试1. 依赖安装配置 pubspec.yaml 后点击DevEco Studio「Pub get」安装依赖2. 设备适配选择模拟器或真实设备确保设备网络正常3. 功能测试验证登录令牌有效性、动态加载、仓库切换、个人信息展示、登出等核心功能检查毛玻璃效果适配性。