feat: 系统消息

This commit is contained in:
guozhigq
2024-06-30 22:01:12 +08:00
parent 54253e7be6
commit 3c7189a260
7 changed files with 226 additions and 3 deletions

View File

@ -548,4 +548,8 @@ class Api {
/// 收到的赞 /// 收到的赞
static const String messageLikeAPi = '/x/msgfeed/like'; static const String messageLikeAPi = '/x/msgfeed/like';
/// 系统通知
static const String messageSystemAPi =
'${HttpString.messageBaseUrl}/x/sys-msg/query_unified_notify';
} }

View File

@ -5,6 +5,7 @@ class HttpString {
static const String appBaseUrl = 'https://app.bilibili.com'; static const String appBaseUrl = 'https://app.bilibili.com';
static const String liveBaseUrl = 'https://api.live.bilibili.com'; static const String liveBaseUrl = 'https://api.live.bilibili.com';
static const String passBaseUrl = 'https://passport.bilibili.com'; static const String passBaseUrl = 'https://passport.bilibili.com';
static const String messageBaseUrl = 'https://message.bilibili.com';
static const List<int> validateStatusCodes = [ static const List<int> validateStatusCodes = [
302, 302,
304, 304,

View File

@ -3,6 +3,7 @@ import 'dart:math';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:pilipala/models/msg/like.dart'; import 'package:pilipala/models/msg/like.dart';
import 'package:pilipala/models/msg/reply.dart'; import 'package:pilipala/models/msg/reply.dart';
import 'package:pilipala/models/msg/system.dart';
import '../models/msg/account.dart'; import '../models/msg/account.dart';
import '../models/msg/session.dart'; import '../models/msg/session.dart';
import '../utils/wbi_sign.dart'; import '../utils/wbi_sign.dart';
@ -149,7 +150,7 @@ class MsgHttp {
'msg[msg_status]': 0, 'msg[msg_status]': 0,
'msg[content]': jsonEncode(content), 'msg[content]': jsonEncode(content),
'msg[timestamp]': DateTime.now().millisecondsSinceEpoch ~/ 1000, 'msg[timestamp]': DateTime.now().millisecondsSinceEpoch ~/ 1000,
'msg[new_face_version]': 0, 'msg[new_face_version]': 1,
'msg[dev_id]': getDevId(), 'msg[dev_id]': getDevId(),
'from_firework': 0, 'from_firework': 0,
'build': 0, 'build': 0,
@ -287,4 +288,28 @@ class MsgHttp {
return {'status': false, 'date': [], 'msg': res.data['message']}; return {'status': false, 'date': [], 'msg': res.data['message']};
} }
} }
static Future messageSystem() async {
var res = await Request().get(Api.messageSystemAPi, data: {
'csrf': await Request.getCsrf(),
'page_size': 20,
'build': 0,
'mobi_app': 'web',
});
if (res.data['code'] == 0) {
try {
print(res.data['data']['system_notify_list']);
return {
'status': true,
'data': res.data['data']['system_notify_list']
.map<MessageSystemModel>((e) => MessageSystemModel.fromJson(e))
.toList(),
};
} catch (err) {
return {'status': false, 'date': [], 'msg': err.toString()};
}
} else {
return {'status': false, 'date': [], 'msg': res.data['message']};
}
}
} }

View File

@ -0,0 +1,77 @@
import 'dart:convert';
class MessageSystemModel {
int? id;
int? cursor;
int? type;
String? title;
Map? content;
Source? source;
String? timeAt;
int? cardType;
String? cardBrief;
String? cardMsgBrief;
String? cardCover;
String? cardStoryTitle;
String? cardLink;
String? mc;
int? isStation;
int? isSend;
int? notifyCursor;
MessageSystemModel({
this.id,
this.cursor,
this.type,
this.title,
this.content,
this.source,
this.timeAt,
this.cardType,
this.cardBrief,
this.cardMsgBrief,
this.cardCover,
this.cardStoryTitle,
this.cardLink,
this.mc,
this.isStation,
this.isSend,
this.notifyCursor,
});
factory MessageSystemModel.fromJson(Map<String, dynamic> jsons) =>
MessageSystemModel(
id: jsons["id"],
cursor: jsons["cursor"],
type: jsons["type"],
title: jsons["title"],
content: json.decode(jsons["content"]),
source: Source.fromJson(jsons["source"]),
timeAt: jsons["time_at"],
cardType: jsons["card_type"],
cardBrief: jsons["card_brief"],
cardMsgBrief: jsons["card_msg_brief"],
cardCover: jsons["card_cover"],
cardStoryTitle: jsons["card_story_title"],
cardLink: jsons["card_link"],
mc: jsons["mc"],
isStation: jsons["is_station"],
isSend: jsons["is_send"],
notifyCursor: jsons["notify_cursor"],
);
}
class Source {
String? name;
String? logo;
Source({
this.name,
this.logo,
});
factory Source.fromJson(Map<String, dynamic> json) => Source(
name: json["name"],
logo: json["logo"],
);
}

View File

@ -1,3 +1,15 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/http/msg.dart';
import 'package:pilipala/models/msg/system.dart';
class MessageSystemController extends GetxController {} class MessageSystemController extends GetxController {
RxList<MessageSystemModel> systemItems = <MessageSystemModel>[].obs;
Future queryMessageSystem({String type = 'init'}) async {
var res = await MsgHttp.messageSystem();
if (res['status']) {
systemItems.addAll(res['data']);
}
return res;
}
}

View File

@ -1,4 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/models/msg/system.dart';
import 'controller.dart';
class MessageSystemPage extends StatefulWidget { class MessageSystemPage extends StatefulWidget {
const MessageSystemPage({super.key}); const MessageSystemPage({super.key});
@ -8,12 +12,112 @@ class MessageSystemPage extends StatefulWidget {
} }
class _MessageSystemPageState extends State<MessageSystemPage> { class _MessageSystemPageState extends State<MessageSystemPage> {
final MessageSystemController _messageSystemCtr =
Get.put(MessageSystemController());
late Future _futureBuilderFuture;
final ScrollController scrollController = ScrollController();
@override
void initState() {
super.initState();
_futureBuilderFuture = _messageSystemCtr.queryMessageSystem();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('系统通知'), title: const Text('系统通知'),
), ),
body: RefreshIndicator(
onRefresh: () async {
await _messageSystemCtr.queryMessageSystem();
},
child: FutureBuilder(
future: _futureBuilderFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return const SizedBox();
}
if (snapshot.data['status']) {
final systemItems = _messageSystemCtr.systemItems;
print(systemItems.length);
return Obx(
() => ListView.separated(
controller: scrollController,
itemBuilder: (context, index) => SystemItem(
item: systemItems[index],
index: index,
messageSystemCtr: _messageSystemCtr,
),
itemCount: systemItems.length,
separatorBuilder: (BuildContext context, int index) {
return Divider(
indent: 14,
endIndent: 14,
height: 1,
color: Colors.grey.withOpacity(0.1),
);
},
),
);
} else {
// 请求错误
return CustomScrollView(
slivers: [
HttpError(
errMsg: snapshot.data['msg'],
fn: () {
setState(() {
_futureBuilderFuture =
_messageSystemCtr.queryMessageSystem();
});
},
)
],
);
}
} else {
return const SizedBox();
}
},
),
),
);
}
}
class SystemItem extends StatelessWidget {
final MessageSystemModel item;
final int index;
final MessageSystemController messageSystemCtr;
const SystemItem(
{super.key,
required this.item,
required this.index,
required this.messageSystemCtr});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(14, 14, 14, 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.title!,
style:
const TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
const SizedBox(height: 4),
Text(
item.timeAt!,
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
const SizedBox(height: 6),
Text(item.content!['web']),
],
),
); );
} }
} }

View File

@ -71,7 +71,7 @@ class _WhisperPageState extends State<WhisperPage> {
..._whisperController.noticesList.map((element) { ..._whisperController.noticesList.map((element) {
return InkWell( return InkWell(
onTap: () { onTap: () {
if (['/messageAt', '/messageSystem'] if (['/messageAt']
.contains(element['path'])) { .contains(element['path'])) {
SmartDialog.showToast('功能开发中'); SmartDialog.showToast('功能开发中');
return; return;