mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
mod: login page: sync orz12/main
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -21,13 +21,10 @@ class Constants {
|
|||||||
static const String traceId =
|
static const String traceId =
|
||||||
'11111111111111111111111111111111:1111111111111111:0:0';
|
'11111111111111111111111111111111:1111111111111111:0:0';
|
||||||
static const String userAgent =
|
static const String userAgent =
|
||||||
'Mozilla/5.0 BiliDroid/1.46.2 (bbcallen@gmail.com) os/android model/vivo mobi_app/android build/1462100 channel/bili innerVer/1462100 osVer/14 network/2';
|
'Mozilla/5.0 BiliDroid/1.46.2 (bbcallen@gmail.com) os/android model/vivo mobi_app/android_hd build/2001100 channel/yingyongbao innerVer/2001100 osVer/14 network/2';
|
||||||
static const String statistics =
|
static const String statistics =
|
||||||
'%7B%22appId%22%3A5%2C%22platform%22%3A3%2C%22version%22%3A%221.46.2%22%2C%22abtest%22%3A%22%22%7D';
|
'%7B%22appId%22%3A5%2C%22platform%22%3A3%2C%22version%22%3A%221.46.2%22%2C%22abtest%22%3A%22%22%7D';
|
||||||
// jsonEncode(
|
//Uri.encodeComponent('{"appId": 5,"platform": 3,"version": "1.46.2","abtest": ""}');
|
||||||
// {"appId": 5, "platform": 3, "version": "1.46.2", "abtest": ""});
|
|
||||||
// Uri.encodeComponent(
|
|
||||||
// '{"appId": 5,"platform": 3,"version": "1.46.2","abtest": ""}');
|
|
||||||
|
|
||||||
//内容来自 https://passport.bilibili.com/web/generic/country/list
|
//内容来自 https://passport.bilibili.com/web/generic/country/list
|
||||||
static const List<Map<String, dynamic>> internationalDialingPrefix = [
|
static const List<Map<String, dynamic>> internationalDialingPrefix = [
|
||||||
|
|||||||
@@ -587,6 +587,9 @@ class Api {
|
|||||||
static const String safeCenterSmsVerify =
|
static const String safeCenterSmsVerify =
|
||||||
'${HttpString.passBaseUrl}/x/safecenter/login/tel/verify';
|
'${HttpString.passBaseUrl}/x/safecenter/login/tel/verify';
|
||||||
|
|
||||||
|
static const String oauth2AccessToken =
|
||||||
|
'${HttpString.passBaseUrl}/x/passport-login/oauth2/access_token';
|
||||||
|
|
||||||
/// 密码加密密钥
|
/// 密码加密密钥
|
||||||
/// disable_rcmd
|
/// disable_rcmd
|
||||||
/// local_id
|
/// local_id
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'dart:convert';
|
|||||||
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:flutter/material.dart';
|
|
||||||
import '../common/constants.dart';
|
import '../common/constants.dart';
|
||||||
import '../models/login/index.dart';
|
import '../models/login/index.dart';
|
||||||
import '../utils/login.dart';
|
import '../utils/login.dart';
|
||||||
@@ -43,6 +42,7 @@ class LoginHttp {
|
|||||||
);
|
);
|
||||||
var res = await Request()
|
var res = await Request()
|
||||||
.post(Api.getTVCode, queryParameters: {...params, 'sign': sign});
|
.post(Api.getTVCode, queryParameters: {...params, 'sign': sign});
|
||||||
|
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
@@ -107,9 +107,10 @@ class LoginHttp {
|
|||||||
int timestamp = DateTime.now().millisecondsSinceEpoch;
|
int timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||||
var data = {
|
var data = {
|
||||||
'appkey': Constants.appKey,
|
'appkey': Constants.appKey,
|
||||||
'build': '1462100',
|
'build': '2001100',
|
||||||
'buvid': buvid,
|
'buvid': buvid,
|
||||||
'c_locale': 'zh_CN',
|
'c_locale': 'zh_CN',
|
||||||
|
'channel': 'yingyongbao',
|
||||||
'cid': cid,
|
'cid': cid,
|
||||||
// if (deviceTouristId != null) 'device_tourist_id': deviceTouristId,
|
// if (deviceTouristId != null) 'device_tourist_id': deviceTouristId,
|
||||||
'disable_rcmd': '0',
|
'disable_rcmd': '0',
|
||||||
@@ -142,6 +143,7 @@ class LoginHttp {
|
|||||||
headers: headers,
|
headers: headers,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.data['code'] == 0 && res.data['data']['recaptcha_url'] == "") {
|
if (res.data['code'] == 0 && res.data['data']['recaptcha_url'] == "") {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
@@ -158,7 +160,7 @@ class LoginHttp {
|
|||||||
// dynamic publicKey = RSAKeyParser().parse(key);
|
// dynamic publicKey = RSAKeyParser().parse(key);
|
||||||
// var params = {
|
// var params = {
|
||||||
// 'appkey': Constants.appKey,
|
// 'appkey': Constants.appKey,
|
||||||
// 'build': '1462100',
|
// 'build': '2001100',
|
||||||
// 'buvid': buvid,
|
// 'buvid': buvid,
|
||||||
// 'c_locale': 'zh_CN',
|
// 'c_locale': 'zh_CN',
|
||||||
// 'channel': 'yingyongbao',
|
// 'channel': 'yingyongbao',
|
||||||
@@ -185,7 +187,7 @@ class LoginHttp {
|
|||||||
// contentType: Headers.formUrlEncodedContentType,
|
// contentType: Headers.formUrlEncodedContentType,
|
||||||
// headers: headers,
|
// headers: headers,
|
||||||
// ));
|
// ));
|
||||||
// debugPrint("getGuestId: $res");
|
// print("getGuestId: $res");
|
||||||
// if (res.data['code'] == 0) {
|
// if (res.data['code'] == 0) {
|
||||||
// return {'status': true, 'data': res.data['data']};
|
// return {'status': true, 'data': res.data['data']};
|
||||||
// } else {
|
// } else {
|
||||||
@@ -211,7 +213,7 @@ class LoginHttp {
|
|||||||
Map<String, String> data = {
|
Map<String, String> data = {
|
||||||
'appkey': Constants.appKey,
|
'appkey': Constants.appKey,
|
||||||
'bili_local_id': deviceId,
|
'bili_local_id': deviceId,
|
||||||
'build': '1462100',
|
'build': '2001100',
|
||||||
'buvid': buvid,
|
'buvid': buvid,
|
||||||
'c_locale': 'zh_CN',
|
'c_locale': 'zh_CN',
|
||||||
'channel': 'yingyongbao',
|
'channel': 'yingyongbao',
|
||||||
@@ -247,7 +249,6 @@ class LoginHttp {
|
|||||||
);
|
);
|
||||||
data['sign'] = sign;
|
data['sign'] = sign;
|
||||||
data.map((key, value) {
|
data.map((key, value) {
|
||||||
debugPrint('$key: $value');
|
|
||||||
return MapEntry<String, dynamic>(key, value);
|
return MapEntry<String, dynamic>(key, value);
|
||||||
});
|
});
|
||||||
var res = await Request().post(
|
var res = await Request().post(
|
||||||
@@ -259,6 +260,7 @@ class LoginHttp {
|
|||||||
//responseType: ResponseType.plain
|
//responseType: ResponseType.plain
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {
|
return {
|
||||||
'status': true,
|
'status': true,
|
||||||
@@ -287,7 +289,7 @@ class LoginHttp {
|
|||||||
Map<String, String> data = {
|
Map<String, String> data = {
|
||||||
'appkey': Constants.appKey,
|
'appkey': Constants.appKey,
|
||||||
'bili_local_id': deviceId,
|
'bili_local_id': deviceId,
|
||||||
'build': '1462100',
|
'build': '2001100',
|
||||||
'buvid': buvid,
|
'buvid': buvid,
|
||||||
'c_locale': 'zh_CN',
|
'c_locale': 'zh_CN',
|
||||||
'captcha_key': captchaKey,
|
'captcha_key': captchaKey,
|
||||||
@@ -321,7 +323,6 @@ class LoginHttp {
|
|||||||
);
|
);
|
||||||
data['sign'] = sign;
|
data['sign'] = sign;
|
||||||
data.map((key, value) {
|
data.map((key, value) {
|
||||||
debugPrint('$key: $value');
|
|
||||||
return MapEntry<String, dynamic>(key, value);
|
return MapEntry<String, dynamic>(key, value);
|
||||||
});
|
});
|
||||||
var res = await Request().post(
|
var res = await Request().post(
|
||||||
@@ -333,6 +334,7 @@ class LoginHttp {
|
|||||||
//responseType: ResponseType.plain
|
//responseType: ResponseType.plain
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
@@ -349,9 +351,12 @@ class LoginHttp {
|
|||||||
static Future safeCenterGetInfo({
|
static Future safeCenterGetInfo({
|
||||||
required String tmpCode,
|
required String tmpCode,
|
||||||
}) async {
|
}) async {
|
||||||
var res = await Request().get(Api.safeCenterGetInfo, queryParameters: {
|
var res = await Request().get(
|
||||||
|
Api.safeCenterGetInfo,
|
||||||
|
queryParameters: {
|
||||||
'tmp_code': tmpCode,
|
'tmp_code': tmpCode,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
@@ -364,9 +369,10 @@ class LoginHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 风控验证手机前的验证码
|
// 风控验证手机前的极验验证码
|
||||||
static Future preCapture() async {
|
static Future preCapture() async {
|
||||||
var res = await Request().post(Api.preCapture);
|
var res = await Request().post(Api.preCapture);
|
||||||
|
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
@@ -379,23 +385,40 @@ class LoginHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 风控验证手机
|
// 风控验证手机:发送短信验证码
|
||||||
static Future safeCenterSmsCode({
|
static Future safeCenterSmsCode({
|
||||||
String? smsType,
|
String? smsType,
|
||||||
required String tmpCode,
|
required String tmpCode,
|
||||||
required String geeChallenge,
|
String? geeChallenge,
|
||||||
required String geeSeccode,
|
String? geeSeccode,
|
||||||
required String geeValidate,
|
String? geeValidate,
|
||||||
required String recaptchaToken,
|
String? recaptchaToken,
|
||||||
|
required String refererUrl,
|
||||||
}) async {
|
}) async {
|
||||||
var res = await Request().post(Api.safeCenterSmsCode, data: {
|
Map<String, String> data = {
|
||||||
|
'disable_rcmd': '0',
|
||||||
'sms_type': smsType ?? 'loginTelCheck',
|
'sms_type': smsType ?? 'loginTelCheck',
|
||||||
'tmp_code': tmpCode,
|
'tmp_code': tmpCode,
|
||||||
'gee_challenge': geeChallenge,
|
if (geeChallenge != null) 'gee_challenge': geeChallenge,
|
||||||
'gee_seccode': geeSeccode,
|
if (geeSeccode != null) 'gee_seccode': geeSeccode,
|
||||||
'gee_validate': geeValidate,
|
if (geeValidate != null) 'gee_validate': geeValidate,
|
||||||
'recaptcha_token': recaptchaToken,
|
if (recaptchaToken != null) 'recaptcha_token': recaptchaToken,
|
||||||
});
|
};
|
||||||
|
String sign = Utils.appSign(
|
||||||
|
data,
|
||||||
|
Constants.appKey,
|
||||||
|
Constants.appSec,
|
||||||
|
);
|
||||||
|
data['sign'] = sign;
|
||||||
|
var res = await Request().post(
|
||||||
|
Api.safeCenterSmsCode,
|
||||||
|
data: data,
|
||||||
|
options:
|
||||||
|
Options(contentType: Headers.formUrlEncodedContentType, headers: {
|
||||||
|
"Referer": refererUrl,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
@@ -408,21 +431,93 @@ class LoginHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future safeCenterSmsVerify(
|
// 风控验证手机:提交短信验证码
|
||||||
{String? type,
|
static Future safeCenterSmsVerify({
|
||||||
|
String? type,
|
||||||
required String code,
|
required String code,
|
||||||
required String tmpCode,
|
required String tmpCode,
|
||||||
required String requestId,
|
required String requestId,
|
||||||
required String source,
|
required String source,
|
||||||
required String captchaKey}) async {
|
required String captchaKey,
|
||||||
var res = await Request().post(Api.safeCenterSmsVerify, data: {
|
required String refererUrl,
|
||||||
|
}) async {
|
||||||
|
Map<String, String> data = {
|
||||||
'type': type ?? 'loginTelCheck',
|
'type': type ?? 'loginTelCheck',
|
||||||
'code': code,
|
'code': code,
|
||||||
'tmp_code': tmpCode,
|
'tmp_code': tmpCode,
|
||||||
'request_id': requestId,
|
'request_id': requestId,
|
||||||
'source': source,
|
'source': source,
|
||||||
'captcha_key': captchaKey,
|
'captcha_key': captchaKey,
|
||||||
|
};
|
||||||
|
String sign = Utils.appSign(
|
||||||
|
data,
|
||||||
|
Constants.appKey,
|
||||||
|
Constants.appSec,
|
||||||
|
);
|
||||||
|
data['sign'] = sign;
|
||||||
|
var res = await Request().post(
|
||||||
|
Api.safeCenterSmsVerify,
|
||||||
|
data: data,
|
||||||
|
options:
|
||||||
|
Options(contentType: Headers.formUrlEncodedContentType, headers: {
|
||||||
|
"Referer": refererUrl,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {'status': true, 'data': res.data['data']};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'code': res.data['code'],
|
||||||
|
'msg': res.data['message'],
|
||||||
|
'data': res.data['data']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 风控验证手机:用oauthCode换回accessToken
|
||||||
|
static Future oauth2AccessToken({
|
||||||
|
required String code,
|
||||||
|
}) async {
|
||||||
|
Map<String, String> data = {
|
||||||
|
'appkey': Constants.appKey,
|
||||||
|
'build': '2001100',
|
||||||
|
'buvid': buvid,
|
||||||
|
// 'c_locale': 'zh_CN',
|
||||||
|
// 'channel': 'yingyongbao',
|
||||||
|
'code': code,
|
||||||
|
// 'device': 'phone',
|
||||||
|
// 'device_id': deviceId,
|
||||||
|
// 'device_name': 'vivo',
|
||||||
|
// 'device_platform': 'Android14vivo',
|
||||||
|
'disable_rcmd': '0',
|
||||||
|
'grant_type': 'authorization_code',
|
||||||
|
'local_id': buvid,
|
||||||
|
'mobi_app': 'android_hd',
|
||||||
|
'platform': 'android',
|
||||||
|
// 's_locale': 'zh_CN',
|
||||||
|
// 'statistics': Constants.statistics,
|
||||||
|
'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(),
|
||||||
|
};
|
||||||
|
String sign = Utils.appSign(
|
||||||
|
data,
|
||||||
|
Constants.appKey,
|
||||||
|
Constants.appSec,
|
||||||
|
);
|
||||||
|
data['sign'] = sign;
|
||||||
|
data.map((key, value) {
|
||||||
|
return MapEntry<String, dynamic>(key, value);
|
||||||
});
|
});
|
||||||
|
var res = await Request().post(
|
||||||
|
Api.oauth2AccessToken,
|
||||||
|
data: data,
|
||||||
|
options: Options(
|
||||||
|
contentType: Headers.formUrlEncodedContentType,
|
||||||
|
headers: headers,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': res.data['data']};
|
return {'status': true, 'data': res.data['data']};
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import 'package:PiliPalaX/models/login/index.dart';
|
|||||||
import '../../utils/login.dart';
|
import '../../utils/login.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:webview_cookie_manager/webview_cookie_manager.dart';
|
import 'package:webview_cookie_manager/webview_cookie_manager.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web;
|
|
||||||
|
|
||||||
import '../../http/constants.dart';
|
import '../../http/constants.dart';
|
||||||
import '../../http/init.dart';
|
import '../../http/init.dart';
|
||||||
@@ -60,6 +59,10 @@ class LoginPageController extends GetxController
|
|||||||
tabController.dispose();
|
tabController.dispose();
|
||||||
qrCodeTimer?.cancel();
|
qrCodeTimer?.cancel();
|
||||||
smsSendCooldownTimer?.cancel();
|
smsSendCooldownTimer?.cancel();
|
||||||
|
telTextController.dispose();
|
||||||
|
usernameTextController.dispose();
|
||||||
|
passwordTextController.dispose();
|
||||||
|
smsCodeTextController.dispose();
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,8 +72,6 @@ class LoginPageController extends GetxController
|
|||||||
qrCodeTimer?.cancel();
|
qrCodeTimer?.cancel();
|
||||||
codeInfo.value = res;
|
codeInfo.value = res;
|
||||||
codeInfo.refresh();
|
codeInfo.refresh();
|
||||||
debugPrint("codeInfo");
|
|
||||||
debugPrint(codeInfo.toString());
|
|
||||||
qrCodeTimer = Timer.periodic(const Duration(milliseconds: 1000), (t) {
|
qrCodeTimer = Timer.periodic(const Duration(milliseconds: 1000), (t) {
|
||||||
qrCodeLeftTime.value = 180 - t.tick;
|
qrCodeLeftTime.value = 180 - t.tick;
|
||||||
if (qrCodeLeftTime <= 0) {
|
if (qrCodeLeftTime <= 0) {
|
||||||
@@ -103,7 +104,6 @@ class LoginPageController extends GetxController
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleTabChange() {
|
void _handleTabChange() {
|
||||||
debugPrint('tabController.index ${tabController.index}');
|
|
||||||
if (tabController.index == 2) {
|
if (tabController.index == 2) {
|
||||||
if (qrCodeTimer == null || qrCodeTimer!.isActive == false) {
|
if (qrCodeTimer == null || qrCodeTimer!.isActive == false) {
|
||||||
refreshQRCode();
|
refreshQRCode();
|
||||||
@@ -120,8 +120,6 @@ class LoginPageController extends GetxController
|
|||||||
'refresh': token_info['refresh_token']
|
'refresh': token_info['refresh_token']
|
||||||
});
|
});
|
||||||
List<dynamic> cookieInfo = cookie_info['cookies'];
|
List<dynamic> cookieInfo = cookie_info['cookies'];
|
||||||
debugPrint("cookieInfo");
|
|
||||||
debugPrint(cookieInfo.toString());
|
|
||||||
List<Cookie> cookies = [];
|
List<Cookie> cookies = [];
|
||||||
String cookieStrings = cookieInfo.map((cookie) {
|
String cookieStrings = cookieInfo.map((cookie) {
|
||||||
String cstr =
|
String cstr =
|
||||||
@@ -140,34 +138,22 @@ class LoginPageController extends GetxController
|
|||||||
}
|
}
|
||||||
Request.dio.options.headers['cookie'] = cookieStrings;
|
Request.dio.options.headers['cookie'] = cookieStrings;
|
||||||
await WebviewCookieManager().setCookies(cookies);
|
await WebviewCookieManager().setCookies(cookies);
|
||||||
for (Cookie item in cookies) {
|
|
||||||
await web.CookieManager().setCookie(
|
|
||||||
url: web.WebUri(item.domain ?? ''),
|
|
||||||
name: item.name,
|
|
||||||
value: item.value,
|
|
||||||
path: item.path ?? '',
|
|
||||||
domain: item.domain,
|
|
||||||
isSecure: item.secure,
|
|
||||||
isHttpOnly: item.httpOnly,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
SmartDialog.showToast('设置登录态失败,$e');
|
SmartDialog.showToast('设置登录态失败,$e');
|
||||||
}
|
}
|
||||||
final result = await UserHttp.userInfo();
|
final result = await UserHttp.userInfo();
|
||||||
if (result['status'] && result['data'].isLogin) {
|
if (result['status'] && result['data'].isLogin) {
|
||||||
SmartDialog.showToast('登录成功,当前采用「'
|
SmartDialog.showToast('登录成功,当前采用「'
|
||||||
'${GStorage.setting.get(SettingBoxKey.defaultRcmdType, defaultValue: 'app')}'
|
'${GStorage.setting.get(SettingBoxKey.defaultRcmdType, defaultValue: 'web')}'
|
||||||
'端」推荐');
|
'端」推荐');
|
||||||
Box userInfoCache = GStorage.userInfo;
|
await GStorage.userInfo.put('userInfoCache', result['data']);
|
||||||
await userInfoCache.put('userInfoCache', result['data']);
|
try {
|
||||||
final HomeController homeCtr = Get.find<HomeController>();
|
final HomeController homeCtr = Get.find<HomeController>();
|
||||||
homeCtr.updateLoginStatus(true);
|
homeCtr.updateLoginStatus(true);
|
||||||
homeCtr.userFace.value = result['data'].face;
|
homeCtr.userFace.value = result['data'].face;
|
||||||
final MediaController? mediaCtr = Get.isRegistered<MediaController>()
|
final MediaController mediaCtr = Get.find<MediaController>();
|
||||||
? Get.find<MediaController>()
|
mediaCtr.mid = result['data'].mid;
|
||||||
: null;
|
} catch (_) {}
|
||||||
mediaCtr?.mid = result['data'].mid;
|
|
||||||
await LoginUtils.refreshLoginStatus(true);
|
await LoginUtils.refreshLoginStatus(true);
|
||||||
} else {
|
} else {
|
||||||
// 获取用户信息失败
|
// 获取用户信息失败
|
||||||
@@ -300,112 +286,145 @@ class LoginPageController extends GetxController
|
|||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
var data = res['data'];
|
var data = res['data'];
|
||||||
for (var key in data.keys) {
|
|
||||||
debugPrint('$key: ${data[key]}');
|
|
||||||
}
|
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
SmartDialog.showToast('登录异常,接口未返回数据:${res["msg"]}');
|
SmartDialog.showToast('登录异常,接口未返回数据:${res["msg"]}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data['status'] == 2) {
|
if (data['status'] == 2) {
|
||||||
SmartDialog.showToast(data['message']);
|
SmartDialog.showToast(data['message']);
|
||||||
return;
|
// return;
|
||||||
//{"code":0,"message":"0","ttl":1,"data":{"status":2,"message":"本次登录环境存在风险, 需使用手机号进行验证或绑定","url":"https://passport.bilibili.com/h5-app/passport/risk/verify?tmp_token=9e785433940891dfa78f033fb7928181&request_id=e5a6d6480df04097870be56c6e60f7ef&source=risk","token_info":null,"cookie_info":null,"sso":null,"is_new":false,"is_tourist":false}}
|
//{"code":0,"message":"0","ttl":1,"data":{"status":2,"message":"本次登录环境存在风险, 需使用手机号进行验证或绑定","url":"https://passport.bilibili.com/h5-app/passport/risk/verify?tmp_token=9e785433940891dfa78f033fb7928181&request_id=e5a6d6480df04097870be56c6e60f7ef&source=risk","token_info":null,"cookie_info":null,"sso":null,"is_new":false,"is_tourist":false}}
|
||||||
//todo: 后续登录流程:https://ivan.hanloth.cn/archives/530/
|
String url = data['url']!;
|
||||||
// String Url = data['url']!;
|
Uri currentUri = Uri.parse(url);
|
||||||
// Uri currentUri = Uri.parse(Url);
|
var safeCenterRes = await LoginHttp.safeCenterGetInfo(
|
||||||
// var safeCenterRes = await LoginHttp.safeCenterGetInfo(
|
tmpCode: currentUri.queryParameters['tmp_token']!);
|
||||||
// tmpCode: currentUri.queryParameters['tmp_token']!);
|
//{"code":0,"message":"0","ttl":1,"data":{"account_info":{"hide_tel":"111*****111","hide_mail":"aaa*****aaaa.aaa","bind_mail":true,"bind_tel":true,"tel_verify":true,"mail_verify":true,"unneeded_check":false,"bind_safe_question":false,"mid":1111111},"member_info":{"nickname":"xxxxxxx","face":"https://i0.hdslb.com/bfs/face/xxxxxxx.jpg","realname_status":false},"sns_info":{"bind_google":false,"bind_fb":false,"bind_apple":false,"bind_qq":true,"bind_weibo":true,"bind_wechat":false},"account_safe":{"score":80}}}
|
||||||
// //{"code":0,"message":"0","ttl":1,"data":{"account_info":{"hide_tel":"111*****111","hide_mail":"aaa*****aaaa.aaa","bind_mail":true,"bind_tel":true,"tel_verify":true,"mail_verify":true,"unneeded_check":false,"bind_safe_question":false,"mid":1111111},"member_info":{"nickname":"xxxxxxx","face":"https://i0.hdslb.com/bfs/face/xxxxxxx.jpg","realname_status":false},"sns_info":{"bind_google":false,"bind_fb":false,"bind_apple":false,"bind_qq":true,"bind_weibo":true,"bind_wechat":false},"account_safe":{"score":80}}}
|
if (!safeCenterRes['status']) {
|
||||||
// if (!safeCenterRes['status']) {
|
SmartDialog.showToast("获取安全验证信息失败,请尝试其它登录方式\n"
|
||||||
// SmartDialog.showToast("获取安全验证信息失败,请尝试其它登录方式\n"
|
"(${safeCenterRes['code']}) ${safeCenterRes['msg']}");
|
||||||
// "(${safeCenterRes['code']}) ${safeCenterRes['msg']}");
|
return;
|
||||||
// return;
|
}
|
||||||
// }
|
Map<String, String> accountInfo = {
|
||||||
// Map<String, String> accountInfo = {
|
"hindTel": safeCenterRes['data']['account_info']!["hide_tel"],
|
||||||
// "hindTel": safeCenterRes['data']['account_info']!["hide_tel"],
|
"hindMail": safeCenterRes['data']['account_info']!["hide_mail"],
|
||||||
// "hindMail": safeCenterRes['data']['account_info']!["hide_mail"],
|
};
|
||||||
// };
|
if (!safeCenterRes['data']['account_info']!['tel_verify']) {
|
||||||
// if (!safeCenterRes['data']['account_info']!['tel_verify']) {
|
SmartDialog.showToast("当前账号未支持手机号验证,请尝试其它登录方式");
|
||||||
// SmartDialog.showToast("当前账号未支持手机号验证,请尝试其它登录方式");
|
return;
|
||||||
// return;
|
}
|
||||||
// }
|
TextEditingController textFieldController = TextEditingController();
|
||||||
// TextEditingController _textFieldController = TextEditingController();
|
String captchaKey = '';
|
||||||
// String captchaKey = '';
|
Get.dialog(AlertDialog(
|
||||||
// Get.dialog(AlertDialog(
|
title: const Text("本次登录需要验证您的手机号"),
|
||||||
// title: const Text("本次登录需要验证您的手机号"),
|
content: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
// content: Column(children: [
|
Text(
|
||||||
// Text(accountInfo['hindTel'] ?? '未能获取手机号'),
|
accountInfo['hindTel'] ?? '未能获取手机号',
|
||||||
// TextField(
|
style: const TextStyle(fontSize: 20),
|
||||||
// controller: _textFieldController,
|
),
|
||||||
// decoration: const InputDecoration(hintText: "请输入短信验证码"),
|
const SizedBox(height: 10),
|
||||||
// ),
|
// 带有清空按钮的输入框
|
||||||
// ]),
|
|
||||||
// actions: <Widget>[
|
|
||||||
// TextButton(
|
|
||||||
// child: const Text("发送验证码 "),
|
|
||||||
// onPressed: () async {
|
|
||||||
// var preCaptureRes = await LoginHttp.preCapture();
|
|
||||||
// if (!preCaptureRes['status']) {
|
|
||||||
// SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n"
|
|
||||||
// "(${preCaptureRes['code']}) ${preCaptureRes['msg']}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// String geeGt = preCaptureRes['data']['gee_gt']!;
|
|
||||||
// String geeChallenge = preCaptureRes['data']['gee_challenge'];
|
|
||||||
// captchaData.token = preCaptureRes['data']['recaptcha_token']!;
|
|
||||||
|
|
||||||
// getCaptcha(geeGt, geeChallenge, () async {
|
TextField(
|
||||||
// var safeCenterSendSmsCodeRes =
|
controller: textFieldController,
|
||||||
// await LoginHttp.safeCenterSmsCode(
|
textAlign: TextAlign.center,
|
||||||
// tmpCode: currentUri.queryParameters['tmp_token']!,
|
decoration: InputDecoration(
|
||||||
// geeChallenge: geeChallenge,
|
hintText: "请输入短信验证码",
|
||||||
// geeSeccode: captchaData.seccode!,
|
suffixIcon: IconButton(
|
||||||
// geeValidate: captchaData.validate!,
|
icon: const Icon(Icons.clear),
|
||||||
// recaptchaToken: captchaData.token!);
|
onPressed: textFieldController.clear,
|
||||||
// if (!safeCenterSendSmsCodeRes['status']) {
|
),
|
||||||
// SmartDialog.showToast("发送短信验证码失败,请尝试其它登录方式\n"
|
),
|
||||||
// "(${safeCenterSendSmsCodeRes['code']}) ${safeCenterSendSmsCodeRes['msg']}");
|
),
|
||||||
// return;
|
]),
|
||||||
// }
|
actions: <Widget>[
|
||||||
// SmartDialog.showToast("短信验证码已发送,请查收");
|
TextButton(
|
||||||
// captchaKey = safeCenterSendSmsCodeRes['data']['captcha_key'];
|
child: const Text("发送验证码 "),
|
||||||
// });
|
onPressed: () async {
|
||||||
// },
|
var preCaptureRes = await LoginHttp.preCapture();
|
||||||
// ),
|
if (!preCaptureRes['status'] || preCaptureRes['data'] == null) {
|
||||||
// TextButton(
|
SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n"
|
||||||
// onPressed: Get.back,
|
"(${preCaptureRes['code']}) ${preCaptureRes['msg']} ${preCaptureRes['data']}");
|
||||||
// child: const Text(" 取消"),
|
}
|
||||||
// ),
|
String? geeGt = preCaptureRes['data']['gee_gt'];
|
||||||
// TextButton(
|
String? geeChallenge = preCaptureRes['data']['gee_challenge'];
|
||||||
// onPressed: () async {
|
captchaData.token = preCaptureRes['data']['recaptcha_token'];
|
||||||
// String? code = _textFieldController.text;
|
if (!isGeeArgumentValid(geeGt, geeChallenge)) {
|
||||||
// if (code.isEmpty) {
|
SmartDialog.showToast("获取极验参数为空,请尝试其它登录方式\n"
|
||||||
// SmartDialog.showToast("请输入短信验证码");
|
"(${preCaptureRes['code']}) ${preCaptureRes['msg']} ${preCaptureRes['data']}");
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// var safeCenterSmsVerifyRes =
|
|
||||||
// await LoginHttp.safeCenterSmsVerify(
|
|
||||||
// code: code,
|
|
||||||
// tmpCode: currentUri.queryParameters['tmp_token']!,
|
|
||||||
// requestId: currentUri.queryParameters['request_id']!,
|
|
||||||
// source: currentUri.queryParameters['source']!,
|
|
||||||
// captchaKey: captchaKey,
|
|
||||||
// );
|
|
||||||
// if (!safeCenterSmsVerifyRes['status']) {
|
|
||||||
// SmartDialog.showToast("验证短信验证码失败,请尝试其它登录方式\n"
|
|
||||||
// "(${safeCenterSmsVerifyRes['code']}) ${safeCenterSmsVerifyRes['msg']}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// SmartDialog.showToast("验证成功,正在登录");
|
|
||||||
// // loginByPassword();
|
|
||||||
// },
|
|
||||||
// child: const Text("确认"),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
|
|
||||||
// return;
|
getCaptcha(geeGt, geeChallenge, () async {
|
||||||
|
var safeCenterSendSmsCodeRes =
|
||||||
|
await LoginHttp.safeCenterSmsCode(
|
||||||
|
tmpCode: currentUri.queryParameters['tmp_token']!,
|
||||||
|
geeChallenge: geeChallenge,
|
||||||
|
geeSeccode: captchaData.seccode,
|
||||||
|
geeValidate: captchaData.validate,
|
||||||
|
recaptchaToken: captchaData.token,
|
||||||
|
refererUrl: url,
|
||||||
|
);
|
||||||
|
if (!safeCenterSendSmsCodeRes['status']) {
|
||||||
|
SmartDialog.showToast("发送短信验证码失败,请尝试其它登录方式\n"
|
||||||
|
"(${safeCenterSendSmsCodeRes['code']}) ${safeCenterSendSmsCodeRes['msg']}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SmartDialog.showToast("短信验证码已发送,请查收");
|
||||||
|
captchaKey = safeCenterSendSmsCodeRes['data']['captcha_key'];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: Get.back,
|
||||||
|
child: const Text(" 取消"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
String? code = textFieldController.text;
|
||||||
|
if (code.isEmpty) {
|
||||||
|
SmartDialog.showToast("请输入短信验证码");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var safeCenterSmsVerifyRes =
|
||||||
|
await LoginHttp.safeCenterSmsVerify(
|
||||||
|
code: code,
|
||||||
|
tmpCode: currentUri.queryParameters['tmp_token']!,
|
||||||
|
requestId: currentUri.queryParameters['request_id']!,
|
||||||
|
source: currentUri.queryParameters['source']!,
|
||||||
|
captchaKey: captchaKey,
|
||||||
|
refererUrl: url,
|
||||||
|
);
|
||||||
|
if (!safeCenterSmsVerifyRes['status']) {
|
||||||
|
SmartDialog.showToast("验证短信验证码失败,请尝试其它登录方式\n"
|
||||||
|
"(${safeCenterSmsVerifyRes['code']}) ${safeCenterSmsVerifyRes['msg']}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SmartDialog.showToast("验证成功,正在登录");
|
||||||
|
var oauth2AccessTokenRes = await LoginHttp.oauth2AccessToken(
|
||||||
|
code: safeCenterSmsVerifyRes['data']['code'],
|
||||||
|
);
|
||||||
|
if (!oauth2AccessTokenRes['status']) {
|
||||||
|
SmartDialog.showToast("登录失败,请尝试其它登录方式\n"
|
||||||
|
"(${oauth2AccessTokenRes['code']}) ${oauth2AccessTokenRes['msg']}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = oauth2AccessTokenRes['data'];
|
||||||
|
if (data['token_info'] == null || data['cookie_info'] == null) {
|
||||||
|
SmartDialog.showToast(
|
||||||
|
'登录异常,接口未返回身份信息,可能是因为账号风控,请尝试其它登录方式。\n${oauth2AccessTokenRes["msg"]},\n $data');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SmartDialog.showToast('正在保存身份信息');
|
||||||
|
await afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||||
|
Get.back();
|
||||||
|
Get.back();
|
||||||
|
},
|
||||||
|
child: const Text("确认"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (data['token_info'] == null || data['cookie_info'] == null) {
|
if (data['token_info'] == null || data['cookie_info'] == null) {
|
||||||
SmartDialog.showToast(
|
SmartDialog.showToast(
|
||||||
@@ -476,9 +495,6 @@ class LoginPageController extends GetxController
|
|||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
SmartDialog.showToast('登录成功');
|
SmartDialog.showToast('登录成功');
|
||||||
var data = res['data'];
|
var data = res['data'];
|
||||||
for (var key in data.keys) {
|
|
||||||
debugPrint('$key: ${data[key]}');
|
|
||||||
}
|
|
||||||
await afterLoginByApp(data['token_info'], data['cookie_info']);
|
await afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||||
Get.back();
|
Get.back();
|
||||||
} else {
|
} else {
|
||||||
@@ -505,6 +521,34 @@ class LoginPageController extends GetxController
|
|||||||
// guestId = guestIdRes['data']['guest_id'];
|
// guestId = guestIdRes['data']['guest_id'];
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
// var preCaptureRes = await LoginHttp.preCapture();
|
||||||
|
// if (!preCaptureRes['status']) {
|
||||||
|
// SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n"
|
||||||
|
// "(${preCaptureRes['code']}) ${preCaptureRes['msg']}");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// String geeGt = preCaptureRes['data']['gee_gt']!;
|
||||||
|
// String geeChallenge = preCaptureRes['data']['gee_challenge'];
|
||||||
|
// captchaData.token = preCaptureRes['data']['recaptcha_token']!;
|
||||||
|
|
||||||
|
// getCaptcha(geeGt, geeChallenge, () async {
|
||||||
|
|
||||||
|
// var safeCenterSendSmsCodeRes =
|
||||||
|
// await LoginHttp.safeCenterSmsCode(
|
||||||
|
// tmpCode: currentUri.queryParameters['tmp_token']!,
|
||||||
|
// geeChallenge: geeChallenge,
|
||||||
|
// geeSeccode: captchaData.seccode!,
|
||||||
|
// geeValidate: captchaData.validate!,
|
||||||
|
// recaptchaToken: captchaData.token!,
|
||||||
|
// refererUrl: url,
|
||||||
|
// );
|
||||||
|
// if (!safeCenterSendSmsCodeRes['status']) {
|
||||||
|
// SmartDialog.showToast("发送短信验证码失败,请尝试其它登录方式\n"
|
||||||
|
// "(${safeCenterSendSmsCodeRes['code']}) ${safeCenterSendSmsCodeRes['msg']}");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// SmartDialog.showToast("短信验证码已发送,请查收");
|
||||||
|
// captchaKey = safeCenterSendSmsCodeRes['data']['captcha_key'];
|
||||||
|
|
||||||
var res = await LoginHttp.sendSmsCode(
|
var res = await LoginHttp.sendSmsCode(
|
||||||
tel: telTextController.text,
|
tel: telTextController.text,
|
||||||
@@ -533,15 +577,34 @@ class LoginPageController extends GetxController
|
|||||||
switch (res['code']) {
|
switch (res['code']) {
|
||||||
case 0:
|
case 0:
|
||||||
case -105:
|
case -105:
|
||||||
String captureUrl = res['data']?['recaptcha_url'] ?? "";
|
String? captureUrl = res['data']?['recaptcha_url'];
|
||||||
if (captureUrl == "") {
|
String? geeGt;
|
||||||
SmartDialog.showToast('验证信息错误:${res["msg"]}\n返回内容:${res["data"]}');
|
String? geeChallenge;
|
||||||
|
if (captureUrl != null && captureUrl.isNotEmpty) {
|
||||||
|
Uri captureUri = Uri.parse(captureUrl);
|
||||||
|
captchaData.token = captureUri.queryParameters['recaptcha_token'];
|
||||||
|
geeGt = captureUri.queryParameters['gee_gt'];
|
||||||
|
geeChallenge = captureUri.queryParameters['gee_challenge'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isGeeArgumentValid(geeGt, geeChallenge)) {
|
||||||
|
debugPrint('验证信息错误:${res["msg"]}\n返回内容:${res["data"]},尝试另一个验证码接口');
|
||||||
|
var preCaptureRes = await LoginHttp.preCapture();
|
||||||
|
if (!preCaptureRes['status'] || preCaptureRes['data'] == null) {
|
||||||
|
SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n"
|
||||||
|
"(${preCaptureRes['code']}) ${preCaptureRes['msg']} ${preCaptureRes['data']}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Uri captureUri = Uri.parse(captureUrl);
|
geeGt = preCaptureRes['data']['gee_gt'];
|
||||||
captchaData.token = captureUri.queryParameters['recaptcha_token']!;
|
geeChallenge = preCaptureRes['data']['gee_challenge'];
|
||||||
String geeGt = captureUri.queryParameters['gee_gt']!;
|
captchaData.token = preCaptureRes['data']['recaptcha_token'];
|
||||||
String geeChallenge = captureUri.queryParameters['gee_challenge']!;
|
}
|
||||||
|
|
||||||
|
if (!isGeeArgumentValid(geeGt, geeChallenge)) {
|
||||||
|
SmartDialog.showToast("获取验证码失败,请尝试其它登录方式\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
getCaptcha(geeGt, geeChallenge, () {
|
getCaptcha(geeGt, geeChallenge, () {
|
||||||
sendSmsCode();
|
sendSmsCode();
|
||||||
});
|
});
|
||||||
@@ -552,5 +615,12 @@ class LoginPageController extends GetxController
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGeeArgumentValid(String? geeGt, String? geeChallenge) {
|
||||||
|
return geeGt?.isNotEmpty == true &&
|
||||||
|
geeChallenge?.isNotEmpty == true &&
|
||||||
|
captchaData.token?.isNotEmpty == true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import 'package:saver_gallery/saver_gallery.dart';
|
import 'package:saver_gallery/saver_gallery.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
import 'controller.dart';
|
import 'controller.dart';
|
||||||
|
|
||||||
@@ -26,21 +25,6 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
bool showPassword = false;
|
bool showPassword = false;
|
||||||
GlobalKey globalKey = GlobalKey();
|
GlobalKey globalKey = GlobalKey();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_loginPageCtr.dispose();
|
|
||||||
_loginPageCtr.telTextController.dispose();
|
|
||||||
_loginPageCtr.usernameTextController.dispose();
|
|
||||||
_loginPageCtr.passwordTextController.dispose();
|
|
||||||
_loginPageCtr.smsCodeTextController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget loginByQRCode() {
|
Widget loginByQRCode() {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -48,8 +32,10 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
const Text('使用 bilibili 官方 App 扫码登录'),
|
const Text('使用 bilibili 官方 App 扫码登录'),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Obx(() => Text('剩余有效时间: ${_loginPageCtr.qrCodeLeftTime} 秒',
|
Obx(() => Text('剩余有效时间: ${_loginPageCtr.qrCodeLeftTime} 秒',
|
||||||
style:
|
style: TextStyle(
|
||||||
const TextStyle(fontFeatures: [FontFeature.tabularFigures()]))),
|
fontFeatures: const [FontFeature.tabularFigures()],
|
||||||
|
color: Theme.of(context).colorScheme.primaryFixedDim))),
|
||||||
|
const SizedBox(height: 5),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -94,8 +80,18 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
),
|
),
|
||||||
RepaintBoundary(
|
RepaintBoundary(
|
||||||
key: globalKey,
|
key: globalKey,
|
||||||
child: Obx(
|
child: Obx(() {
|
||||||
() => QrImageView(
|
if (_loginPageCtr.codeInfo.value['data']?['url'] == null) {
|
||||||
|
return Container(
|
||||||
|
height: 200,
|
||||||
|
width: 200,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
semanticsLabel: '二维码加载中',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return QrImageView(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
eyeStyle: QrEyeStyle(
|
eyeStyle: QrEyeStyle(
|
||||||
eyeShape: QrEyeShape.square,
|
eyeShape: QrEyeShape.square,
|
||||||
@@ -105,33 +101,39 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
dataModuleShape: QrDataModuleShape.square,
|
dataModuleShape: QrDataModuleShape.square,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
),
|
),
|
||||||
data: _loginPageCtr.codeInfo.value['data']?['url'] ?? "",
|
data: _loginPageCtr.codeInfo.value['data']!['url']!,
|
||||||
size: 200,
|
size: 200,
|
||||||
semanticsLabel: '二维码',
|
semanticsLabel: '二维码',
|
||||||
),
|
);
|
||||||
),
|
}),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Obx(() => Text(_loginPageCtr.statusQRCode.value)),
|
Obx(() => Text(
|
||||||
|
_loginPageCtr.statusQRCode.value,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.secondaryFixedDim),
|
||||||
|
)),
|
||||||
Obx(() => GestureDetector(
|
Obx(() => GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
//以外部方式打开此链接
|
//以外部方式打开此链接
|
||||||
launchUrlString(
|
// launchUrlString(
|
||||||
_loginPageCtr.codeInfo.value['data']?['url'] ?? "",
|
// _loginPageCtr.codeInfo.value['data']?['url'] ?? "",
|
||||||
mode: LaunchMode.externalApplication);
|
// mode: LaunchMode.externalApplication);
|
||||||
|
// 复制到剪贴板
|
||||||
|
Clipboard.setData(ClipboardData(
|
||||||
|
text: _loginPageCtr.codeInfo.value['data']?['url'] ?? ""));
|
||||||
|
SmartDialog.showToast('已复制到剪贴板,可粘贴至已登录的app私信处发送,然后点击已发送的链接打开',
|
||||||
|
displayTime: const Duration(seconds: 5));
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding:
|
padding:
|
||||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
||||||
child: Text(
|
child: Text(_loginPageCtr.codeInfo.value['data']?['url'] ?? "",
|
||||||
_loginPageCtr.codeInfo.value['data']?['url'] ?? "",
|
|
||||||
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.onSurface
|
.onSurface
|
||||||
.withOpacity(0.4),
|
.withOpacity(0.4))),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
Padding(
|
Padding(
|
||||||
@@ -177,7 +179,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
inputFormatters: [FilteringTextInputFormatter.deny(RegExp(r"\s"))],
|
inputFormatters: [FilteringTextInputFormatter.deny(RegExp(r"\s"))],
|
||||||
controller: _loginPageCtr.passwordTextController,
|
controller: _loginPageCtr.passwordTextController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
prefixIcon: const Icon(Icons.lock),
|
prefixIcon: const Icon(Icons.password),
|
||||||
border: const UnderlineInputBorder(),
|
border: const UnderlineInputBorder(),
|
||||||
labelText: '密码',
|
labelText: '密码',
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
@@ -265,7 +267,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
),
|
),
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
onPressed: _loginPageCtr.loginByPassword,
|
onPressed: _loginPageCtr.loginByPassword,
|
||||||
icon: const Icon(Icons.login_outlined),
|
icon: const Icon(Icons.login),
|
||||||
label: const Text('登录'),
|
label: const Text('登录'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
@@ -377,7 +379,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
controller: _loginPageCtr.smsCodeTextController,
|
controller: _loginPageCtr.smsCodeTextController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
prefixIcon: Icon(Icons.key),
|
prefixIcon: Icon(Icons.sms),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
labelText: '验证码',
|
labelText: '验证码',
|
||||||
),
|
),
|
||||||
@@ -402,7 +404,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
onPressed: _loginPageCtr.loginBySmsCode,
|
onPressed: _loginPageCtr.loginBySmsCode,
|
||||||
icon: const Icon(Icons.login_outlined),
|
icon: const Icon(Icons.login),
|
||||||
label: const Text('登录'),
|
label: const Text('登录'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
@@ -442,15 +444,21 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
Tab(
|
Tab(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [Icon(Icons.lock), Text(' 密码')])),
|
children: [Icon(Icons.password), Text(' 密码')],
|
||||||
|
),
|
||||||
|
),
|
||||||
Tab(
|
Tab(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [Icon(Icons.key), Text(' 短信')])),
|
children: [Icon(Icons.sms), Text(' 短信')],
|
||||||
|
),
|
||||||
|
),
|
||||||
Tab(
|
Tab(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [Icon(Icons.qr_code), Text(' 扫码')])),
|
children: [Icon(Icons.qr_code), Text(' 扫码')],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
controller: _loginPageCtr.tabController,
|
controller: _loginPageCtr.tabController,
|
||||||
))
|
))
|
||||||
@@ -459,8 +467,8 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
bottom: orientation == Orientation.portrait
|
bottom: orientation == Orientation.portrait
|
||||||
? TabBar(
|
? TabBar(
|
||||||
tabs: const [
|
tabs: const [
|
||||||
Tab(icon: Icon(Icons.lock), text: '密码'),
|
Tab(icon: Icon(Icons.password), text: '密码'),
|
||||||
Tab(icon: Icon(Icons.key), text: '短信'),
|
Tab(icon: Icon(Icons.sms), text: '短信'),
|
||||||
Tab(icon: Icon(Icons.qr_code), text: '扫码'),
|
Tab(icon: Icon(Icons.qr_code), text: '扫码'),
|
||||||
],
|
],
|
||||||
controller: _loginPageCtr.tabController,
|
controller: _loginPageCtr.tabController,
|
||||||
|
|||||||
Reference in New Issue
Block a user