import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; /// 用户数据模型 class Person { final String userId; final String name; final String departmentName; final String phone; Person({required this.userId, required this.name, required this.departmentName, required this.phone}); factory Person.fromJson(Map json) { return Person( userId: json['id'] ?? '' , name: json['username'] ?? '', departmentName: json['departmentName'] ?? '', phone: json['phone'] ?? '', ); } } /// 原回调签名(向后兼容) typedef PersonSelectCallback = void Function(String userId, String name); /// 新回调签名,增加可选 index(int,默认 0) typedef PersonSelectCallbackWithIndex = void Function(String userId, String name, int index); /// 新增:带 data 的回调(不会替换原有 typedef,向后兼容) typedef PersonSelectCallbackWithData = void Function(String userId, String name, Map data); /// 新增:带 index 和 data 的回调 typedef PersonSelectCallbackWithIndexAndData = void Function(String userId, String name, int index, Map data); /// 底部弹窗人员选择器(使用预先传入的原始数据列表,不做接口请求) class DepartmentPersonPicker { /// 显示人员选择弹窗 /// /// [personsData]: 已拉取并缓存的原始 Map 列表(每项最好是 Map) /// [onSelected]: 选中后回调 USER_ID 和 NAME(向后兼容旧代码) /// [onSelectedWithIndex]: 可选的新回调,额外返回 index(index 为在原始 personsData/_all 中的下标,找不到则为 0) /// [onSelectedWithData]: 可选回调,返回 userId/name + 选中项的完整原始 Map(不影响旧回调) /// [onSelectedWithIndexWithData]: 可选回调,返回 userId/name/index + 选中项的完整原始 Map(优先级最高) static Future show( BuildContext context, { required List personsData, PersonSelectCallback? onSelected, PersonSelectCallbackWithIndex? onSelectedWithIndex, PersonSelectCallbackWithData? onSelectedWithData, PersonSelectCallbackWithIndexAndData? onSelectedWithIndexWithData, }) async { // 至少传入一个回调(保持对旧调用的兼容) assert( onSelected != null || onSelectedWithIndex != null || onSelectedWithData != null || onSelectedWithIndexWithData != null, '请至少传入一个回调:onSelected / onSelectedWithIndex / onSelectedWithData / onSelectedWithIndexWithData', ); // 转换为模型(personsData 可能包含非 Map 的条目) final List _all = personsData.map((e) { if (e is Map) { return Person.fromJson(e); } else { // 非 map 情况按字符串处理 final s = e?.toString() ?? ''; return Person(userId: s, name: s, departmentName: '', phone: ''); } }).toList(); List _filtered = List.from(_all); String _selectedName = ''; String _selectedId = ''; final TextEditingController _searchController = TextEditingController(); await showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(12)), ), builder: (ctx) { return StatefulBuilder( builder: (BuildContext ctx, StateSetter setState) { // 搜索逻辑 void _onSearch(String v) { final q = v.toLowerCase().trim(); setState(() { if (q.isEmpty) { _filtered = List.from(_all); } else { _filtered = _all.where((p) { final nameLower = p.name.toLowerCase(); final phoneLower = p.phone.toString().toLowerCase(); return nameLower.contains(q) || phoneLower.contains(q); }).toList(); } }); } // 根据选中的 userId 在原始 personsData 中找到对应的原始 Map(若不存在则生成一个简单 Map) Map _findOriginalData(String userId) { try { final idx = personsData.indexWhere((raw) { if (raw is Map) { final id = raw['id']?.toString() ?? raw['userId']?.toString() ?? ''; return id == userId; } else { return raw?.toString() == userId; } }); if (idx >= 0) { final raw = personsData[idx]; if (raw is Map) return Map.from(raw); return {'id': userId, 'username': _selectedName}; } else { // 找不到则返回一个最小信息 map return {'id': userId, 'username': _selectedName}; } } catch (e) { return {'id': userId, 'username': _selectedName}; } } return SafeArea( child: SizedBox( height: MediaQuery.of(ctx).size.height * 0.75, child: Column( children: [ // 顶部:取消、搜索、确定 Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: [ TextButton( onPressed: () => Navigator.of(ctx).pop(), child: const Text( '取消', style: TextStyle(fontSize: 16), ), ), Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: SearchBarWidget( controller: _searchController, onTextChanged: _onSearch, isShowSearchButton: false, onSearch: (keyboard) {}, ), ), ), TextButton( onPressed: _selectedId.isEmpty ? null : () { Navigator.of(ctx).pop(); // 计算 index(在原始 _all 列表中的下标) final idx = _all.indexWhere((p) => p.userId == _selectedId); final validIndex = idx >= 0 ? idx : 0; // 找到原始 data(Map) final dataMap = _findOriginalData(_selectedId); // 优先调用带 index 和 data 的回调(最高优先) if (onSelectedWithIndexWithData != null) { onSelectedWithIndexWithData(_selectedId, _selectedName, validIndex, dataMap); return; } // 然后是带 data 的回调(只返回 data,不返回 index) if (onSelectedWithData != null) { onSelectedWithData(_selectedId, _selectedName, dataMap); return; } // 然后是带 index 的旧回调 if (onSelectedWithIndex != null) { onSelectedWithIndex(_selectedId, _selectedName, validIndex); return; } // 最后回退到最原始的回调(仅 userId + name) if (onSelected != null) { onSelected(_selectedId, _selectedName); return; } }, child: const Text( '确定', style: TextStyle(color: Colors.green, fontSize: 16), ), ), ], ), ), const Divider(height: 1), // 列表 Expanded( child: ListView.separated( itemCount: _filtered.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, index) { final person = _filtered[index]; final selected = person.userId == _selectedId; return ListTile( titleAlignment: ListTileTitleAlignment.center, title: Text('${person.name}-${person.phone}(${person.departmentName})'), trailing: selected ? const Icon(Icons.check, color: Colors.green) : null, onTap: () => setState(() { _selectedId = person.userId; _selectedName = person.name; }), ); }, ), ), ], ), ), ); }, ); }, ); } }