信息类型增加_邀请奖励

This commit is contained in:
roxy 2026-04-28 10:07:29 +08:00
parent 24c4a4b70c
commit 78c3a95160
8 changed files with 260 additions and 1 deletions

View File

@ -308,6 +308,7 @@
"ownerSendTheRedEnvelope": "أرسل مالك الغرفة عملات المكافأة.",
"rewardCoins": "عملات المكافأة:{1} عملة",
"signInRewardReceived": "تم تسجيل الدخول بنجاح. المكافأة: {1}",
"registerRewardReceived": "تم استلام مكافأة التسجيل: {1}",
"lastWeekProgress": "تقدم الأسبوع الماضي",
"currentProgress": "التقدم الحالي",
"coins2": "{1} عملات",

View File

@ -162,6 +162,7 @@
"ownerSendTheRedEnvelope": "মালিক পুরস্কার কয়েন পাঠিয়েছেন।",
"rewardCoins": "পুরস্কার কয়েন:{1} কয়েন",
"signInRewardReceived": "সাইন ইন সফল হয়েছে। পুরস্কার: {1}",
"registerRewardReceived": "রেজিস্ট্রেশন পুরস্কার পাওয়া গেছে: {1}",
"lastWeekProgress": "গত সপ্তাহের অগ্রগতি",
"redEnvelopeTips2": "*লাল খাম সময়সীমার মধ্যে দাবি না করলে, বাকি কয়েন প্রেরক ব্যবহারকারীকে ফেরত দেওয়া হবে।",
"goToRecharge": "রিচার্জ করতে যান",

View File

@ -134,6 +134,7 @@
"ownerSendTheRedEnvelope": "The owner sent reward coins.",
"rewardCoins": "Reward coins:{1} coins",
"signInRewardReceived": "Signed in successfully. Reward: {1}",
"registerRewardReceived": "Registration reward received: {1}",
"lastWeekProgress": "Last week's progress",
"redEnvelopeTips2": "*If the red envelope is not claimed within the time limit, the remaining coins will be returned to the user who sent the red envelope.",
"goToRecharge": "Go to recharge",

View File

@ -123,6 +123,7 @@
"ownerSendTheRedEnvelope": "Sahip ödül jettonlarını gönderdi.",
"rewardCoins": "Ödül jettonları:{1} jetton",
"signInRewardReceived": "Giriş başarılı. Ödül: {1}",
"registerRewardReceived": "Kayıt ödülü alındı: {1}",
"lastWeekProgress": "Geçen Haftanın İlerlemesi",
"redEnvelopeTips2": "*Kırmızı zarf zaman sınırı içinde talep edilmezse, kalan jettonlar gönderen kullanıcıya iade edilecektir.",
"goToRecharge": "Yüklemeye Git",

View File

@ -1612,6 +1612,9 @@ class SCAppLocalizations {
String signInRewardReceived(String name) =>
translate('signInRewardReceived').replaceAll('{1}', name);
String registerRewardReceived(String name) =>
translate('registerRewardReceived').replaceAll('{1}', name);
String deleteAccount2(String name) =>
translate('deleteAccount2').replaceAll('{1}', name);

View File

@ -584,6 +584,13 @@ class _MessageItem extends StatelessWidget {
) {
_showMsgItemMenu(ct, content);
}, context);
} else if (_isRegisterRewardGrantedType(type)) {
return SCSystemMessageUtils.buildRegisterRewardGrantedMessage(data, (
ct,
content,
) {
_showMsgItemMenu(ct, content);
}, context);
} else if (type == SCSysytemMessageType.USER_SPECIAL_AUDIT_RESULTS.name) {
if (data["content"] != null) {
return Builder(
@ -883,6 +890,11 @@ class _MessageItem extends StatelessWidget {
);
}
bool _isRegisterRewardGrantedType(String type) {
return type.trim().toUpperCase().replaceAll(' ', '_') ==
SCSysytemMessageType.REGISTER_REWARD_GRANTED.name;
}
void _showMsgItemMenu(BuildContext ct, String content) {
SmartDialog.showAttach(
tag: "showMsgItemMenu",

View File

@ -15,4 +15,5 @@ enum SCSysytemMessageType{
CP_LOVE_LETTER,
USER_COINS_RECEIVED,
COIN_SELLER_COINS_RECEIVED,
}
REGISTER_REWARD_GRANTED,
}

View File

@ -1425,4 +1425,243 @@ class SCSystemMessageUtils {
}
return Container();
}
static Widget buildRegisterRewardGrantedMessage(
data,
Function(BuildContext ct, String content) showMsgItemMenu,
BuildContext context,
) {
final content = _registerRewardGrantedContent(data, context);
return Builder(
builder: (ct) {
return GestureDetector(
onLongPress: () {
showMsgItemMenu(ct, content);
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [BoxShadow(blurRadius: 2.w, color: Colors.black26)],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(0),
topRight: Radius.circular(8.w),
bottomLeft: Radius.circular(8.w),
bottomRight: Radius.circular(8),
),
),
padding: EdgeInsets.all(8.0.w),
child: ExtendedText(
content,
style: TextStyle(fontSize: 14.sp, color: Colors.black54),
),
),
);
},
);
}
static String _registerRewardGrantedContent(
dynamic data,
BuildContext context,
) {
final l10n = SCAppLocalizations.of(context)!;
final rewards =
_extractRegisterRewardItems(data)
.map((item) => _registerRewardItemLabel(l10n, item))
.where((item) => item.isNotEmpty)
.toList();
if (rewards.isNotEmpty) {
return l10n.registerRewardReceived(rewards.join(', '));
}
final plainContent = _plainRegisterRewardContent(data);
if (plainContent.isNotEmpty) {
return l10n.registerRewardReceived(plainContent);
}
return l10n.receiveSucc;
}
static List<dynamic> _extractRegisterRewardItems(dynamic value) {
final decoded = _decodeJsonValue(value);
if (decoded is List) {
return decoded;
}
if (decoded is Map) {
final nestedItems = _extractNestedRegisterRewardItems(decoded);
if (nestedItems.isNotEmpty) {
return nestedItems;
}
if (_looksLikeRewardItem(decoded)) {
return [decoded];
}
}
return const <dynamic>[];
}
static String _registerRewardItemLabel(
SCAppLocalizations l10n,
dynamic item,
) {
final decoded = _decodeJsonValue(item);
if (decoded is! Map) {
return _readPlainText(decoded);
}
if (!_looksLikeRewardItem(decoded)) {
final nestedItems = _extractNestedRegisterRewardItems(decoded);
if (nestedItems.isNotEmpty) {
return nestedItems
.map((item) => _registerRewardItemLabel(l10n, item))
.where((item) => item.isNotEmpty)
.join(', ');
}
}
final type = _readPlainText(decoded['type']).trim().toUpperCase();
final detailType =
_readPlainText(decoded['detailType']).trim().toUpperCase();
final quantity = _rewardQuantity(decoded);
if (type == 'GOLD' ||
type == 'COIN' ||
type == 'COINS' ||
detailType == 'GOLD' ||
detailType == 'COIN' ||
detailType == 'COINS') {
return l10n.coins2(quantity.isEmpty ? '0' : quantity);
}
final name = _pickFirstNonEmpty([
_readPlainText(decoded['name']),
_readPlainText(decoded['badgeName']),
_readPlainText(decoded['remark']),
_readPlainText(decoded['title']),
_readPlainText(decoded['content']),
detailType,
type,
]);
if (name.isEmpty) {
return '';
}
final count = _asInt(decoded['quantity']);
if (count > 1) {
return '$name x$count';
}
return name;
}
static List<dynamic> _extractNestedRegisterRewardItems(
Map<dynamic, dynamic> value,
) {
const nestedKeys = [
'rewardItems',
'rewards',
'items',
'activityRewardProps',
'rewardConfig',
'propsGroup',
'propsGroups',
'data',
'content',
];
for (final key in nestedKeys) {
final items = _extractRegisterRewardItems(value[key]);
if (items.isNotEmpty) {
return items;
}
}
return const <dynamic>[];
}
static String _rewardQuantity(Map<dynamic, dynamic> item) {
final quantity = _asInt(item['quantity']);
if (quantity > 0) {
return quantity.toString();
}
return _pickFirstNonEmpty([
_readPlainText(item['amount']),
_readPlainText(item['content']),
]);
}
static String _plainRegisterRewardContent(dynamic data) {
final decoded = _decodeJsonValue(data);
if (decoded is Map) {
return _pickFirstNonEmpty([
_readPlainText(decoded['message']),
_readPlainText(decoded['title']),
_readPlainText(decoded['content']),
]);
}
return _readPlainText(decoded);
}
static dynamic _decodeJsonValue(dynamic value) {
if (value is! String) {
return value;
}
final text = value.trim();
if (!_looksLikeStructuredText(text)) {
return value;
}
try {
return jsonDecode(text);
} catch (_) {
return value;
}
}
static bool _looksLikeRewardItem(Map<dynamic, dynamic> value) {
const rewardKeys = [
'type',
'detailType',
'name',
'quantity',
'amount',
'remark',
'badgeName',
];
return rewardKeys.any(value.containsKey);
}
static String _pickFirstNonEmpty(List<String> values) {
for (final value in values) {
final text = value.trim();
if (text.isNotEmpty) {
return text;
}
}
return '';
}
static String _readPlainText(dynamic value) {
final text = _asString(value).trim();
if (text.isEmpty || _looksLikeStructuredText(text)) {
return '';
}
return text;
}
static bool _looksLikeStructuredText(String value) {
final text = value.trimLeft();
return text.startsWith('{') || text.startsWith('[');
}
static String _asString(dynamic value) {
if (value == null) {
return '';
}
return value.toString();
}
static int _asInt(dynamic value) {
if (value is int) {
return value;
}
if (value is num) {
return value.toInt();
}
return int.tryParse(_asString(value)) ?? 0;
}
}