feat(mobile,account-service): 统一发送服务 + 员工目录接口 + 好友申请五态/验证消息(B-52 施工 2/3)

- message_send_service:所有消息走统一门禁(登录/连接/空接收方/好友校验),
  失败打印 SDK 原始 code 并映射中文提示,不再只吞异常
- chat_screen 接入统一发送服务,失败提示真实原因
- account-service 新增 GET /api/directory(登录用户可读启用员工,用于添加同事)
- add_friend_screen 增加可编辑验证消息(视觉规范 4.2)
- new_friends_screen 五态 + 窄屏(<360)按钮组换行不挤压姓名(视觉规范 5.3)

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
编码工程师
2026-08-16 02:16:00 +08:00
co-authored by multica-agent
parent d6ef6eb9a4
commit 12b0a1c943
5 changed files with 232 additions and 41 deletions
+20 -2
View File
@@ -3,7 +3,7 @@ import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
import '../theme.dart';
/// 添加同事:输入对方工号(userID)发送好友申请
/// 添加同事:输入对方工号(userID)+ 可编辑验证消息,发送好友申请
class AddFriendScreen extends StatefulWidget {
const AddFriendScreen({super.key});
@@ -13,11 +13,13 @@ class AddFriendScreen extends StatefulWidget {
class _AddFriendScreenState extends State<AddFriendScreen> {
final TextEditingController _idCtrl = TextEditingController();
final TextEditingController _msgCtrl = TextEditingController(text: '你好,我想加你为同事');
bool _sending = false;
@override
void dispose() {
_idCtrl.dispose();
_msgCtrl.dispose();
super.dispose();
}
@@ -29,7 +31,7 @@ class _AddFriendScreenState extends State<AddFriendScreen> {
}
setState(() => _sending = true);
try {
await OpenIM.iMManager.friendshipManager.addFriend(userID: userID, reason: '你好,我想加你为同事');
await OpenIM.iMManager.friendshipManager.addFriend(userID: userID, reason: _msgCtrl.text.trim());
if (!mounted) return;
_toast('申请已发送,等对方通过');
Navigator.of(context).pop();
@@ -66,6 +68,22 @@ class _AddFriendScreenState extends State<AddFriendScreen> {
),
),
),
const SizedBox(height: AppGap.x4),
TextField(
controller: _msgCtrl,
maxLines: 3,
minLines: 2,
decoration: InputDecoration(
hintText: '验证消息(可不填)',
hintStyle: const TextStyle(color: AppColors.textSecondary),
filled: true,
fillColor: AppColors.searchBg,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide.none,
),
),
),
const SizedBox(height: AppGap.x6),
SizedBox(
height: 48,