import 'package:flutter/material.dart'; import '../../api/oa_client.dart'; import '../desk_theme.dart'; import '../widgets/desk_widgets.dart'; class DeskPickPeoplePage extends StatefulWidget { const DeskPickPeoplePage({ super.key, required this.api, required this.title, this.multiple = true, this.exclude = const {}, }); final OaClient api; final String title; final bool multiple; final Set exclude; @override State createState() => _DeskPickPeoplePageState(); } class _DeskPickPeoplePageState extends State { List> _items = []; final _selected = {}; String _q = ''; bool _loading = true; @override void initState() { super.initState(); _load(); } Future _load() async { try { final data = await widget.api.get('/staff'); if (!mounted) return; setState(() { _items = asMaps(data); _loading = false; }); } catch (_) { if (mounted) setState(() => _loading = false); } } void _confirm() { Navigator.pop( context, _selected.entries.map((e) => {'id': e.key, 'name': e.value}).toList(), ); } @override Widget build(BuildContext context) { final shown = _items.where((e) { final id = '${e['id']}'; if (widget.exclude.contains(id)) return false; if (_q.isEmpty) return true; return '${e['name']}${e['department']}${e['title']}'.contains(_q); }).toList(); return Scaffold( backgroundColor: kDeskBg, body: Column( children: [ DeskPaneHeader( title: widget.title, leading: IconButton(icon: const Icon(Icons.close, size: 20), onPressed: () => Navigator.pop(context)), actions: [ if (widget.multiple) TextButton(onPressed: _selected.isEmpty ? null : _confirm, child: Text('确定(${_selected.length})')), ], bottom: Padding( padding: const EdgeInsets.fromLTRB(14, 0, 14, 10), child: DeskSearchField(hint: '搜索同事', onChanged: (v) => setState(() => _q = v.trim())), ), ), if (_loading) const LinearProgressIndicator(minHeight: 2, color: kDeskBind), Expanded( child: ListView.builder( itemCount: shown.length, itemBuilder: (_, i) { final r = shown[i]; final id = '${r['id']}'; final name = '${r['name'] ?? ''}'; final on = _selected.containsKey(id); return Material( color: on ? kDeskActive : Colors.white, child: InkWell( onTap: () { if (!widget.multiple) { Navigator.pop(context, [ {'id': id, 'name': name, 'avatarFileId': '${r['avatarFileId'] ?? ''}'}, ]); return; } setState(() { if (on) { _selected.remove(id); } else { _selected[id] = name; } }); }, child: Padding( padding: const EdgeInsets.fromLTRB(14, 10, 14, 10), child: Row( children: [ DeskAvatar(label: name, fileId: '${r['avatarFileId'] ?? ''}', api: widget.api, size: 36), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), Text('${r['department'] ?? ''} ${r['title'] ?? ''}'.trim(), style: const TextStyle(fontSize: 12, color: kDeskMute)), ], ), ), if (widget.multiple) Icon(on ? Icons.check_circle : Icons.circle_outlined, color: on ? kDeskBind : kDeskMute, size: 20), ], ), ), ), ); }, ), ), ], ), ); } }