客户端默认指向 jxd.jinniu.ink 的 HTTPS/WSS;登录后把 OpenIM userID 设为极光 alias。 华为 agconnect-services.json 不伪造、不入库。Master Secret 只从服务器文件注入。 Co-authored-by: multica-agent <github@multica.ai>
185 lines
6.6 KiB
Dart
185 lines
6.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
|
|
|
|
import '../services/im_service.dart';
|
|
import '../services/push_service.dart';
|
|
import '../theme.dart';
|
|
import '../widgets/avatar.dart';
|
|
import 'login_screen.dart';
|
|
|
|
/// 「我的」页:大头像 + 姓名 + 工号,设置 / 关于 / 退出登录
|
|
class MineScreen extends StatefulWidget {
|
|
const MineScreen({super.key});
|
|
|
|
@override
|
|
State<MineScreen> createState() => _MineScreenState();
|
|
}
|
|
|
|
class _MineScreenState extends State<MineScreen> {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
IMService.instance.refreshSelfInfo();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('我的')),
|
|
body: AnimatedBuilder(
|
|
animation: IMService.instance,
|
|
builder: (context, _) {
|
|
final user = IMService.instance.selfInfo;
|
|
final nickname = user?.nickname?.isNotEmpty == true ? user!.nickname! : '';
|
|
final userID = IMService.instance.currentUserID ?? '';
|
|
return ListView(
|
|
children: [
|
|
// 头部:大头像 + 姓名 + 工号
|
|
Container(
|
|
color: AppColors.pageBg,
|
|
padding: const EdgeInsets.all(AppGap.x4),
|
|
child: Row(
|
|
children: [
|
|
NameAvatar(name: nickname.isNotEmpty ? nickname : userID, faceURL: user?.faceURL, size: 64),
|
|
const SizedBox(width: AppGap.x4),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
nickname.isNotEmpty ? nickname : userID,
|
|
style: const TextStyle(fontSize: AppFont.title, fontWeight: FontWeight.w600, color: AppColors.textPrimary),
|
|
),
|
|
const SizedBox(height: AppGap.x1),
|
|
Text(
|
|
'工号:$userID',
|
|
style: const TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: AppGap.x3),
|
|
_item(Icons.settings_outlined, '设置', () => _showSettings(nickname)),
|
|
const Divider(indent: AppGap.x4),
|
|
_item(Icons.info_outline, '关于', _showAbout),
|
|
const Divider(indent: AppGap.x4),
|
|
ListTile(
|
|
leading: const Icon(Icons.logout, color: AppColors.danger),
|
|
title: const Text('退出登录', style: TextStyle(fontSize: AppFont.body, color: AppColors.danger)),
|
|
onTap: _confirmLogout,
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _item(IconData icon, String label, VoidCallback onTap) {
|
|
return ListTile(
|
|
leading: Icon(icon, color: AppColors.textPrimary),
|
|
title: Text(label, style: const TextStyle(fontSize: AppFont.body)),
|
|
trailing: const Icon(Icons.chevron_right, color: AppColors.textSecondary),
|
|
onTap: onTap,
|
|
);
|
|
}
|
|
|
|
/// 设置:目前只有修改昵称
|
|
void _showSettings(String currentNickname) {
|
|
final ctrl = TextEditingController(text: currentNickname);
|
|
showModalBottomSheet(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
builder: (ctx) => Padding(
|
|
padding: EdgeInsets.only(
|
|
left: AppGap.x4,
|
|
right: AppGap.x4,
|
|
top: AppGap.x4,
|
|
bottom: MediaQuery.of(ctx).viewInsets.bottom + AppGap.x4,
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
const Text('修改昵称', style: TextStyle(fontSize: AppFont.title, fontWeight: FontWeight.w600)),
|
|
const SizedBox(height: AppGap.x4),
|
|
TextField(
|
|
controller: ctrl,
|
|
decoration: InputDecoration(
|
|
hintText: '请输入新昵称',
|
|
filled: true,
|
|
fillColor: AppColors.searchBg,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
borderSide: BorderSide.none,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: AppGap.x4),
|
|
FilledButton(
|
|
onPressed: () async {
|
|
final name = ctrl.text.trim();
|
|
if (name.isEmpty) return;
|
|
try {
|
|
await OpenIM.iMManager.userManager.setSelfInfo(nickname: name);
|
|
await IMService.instance.refreshSelfInfo();
|
|
if (ctx.mounted) Navigator.of(ctx).pop();
|
|
} catch (_) {
|
|
if (ctx.mounted) {
|
|
ScaffoldMessenger.of(ctx).showSnackBar(
|
|
const SnackBar(content: Text('修改失败,请检查网络后重试'), duration: Duration(seconds: 2)),
|
|
);
|
|
}
|
|
}
|
|
},
|
|
style: FilledButton.styleFrom(backgroundColor: AppColors.primary),
|
|
child: const Text('保存', style: TextStyle(fontSize: AppFont.body)),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showAbout() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (ctx) => AlertDialog(
|
|
title: const Text('关于畅联'),
|
|
content: const Text('畅联 1.0.0\n公司内部通讯工具,供同事之间消息、文件与语音通话使用。'),
|
|
actions: [
|
|
TextButton(onPressed: () => Navigator.of(ctx).pop(), child: const Text('知道了')),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _confirmLogout() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (ctx) => AlertDialog(
|
|
title: const Text('退出登录'),
|
|
content: const Text('退出后要重新输入工号和密码,确定退出吗?'),
|
|
actions: [
|
|
TextButton(onPressed: () => Navigator.of(ctx).pop(), child: const Text('取消')),
|
|
TextButton(
|
|
onPressed: () async {
|
|
Navigator.of(ctx).pop();
|
|
await LoginScreen.clearCredential();
|
|
await PushService.instance.unbindUser();
|
|
await IMService.instance.logout();
|
|
if (!mounted) return;
|
|
Navigator.of(context).pushAndRemoveUntil(
|
|
MaterialPageRoute(builder: (_) => const LoginScreen()),
|
|
(route) => false,
|
|
);
|
|
},
|
|
child: const Text('退出', style: TextStyle(color: AppColors.danger)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|