427 lines
13 KiB
Dart
427 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:qr_flutter/qr_flutter.dart';
|
|
import '../../../../core/di/injection_container.dart';
|
|
|
|
/// 分享页面 - 显示邀请链接和二维码
|
|
/// 进入页面时自动调用 API 生成短链,显示二维码
|
|
class SharePage extends ConsumerStatefulWidget {
|
|
/// 初始分享链接 (fallback)
|
|
final String shareLink;
|
|
/// 邀请码
|
|
final String? referralCode;
|
|
|
|
const SharePage({
|
|
super.key,
|
|
required this.shareLink,
|
|
this.referralCode,
|
|
});
|
|
|
|
@override
|
|
ConsumerState<SharePage> createState() => _SharePageState();
|
|
}
|
|
|
|
class _SharePageState extends ConsumerState<SharePage> {
|
|
/// 实际显示的分享链接 (API 返回的短链)
|
|
late String _displayLink;
|
|
/// 是否正在加载
|
|
bool _isLoading = true;
|
|
/// 错误信息
|
|
String? _errorMessage;
|
|
/// 推荐码(从 API 获取后保存)
|
|
String? _referralCode;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_displayLink = widget.shareLink; // 默认使用传入的链接
|
|
_loadShareLink();
|
|
}
|
|
|
|
/// APK 下载基础链接
|
|
static const String _apkDownloadUrl = 'https://s3.szaiai.com/rwadurian/app-release.apk';
|
|
|
|
/// 加载分享链接 (使用 APK 下载链接 + 推荐码)
|
|
Future<void> _loadShareLink() async {
|
|
try {
|
|
setState(() {
|
|
_isLoading = true;
|
|
_errorMessage = null;
|
|
});
|
|
|
|
final referralService = ref.read(referralServiceProvider);
|
|
|
|
// 调用 API 获取推荐码
|
|
final linkResponse = await referralService.generateReferralLink();
|
|
|
|
if (mounted) {
|
|
setState(() {
|
|
// 使用 APK 下载链接 + 推荐码参数
|
|
_referralCode = linkResponse.referralCode;
|
|
_displayLink = '$_apkDownloadUrl?ref=$_referralCode';
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
debugPrint('加载分享链接失败: $e');
|
|
if (mounted) {
|
|
setState(() {
|
|
_isLoading = false;
|
|
// 失败时使用传入的推荐码构造链接
|
|
if (widget.referralCode != null && widget.referralCode!.isNotEmpty) {
|
|
_referralCode = widget.referralCode;
|
|
_displayLink = '$_apkDownloadUrl?ref=${widget.referralCode}';
|
|
} else {
|
|
_displayLink = _apkDownloadUrl;
|
|
}
|
|
_errorMessage = '加载失败,使用默认链接';
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 复制链接到剪贴板
|
|
void _copyLink() {
|
|
Clipboard.setData(ClipboardData(text: _displayLink));
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('链接已复制'),
|
|
backgroundColor: Color(0xFFD4A84B),
|
|
duration: Duration(seconds: 2),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 返回上一页
|
|
void _goBack() {
|
|
context.pop();
|
|
}
|
|
|
|
/// 确认按钮点击
|
|
void _onConfirm() {
|
|
context.pop();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: Container(
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
// 渐变背景 - 从浅黄到白色
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Color(0xFFFFF7E6), // 浅黄色顶部
|
|
Color(0xFFFFFDF8), // 接近白色底部
|
|
],
|
|
),
|
|
),
|
|
child: SafeArea(
|
|
child: Column(
|
|
children: [
|
|
// 顶部导航栏
|
|
_buildAppBar(),
|
|
// 内容区域
|
|
Expanded(
|
|
child: Center(
|
|
child: SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 24),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// QR 码区域
|
|
_buildQrCodeSection(),
|
|
const SizedBox(height: 32),
|
|
// 链接输入框
|
|
_buildLinkSection(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
// 底部确认按钮
|
|
_buildFooter(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 构建顶部导航栏
|
|
Widget _buildAppBar() {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
|
child: Row(
|
|
children: [
|
|
// 返回按钮
|
|
GestureDetector(
|
|
onTap: _goBack,
|
|
child: Container(
|
|
width: 28,
|
|
height: 28,
|
|
alignment: Alignment.center,
|
|
child: const Icon(
|
|
Icons.arrow_back_ios,
|
|
color: Color(0xFF8C6A3E),
|
|
size: 20,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
// 标题
|
|
const Expanded(
|
|
child: Text(
|
|
'分享页面',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontFamily: 'Segoe UI',
|
|
fontWeight: FontWeight.w600,
|
|
height: 1.56,
|
|
color: Color(0xFF8C6A3E),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 构建 QR 码区域
|
|
Widget _buildQrCodeSection() {
|
|
return Column(
|
|
children: [
|
|
Container(
|
|
width: 256,
|
|
height: 256,
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFFAF3E3),
|
|
borderRadius: BorderRadius.circular(24),
|
|
boxShadow: const [
|
|
BoxShadow(
|
|
color: Color(0x1A8C6A3E), // rgba(140, 106, 62, 0.1)
|
|
blurRadius: 30,
|
|
offset: Offset(0, 8),
|
|
),
|
|
],
|
|
),
|
|
child: Center(
|
|
child: _isLoading
|
|
? const CircularProgressIndicator(
|
|
color: Color(0xFFD4A84B),
|
|
strokeWidth: 2,
|
|
)
|
|
: QrImageView(
|
|
data: _displayLink,
|
|
version: QrVersions.auto,
|
|
size: 200,
|
|
backgroundColor: Colors.transparent,
|
|
eyeStyle: const QrEyeStyle(
|
|
eyeShape: QrEyeShape.square,
|
|
color: Color(0xFF8C6A3E),
|
|
),
|
|
dataModuleStyle: const QrDataModuleStyle(
|
|
dataModuleShape: QrDataModuleShape.square,
|
|
color: Color(0xFF8C6A3E),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
// 推荐码显示
|
|
if (_referralCode != null && _referralCode!.isNotEmpty) ...[
|
|
const SizedBox(height: 16),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFF8F1E2),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const Text(
|
|
'我的推荐码:',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontFamily: 'Segoe UI',
|
|
color: Color(0xFF8C6A3E),
|
|
),
|
|
),
|
|
Text(
|
|
_referralCode!,
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontFamily: 'Segoe UI',
|
|
fontWeight: FontWeight.w700,
|
|
color: Color(0xFFD4A84B),
|
|
letterSpacing: 1,
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
GestureDetector(
|
|
onTap: _copyReferralCode,
|
|
child: const Icon(
|
|
Icons.copy_outlined,
|
|
color: Color(0xFF8C6A3E),
|
|
size: 18,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
],
|
|
);
|
|
}
|
|
|
|
/// 复制推荐码
|
|
void _copyReferralCode() {
|
|
if (_referralCode != null && _referralCode!.isNotEmpty) {
|
|
Clipboard.setData(ClipboardData(text: _referralCode!));
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('推荐码已复制'),
|
|
backgroundColor: Color(0xFFD4A84B),
|
|
duration: Duration(seconds: 2),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 构建链接显示区域
|
|
Widget _buildLinkSection() {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
width: double.infinity,
|
|
constraints: const BoxConstraints(maxWidth: 296),
|
|
padding: const EdgeInsets.fromLTRB(16, 8, 12, 8),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFF8F1E2),
|
|
borderRadius: BorderRadius.circular(9999), // 胶囊形状
|
|
),
|
|
child: Row(
|
|
children: [
|
|
// 链接文本
|
|
Expanded(
|
|
child: _isLoading
|
|
? const Text(
|
|
'加载中...',
|
|
style: TextStyle(
|
|
fontSize: 13.7,
|
|
fontFamily: 'Segoe UI',
|
|
height: 1.5,
|
|
color: Color(0xFFB0A090),
|
|
),
|
|
)
|
|
: Text(
|
|
_displayLink,
|
|
style: const TextStyle(
|
|
fontSize: 13.7,
|
|
fontFamily: 'Segoe UI',
|
|
height: 1.5,
|
|
color: Color(0xFF8C6A3E),
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
// 复制按钮
|
|
GestureDetector(
|
|
onTap: _isLoading ? null : _copyLink,
|
|
child: Container(
|
|
width: 32,
|
|
height: 32,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(9999),
|
|
boxShadow: const [
|
|
BoxShadow(
|
|
color: Color(0x0D000000), // rgba(0, 0, 0, 0.05)
|
|
blurRadius: 2,
|
|
offset: Offset(0, 1),
|
|
),
|
|
],
|
|
),
|
|
child: Center(
|
|
child: Icon(
|
|
Icons.copy_outlined,
|
|
color: _isLoading
|
|
? const Color(0xFFB0A090)
|
|
: const Color(0xFF8C6A3E),
|
|
size: 18,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// 错误提示
|
|
if (_errorMessage != null) ...[
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
_errorMessage!,
|
|
style: const TextStyle(
|
|
fontSize: 12,
|
|
color: Color(0xFFB0A090),
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 构建底部确认按钮
|
|
Widget _buildFooter() {
|
|
return Container(
|
|
padding: const EdgeInsets.all(24),
|
|
child: GestureDetector(
|
|
onTap: _onConfirm,
|
|
child: Container(
|
|
width: double.infinity,
|
|
height: 60,
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFD1A45B),
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: const [
|
|
BoxShadow(
|
|
color: Color(0x4DD1A45B), // rgba(209, 164, 91, 0.3)
|
|
blurRadius: 15,
|
|
offset: Offset(0, 10),
|
|
),
|
|
BoxShadow(
|
|
color: Color(0x4DD1A45B), // rgba(209, 164, 91, 0.3)
|
|
blurRadius: 6,
|
|
offset: Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: const Center(
|
|
child: Text(
|
|
'确认',
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontFamily: 'Segoe UI',
|
|
fontWeight: FontWeight.w700,
|
|
height: 1.56,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|