import 'package:flutter/material.dart'; import '../api/oa_client.dart'; import '../session/session.dart'; import '../theme.dart'; import '../widgets/wecom.dart'; import 'chat_page.dart'; class OrgBrowsePage extends StatefulWidget { const OrgBrowsePage({ super.key, required this.session, required this.api, required this.staff, this.parentId, this.title = '组织架构', this.deptName, }); final SessionStore session; final OaClient api; final List> staff; final String? parentId; final String title; final String? deptName; @override State createState() => _OrgBrowsePageState(); } class _OrgBrowsePageState extends State { List> _depts = []; bool _loading = true; @override void initState() { super.initState(); _load(); } Future _load() async { try { final data = await widget.api.get('/departments'); if (!mounted) return; setState(() { _depts = asMaps(data); _loading = false; }); } catch (_) { if (mounted) setState(() => _loading = false); } } List> get _children { if (_depts.isEmpty) return const []; return _depts.where((e) { final pid = '${e['parentId'] ?? ''}'; if (widget.parentId == null || widget.parentId!.isEmpty) return pid.isEmpty || pid == 'null'; return pid == widget.parentId; }).toList(); } List> get _people { final name = widget.deptName; if (name == null || name.isEmpty) return const []; final me = widget.session.userId; return widget.staff.where((e) => '${e['department']}' == name && '${e['id']}' != me).toList(); } int _countOf(Map d) { final c = d['_count']; if (c is Map && c['employees'] != null) return (c['employees'] as num).toInt(); return widget.staff.where((e) => '${e['department']}' == '${d['name']}').length; } void _openPerson(Map r) { Navigator.of(context).push(MaterialPageRoute( builder: (_) => ChatPage( session: widget.session, api: widget.api, peerId: '${r['id']}', peerName: '${r['name'] ?? '同事'}', peerAvatarFileId: '${r['avatarFileId'] ?? ''}', ), )); } @override Widget build(BuildContext context) { final children = _children; final people = _people; final fallbackDepts = {}; if (_depts.isEmpty && (widget.parentId == null || widget.parentId!.isEmpty)) { for (final r in widget.staff) { final d = '${r['department'] ?? ''}'; if (d.isNotEmpty) fallbackDepts.add(d); } } return Scaffold( backgroundColor: kPaper, appBar: AppBar(title: Text(widget.title), leading: const BackButton()), body: _loading ? const Center(child: CircularProgressIndicator()) : ListView( children: [ const SizedBox(height: 12), if (children.isNotEmpty) CellGroup( children: [ for (var i = 0; i < children.length; i++) Cell( title: '${children[i]['name'] ?? ''}', subtitle: '${_countOf(children[i])} 人', leading: const SquareAvatar(label: '部', color: kBind, icon: Icons.apartment, size: 36), showLine: i != children.length - 1, onTap: () => Navigator.of(context).push(MaterialPageRoute( builder: (_) => OrgBrowsePage( session: widget.session, api: widget.api, staff: widget.staff, parentId: '${children[i]['id']}', title: '${children[i]['name'] ?? '部门'}', deptName: '${children[i]['name'] ?? ''}', ), )), ), ], ) else if (fallbackDepts.isNotEmpty) CellGroup( children: [ for (final d in (fallbackDepts.toList()..sort())) Cell( title: d, subtitle: '${widget.staff.where((e) => '${e['department']}' == d).length} 人', leading: const SquareAvatar(label: '部', color: kBind, icon: Icons.apartment, size: 36), onTap: () => Navigator.of(context).push(MaterialPageRoute( builder: (_) => OrgBrowsePage( session: widget.session, api: widget.api, staff: widget.staff, parentId: '__leaf__', title: d, deptName: d, ), )), ), ], ), if (people.isNotEmpty) ...[ Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 8), child: Text('${widget.deptName} · ${people.length} 人', style: const TextStyle(fontSize: 13, color: kMute)), ), CellGroup( children: [ for (var i = 0; i < people.length; i++) Cell( title: '${people[i]['name'] ?? ''}', subtitle: '${people[i]['title'] ?? ''}', leading: SquareAvatar( label: '${people[i]['name'] ?? ''}', fileId: '${people[i]['avatarFileId'] ?? ''}', api: widget.api, size: 36, ), showLine: i != people.length - 1, onTap: () => _openPerson(people[i]), ), ], ), ], if (children.isEmpty && fallbackDepts.isEmpty && people.isEmpty) const Padding( padding: EdgeInsets.only(top: 48), child: Center(child: Text('这个部门还没有人', style: TextStyle(color: kMute))), ), ], ), ); } }