Merge branch 'design'
This commit is contained in:
@ -606,4 +606,7 @@ class Api {
|
||||
|
||||
/// 番剧点赞投币收藏状态
|
||||
static const String bangumiActionStatus = '/pgc/season/episode/community';
|
||||
|
||||
/// @我的
|
||||
static const String messageAtAPi = '/x/msgfeed/at?';
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pilipala/models/msg/at.dart';
|
||||
import 'package:pilipala/models/msg/like.dart';
|
||||
import 'package:pilipala/models/msg/reply.dart';
|
||||
import 'package:pilipala/models/msg/system.dart';
|
||||
@ -350,4 +351,24 @@ class MsgHttp {
|
||||
return {'status': false, 'date': [], 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
|
||||
// @我的
|
||||
static Future messageAt() async {
|
||||
var res = await Request().get(Api.messageAtAPi, data: {
|
||||
'build': 0,
|
||||
'mobi_app': 'web',
|
||||
});
|
||||
if (res.data['code'] == 0) {
|
||||
try {
|
||||
return {
|
||||
'status': true,
|
||||
'data': MessageAtModel.fromJson(res.data['data']),
|
||||
};
|
||||
} catch (err) {
|
||||
return {'status': false, 'data': [], 'msg': err.toString()};
|
||||
}
|
||||
} else {
|
||||
return {'status': false, 'data': [], 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,13 +136,13 @@ class ReplyHttp {
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
static Future uploadImage({required XFile xFile, String type = 'im'}) async {
|
||||
static Future uploadImage(
|
||||
{required XFile xFile, String type = 'new_dyn'}) async {
|
||||
var formData = FormData.fromMap({
|
||||
'file_up': await xFileToMultipartFile(xFile),
|
||||
'biz': type,
|
||||
'csrf': await Request.getCsrf(),
|
||||
'build': 0,
|
||||
'mobi_app': 'web',
|
||||
'category': 'daily',
|
||||
});
|
||||
var res = await Request().post(
|
||||
Api.uploadImage,
|
||||
|
140
lib/models/msg/at.dart
Normal file
140
lib/models/msg/at.dart
Normal file
@ -0,0 +1,140 @@
|
||||
class MessageAtModel {
|
||||
Cursor? cursor;
|
||||
List<MessageAtItems>? items;
|
||||
|
||||
MessageAtModel({this.cursor, this.items});
|
||||
|
||||
MessageAtModel.fromJson(Map<String, dynamic> json) {
|
||||
cursor = json['cursor'] != null ? Cursor.fromJson(json['cursor']) : null;
|
||||
if (json['items'] != null) {
|
||||
items = <MessageAtItems>[];
|
||||
json['items'].forEach((v) {
|
||||
items!.add(MessageAtItems.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Cursor {
|
||||
Cursor({
|
||||
this.id,
|
||||
this.isEnd,
|
||||
this.time,
|
||||
});
|
||||
|
||||
int? id;
|
||||
bool? isEnd;
|
||||
int? time;
|
||||
|
||||
Cursor.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
isEnd = json['isEnd'];
|
||||
time = json['time'];
|
||||
}
|
||||
}
|
||||
|
||||
class MessageAtItems {
|
||||
int? id;
|
||||
int? atTime;
|
||||
User? user;
|
||||
MessageAtItem? item;
|
||||
|
||||
MessageAtItems({this.id, this.atTime, this.user, this.item});
|
||||
|
||||
MessageAtItems.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
atTime = json['at_time'];
|
||||
user = json['user'] != null ? User.fromJson(json['user']) : null;
|
||||
item = json['item'] != null ? MessageAtItem.fromJson(json['item']) : null;
|
||||
}
|
||||
}
|
||||
|
||||
class MessageAtItem {
|
||||
String? type;
|
||||
String? business;
|
||||
int? businessId;
|
||||
String? title;
|
||||
String? image;
|
||||
String? uri;
|
||||
int? subjectId;
|
||||
int? rootId;
|
||||
int? targetId;
|
||||
int? sourceId;
|
||||
String? sourceContent;
|
||||
String? nativeUri;
|
||||
List<User>? atDetails;
|
||||
List<dynamic>? topicDetails;
|
||||
bool? hideReplyButton;
|
||||
|
||||
MessageAtItem({
|
||||
this.type,
|
||||
this.business,
|
||||
this.businessId,
|
||||
this.title,
|
||||
this.image,
|
||||
this.uri,
|
||||
this.subjectId,
|
||||
this.rootId,
|
||||
this.targetId,
|
||||
this.sourceId,
|
||||
this.sourceContent,
|
||||
this.nativeUri,
|
||||
this.atDetails,
|
||||
this.topicDetails,
|
||||
this.hideReplyButton,
|
||||
});
|
||||
|
||||
MessageAtItem.fromJson(Map<String, dynamic> json) {
|
||||
type = json['type'];
|
||||
business = json['business'];
|
||||
businessId = json['business_id'];
|
||||
title = json['title'];
|
||||
image = json['image'];
|
||||
uri = json['uri'];
|
||||
subjectId = json['subject_id'];
|
||||
rootId = json['root_id'];
|
||||
targetId = json['target_id'];
|
||||
sourceId = json['source_id'];
|
||||
sourceContent = json['source_content'];
|
||||
nativeUri = json['native_uri'];
|
||||
if (json['at_details'] != null) {
|
||||
atDetails = <User>[];
|
||||
json['at_details'].forEach((v) {
|
||||
atDetails!.add(User.fromJson(v));
|
||||
});
|
||||
}
|
||||
if (json['topic_details'] != null) {
|
||||
topicDetails = <dynamic>[];
|
||||
json['topic_details'].forEach((v) {
|
||||
topicDetails!.add(v);
|
||||
});
|
||||
}
|
||||
hideReplyButton = json['hide_reply_button'];
|
||||
}
|
||||
}
|
||||
|
||||
class User {
|
||||
int? mid;
|
||||
int? fans;
|
||||
String? nickname;
|
||||
String? avatar;
|
||||
String? midLink;
|
||||
bool? follow;
|
||||
|
||||
User(
|
||||
{this.mid,
|
||||
this.fans,
|
||||
this.nickname,
|
||||
this.avatar,
|
||||
this.midLink,
|
||||
this.follow});
|
||||
|
||||
User.fromJson(Map<String, dynamic> json) {
|
||||
mid = json['mid'];
|
||||
fans = json['fans'];
|
||||
nickname = json['nickname'];
|
||||
avatar = json['avatar'];
|
||||
midLink = json['mid_link'];
|
||||
follow = json['follow'];
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/member.dart';
|
||||
import 'package:pilipala/models/member/archive.dart';
|
||||
import 'package:pilipala/utils/global_data_cache.dart';
|
||||
|
||||
class MemberArchiveController extends GetxController {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
@ -17,12 +18,18 @@ class MemberArchiveController extends GetxController {
|
||||
].obs;
|
||||
RxList<VListItemModel> archivesList = <VListItemModel>[].obs;
|
||||
RxBool isLoading = false.obs;
|
||||
late int ownerMid;
|
||||
RxBool isOwner = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
mid = int.parse(Get.parameters['mid']!);
|
||||
currentOrder.value = orderList.first;
|
||||
ownerMid = GlobalDataCache().userInfo != null
|
||||
? GlobalDataCache().userInfo!.mid!
|
||||
: -1;
|
||||
isOwner.value = mid == -1 || mid == ownerMid;
|
||||
}
|
||||
|
||||
// 获取用户投稿
|
||||
|
@ -51,8 +51,9 @@ class _MemberArchivePageState extends State<MemberArchivePage> {
|
||||
centerTitle: false,
|
||||
title: Obx(
|
||||
() => Text(
|
||||
'他的投稿 - ${_memberArchivesController.currentOrder['label']}',
|
||||
style: Theme.of(context).textTheme.titleMedium),
|
||||
'${_memberArchivesController.isOwner.value ? '我' : 'Ta'}的投稿 - ${_memberArchivesController.currentOrder['label']}',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
// Obx(
|
||||
|
@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/member.dart';
|
||||
import 'package:pilipala/models/member/article.dart';
|
||||
import 'package:pilipala/utils/global_data_cache.dart';
|
||||
|
||||
class MemberArticleController extends GetxController {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
@ -12,11 +13,17 @@ class MemberArticleController extends GetxController {
|
||||
bool hasMore = true;
|
||||
RxBool isLoading = false.obs;
|
||||
RxList<MemberArticleItemModel> articleList = <MemberArticleItemModel>[].obs;
|
||||
late int ownerMid;
|
||||
RxBool isOwner = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
mid = int.parse(Get.parameters['mid']!);
|
||||
ownerMid = GlobalDataCache().userInfo != null
|
||||
? GlobalDataCache().userInfo!.mid!
|
||||
: -1;
|
||||
isOwner.value = mid == -1 || mid == ownerMid;
|
||||
}
|
||||
|
||||
Future getMemberArticle(type) async {
|
||||
|
@ -50,7 +50,12 @@ class _MemberArticlePageState extends State<MemberArticlePage> {
|
||||
appBar: AppBar(
|
||||
titleSpacing: 0,
|
||||
centerTitle: false,
|
||||
title: const Text('Ta的图文', style: TextStyle(fontSize: 16)),
|
||||
title: Obx(
|
||||
() => Text(
|
||||
'${_memberArticleController.isOwner.value ? '我' : 'Ta'}的图文',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/member.dart';
|
||||
import 'package:pilipala/models/dynamics/result.dart';
|
||||
import 'package:pilipala/utils/global_data_cache.dart';
|
||||
|
||||
class MemberDynamicsController extends GetxController {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
@ -10,11 +11,17 @@ class MemberDynamicsController extends GetxController {
|
||||
int count = 0;
|
||||
bool hasMore = true;
|
||||
RxList<DynamicItemModel> dynamicsList = <DynamicItemModel>[].obs;
|
||||
late int ownerMid;
|
||||
RxBool isOwner = false.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
mid = int.parse(Get.parameters['mid']!);
|
||||
ownerMid = GlobalDataCache().userInfo != null
|
||||
? GlobalDataCache().userInfo!.mid!
|
||||
: -1;
|
||||
isOwner.value = mid == -1 || mid == ownerMid;
|
||||
}
|
||||
|
||||
Future getMemberDynamic(type) async {
|
||||
|
@ -56,7 +56,12 @@ class _MemberDynamicsPageState extends State<MemberDynamicsPage> {
|
||||
appBar: AppBar(
|
||||
titleSpacing: 0,
|
||||
centerTitle: false,
|
||||
title: Text('他的动态', style: Theme.of(context).textTheme.titleMedium),
|
||||
title: Obx(
|
||||
() => Text(
|
||||
'${_memberDynamicController.isOwner.value ? '我' : 'Ta'}的动态',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: CustomScrollView(
|
||||
controller: _memberDynamicController.scrollController,
|
||||
|
@ -1,3 +1,27 @@
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/http/msg.dart';
|
||||
import 'package:pilipala/models/msg/at.dart';
|
||||
|
||||
class MessageAtController extends GetxController {}
|
||||
class MessageAtController extends GetxController {
|
||||
Cursor? cursor;
|
||||
RxList<MessageAtItems> atItems = <MessageAtItems>[].obs;
|
||||
|
||||
Future queryMessageAt({String type = 'init'}) async {
|
||||
if (cursor != null && cursor!.isEnd == true) {
|
||||
return {};
|
||||
}
|
||||
var res = await MsgHttp.messageAt();
|
||||
if (res['status']) {
|
||||
cursor = res['data'].cursor;
|
||||
if (type == 'init') {
|
||||
atItems.value = res['data'].items;
|
||||
} else {
|
||||
atItems.addAll(res['data'].items);
|
||||
}
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,14 @@
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pilipala/common/widgets/http_error.dart';
|
||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||
import 'package:pilipala/common/widgets/no_data.dart';
|
||||
import 'package:pilipala/models/msg/at.dart';
|
||||
import 'package:pilipala/pages/message/utils/index.dart';
|
||||
import 'package:pilipala/utils/utils.dart';
|
||||
|
||||
import 'controller.dart';
|
||||
|
||||
class MessageAtPage extends StatefulWidget {
|
||||
const MessageAtPage({super.key});
|
||||
@ -8,12 +18,179 @@ class MessageAtPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageAtPageState extends State<MessageAtPage> {
|
||||
final MessageAtController _messageAtCtr = Get.put(MessageAtController());
|
||||
late Future _futureBuilderFuture;
|
||||
final ScrollController scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_futureBuilderFuture = _messageAtCtr.queryMessageAt();
|
||||
scrollController.addListener(
|
||||
() async {
|
||||
if (scrollController.position.pixels >=
|
||||
scrollController.position.maxScrollExtent - 200) {
|
||||
EasyThrottle.throttle('follow', const Duration(seconds: 1), () {
|
||||
_messageAtCtr.queryMessageAt(type: 'onLoad');
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('@我的'),
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _messageAtCtr.queryMessageAt(type: 'init');
|
||||
},
|
||||
child: FutureBuilder(
|
||||
future: _futureBuilderFuture,
|
||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
final Map<String, dynamic>? data = snapshot.data;
|
||||
if (data != null && data['status']) {
|
||||
final RxList<MessageAtItems> atItems = _messageAtCtr.atItems;
|
||||
return Obx(
|
||||
() => atItems.isEmpty
|
||||
? const CustomScrollView(slivers: [NoData()])
|
||||
: ListView.separated(
|
||||
controller: scrollController,
|
||||
itemBuilder: (context, index) => AtItem(
|
||||
item: atItems[index],
|
||||
index: index,
|
||||
messageAtCtr: _messageAtCtr,
|
||||
),
|
||||
itemCount: atItems.length,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(
|
||||
indent: 66,
|
||||
endIndent: 14,
|
||||
height: 1,
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// 请求错误
|
||||
return HttpError(
|
||||
errMsg: data?['msg'] ?? '请求异常',
|
||||
fn: () {
|
||||
setState(() {
|
||||
_futureBuilderFuture = _messageAtCtr.queryMessageAt();
|
||||
});
|
||||
},
|
||||
isInSliver: false,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AtItem extends StatelessWidget {
|
||||
final MessageAtItems item;
|
||||
final int index;
|
||||
final MessageAtController messageAtCtr;
|
||||
|
||||
const AtItem({
|
||||
super.key,
|
||||
required this.item,
|
||||
required this.index,
|
||||
required this.messageAtCtr,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color outline = Theme.of(context).colorScheme.outline;
|
||||
final User user = item.user!;
|
||||
final String heroTag = Utils.makeHeroTag(user.mid);
|
||||
final Uri uri = Uri.parse(item.item!.uri!);
|
||||
|
||||
/// bilibili://
|
||||
final Uri nativeUri = Uri.parse(item.item!.nativeUri!);
|
||||
final String type = item.item!.type!;
|
||||
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
MessageUtils.onClickMessage(context, uri, nativeUri, type);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.toNamed('/member?mid=${item.user!.mid}',
|
||||
arguments: {'face': item.user!.avatar, 'heroTag': heroTag});
|
||||
},
|
||||
child: Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
width: 42,
|
||||
height: 42,
|
||||
type: 'avatar',
|
||||
src: item.user!.avatar,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text.rich(TextSpan(children: [
|
||||
TextSpan(text: item.user!.nickname!),
|
||||
const TextSpan(text: ' '),
|
||||
if (item.item!.type! == 'reply')
|
||||
TextSpan(
|
||||
text: '在评论中@了我',
|
||||
style: TextStyle(color: outline),
|
||||
),
|
||||
])),
|
||||
const SizedBox(height: 6),
|
||||
Text(item.item!.sourceContent!),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
Utils.dateFormat(item.atTime!, formatType: 'detail'),
|
||||
style: TextStyle(color: outline),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 25),
|
||||
if (item.item!.type! == 'reply')
|
||||
Container(
|
||||
width: 60,
|
||||
height: 80,
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Text(
|
||||
item.item!.title!,
|
||||
maxLines: 3,
|
||||
style: const TextStyle(fontSize: 12, letterSpacing: 0.3),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,11 @@ class MessageLikeController extends GetxController {
|
||||
id: params['id'], likeTime: params['likeTime']);
|
||||
if (res['status']) {
|
||||
cursor = res['data'].total.cursor;
|
||||
likeItems.addAll(res['data'].total.items);
|
||||
if (type == 'init') {
|
||||
likeItems.value = res['data'].total.items;
|
||||
} else {
|
||||
likeItems.addAll(res['data'].total.items);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -13,13 +13,20 @@ class MessageUtils {
|
||||
BuildContext context, Uri uri, Uri nativeUri, String type) async {
|
||||
final String path = uri.path;
|
||||
final String bvid = path.split('/').last;
|
||||
String? sourceType;
|
||||
final String nativePath = nativeUri.path;
|
||||
final String oid = nativePath.split('/').last;
|
||||
String oid = nativePath.split('/').last;
|
||||
final Map<String, String> queryParameters = nativeUri.queryParameters;
|
||||
final String? argCid = queryParameters['cid'];
|
||||
// final String? page = queryParameters['page'];
|
||||
final String? commentRootId = queryParameters['comment_root_id'];
|
||||
String? commentRootId = queryParameters['comment_root_id'];
|
||||
// final String? commentSecondaryId = queryParameters['comment_secondary_id'];
|
||||
if (nativePath.contains('detail')) {
|
||||
// 动态详情
|
||||
sourceType = 'opus';
|
||||
oid = nativePath.split('/')[3];
|
||||
commentRootId = nativePath.split('/')[4];
|
||||
}
|
||||
switch (type) {
|
||||
case 'video':
|
||||
case 'danmu':
|
||||
@ -42,7 +49,12 @@ class MessageUtils {
|
||||
case 'reply':
|
||||
debugPrint('commentRootId: $oid, $commentRootId');
|
||||
navigateToComment(
|
||||
context, oid, commentRootId!, ReplyType.video, nativeUri);
|
||||
context,
|
||||
oid,
|
||||
commentRootId!,
|
||||
sourceType == 'opus' ? ReplyType.dynamics : ReplyType.video,
|
||||
nativeUri,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -11,7 +11,7 @@ class VideoReplyReplyController extends GetxController {
|
||||
int? aid;
|
||||
// rpid 请求楼中楼回复
|
||||
String? rpid;
|
||||
ReplyType replyType = ReplyType.video;
|
||||
ReplyType? replyType;
|
||||
bool showRoot = false;
|
||||
ReplyItemModel? rootReply;
|
||||
RxList<ReplyItemModel> replyList = <ReplyItemModel>[].obs;
|
||||
@ -40,7 +40,7 @@ class VideoReplyReplyController extends GetxController {
|
||||
oid: aid!,
|
||||
root: rpid!,
|
||||
pageNum: currentPage + 1,
|
||||
type: replyType.index,
|
||||
type: (replyType ?? ReplyType.video).index,
|
||||
);
|
||||
if (res['status']) {
|
||||
final List<ReplyItemModel> replies = res['data'].replies;
|
||||
|
@ -73,11 +73,6 @@ class _WhisperPageState extends State<WhisperPage> {
|
||||
..._whisperController.noticesList.map((element) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
if (['/messageAt']
|
||||
.contains(element['path'])) {
|
||||
SmartDialog.showToast('功能开发中');
|
||||
return;
|
||||
}
|
||||
Get.toNamed(element['path']);
|
||||
|
||||
if (element['count'] > 0) {
|
||||
|
Reference in New Issue
Block a user