feat(reward): 新增客户端奖励中心
This commit is contained in:
1 parent
67670d46b1
commit
bea08110c9
68 files changed
+3987
-332
No files matched your search
@@ -0,0 +1,164 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/data/models/reward.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
|
||||
const double _coinInnerInsetRatio = 0.1;
|
||||
const double _coinLetterRatio = 0.46;
|
||||
const double _taskIconSize = 46;
|
||||
const double _taskIconRadius = 12;
|
||||
const double _taskGlyphSize = 24;
|
||||
const double _adIconWidth = 28;
|
||||
const double _adIconHeight = 22;
|
||||
const double _adIconRadius = 4;
|
||||
const double _adUnderlineWidth = 12;
|
||||
const double _adUnderlineHeight = 2;
|
||||
const double _adUnderlineBottom = -5;
|
||||
const Color _coinOuter = Color(0xFFF6B84E);
|
||||
const Color _coinInnerStart = Color(0xFFFFD98B);
|
||||
const Color _coinInnerEnd = Color(0xFFE39B31);
|
||||
const Color _coinBorder = Color(0xFFFFE0A1);
|
||||
const Color _taskIconStart = Color(0xFF4C171E);
|
||||
const Color _taskIconEnd = Color(0xFF281014);
|
||||
const Color _taskIconSurface = Color(0xFF202022);
|
||||
|
||||
/// 奖励中心统一金币图标。
|
||||
class RewardCoinIcon extends StatelessWidget {
|
||||
const RewardCoinIcon({super.key, required this.size});
|
||||
|
||||
final double size;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final inset = size * _coinInnerInsetRatio;
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
padding: EdgeInsets.all(inset),
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: _coinOuter,
|
||||
boxShadow: [BoxShadow(color: Color(0x4DF6B84E), blurRadius: 6)],
|
||||
),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [_coinInnerStart, _coinInnerEnd],
|
||||
),
|
||||
border: Border.all(color: _coinBorder),
|
||||
),
|
||||
child: Text(
|
||||
'N',
|
||||
style: TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: size * _coinLetterRatio,
|
||||
fontWeight: FontWeight.w900,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 奖励中心签到按钮的广告标识。
|
||||
class RewardAdIcon extends StatelessWidget {
|
||||
const RewardAdIcon({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: _adIconWidth,
|
||||
height: _adIconHeight,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: _adIconWidth,
|
||||
height: _adIconHeight,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: AppColors.textPrimary, width: 2),
|
||||
borderRadius: BorderRadius.circular(_adIconRadius),
|
||||
),
|
||||
child: const Text(
|
||||
'AD',
|
||||
style: TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w900,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: _adUnderlineBottom,
|
||||
child: Container(
|
||||
width: _adUnderlineWidth,
|
||||
height: _adUnderlineHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.textPrimary,
|
||||
borderRadius: BorderRadius.circular(_adUnderlineHeight),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据后台任务类型绘制任务图标,不绑定具体任务文案。
|
||||
class RewardTaskLeading extends StatelessWidget {
|
||||
const RewardTaskLeading({super.key, required this.task});
|
||||
|
||||
final RewardTask task;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final invite = _isInviteTask(task);
|
||||
return Container(
|
||||
width: _taskIconSize,
|
||||
height: _taskIconSize,
|
||||
decoration: BoxDecoration(
|
||||
shape: invite ? BoxShape.circle : BoxShape.rectangle,
|
||||
borderRadius: invite ? null : BorderRadius.circular(_taskIconRadius),
|
||||
gradient: invite
|
||||
? const LinearGradient(colors: [_taskIconStart, _taskIconEnd])
|
||||
: null,
|
||||
color: invite ? null : _taskIconSurface,
|
||||
),
|
||||
child: Icon(
|
||||
_taskIcon(task),
|
||||
color: AppColors.textPrimary,
|
||||
size: _taskGlyphSize,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool _isInviteTask(RewardTask task) {
|
||||
final code = task.code.toUpperCase();
|
||||
return task.type == 'INVITE_FRIEND' || code.contains('INVITE');
|
||||
}
|
||||
|
||||
IconData _taskIcon(RewardTask task) {
|
||||
final code = task.code.toUpperCase();
|
||||
if (code.contains('FACEBOOK')) return Icons.facebook_rounded;
|
||||
if (code.contains('YOUTUBE')) return Icons.smart_display_rounded;
|
||||
return switch (task.type) {
|
||||
'WATCH_DURATION' => Icons.play_circle_outline_rounded,
|
||||
'WATCH_EPISODES' => Icons.video_collection_outlined,
|
||||
'COMPLETE_PROFILE' => Icons.person_outline_rounded,
|
||||
'FIRST_PURCHASE' => Icons.shopping_bag_outlined,
|
||||
'INVITE_FRIEND' => Icons.card_giftcard_rounded,
|
||||
_ => Icons.stars_rounded,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user