添加设备代码信息到 Android 和 iOS 平台信息;更新 Auth 页面以使用新的 TextEditingController 管理输入;重构推流测试页面以支持动态 RTMP URL 解析;删除不再需要的测试文件。
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
/// 获取 TOKEN 响应模型
|
||||
class GetTokenResModel {
|
||||
GetTokenResModel({required this.deviceAccessToken});
|
||||
|
||||
final String deviceAccessToken;
|
||||
|
||||
factory GetTokenResModel.fromJson(Map<String, dynamic> json) {
|
||||
return GetTokenResModel(
|
||||
deviceAccessToken: (json['deviceAccessToken'] ?? '').toString(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'deviceAccessToken': deviceAccessToken};
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/app/router/app_navigator.dart';
|
||||
import 'package:recording_tool/features/auth/view_model_auth/view_model_auth.dart';
|
||||
import 'package:recording_tool/features/scan_qrcode/pages/page_scan_qrcode.dart';
|
||||
import 'package:recording_tool/shared/widgets/widgets.dart';
|
||||
|
||||
class AuthPageWidget extends StatefulWidget {
|
||||
class AuthPageWidget extends ConsumerStatefulWidget {
|
||||
const AuthPageWidget({super.key});
|
||||
|
||||
@override
|
||||
State<AuthPageWidget> createState() => _AuthPageWidgetState();
|
||||
ConsumerState<AuthPageWidget> createState() => _AuthPageWidgetState();
|
||||
}
|
||||
|
||||
class _AuthPageWidgetState extends State<AuthPageWidget> {
|
||||
class _AuthPageWidgetState extends ConsumerState<AuthPageWidget> {
|
||||
late TextEditingController? _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final authState = ref.watch(authProvider);
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -26,7 +44,7 @@ class _AuthPageWidgetState extends State<AuthPageWidget> {
|
||||
SizedBox(
|
||||
width: 280.w,
|
||||
height: 80.h,
|
||||
child: AppTextField(initialValue: 'hhh'),
|
||||
child: AppTextField(initialValue: 'hhh', controller: _controller),
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
SizedBox(
|
||||
@@ -34,8 +52,20 @@ class _AuthPageWidgetState extends State<AuthPageWidget> {
|
||||
height: 80.h,
|
||||
child: AppButton(
|
||||
label: '确定',
|
||||
onPressed: () {
|
||||
AppNavigator.push(const ScanQrCodePage());
|
||||
onPressed: () async {
|
||||
final code = _controller?.text;
|
||||
final success = await ref
|
||||
.read(authProvider.notifier)
|
||||
.auth(code ?? '');
|
||||
if (!mounted) return;
|
||||
if (success) {
|
||||
AppNavigator.push(const ScanQrCodePage());
|
||||
return;
|
||||
}
|
||||
final message = ref.read(authProvider).errorMessage;
|
||||
if (message != null && message.isNotEmpty) {
|
||||
AppToast.show(message);
|
||||
}
|
||||
// return;
|
||||
// AppNavigator.push(
|
||||
// const WebviewPage(
|
||||
@@ -45,6 +75,7 @@ class _AuthPageWidgetState extends State<AuthPageWidget> {
|
||||
// );
|
||||
},
|
||||
variant: AppButtonVariant.secondary,
|
||||
isLoading: authState.isLoading,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:recording_tool/app/config/api_common.dart';
|
||||
import 'package:recording_tool/core/cache/app_storage.dart';
|
||||
import 'package:recording_tool/core/cache/storage_keys.dart';
|
||||
import 'package:recording_tool/core/network/providers/dio_providers.dart';
|
||||
import 'package:recording_tool/core/utils/device_utils.dart';
|
||||
import 'package:recording_tool/features/auth/model/model_auth.dart';
|
||||
|
||||
class AuthServer {
|
||||
/// [passCode] 口令码
|
||||
static Future<GetTokenResModel> login(String passCode, Ref ref) async {
|
||||
final deviceCode = await DeviceUtils.deviceCode();
|
||||
if (deviceCode.isEmpty) {
|
||||
throw const FormatException('无法获取设备标识');
|
||||
}
|
||||
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
final data = await apiClient.post<GetTokenResModel>(
|
||||
AuthApi.getToken.path,
|
||||
data: {'deviceCode': deviceCode, 'passCode': passCode},
|
||||
parser: (json) => GetTokenResModel.fromJson(json as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
if (data.deviceAccessToken.isEmpty) {
|
||||
throw const FormatException('登录响应缺少 TOKEN');
|
||||
}
|
||||
|
||||
await AppStorage.setString(StorageKeys.authToken, data.deviceAccessToken);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class AuthState {
|
||||
const AuthState({this.isLoading = false, this.errorMessage});
|
||||
|
||||
final bool isLoading;
|
||||
final String? errorMessage;
|
||||
|
||||
AuthState copyWith({bool? isLoading, String? errorMessage}) {
|
||||
return AuthState(
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
errorMessage: errorMessage,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_riverpod/legacy.dart';
|
||||
import 'package:recording_tool/core/network/api_exception.dart';
|
||||
import 'package:recording_tool/features/auth/server/server_auth.dart';
|
||||
import 'package:recording_tool/features/auth/state/state_auth.dart';
|
||||
|
||||
final authProvider = StateNotifierProvider<AuthViewModel, AuthState>((ref) {
|
||||
return AuthViewModel(ref);
|
||||
});
|
||||
|
||||
class AuthViewModel extends StateNotifier<AuthState> {
|
||||
AuthViewModel(this._ref) : super(const AuthState());
|
||||
final Ref _ref;
|
||||
|
||||
/// 鉴权获取 token
|
||||
Future<bool> auth(String code) async {
|
||||
final passCode = code.trim();
|
||||
if (passCode.isEmpty) {
|
||||
state = const AuthState(errorMessage: '请输入执裁口令');
|
||||
return false;
|
||||
}
|
||||
|
||||
state = const AuthState(isLoading: true);
|
||||
try {
|
||||
await AuthServer.login(passCode, _ref);
|
||||
state = const AuthState();
|
||||
return true;
|
||||
} on FormatException catch (error) {
|
||||
state = AuthState(errorMessage: error.message);
|
||||
return false;
|
||||
} on ApiException catch (error) {
|
||||
state = AuthState(errorMessage: error.message);
|
||||
return false;
|
||||
} catch (_) {
|
||||
state = const AuthState(errorMessage: '认证失败,请重试');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user