- 移除 @riverpod/@freezed 注解依赖,全部改为手写 Provider(无需 build_runner) · LoginState 改为纯 Dart,LoginViewModel/ThemeViewModel/ChatViewModel 改为 Notifier · UserNotifier 改为 FamilyAsyncNotifier<User?,int>,mini_app_provider 改为手写 Provider · 15 个 StreamProvider/StreamProvider.family 从 @riverpod 迁移至手写 - 发送消息(#25) · SendMessageRequest/SendMessageResponse DTO · SendMessageUseCase:乐观写入 DB → HTTP POST → 更新 Chat 摘要 - 接收消息 WS(#26) · WsMessageService:监听 mode2 WS 帧 → HTTP 补拉 → DB 写入 → Chat 更新 · FetchHistoryRequest/FetchHistoryResponse DTO(GET /app/api/chat/history) · FetchHistoryUseCase:拉取 → insertOrReplaceAll - DI 装配(chat_service_providers.dart) · wsMessageServiceProvider、sendMessageUseCaseProvider、fetchHistoryUseCaseProvider - 聊天列表页(#27) · ChatListViewModel(Notifier<void>)+ chat_page.dart 真实会话列表 UI · ListTile:头像首字母、最新消息摘要、未读角标、时间格式化 - 聊天详情页(#28) · ChatDetailViewModel(FamilyNotifier<ChatDetailState,int>)+ chat_detail_page.dart · 消息气泡(自己/他人分左右)、底部输入框、发送状态与错误提示 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
79 lines
2.0 KiB
Dart
79 lines
2.0 KiB
Dart
import 'package:json_annotation/json_annotation.dart';
|
||
import 'package:networks_sdk/networks_sdk.dart';
|
||
|
||
import 'package:im_app/core/foundation/api_paths.dart';
|
||
|
||
part 'send_otp_request.g.dart';
|
||
|
||
/// 发送验证码响应
|
||
///
|
||
/// code: 0 时 [expiryTime] 有值;
|
||
/// code: 30174(触发图片验证)时 [android] / [ios] / [web] / [extras] 有值。
|
||
class SendOtpResponse {
|
||
/// 验证码有效期(秒)
|
||
@JsonKey(name: 'expiry_time')
|
||
final int? expiryTime;
|
||
|
||
/// Android CAPTCHA SDK token
|
||
final String? android;
|
||
|
||
/// iOS CAPTCHA SDK token
|
||
final String? ios;
|
||
|
||
/// Web CAPTCHA SDK token
|
||
final String? web;
|
||
|
||
/// CAPTCHA 平台扩展参数(预留字段)
|
||
final Map<String, dynamic>? extras;
|
||
|
||
const SendOtpResponse({
|
||
this.expiryTime,
|
||
this.android,
|
||
this.ios,
|
||
this.web,
|
||
this.extras,
|
||
});
|
||
|
||
factory SendOtpResponse.fromJson(Map<String, dynamic> json) => SendOtpResponse(
|
||
expiryTime: (json['expiry_time'] as num?)?.toInt(),
|
||
android: json['android'] as String?,
|
||
ios: json['ios'] as String?,
|
||
web: json['web'] as String?,
|
||
extras: json['extras'] as Map<String, dynamic>?,
|
||
);
|
||
}
|
||
|
||
/// # /app/api/auth/vcode/get — 发送手机验证码
|
||
///
|
||
/// 响应 `data: { "expiry_time": 180 }`,返回验证码有效期(秒)。
|
||
///
|
||
/// ## 数据流位置
|
||
///
|
||
/// ```
|
||
/// AuthRepositoryImpl.sendOtp(countryCode, contact)
|
||
/// → _client.executeRequest( ★ SendOtpRequest ★ ) ← 你在这里
|
||
/// → 服务端 POST /app/api/auth/vcode/get
|
||
/// → 响应 { expiry_time: 180 } → SendOtpResponse
|
||
/// ```
|
||
@ApiRequest(
|
||
path: ApiPaths.authSendOtp,
|
||
method: HttpMethod.post,
|
||
responseType: SendOtpResponse,
|
||
requestType: ApiRequestType.login,
|
||
)
|
||
class SendOtpRequest extends ApiRequestable<SendOtpResponse>
|
||
with _$SendOtpRequestApi {
|
||
@JsonKey(name: 'country_code')
|
||
final String countryCode;
|
||
final String contact;
|
||
|
||
/// type=1 表示手机号验证
|
||
final int type;
|
||
|
||
SendOtpRequest({
|
||
required this.countryCode,
|
||
required this.contact,
|
||
this.type = 1,
|
||
});
|
||
}
|