import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import '../api/oa_client.dart'; import '../labels.dart'; import '../session/session.dart'; import '../theme.dart'; import '../widgets/wecom.dart'; class ProfilePage extends StatefulWidget { const ProfilePage({super.key, required this.session, required this.api}); final SessionStore session; final OaClient api; @override State createState() => _ProfilePageState(); } class _ProfilePageState extends State { bool _busy = false; Future _refreshMe() async { final me = await widget.api.get('/auth/me'); if (me is Map) await widget.session.patchUser(Map.from(me)); } Future _pickAvatar() async { final x = await ImagePicker().pickImage(source: ImageSource.gallery, imageQuality: 85, maxWidth: 800); if (x == null) return; setState(() => _busy = true); try { await widget.api.uploadFile( filePath: x.path, filename: x.name.isEmpty ? 'avatar.jpg' : x.name, bizType: 'USER_AVATAR', bizId: widget.session.userId, ); await _refreshMe(); if (mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('头像已更新'))); } catch (e) { if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('$e'))); } finally { if (mounted) setState(() => _busy = false); } } Future _editName() async { final c = TextEditingController(text: widget.session.displayName); final ok = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('修改姓名'), content: TextField(controller: c, decoration: const InputDecoration(hintText: '显示名')), actions: [ TextButton(onPressed: () => Navigator.pop(ctx, false), child: const Text('取消')), FilledButton(onPressed: () => Navigator.pop(ctx, true), child: const Text('保存')), ], ), ); if (ok != true || c.text.trim().isEmpty) return; try { final me = await widget.api.patch('/auth/profile', {'displayName': c.text.trim()}); if (me is Map) await widget.session.patchUser(Map.from(me)); if (mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已保存'))); } catch (e) { if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('$e'))); } } Future _editPassword() async { final oldC = TextEditingController(); final newC = TextEditingController(); final ok = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('修改密码'), content: Column( mainAxisSize: MainAxisSize.min, children: [ TextField(controller: oldC, obscureText: true, decoration: const InputDecoration(hintText: '当前密码')), const SizedBox(height: 8), TextField(controller: newC, obscureText: true, decoration: const InputDecoration(hintText: '新密码(至少 6 位)')), ], ), actions: [ TextButton(onPressed: () => Navigator.pop(ctx, false), child: const Text('取消')), FilledButton(onPressed: () => Navigator.pop(ctx, true), child: const Text('保存')), ], ), ); if (ok != true) return; try { await widget.api.patch('/auth/password', {'oldPassword': oldC.text, 'newPassword': newC.text}); if (mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('密码已更新'))); } catch (e) { if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('$e'))); } } @override Widget build(BuildContext context) { final s = widget.session; final avatarId = '${s.user['avatarFileId'] ?? ''}'; return Scaffold( backgroundColor: kPaper, appBar: AppBar(title: const Text('个人资料')), body: ListView( children: [ const SizedBox(height: 12), CellGroup( children: [ Cell( title: '头像', trailing: SquareAvatar( label: s.displayName, size: 48, fileId: avatarId.isEmpty ? null : avatarId, api: widget.api, ), onTap: _busy ? null : _pickAvatar, ), Cell(title: '姓名', subtitle: s.displayName, onTap: _editName), Cell(title: '账号', subtitle: '${s.user['username'] ?? ''}'), Cell( title: '角色', subtitle: s.roles.map(zh).join(' · '), showLine: false, ), ], ), CellGroup( children: [ Cell(title: '修改密码', onTap: _editPassword, showLine: false), ], ), ], ), ); } }