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; Person({required this.userId, required this.name}); factory Person.fromJson(Map json) { return Person( userId: json['USER_ID'] as String, name: json['NAME'] as String, ); } } /// 原回调签名(向后兼容) typedef PersonSelectCallback = void Function(String userId, String name); /// 新回调签名,增加可选 index(int,默认 0) typedef PersonSelectCallbackWithIndex = void Function(String userId, String name, int index); /// 底部弹窗人员选择器(使用预先传入的原始数据列表,不做接口请求) class DepartmentPersonPicker { /// 显示人员选择弹窗 /// /// [personsData]: 已拉取并缓存的原始 Map 列表 /// [onSelected]: 选中后回调 USER_ID 和 NAME(向后兼容旧代码) /// [onSelectedWithIndex]: 可选的新回调,额外返回 index(index 为在原始 personsData/_all 中的下标,找不到则为 0) static Future show( BuildContext context, { required List> personsData, PersonSelectCallback? onSelected, PersonSelectCallbackWithIndex? onSelectedWithIndex, }) async { // 至少传入一个回调(保持对旧调用的兼容) assert(onSelected != null || onSelectedWithIndex != null, '请至少传入 onSelected 或 onSelectedWithIndex'); // 转换为模型 final List _all = personsData.map((e) => Person.fromJson(e)).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(() { _filtered = q.isEmpty ? List.from(_all) : _all.where((p) => p.name.toLowerCase().contains(q)).toList(); }); } 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; // 优先调用带 index 的回调(新),否则调用旧回调 if (onSelectedWithIndex != null) { onSelectedWithIndex(_selectedId, _selectedName, validIndex); } else if (onSelected != null) { onSelected(_selectedId, _selectedName); } }, 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), trailing: selected ? const Icon(Icons.check, color: Colors.green) : null, onTap: () => setState(() { _selectedId = person.userId; _selectedName = person.name; }), ); }, ), ), ], ), ), ); }, ); }, ); } }