Merge branch 'main' into design

This commit is contained in:
guozhigq
2024-06-08 13:16:13 +08:00
15 changed files with 526 additions and 151 deletions

1
assets/loading.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -400,12 +400,24 @@ class Api {
'${HttpString.passBaseUrl}/x/passport-login/captcha?source=main_web'; '${HttpString.passBaseUrl}/x/passport-login/captcha?source=main_web';
// web端短信验证码 // web端短信验证码
static const String smsCode = static const String webSmsCode =
'${HttpString.passBaseUrl}/x/passport-login/web/sms/send'; '${HttpString.passBaseUrl}/x/passport-login/web/sms/send';
// web端验证码登录 // web端验证码登录
static const String webSmsLogin =
'${HttpString.passBaseUrl}/x/passport-login/web/login/sms';
// web端密码登录 // web端密码登录
static const String loginInByWebPwd =
'${HttpString.passBaseUrl}/x/passport-login/web/login';
// web端二维码
static const String qrCodeApi =
'${HttpString.passBaseUrl}/x/passport-login/web/qrcode/generate';
// 扫码登录
static const String loginInByQrcode =
'${HttpString.passBaseUrl}/x/passport-login/web/qrcode/poll';
// app端短信验证码 // app端短信验证码
static const String appSmsCode = static const String appSmsCode =

View File

@ -3,6 +3,7 @@ import 'dart:math';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:encrypt/encrypt.dart'; import 'package:encrypt/encrypt.dart';
import 'package:pilipala/http/constants.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import '../models/login/index.dart'; import '../models/login/index.dart';
import '../utils/login.dart'; import '../utils/login.dart';
@ -21,32 +22,32 @@ class LoginHttp {
} }
} }
static Future sendSmsCode({ // static Future sendSmsCode({
int? cid, // int? cid,
required int tel, // required int tel,
required String token, // required String token,
required String challenge, // required String challenge,
required String validate, // required String validate,
required String seccode, // required String seccode,
}) async { // }) async {
var res = await Request().post( // var res = await Request().post(
Api.appSmsCode, // Api.appSmsCode,
data: { // data: {
'cid': cid, // 'cid': cid,
'tel': tel, // 'tel': tel,
"source": "main_web", // "source": "main_web",
'token': token, // 'token': token,
'challenge': challenge, // 'challenge': challenge,
'validate': validate, // 'validate': validate,
'seccode': seccode, // 'seccode': seccode,
}, // },
options: Options( // options: Options(
contentType: Headers.formUrlEncodedContentType, // contentType: Headers.formUrlEncodedContentType,
// headers: {'user-agent': ApiConstants.userAgent} // // headers: {'user-agent': ApiConstants.userAgent}
), // ),
); // );
print(res); // print(res);
} // }
// web端验证码 // web端验证码
static Future sendWebSmsCode({ static Future sendWebSmsCode({
@ -60,6 +61,7 @@ class LoginHttp {
Map data = { Map data = {
'cid': cid, 'cid': cid,
'tel': tel, 'tel': tel,
"source": "main_web",
'token': token, 'token': token,
'challenge': challenge, 'challenge': challenge,
'validate': validate, 'validate': validate,
@ -67,17 +69,56 @@ class LoginHttp {
}; };
FormData formData = FormData.fromMap({...data}); FormData formData = FormData.fromMap({...data});
var res = await Request().post( var res = await Request().post(
Api.smsCode, Api.webSmsCode,
data: formData, data: formData,
options: Options( options: Options(
contentType: Headers.formUrlEncodedContentType, contentType: Headers.formUrlEncodedContentType,
), ),
); );
print(res); if (res.data['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {'status': false, 'data': [], 'msg': res.data['message']};
}
} }
// web端验证码登录 // web端验证码登录
static Future loginInByWebSmsCode() async {} static Future loginInByWebSmsCode({
int? cid,
required int tel,
required int code,
required String captchaKey,
}) async {
// webSmsLogin
Map data = {
"cid": cid,
"tel": tel,
"code": code,
"source": "main_mini",
"keep": 0,
"captcha_key": captchaKey,
"go_url": HttpString.baseUrl
};
FormData formData = FormData.fromMap({...data});
var res = await Request().post(
Api.webSmsLogin,
data: formData,
options: Options(
contentType: Headers.formUrlEncodedContentType,
),
);
if (res.data['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {'status': false, 'data': [], 'msg': res.data['message']};
}
}
// web端密码登录 // web端密码登录
static Future liginInByWebPwd() async {} static Future liginInByWebPwd() async {}
@ -173,4 +214,69 @@ class LoginHttp {
); );
print(res); print(res);
} }
// web端密码登录
static Future loginInByWebPwd({
required int username,
required String password,
required String token,
required String challenge,
required String validate,
required String seccode,
}) async {
Map data = {
'username': username,
'password': password,
'keep': 0,
'token': token,
'challenge': challenge,
'validate': validate,
'seccode': seccode,
'source': 'main-fe-header',
"go_url": HttpString.baseUrl
};
FormData formData = FormData.fromMap({...data});
var res = await Request().post(
Api.loginInByWebPwd,
data: formData,
options: Options(
contentType: Headers.formUrlEncodedContentType,
),
);
if (res.data['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {'status': false, 'data': [], 'msg': res.data['message']};
}
}
// web端登录二维码
static Future getWebQrcode() async {
var res = await Request().get(Api.qrCodeApi);
if (res.data['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {'status': false, 'data': [], 'msg': res.data['message']};
}
}
// web端二维码轮询登录状态
static Future queryWebQrcodeStatus(String qrcodeKey) async {
var res = await Request()
.get(Api.loginInByQrcode, data: {'qrcode_key': qrcodeKey});
if (res.data['data']['code'] == 0) {
return {
'status': true,
'data': res.data['data'],
};
} else {
return {'status': false, 'data': [], 'msg': res.data['message']};
}
}
} }

View File

@ -69,9 +69,10 @@ class RecVideoItemAppModel {
: null; : null;
// 由于app端api并不会直接返回与owner的关注状态 // 由于app端api并不会直接返回与owner的关注状态
// 所以借用推荐原因是否为“已关注”、“新关注”等判别关注状态从而与web端接口等效 // 所以借用推荐原因是否为“已关注”、“新关注”等判别关注状态从而与web端接口等效
RegExp regex = RegExp(r'已关注|新关注');
isFollowed = rcmdReason != null && isFollowed = rcmdReason != null &&
rcmdReason!.content != null && rcmdReason!.content != null &&
rcmdReason!.content!.contains('关注') regex.hasMatch(rcmdReason!.content!)
? 1 ? 1
: 0; : 0;
// 如果是就无需再显示推荐原因交由view统一处理即可 // 如果是就无需再显示推荐原因交由view统一处理即可

View File

@ -1,11 +1,14 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:encrypt/encrypt.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/http/login.dart'; import 'package:pilipala/http/login.dart';
import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart'; import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart';
import 'package:pilipala/models/login/index.dart'; import 'package:pilipala/models/login/index.dart';
import 'package:pilipala/utils/login.dart';
class LoginPageController extends GetxController { class LoginPageController extends GetxController {
final GlobalKey mobFormKey = GlobalKey<FormState>(); final GlobalKey mobFormKey = GlobalKey<FormState>();
@ -26,9 +29,23 @@ class LoginPageController extends GetxController {
final Gt3FlutterPlugin captcha = Gt3FlutterPlugin(); final Gt3FlutterPlugin captcha = Gt3FlutterPlugin();
// 倒计时60s
RxInt seconds = 60.obs;
late Timer timer;
RxBool smsCodeSendStatus = false.obs;
// 默认密码登录 // 默认密码登录
RxInt loginType = 0.obs; RxInt loginType = 0.obs;
late String captchaKey;
late int tel;
late int webSmsCode;
RxInt validSeconds = 180.obs;
late Timer validTimer;
late String qrcodeKey;
// 监听pageView切换 // 监听pageView切换
void onPageChange(int index) { void onPageChange(int index) {
currentIndex.value = index; currentIndex.value = index;
@ -43,6 +60,7 @@ class LoginPageController extends GetxController {
curve: Curves.easeInOut, curve: Curves.easeInOut,
); );
passwordTextFieldNode.requestFocus(); passwordTextFieldNode.requestFocus();
(mobFormKey.currentState as FormState).save();
} }
} }
@ -86,18 +104,64 @@ class LoginPageController extends GetxController {
} }
} }
// 验证码登录 // web端密码登录
void loginInByCode() { void loginInByWebPassword() async {
if ((msgCodeFormKey.currentState as FormState).validate()) {} if ((passwordFormKey.currentState as FormState).validate()) {
getCaptcha((data) async {
CaptchaDataModel captchaData = data;
var webKeyRes = await LoginHttp.getWebKey();
if (webKeyRes['status']) {
String rhash = webKeyRes['data']['hash'];
String key = webKeyRes['data']['key'];
dynamic publicKey = RSAKeyParser().parse(key);
String passwordEncryptyed = Encrypter(RSA(publicKey: publicKey))
.encrypt(rhash + passwordTextController.text)
.base64;
var res = await LoginHttp.loginInByWebPwd(
username: tel,
password: passwordEncryptyed,
token: captchaData.token!,
challenge: captchaData.geetest!.challenge!,
validate: captchaData.validate!,
seccode: captchaData.seccode!,
);
if (res['status']) {
await LoginUtils.confirmLogin('', null);
} else {
SmartDialog.showToast(res['msg']);
}
} else {
SmartDialog.showToast(webKeyRes['msg']);
}
});
}
} }
// app端验证码 // web端验证码登录
void getMsgCode() async { void loginInByCode() async {
if ((msgCodeFormKey.currentState as FormState).validate()) {
(msgCodeFormKey.currentState as FormState).save();
var res = await LoginHttp.loginInByWebSmsCode(
cid: 86,
tel: tel,
code: webSmsCode,
captchaKey: captchaKey,
);
if (res['status']) {
await LoginUtils.confirmLogin('', null);
} else {
SmartDialog.showToast(res['msg']);
}
}
}
// 获取app端验证码
void getAppMsgCode() async {
getCaptcha((data) async { getCaptcha((data) async {
CaptchaDataModel captchaData = data; CaptchaDataModel captchaData = data;
var res = await LoginHttp.sendAppSmsCode( var res = await LoginHttp.sendAppSmsCode(
cid: 86, cid: 86,
tel: 13734077064, tel: tel,
token: captchaData.token!, token: captchaData.token!,
challenge: captchaData.geetest!.challenge!, challenge: captchaData.geetest!.challenge!,
validate: captchaData.validate!, validate: captchaData.validate!,
@ -121,7 +185,7 @@ class LoginPageController extends GetxController {
captcha.addEventHandler(onShow: (Map<String, dynamic> message) async { captcha.addEventHandler(onShow: (Map<String, dynamic> message) async {
SmartDialog.dismiss(); SmartDialog.dismiss();
}, onClose: (Map<String, dynamic> message) async { }, onClose: (Map<String, dynamic> message) async {
SmartDialog.showToast('关闭验证'); SmartDialog.showToast('取消验证');
}, onResult: (Map<String, dynamic> message) async { }, onResult: (Map<String, dynamic> message) async {
debugPrint("Captcha result: $message"); debugPrint("Captcha result: $message");
String code = message["code"]; String code = message["code"];
@ -201,4 +265,72 @@ class LoginPageController extends GetxController {
captcha.startCaptcha(registerData); captcha.startCaptcha(registerData);
} else {} } else {}
} }
// 获取web端验证码
void getWebMsgCode() async {
getCaptcha((data) async {
CaptchaDataModel captchaData = data;
var res = await LoginHttp.sendWebSmsCode(
cid: 86,
tel: tel,
token: captchaData.token!,
challenge: captchaData.geetest!.challenge!,
validate: captchaData.validate!,
seccode: captchaData.seccode!,
);
if (res['status']) {
captchaKey = res['data']['captcha_key'];
SmartDialog.showToast('验证码已发送');
// 倒计时60s
smsCodeSendStatus.value = true;
startTimer();
} else {
SmartDialog.showToast(res['msg']);
}
});
}
// 验证码倒计时
void startTimer() {
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (seconds.value > 0) {
seconds.value--;
} else {
seconds.value = 60;
smsCodeSendStatus.value = false;
timer.cancel();
}
});
}
// 获取登录二维码
Future getWebQrcode() async {
var res = await LoginHttp.getWebQrcode();
validSeconds.value = 180;
if (res['status']) {
qrcodeKey = res['data']['qrcode_key'];
validTimer = Timer.periodic(const Duration(seconds: 1), (validTimer) {
if (validSeconds.value > 0) {
validSeconds.value--;
queryWebQrcodeStatus();
} else {
getWebQrcode();
validTimer.cancel();
}
});
return res;
} else {
SmartDialog.showToast(res['msg']);
}
}
// 轮询二维码登录状态
Future queryWebQrcodeStatus() async {
var res = await LoginHttp.queryWebQrcodeStatus(qrcodeKey);
if (res['status']) {
await LoginUtils.confirmLogin('', null);
validTimer.cancel();
Get.back();
}
}
} }

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'controller.dart'; import 'controller.dart';
@ -37,6 +38,105 @@ class _LoginPageState extends State<LoginPage> {
icon: const Icon(Icons.arrow_back), icon: const Icon(Icons.arrow_back),
), ),
), ),
actions: [
IconButton(
tooltip: '浏览器打开',
onPressed: () {
Get.offNamed(
'/webview',
parameters: {
'url': 'https://passport.bilibili.com/h5-app/passport/login',
'type': 'login',
'pageTitle': '登录bilibili',
},
);
},
icon: const Icon(Icons.language),
),
IconButton(
tooltip: '二维码登录',
onPressed: () {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, StateSetter setState) {
return AlertDialog(
title: Row(
children: [
const Text('扫码登录'),
IconButton(
onPressed: () {
setState(() {});
},
icon: const Icon(Icons.refresh),
),
],
),
contentPadding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
content: AspectRatio(
aspectRatio: 1,
child: Container(
width: 200,
padding: const EdgeInsets.all(12),
child: FutureBuilder(
future: _loginPageCtr.getWebQrcode(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
if (snapshot.data == null) {
return const SizedBox();
}
Map data = snapshot.data as Map;
return QrImageView(
data: data['data']['url'],
backgroundColor: Colors.transparent,
);
} else {
return const Center(
child: SizedBox(
width: 40,
height: 40,
child: CircularProgressIndicator(),
),
);
}
},
),
),
),
actions: [
TextButton(
onPressed: () {},
child: Obx(() {
return Text(
'有效期: ${_loginPageCtr.validSeconds.value}s',
style: Theme.of(context).textTheme.titleMedium,
);
}),
),
TextButton(
onPressed: () {},
child: Text(
'检查登录状态',
style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.titleMedium!
.fontSize,
),
),
)
],
);
});
},
);
},
icon: const Icon(Icons.qr_code),
),
const SizedBox(width: 22),
],
), ),
body: PageView( body: PageView(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
@ -93,35 +193,12 @@ class _LoginPageState extends State<LoginPage> {
validator: (v) { validator: (v) {
return v!.trim().isNotEmpty ? null : "手机号码不能为空"; return v!.trim().isNotEmpty ? null : "手机号码不能为空";
}, },
onSaved: (val) { onSaved: (val) => _loginPageCtr.tel = int.parse(val!),
print(val);
},
onEditingComplete: () { onEditingComplete: () {
_loginPageCtr.nextStep(); _loginPageCtr.nextStep();
}, },
), ),
), ),
GestureDetector(
onTap: () {
Get.offNamed(
'/webview',
parameters: {
'url':
'https://passport.bilibili.com/h5-app/passport/login',
'type': 'login',
'pageTitle': '登录bilibili',
},
);
},
child: Padding(
padding: const EdgeInsets.only(left: 2),
child: Text(
'使用网页端登录',
style: TextStyle(
color: Theme.of(context).colorScheme.primary),
),
),
),
const Spacer(), const Spacer(),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -236,7 +313,7 @@ class _LoginPageState extends State<LoginPage> {
.primary, // 设置按钮背景色 .primary, // 设置按钮背景色
), ),
onPressed: () => onPressed: () =>
_loginPageCtr.loginInByAppPassword(), _loginPageCtr.loginInByWebPassword(),
child: const Text('确认登录'), child: const Text('确认登录'),
) )
], ],
@ -308,21 +385,28 @@ class _LoginPageState extends State<LoginPage> {
? null ? null
: "验证码不能为空"; : "验证码不能为空";
}, },
onSaved: (val) { onSaved: (val) => _loginPageCtr.webSmsCode =
print(val); int.parse(val!),
},
), ),
Positioned( Obx(() {
right: 8, return Positioned(
top: 4, right: 8,
child: Center( top: 0,
child: TextButton( child: Center(
onPressed: () => child: TextButton(
_loginPageCtr.getMsgCode(), onPressed: _loginPageCtr
child: const Text('获取验证码'), .smsCodeSendStatus.value
? null
: () =>
_loginPageCtr.getWebMsgCode(),
child: _loginPageCtr
.smsCodeSendStatus.value
? Text(
'重新获取(${_loginPageCtr.seconds.value}s)')
: const Text('获取验证码')),
), ),
), );
), })
], ],
), ),
), ),

View File

@ -6,7 +6,6 @@ import 'package:pilipala/http/user.dart';
import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/models/common/theme_type.dart';
import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/user/info.dart';
import 'package:pilipala/models/user/stat.dart'; import 'package:pilipala/models/user/stat.dart';
import 'package:pilipala/utils/route_push.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
class MineController extends GetxController { class MineController extends GetxController {
@ -34,8 +33,8 @@ class MineController extends GetxController {
onLogin() async { onLogin() async {
if (!userLogin.value) { if (!userLogin.value) {
RoutePush.loginPush(); // RoutePush.loginPush();
// Get.toNamed('/loginPage'); Get.toNamed('/loginPage');
} else { } else {
int mid = userInfo.value.mid!; int mid = userInfo.value.mid!;
String face = userInfo.value.face!; String face = userInfo.value.face!;

View File

@ -5,6 +5,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:lottie/lottie.dart';
import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/index.dart';
@ -97,11 +98,14 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
); );
} }
} else { } else {
return const SliverToBoxAdapter( return SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
height: 100, height: 100,
child: Center( child: Center(
child: CircularProgressIndicator(), child: Lottie.asset(
'assets/loading.json',
width: 200,
),
), ),
), ),
); );
@ -595,8 +599,4 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
); );
}); });
} }
// Widget StaffPanel(BuildContext context, videoIntroController) {
// return
// }
} }

View File

@ -76,7 +76,7 @@ class WebviewController extends GetxController {
(url.startsWith( (url.startsWith(
'https://passport.bilibili.com/web/sso/exchange_cookie') || 'https://passport.bilibili.com/web/sso/exchange_cookie') ||
url.startsWith('https://m.bilibili.com/'))) { url.startsWith('https://m.bilibili.com/'))) {
confirmLogin(url); LoginUtils.confirmLogin(url, controller);
} }
}, },
onWebResourceError: (WebResourceError error) {}, onWebResourceError: (WebResourceError error) {},
@ -97,54 +97,4 @@ class WebviewController extends GetxController {
) )
..loadRequest(Uri.parse(url)); ..loadRequest(Uri.parse(url));
} }
confirmLogin(url) async {
var content = '';
if (url != null) {
content = '${content + url}; \n';
}
try {
await SetCookie.onSet();
final result = await UserHttp.userInfo();
if (result['status'] && result['data'].isLogin) {
SmartDialog.showToast('登录成功');
try {
Box userInfoCache = GStrorage.userInfo;
if (!userInfoCache.isOpen) {
userInfoCache = await Hive.openBox('userInfo');
}
await userInfoCache.put('userInfoCache', result['data']);
final HomeController homeCtr = Get.find<HomeController>();
homeCtr.updateLoginStatus(true);
homeCtr.userFace.value = result['data'].face;
final MediaController mediaCtr = Get.find<MediaController>();
mediaCtr.mid = result['data'].mid;
await LoginUtils.refreshLoginStatus(true);
} catch (err) {
SmartDialog.show(builder: (BuildContext context) {
return AlertDialog(
title: const Text('登录遇到问题'),
content: Text(err.toString()),
actions: [
TextButton(
onPressed: () => controller.reload(),
child: const Text('确认'),
)
],
);
});
}
Get.back();
} else {
// 获取用户信息失败
SmartDialog.showToast(result['msg']);
Clipboard.setData(ClipboardData(text: result['msg']));
}
} catch (e) {
SmartDialog.showNotify(msg: e.toString(), notifyType: NotifyType.warning);
content = content + e.toString();
Clipboard.setData(ClipboardData(text: content));
}
}
} }

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/utils/login.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'controller.dart'; import 'controller.dart';
import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter/webview_flutter.dart';
@ -43,7 +44,8 @@ class _WebviewPageState extends State<WebviewPage> {
Obx( Obx(
() => _webviewController.type.value == 'login' () => _webviewController.type.value == 'login'
? TextButton( ? TextButton(
onPressed: () => _webviewController.confirmLogin(null), onPressed: () =>
LoginUtils.confirmLogin(null, _webviewController),
child: const Text('刷新登录状态'), child: const Text('刷新登录状态'),
) )
: const SizedBox(), : const SizedBox(),

View File

@ -7,6 +7,7 @@ import 'package:flutter_volume_controller/flutter_volume_controller.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:lottie/lottie.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart'; import 'package:media_kit_video/media_kit_video.dart';
import 'package:pilipala/models/common/gesture_mode.dart'; import 'package:pilipala/models/common/gesture_mode.dart';
@ -913,9 +914,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
colors: [Colors.black26, Colors.transparent], colors: [Colors.black26, Colors.transparent],
), ),
), ),
child: Image.asset( child: Lottie.asset(
'assets/images/loading.gif', 'assets/loading.json',
height: 25, width: 200,
), ),
), ),
); );

View File

@ -2,12 +2,18 @@ import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/pages/dynamics/index.dart'; import 'package:pilipala/pages/dynamics/index.dart';
import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/media/index.dart'; import 'package:pilipala/pages/media/index.dart';
import 'package:pilipala/pages/mine/index.dart'; import 'package:pilipala/pages/mine/index.dart';
import 'package:pilipala/utils/cookie.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
class LoginUtils { class LoginUtils {
@ -57,4 +63,56 @@ class LoginUtils {
String uuid = getUUID() + getUUID(); String uuid = getUUID() + getUUID();
return 'XY${uuid.substring(0, 35).toUpperCase()}'; return 'XY${uuid.substring(0, 35).toUpperCase()}';
} }
static confirmLogin(url, controller) async {
var content = '';
if (url != null) {
content = '${content + url}; \n';
}
try {
await SetCookie.onSet();
final result = await UserHttp.userInfo();
if (result['status'] && result['data'].isLogin) {
SmartDialog.showToast('登录成功');
try {
Box userInfoCache = GStrorage.userInfo;
if (!userInfoCache.isOpen) {
userInfoCache = await Hive.openBox('userInfo');
}
await userInfoCache.put('userInfoCache', result['data']);
final HomeController homeCtr = Get.find<HomeController>();
homeCtr.updateLoginStatus(true);
homeCtr.userFace.value = result['data'].face;
final MediaController mediaCtr = Get.find<MediaController>();
mediaCtr.mid = result['data'].mid;
await LoginUtils.refreshLoginStatus(true);
} catch (err) {
SmartDialog.show(builder: (BuildContext context) {
return AlertDialog(
title: const Text('登录遇到问题'),
content: Text(err.toString()),
actions: [
TextButton(
onPressed: controller != null
? () => controller.reload()
: SmartDialog.dismiss,
child: const Text('确认'),
)
],
);
});
}
Get.back();
} else {
// 获取用户信息失败
SmartDialog.showToast(result['msg']);
Clipboard.setData(ClipboardData(text: result['msg']));
}
} catch (e) {
SmartDialog.showNotify(msg: e.toString(), notifyType: NotifyType.warning);
content = content + e.toString();
Clipboard.setData(ClipboardData(text: content));
}
}
} }

View File

@ -674,10 +674,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: gt3_flutter_plugin name: gt3_flutter_plugin
sha256: f12bff2bfbcf27467833f8d564dcc24ee2f1b3254a7c7cf5eb2c4590baf11cc1 sha256: "08f35692e937770ad6b3e2017eb8ef81839a82b8a63f5acf3abab14b688fc36c"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.0.8" version: "0.1.0"
hive: hive:
dependency: "direct main" dependency: "direct main"
description: description:
@ -862,6 +862,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
lottie:
dependency: "direct main"
description:
name: lottie
sha256: "6a24ade5d3d918c306bb1c21a6b9a04aab0489d51a2582522eea820b4093b62b"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.2"
mailer: mailer:
dependency: transitive dependency: transitive
description: description:
@ -973,10 +981,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: mime name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
nm: nm:
dependency: transitive dependency: transitive
description: description:
@ -1046,10 +1054,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.1" version: "2.1.3"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
@ -1062,10 +1070,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.3.1" version: "2.4.0"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@ -1210,6 +1218,22 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
qr:
dependency: transitive
description:
name: qr
sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
qr_flutter:
dependency: "direct main"
description:
name: qr_flutter
sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.0"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@ -1230,10 +1254,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: saver_gallery name: saver_gallery
sha256: "2657953427ebe5a3b2d08157d41587c01923ccce3f1a616d55082be7470f8530" sha256: "0f740608072053a0da3b19cc5812a87e36f5c3c0b959d2475c4eb3d697f4a782"
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.1" version: "3.0.3"
screen_brightness: screen_brightness:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -132,7 +132,7 @@ dependencies:
# html渲染 # html渲染
flutter_html: ^3.0.0-beta.2 flutter_html: ^3.0.0-beta.2
# 极验 # 极验
gt3_flutter_plugin: ^0.0.8 gt3_flutter_plugin: ^0.1.0
uuid: ^3.0.7 uuid: ^3.0.7
scrollable_positioned_list: ^0.3.8 scrollable_positioned_list: ^0.3.8
catcher_2: ^1.2.6 catcher_2: ^1.2.6
@ -144,6 +144,9 @@ dependencies:
expandable: ^5.0.1 expandable: ^5.0.1
# 投屏 # 投屏
dlna_dart: ^0.0.8 dlna_dart: ^0.0.8
lottie: ^3.1.2
# 二维码
qr_flutter: ^4.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@ -203,6 +206,7 @@ flutter:
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
assets: assets:
- assets/
- assets/images/ - assets/images/
- assets/images/lv/ - assets/images/lv/
- assets/images/logo/ - assets/images/logo/