网络请求打通,ws 打通

This commit is contained in:
Cody
2026-03-09 19:05:55 +08:00
parent 997d821447
commit 3c1976b343
60 changed files with 1392 additions and 552 deletions

View File

@@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import 'package:im_app/features/login/presentation/login_state.dart';
/// 登录步骤 2 — 输入验证码并完成登录
///
/// 纯展示组件,所有交互通过回调传出,不持有任何状态。
///
/// 使用方式:
/// ```dart
/// LoginOtpStep(
/// otpCtrl: _otpCtrl,
/// state: state,
/// onVerifyAndLogin: _verifyAndLogin,
/// onBackToPhone: _backToPhone,
/// )
/// ```
class LoginOtpStep extends StatelessWidget {
const LoginOtpStep({
super.key,
required this.otpCtrl,
required this.state,
required this.onVerifyAndLogin,
required this.onBackToPhone,
});
final TextEditingController otpCtrl;
final LoginState state;
final VoidCallback onVerifyAndLogin;
final VoidCallback onBackToPhone;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'输入验证码',
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'验证码已发送至 ${state.countryCode} ${state.maskedContact}',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 32),
TextField(
controller: otpCtrl,
keyboardType: TextInputType.number,
maxLength: 4,
decoration: const InputDecoration(
labelText: '4 位验证码',
border: OutlineInputBorder(),
counterText: '',
),
autofillHints: const [AutofillHints.oneTimeCode],
),
const SizedBox(height: 24),
if (state.error != null)
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Text(
state.error!,
style: TextStyle(color: Theme.of(context).colorScheme.error),
textAlign: TextAlign.center,
),
),
FilledButton(
onPressed: state.isLoading ? null : onVerifyAndLogin,
child: state.isLoading
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('登录'),
),
const SizedBox(height: 12),
TextButton(
onPressed: state.isLoading ? null : onBackToPhone,
child: const Text('返回修改手机号'),
),
],
);
}
}

View File

@@ -0,0 +1,93 @@
import 'package:flutter/material.dart';
import 'package:im_app/features/login/presentation/login_state.dart';
/// 登录步骤 1 — 输入国家代码 + 手机号
///
/// 纯展示组件,所有交互通过回调传出,不持有任何状态。
///
/// 使用方式:
/// ```dart
/// LoginPhoneStep(
/// phoneCtrl: _phoneCtrl,
/// state: state,
/// onSendOtp: () => _sendOtp(state),
/// )
/// ```
class LoginPhoneStep extends StatelessWidget {
const LoginPhoneStep({
super.key,
required this.phoneCtrl,
required this.state,
required this.onSendOtp,
});
final TextEditingController phoneCtrl;
final LoginState state;
final VoidCallback onSendOtp;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'手机号登录',
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).colorScheme.outline,
),
borderRadius: BorderRadius.circular(4),
),
child: Text(
state.countryCode,
style: Theme.of(context).textTheme.bodyLarge,
),
),
const SizedBox(width: 8),
Expanded(
child: TextField(
controller: phoneCtrl,
keyboardType: TextInputType.phone,
decoration: const InputDecoration(
labelText: '手机号',
border: OutlineInputBorder(),
),
autofillHints: const [AutofillHints.telephoneNumber],
),
),
],
),
const SizedBox(height: 24),
if (state.error != null)
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Text(
state.error!,
style: TextStyle(color: Theme.of(context).colorScheme.error),
textAlign: TextAlign.center,
),
),
FilledButton(
onPressed: state.isLoading ? null : onSendOtp,
child: state.isLoading
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('获取验证码'),
),
],
);
}
}