fix(mobile-next): 我的信息改走 OpenIM SDK,避免账号服务 404
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
1895830907
commit
9001688c9e
@@ -33,6 +33,7 @@ export 'src/utils/sp_util.dart';
|
|||||||
export 'src/utils/utils.dart';
|
export 'src/utils/utils.dart';
|
||||||
export 'src/utils/voice_record.dart';
|
export 'src/utils/voice_record.dart';
|
||||||
export 'src/utils/api_service.dart';
|
export 'src/utils/api_service.dart';
|
||||||
|
export 'src/utils/user_full_info_mapper.dart';
|
||||||
export 'src/widgets/avatar_view.dart';
|
export 'src/widgets/avatar_view.dart';
|
||||||
export 'src/widgets/azlist_view.dart';
|
export 'src/widgets/azlist_view.dart';
|
||||||
export 'src/widgets/bottom_bar.dart';
|
export 'src/widgets/bottom_bar.dart';
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
|
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -11,14 +10,19 @@ import 'package:sprintf/sprintf.dart';
|
|||||||
import 'utils/api_service.dart';
|
import 'utils/api_service.dart';
|
||||||
|
|
||||||
class Apis {
|
class Apis {
|
||||||
static Options get imTokenOptions => Options(headers: {'token': DataSp.imToken});
|
static Options get imTokenOptions =>
|
||||||
|
Options(headers: {'token': DataSp.imToken});
|
||||||
|
|
||||||
static Options get chatTokenOptions => Options(headers: {'token': DataSp.chatToken});
|
static Options get chatTokenOptions =>
|
||||||
|
Options(headers: {'token': DataSp.chatToken});
|
||||||
|
|
||||||
static StreamController kickoffController = StreamController<int>.broadcast();
|
static StreamController kickoffController = StreamController<int>.broadcast();
|
||||||
|
|
||||||
static void _kickoff(int? errCode) {
|
static void _kickoff(int? errCode) {
|
||||||
if (errCode == 1501 || errCode == 1503 || errCode == 1504 || errCode == 1505) {
|
if (errCode == 1501 ||
|
||||||
|
errCode == 1503 ||
|
||||||
|
errCode == 1504 ||
|
||||||
|
errCode == 1505) {
|
||||||
kickoffController.sink.add(errCode);
|
kickoffController.sink.add(errCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,43 +201,16 @@ class Apis {
|
|||||||
int? allowBeep,
|
int? allowBeep,
|
||||||
int? allowVibration,
|
int? allowVibration,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
// 原 chat `/user/update` 已随 :10008 下线。OpenIM 只同步昵称/头像;
|
||||||
Map<String, dynamic> param = {'userID': userID};
|
// 邮箱、性别、生日等业务字段由调用方更新本地状态,不打账号服务。
|
||||||
void put(String key, dynamic value) {
|
if (userID.isEmpty) return {};
|
||||||
if (null != value) {
|
if (nickname != null || faceURL != null) {
|
||||||
param[key] = value;
|
await OpenIM.iMManager.userManager.setSelfInfo(
|
||||||
}
|
nickname: nickname,
|
||||||
}
|
faceURL: faceURL,
|
||||||
|
|
||||||
put('account', account);
|
|
||||||
put('phoneNumber', phoneNumber);
|
|
||||||
put('areaCode', areaCode);
|
|
||||||
put('email', email);
|
|
||||||
put('nickname', nickname);
|
|
||||||
put('faceURL', faceURL);
|
|
||||||
put('gender', gender);
|
|
||||||
put('gender', gender);
|
|
||||||
put('level', level);
|
|
||||||
put('birth', birth);
|
|
||||||
put('allowAddFriend', allowAddFriend);
|
|
||||||
put('allowBeep', allowBeep);
|
|
||||||
put('allowVibration', allowVibration);
|
|
||||||
|
|
||||||
return HttpUtil.post(
|
|
||||||
Urls.updateUserInfo,
|
|
||||||
data: {
|
|
||||||
...param,
|
|
||||||
'platform': IMUtils.getPlatform(),
|
|
||||||
},
|
|
||||||
options: chatTokenOptions,
|
|
||||||
);
|
);
|
||||||
} catch (e, s) {
|
|
||||||
final t = e as (int, String?);
|
|
||||||
final errCode = t.$1;
|
|
||||||
final errMsg = t.$2;
|
|
||||||
_kickoff(errCode);
|
|
||||||
Logger.print('e:$errCode s:$errMsg');
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<List<FriendInfo>> searchFriendInfo(
|
static Future<List<FriendInfo>> searchFriendInfo(
|
||||||
@@ -251,7 +228,9 @@ class Apis {
|
|||||||
options: chatTokenOptions,
|
options: chatTokenOptions,
|
||||||
);
|
);
|
||||||
if (data['users'] is List) {
|
if (data['users'] is List) {
|
||||||
return (data['users'] as List).map((e) => FriendInfo.fromJson(e)).toList();
|
return (data['users'] as List)
|
||||||
|
.map((e) => FriendInfo.fromJson(e))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
@@ -269,26 +248,16 @@ class Apis {
|
|||||||
int showNumber = 10,
|
int showNumber = 10,
|
||||||
required List<String> userIDList,
|
required List<String> userIDList,
|
||||||
}) async {
|
}) async {
|
||||||
|
if (userIDList.isEmpty) return [];
|
||||||
try {
|
try {
|
||||||
final data = await HttpUtil.post(
|
final users = await OpenIM.iMManager.userManager.getUsersInfo(
|
||||||
Urls.getUsersFullInfo,
|
userIDList: userIDList,
|
||||||
data: {
|
|
||||||
'pagination': {'pageNumber': pageNumber, 'showNumber': showNumber},
|
|
||||||
'userIDs': userIDList,
|
|
||||||
'platform': IMUtils.getPlatform(),
|
|
||||||
},
|
|
||||||
options: chatTokenOptions,
|
|
||||||
);
|
);
|
||||||
if (data['users'] is List) {
|
return users
|
||||||
return (data['users'] as List).map((e) => UserFullInfo.fromJson(e)).toList();
|
.map((e) => UserFullInfoMapper.fromImJson(e.toJson()))
|
||||||
}
|
.toList();
|
||||||
return null;
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
final t = e as (int, String?);
|
Logger.print('getUserFullInfo e:$e s:$s');
|
||||||
final errCode = t.$1;
|
|
||||||
final errMsg = t.$2;
|
|
||||||
_kickoff(errCode);
|
|
||||||
Logger.print('e:$errCode s:$errMsg');
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,34 +267,20 @@ class Apis {
|
|||||||
int pageNumber = 1,
|
int pageNumber = 1,
|
||||||
int showNumber = 10,
|
int showNumber = 10,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
final keyword = content.trim();
|
||||||
final data = await HttpUtil.post(
|
if (keyword.isEmpty) return [];
|
||||||
Urls.searchUserFullInfo,
|
if (pageNumber > 1) return [];
|
||||||
data: {
|
return getUserFullInfo(userIDList: [keyword], showNumber: showNumber);
|
||||||
'pagination': {'pageNumber': pageNumber, 'showNumber': showNumber},
|
|
||||||
'keyword': content,
|
|
||||||
},
|
|
||||||
options: chatTokenOptions,
|
|
||||||
);
|
|
||||||
if (data['users'] is List) {
|
|
||||||
return (data['users'] as List).map((e) => UserFullInfo.fromJson(e)).toList();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (e, s) {
|
|
||||||
final t = e as (int, String?);
|
|
||||||
final errCode = t.$1;
|
|
||||||
final errMsg = t.$2;
|
|
||||||
_kickoff(errCode);
|
|
||||||
Logger.print('e:$errCode s:$errMsg');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<UserFullInfo?> queryMyFullInfo() async {
|
static Future<UserFullInfo?> queryMyFullInfo() async {
|
||||||
final list = await Apis.getUserFullInfo(
|
try {
|
||||||
userIDList: [OpenIM.iMManager.userID],
|
final user = await OpenIM.iMManager.userManager.getSelfUserInfo();
|
||||||
);
|
return UserFullInfoMapper.fromImJson(user.toJson());
|
||||||
return list?.firstOrNull;
|
} catch (e, s) {
|
||||||
|
Logger.print('queryMyFullInfo e:$e s:$s');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> requestVerificationCode({
|
static Future<bool> requestVerificationCode({
|
||||||
@@ -353,7 +308,8 @@ class Apis {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<SignalingCertificate> getTokenForRTC(String roomID, String userID) async {
|
static Future<SignalingCertificate> getTokenForRTC(
|
||||||
|
String roomID, String userID) async {
|
||||||
return HttpUtil.post(
|
return HttpUtil.post(
|
||||||
Urls.getTokenForRTC,
|
Urls.getTokenForRTC,
|
||||||
data: {
|
data: {
|
||||||
@@ -410,7 +366,10 @@ class Apis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<Map<String, dynamic>> getClientConfig() async {
|
static Future<Map<String, dynamic>> getClientConfig() async {
|
||||||
return {'discoverPageURL': Config.discoverPageURL, 'allowSendMsgNotFriend': Config.allowSendMsgNotFriend};
|
return {
|
||||||
|
'discoverPageURL': Config.discoverPageURL,
|
||||||
|
'allowSendMsgNotFriend': Config.allowSendMsgNotFriend
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _catchError(Object e, StackTrace s, {bool forceBack = true}) {
|
static void _catchError(Object e, StackTrace s, {bool forceBack = true}) {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ class Urls {
|
|||||||
"${Config.imApiUrl}/manager/get_users_online_status";
|
"${Config.imApiUrl}/manager/get_users_online_status";
|
||||||
static String get queryAllUsers =>
|
static String get queryAllUsers =>
|
||||||
"${Config.imApiUrl}/manager/get_all_users_uid";
|
"${Config.imApiUrl}/manager/get_all_users_uid";
|
||||||
|
// 以下 chat 路径仅作历史对照。账号服务 :10010 没有这些路由;
|
||||||
|
// 用户资料读写已改走 OpenIM SDK,见 Apis.getUserFullInfo / updateUserInfo。
|
||||||
static String get updateUserInfo => "${Config.appAuthUrl}/user/update";
|
static String get updateUserInfo => "${Config.appAuthUrl}/user/update";
|
||||||
static String get searchFriendInfo => "${Config.appAuthUrl}/friend/search";
|
static String get searchFriendInfo => "${Config.appAuthUrl}/friend/search";
|
||||||
static String get getUsersFullInfo => "${Config.appAuthUrl}/user/find/full";
|
static String get getUsersFullInfo => "${Config.appAuthUrl}/user/find/full";
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import '../models/user_full_info.dart';
|
||||||
|
|
||||||
|
/// 把 OpenIM 公开资料收成原 chat 服务 `UserFullInfo` 形状。
|
||||||
|
///
|
||||||
|
/// 官方 `open-im-chat`(:10008 `/user/find/full`)已下线,账号服务 :10010
|
||||||
|
/// 没有这条路由。SDK 只保证 userID / nickname / faceURL / ex / 勿扰。
|
||||||
|
class UserFullInfoMapper {
|
||||||
|
UserFullInfoMapper._();
|
||||||
|
|
||||||
|
static UserFullInfo fromImJson(Map<String, dynamic> json) {
|
||||||
|
return UserFullInfo.fromJson({
|
||||||
|
'userID': json['userID'],
|
||||||
|
'nickname': json['nickname'],
|
||||||
|
'faceURL': json['faceURL'],
|
||||||
|
'ex': json['ex'],
|
||||||
|
'remark': json['remark'],
|
||||||
|
'globalRecvMsgOpt': json['globalRecvMsgOpt'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<UserFullInfo> fromImList(Iterable<Map<String, dynamic>> items) {
|
||||||
|
return items.map(fromImJson).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:openim_common/openim_common.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('把 OpenIM 公开资料映射成我的信息可用字段', () {
|
||||||
|
final info = UserFullInfoMapper.fromImJson({
|
||||||
|
'userID': '10001',
|
||||||
|
'nickname': '张三',
|
||||||
|
'faceURL': 'http://example/a.png',
|
||||||
|
'ex': '',
|
||||||
|
'globalRecvMsgOpt': 0,
|
||||||
|
});
|
||||||
|
expect(info.userID, '10001');
|
||||||
|
expect(info.nickname, '张三');
|
||||||
|
expect(info.faceURL, 'http://example/a.png');
|
||||||
|
expect(info.globalRecvMsgOpt, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('不把 chat 业务字段当成仍可从账号服务拿到', () {
|
||||||
|
final info = UserFullInfoMapper.fromImJson({
|
||||||
|
'userID': '10001',
|
||||||
|
'nickname': '张三',
|
||||||
|
'phoneNumber': '13800000000',
|
||||||
|
'email': 'a@b.c',
|
||||||
|
'gender': 1,
|
||||||
|
});
|
||||||
|
expect(info.userID, '10001');
|
||||||
|
expect(info.nickname, '张三');
|
||||||
|
expect(info.phoneNumber, isNull);
|
||||||
|
expect(info.email, isNull);
|
||||||
|
expect(info.gender, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('空列表保持为空', () {
|
||||||
|
expect(UserFullInfoMapper.fromImList(const []), isEmpty);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user