feat(mobile-next): 工号登录与目录薄适配,并完成登录/会话/聊天/通讯录第一批界面
Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
d787c0a477
commit
60b6590409
@@ -0,0 +1,80 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../config/app_endpoints.dart';
|
||||
|
||||
class AuthResult {
|
||||
final String userID;
|
||||
final String imToken;
|
||||
final String nickname;
|
||||
|
||||
AuthResult({required this.userID, required this.imToken, required this.nickname});
|
||||
|
||||
factory AuthResult.fromJson(Map<String, dynamic> json) => AuthResult(
|
||||
userID: json['userID']?.toString() ?? '',
|
||||
imToken: json['imToken']?.toString() ?? '',
|
||||
nickname: json['nickname']?.toString() ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
class AuthException implements Exception {
|
||||
final String message;
|
||||
final bool network;
|
||||
|
||||
AuthException(this.message, {this.network = false});
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
|
||||
/// 公司工号登录。只走账号服务 POST /api/login,不改 OpenIM Server。
|
||||
class AuthApi {
|
||||
AuthApi({Dio? dio})
|
||||
: _dio = dio ??
|
||||
Dio(BaseOptions(
|
||||
baseUrl: AppEndpoints.authApiBase,
|
||||
connectTimeout: const Duration(seconds: 10),
|
||||
receiveTimeout: const Duration(seconds: 10),
|
||||
));
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
Map<String, dynamic> _unwrap(dynamic body) {
|
||||
if (body is Map<String, dynamic>) {
|
||||
if (body['code'] == 0 && body['data'] is Map) {
|
||||
return Map<String, dynamic>.from(body['data'] as Map);
|
||||
}
|
||||
final msg = body['msg']?.toString() ?? '';
|
||||
throw AuthException(msg.isNotEmpty ? msg : '工号或密码不正确');
|
||||
}
|
||||
throw AuthException('工号或密码不正确');
|
||||
}
|
||||
|
||||
Future<AuthResult> login({
|
||||
required String staffNo,
|
||||
required String password,
|
||||
required int platformID,
|
||||
}) async {
|
||||
try {
|
||||
final resp = await _dio.post('/api/login', data: {
|
||||
'staffNo': staffNo,
|
||||
'password': password,
|
||||
'platformID': platformID,
|
||||
});
|
||||
final result = AuthResult.fromJson(_unwrap(resp.data));
|
||||
if (result.userID.isEmpty || result.imToken.isEmpty) {
|
||||
throw AuthException('工号或密码不正确');
|
||||
}
|
||||
return result;
|
||||
} on DioException catch (e) {
|
||||
final data = e.response?.data;
|
||||
if (data is Map && data['msg'] != null && data['msg'].toString().isNotEmpty) {
|
||||
throw AuthException(data['msg'].toString());
|
||||
}
|
||||
throw AuthException('网络异常,请稍后重试', network: true);
|
||||
} on AuthException {
|
||||
rethrow;
|
||||
} catch (_) {
|
||||
throw AuthException('网络异常,请稍后重试', network: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:openim/core/controller/im_controller.dart';
|
||||
import 'package:openim/pages/conversation/conversation_logic.dart';
|
||||
import 'package:openim/routes/app_navigator.dart';
|
||||
import 'package:openim_common/openim_common.dart';
|
||||
|
||||
import 'auth_api.dart';
|
||||
|
||||
class CompanyLoginLogic extends GetxController {
|
||||
final staffCtrl = TextEditingController();
|
||||
final pwdCtrl = TextEditingController();
|
||||
final obscure = true.obs;
|
||||
final submitting = false.obs;
|
||||
final staffError = RxnString();
|
||||
final pwdError = RxnString();
|
||||
final toast = RxnString();
|
||||
|
||||
final _auth = AuthApi();
|
||||
final _im = Get.find<IMController>();
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
staffCtrl.dispose();
|
||||
pwdCtrl.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
void toggleObscure() => obscure.toggle();
|
||||
|
||||
Future<void> submit() async {
|
||||
if (submitting.value) return;
|
||||
final staffNo = staffCtrl.text.trim();
|
||||
final password = pwdCtrl.text;
|
||||
staffError.value = staffNo.isEmpty ? '请输入工号' : null;
|
||||
pwdError.value = password.isEmpty ? '请输入密码' : null;
|
||||
if (staffNo.isEmpty || password.isEmpty) return;
|
||||
|
||||
submitting.value = true;
|
||||
toast.value = null;
|
||||
try {
|
||||
final result = await _auth.login(
|
||||
staffNo: staffNo,
|
||||
password: password,
|
||||
platformID: IMUtils.getPlatform(),
|
||||
);
|
||||
final cert = LoginCertificate.fromJson({
|
||||
'userID': result.userID,
|
||||
'imToken': result.imToken,
|
||||
'chatToken': result.imToken,
|
||||
});
|
||||
await DataSp.putLoginCertificate(cert);
|
||||
await DataSp.putLoginAccount({'phoneNumber': staffNo, 'loginType': 2});
|
||||
await DataSp.putLoginType(2);
|
||||
Logger.print('company login : ${result.userID}');
|
||||
await _im.login(result.userID, result.imToken);
|
||||
final conversations = await ConversationLogic.getConversationFirstPage();
|
||||
Get.find<CacheController>().resetCache();
|
||||
AppNavigator.startMain(conversations: conversations);
|
||||
} on AuthException catch (e) {
|
||||
toast.value = e.network ? '网络异常,请稍后重试' : '工号或密码不正确';
|
||||
} catch (e, s) {
|
||||
Logger.print('company login e: $e $s');
|
||||
toast.value = '网络异常,请稍后重试';
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user