import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../constants/app_constants.dart'; /// 时间: 2026-03-27 /// 功能: 权限管理页面 /// 介绍: 管理应用所需权限,包括震动、网络、剪切板等 /// 最新变化: 新建权限管理页面 class PermissionPage extends StatefulWidget { const PermissionPage({super.key}); @override State createState() => _PermissionPageState(); } class _PermissionPageState extends State { bool _vibrationEnabled = true; bool _networkEnabled = true; bool _clipboardEnabled = true; @override void initState() { super.initState(); _loadPermissionSettings(); } Future _loadPermissionSettings() async { final prefs = await SharedPreferences.getInstance(); setState(() { _vibrationEnabled = prefs.getBool('vibration_enabled') ?? true; _networkEnabled = prefs.getBool('network_enabled') ?? true; _clipboardEnabled = prefs.getBool('clipboard_enabled') ?? true; }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F5F5), appBar: AppBar( title: Text( '权限管理', style: TextStyle( color: AppConstants.primaryColor, fontWeight: FontWeight.bold, ), ), backgroundColor: Colors.white, elevation: 0, centerTitle: true, leading: IconButton( icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), onPressed: () => Navigator.pop(context), ), actions: [ IconButton( icon: Icon(Icons.info_outline, color: AppConstants.primaryColor), onPressed: _showPermissionInfoDialog, ), ], ), body: ListView( padding: const EdgeInsets.all(16), children: [ _buildPermissionGroup('权限列表', [ _buildPermissionItem( '网络访问', '访问网络获取诗词内容和数据', Icons.wifi, _networkEnabled, null, ), _buildPermissionItem( '震动反馈', '操作时的震动反馈,提升交互体验', Icons.vibration, _vibrationEnabled, null, ), _buildPermissionItem( '剪切板', '复制诗词内容到剪切板', Icons.content_copy, _clipboardEnabled, null, ), _buildPermissionItem( '播放声音', '播放内置提示音', Icons.audio_file, _clipboardEnabled, null, ), _buildPermissionItem( '分享能力', '调用系统分享接口', Icons.share, _clipboardEnabled, null, ), ]), const SizedBox(height: 16), _buildPermissionGroup('权限说明', [ _buildInfoItem('震动反馈', '用于点赞、收藏等操作的触觉反馈,提升用户体验。'), _buildInfoItem('网络访问', '用于获取诗词内容、排行榜数据、用户信息等。'), _buildInfoItem('剪切板', '用于复制诗词内容,方便用户分享和记录。'), _buildInfoItem('播放声音', '用于主页点击提示音,提升用户体验。'), _buildInfoItem('分享能力', '用于分享诗词内容到社交媒体平台。'), ]), const SizedBox(height: 16), _buildSandboxInfoCard(), const SizedBox(height: 16), _buildProjectSupplement(), const SizedBox(height: 24), _buildBottomTip(), ], ), ); } Widget _buildPermissionGroup(String title, List items) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Icon( Icons.security, color: AppConstants.primaryColor, size: 20, ), const SizedBox(width: 8), Text( title, style: TextStyle( color: AppConstants.primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ), const Divider(height: 1), ...items, ], ), ); } Widget _buildPermissionItem( String title, String description, IconData icon, bool enabled, Function(bool)? onToggle, ) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: AppConstants.primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: AppConstants.primaryColor, size: 20), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2, ), decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(4), ), child: Text( '已开启', style: TextStyle(fontSize: 10, color: Colors.grey[600]), ), ), ], ), const SizedBox(height: 2), Text( description, style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], ), ), Icon(Icons.lock, color: Colors.grey[400], size: 20), ], ), ); } Widget _buildInfoItem(String title, String description) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 4, height: 4, margin: const EdgeInsets.only(top: 6), decoration: BoxDecoration( color: AppConstants.primaryColor, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), // const SizedBox(height: 4), Text( description, style: TextStyle( fontSize: 12, color: Colors.grey[600], height: 1.5, ), ), ], ), ), ], ), ); } Widget _buildProjectSupplement() { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Icon(Icons.build, color: AppConstants.primaryColor, size: 20), const SizedBox(width: 8), Text( '项目补充完善', style: TextStyle( color: AppConstants.primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ), const Divider(height: 1), _buildSupplementItem( '用户反馈', '帮助我们改进产品', Icons.feedback, () => _showFeedbackDialog(), ), _buildSupplementItem( '功能建议', '提出您希望的功能', Icons.lightbulb, () => _showSuggestionDialog(), ), // _buildSupplementItem( // 'Bug报告', // '报告遇到的问题', // Icons.bug_report, // () => _showBugReportDialog(), // ), // _buildSupplementItem( // '参与开发', // '成为贡献者', // Icons.code, // () => _showContributionDialog(), // ), ], ), ); } Widget _buildSupplementItem( String title, String description, IconData icon, VoidCallback onTap, ) { return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: AppConstants.primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: AppConstants.primaryColor, size: 20), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 2), Text( description, style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], ), ), Icon(Icons.chevron_right, color: Colors.grey[400]), ], ), ), ); } void _showFeedbackDialog() { showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ Icon(Icons.feedback, color: AppConstants.primaryColor), const SizedBox(width: 8), const Text('用户反馈'), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ RichText( text: TextSpan( style: const TextStyle( fontSize: 14, height: 1.5, color: Colors.black87, ), children: [ const TextSpan(text: '软件内暂时无法反馈,请前往应用商店搜索 '), TextSpan( text: '情景诗词', style: TextStyle( color: AppConstants.primaryColor, fontWeight: FontWeight.bold, ), ), const TextSpan(text: ' 在详细页面 点击提交心愿单'), ], ), ), const SizedBox(height: 12), Text( '记得五星好评 ⭐', style: TextStyle( fontSize: 14, color: AppConstants.primaryColor, fontWeight: FontWeight.w500, ), ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text( '确定', style: TextStyle(color: AppConstants.primaryColor), ), ), ], ), ); } void _showSuggestionDialog() { showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ Icon(Icons.lightbulb, color: AppConstants.primaryColor), const SizedBox(width: 8), const Text('功能建议'), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ RichText( text: TextSpan( style: const TextStyle( fontSize: 14, height: 1.5, color: Colors.black87, ), children: [ const TextSpan(text: '软件内暂时无法反馈,请前往应用商店搜索 '), TextSpan( text: '情景诗词', style: TextStyle( color: AppConstants.primaryColor, fontWeight: FontWeight.bold, ), ), const TextSpan(text: ' 在详细页面 点击提交心愿单'), ], ), ), const SizedBox(height: 12), Text( '记得五星好评 ⭐', style: TextStyle( fontSize: 14, color: AppConstants.primaryColor, fontWeight: FontWeight.w500, ), ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text( '确定', style: TextStyle(color: AppConstants.primaryColor), ), ), ], ), ); } void _showPermissionInfoDialog() { showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ Icon(Icons.info, color: AppConstants.primaryColor), const SizedBox(width: 8), const Text('基础权限说明'), ], ), content: const Text( '系统赋予的基础软件权限无法拒绝;自带权限默认开启,用户无需动态授权,系统层关闭后,将无法正常使用应用。', style: TextStyle(fontSize: 14, height: 1.5), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text( '确定', style: TextStyle(color: AppConstants.primaryColor), ), ), ], ), ); } Widget _buildSandboxInfoCard() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppConstants.primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.shield, color: AppConstants.primaryColor, size: 20, ), ), const SizedBox(width: 12), Text( '沙盒运行说明', style: TextStyle( color: AppConstants.primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 12), const Divider(height: 1), const SizedBox(height: 12), Text( '本软件严格遵循移动平台沙盒机制运行,确保您的数据安全:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.grey[800], ), ), const SizedBox(height: 12), _buildSandboxItem('📱 沙盒隔离', '软件在独立沙盒环境中运行,无法访问系统其他应用数据'), const SizedBox(height: 8), _buildSandboxItem('📄 无文件创建', '不会在设备上创建额外文件,所有数据通过网络获取'), const SizedBox(height: 8), _buildSandboxItem('🔒 权限透明', '仅使用必要权限,此类权限均为基础权限'), const SizedBox(height: 8), _buildSandboxItem('💾 本地存储', '仅使用 SharedPreferences 存储少量用户偏好设置'), ], ), ); } Widget _buildSandboxItem(String title, String description) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 4, height: 4, margin: const EdgeInsets.only(top: 8), decoration: BoxDecoration( color: AppConstants.primaryColor, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.grey[800], ), ), const SizedBox(height: 4), Text( description, style: TextStyle( fontSize: 12, color: Colors.grey[600], height: 1.5, ), ), ], ), ), ], ); } Widget _buildBottomTip() { return Center( child: Padding( padding: const EdgeInsets.only(bottom: 32), child: Text( '到底了', style: TextStyle( fontSize: 14, color: Colors.grey[400], fontWeight: FontWeight.w500, ), ), ), ); } }