- 登录:工号+密码走 account-service /api/login,自动登录、被踢下线回登录页 - 消息:会话列表(未读角标/免打扰/时间)、单聊群聊、文字/语音/图片/文件消息、失败重发、历史分页 - 通讯录:新的同事/我的群聊入口、按部门分组(好友 ex 字段)、搜索 - 通话:一对一语音通话(信令走 OpenIM 自定义消息 + LiveKit,token 走 /api/rtc_token) - 界面按确认效果图 m1/m2/m3 实现,主色 #3B87F5,四态视图齐全,无英文残留
68 lines
2.0 KiB
Dart
68 lines
2.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../theme.dart';
|
|
|
|
/// 消息列表 / 通讯录共用的搜索框(效果图 m1/m3):
|
|
/// 未输入时「放大镜 + 搜索」居中显示,输入后正常左对齐。
|
|
class SearchBox extends StatefulWidget {
|
|
final ValueChanged<String> onChanged;
|
|
|
|
const SearchBox({super.key, required this.onChanged});
|
|
|
|
@override
|
|
State<SearchBox> createState() => _SearchBoxState();
|
|
}
|
|
|
|
class _SearchBoxState extends State<SearchBox> {
|
|
final TextEditingController _ctrl = TextEditingController();
|
|
|
|
@override
|
|
void dispose() {
|
|
_ctrl.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: AppGap.x3, vertical: AppGap.x2),
|
|
child: Stack(
|
|
alignment: Alignment.centerLeft,
|
|
children: [
|
|
TextField(
|
|
controller: _ctrl,
|
|
onChanged: (v) {
|
|
setState(() {});
|
|
widget.onChanged(v.trim());
|
|
},
|
|
decoration: InputDecoration(
|
|
filled: true,
|
|
fillColor: AppColors.searchBg,
|
|
isDense: true,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: AppGap.x3, vertical: AppGap.x2),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
),
|
|
),
|
|
// 空内容时的居中占位(不拦截点击,点按穿透到输入框)
|
|
if (_ctrl.text.isEmpty)
|
|
const IgnorePointer(
|
|
child: Center(
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(Icons.search, size: 20, color: AppColors.textSecondary),
|
|
SizedBox(width: AppGap.x1),
|
|
Text('搜索', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|