import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; import 'package:qhd_prevention/http/ApiService.dart'; // 数据模型 class CategoryTypeThree { final String id; final String name; final String pdId; final List children; CategoryTypeThree({ required this.id, required this.name, required this.pdId, this.children = const [], }); factory CategoryTypeThree.fromJson(Map json) { return CategoryTypeThree( id: json['dataId'] != null ? json['dataId'].toString() : "", name: json['dataName'] != null ? json['dataName'].toString() : "", pdId: json['parentId'] != null ? json['parentId'].toString() : "", children: _parseChildren(json['children']), ); } static List _parseChildren(dynamic childrenData) { if (childrenData == null) return []; if (childrenData is! List) return []; return childrenData .whereType>() .map((e) => CategoryTypeThree.fromJson(e)) .toList(); } } /// 弹窗回调签名:返回选中项的 id 和 name typedef DeptSelectCallback = void Function(String id, String name,String pdId); class DepartmentPickerThree extends StatefulWidget { /// 回调,返回选中部门 id 与 name final DeptSelectCallback onSelected; final listdata; const DepartmentPickerThree({Key? key, required this.onSelected, required this.listdata}) : super(key: key); @override _DepartmentPickerThreeState createState() => _DepartmentPickerThreeState(); } class _DepartmentPickerThreeState extends State { String selectedId = ''; String selectedPDId = ''; String selectedName = ''; Set expandedSet = {}; List original = []; List filtered = []; bool loading = true; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); // 初始均为空 selectedId = ''; selectedName = ''; selectedPDId = ''; expandedSet = {}; _searchController.addListener(_onSearchChanged); original = (widget.listdata as List) .whereType>() .map((json) => CategoryTypeThree.fromJson(json)) // 显式指定map的泛型类型 .toList(); filtered = original; loading = false; } @override void dispose() { _searchController.removeListener(_onSearchChanged); _searchController.dispose(); super.dispose(); } void _onSearchChanged() { final query = _searchController.text.toLowerCase().trim(); setState(() { filtered = query.isEmpty ? original : _filterCategories(original, query); }); } List _filterCategories(List list, String query) { List result = []; for (var cat in list) { final children = _filterCategories(cat.children, query); if (cat.name.toLowerCase().contains(query) || children.isNotEmpty) { result.add(CategoryTypeThree(id: cat.id, name: cat.name,pdId:cat.pdId, children: children)); } } return result; } Widget _buildRow(CategoryTypeThree cat, int indent) { final hasChildren = cat.children.isNotEmpty; final isExpanded = expandedSet.contains(cat.id); final isSelected = cat.id == selectedId; return Column( children: [ InkWell( onTap: () { setState(() { if (hasChildren) { isExpanded ? expandedSet.remove(cat.id) : expandedSet.add(cat.id); selectedPDId=cat.pdId; }else{ selectedPDId=cat.id; } selectedId = cat.id; selectedName = cat.name; }); }, child: Container( color: Colors.white, child: Row( children: [ SizedBox(width: 16.0 * indent), SizedBox( width: 24, child: hasChildren ? Icon(isExpanded ? Icons.arrow_drop_down_rounded : Icons.arrow_right_rounded, size: 35, color: Colors.grey[600]) : const SizedBox.shrink(), ), const SizedBox(width: 5), Expanded( child: Padding( padding: const EdgeInsets.symmetric(vertical: 12), child: Text(cat.name), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Icon( isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, color: Colors.blue, ), ), ], ), ), ), if (hasChildren && isExpanded) ...cat.children.map((c) => _buildRow(c, indent + 1)), ], ); } @override Widget build(BuildContext context) { return Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height * 0.7, color: Colors.white, child: Column( children: [ Container( color: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: [ GestureDetector( onTap: () => Navigator.of(context).pop(), child: const Text('取消', style: TextStyle(fontSize: 16)), ), Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: SearchBarWidget( controller: _searchController, isShowSearchButton: false, onSearch: (keyboard) { }, ), ), ), GestureDetector( onTap: () { Navigator.of(context).pop(); widget.onSelected(selectedId, selectedName,selectedPDId); }, child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.blue)), ), ], ), ), Divider(), Expanded( child: loading ? const Center(child: CircularProgressIndicator()) : Container( color: Colors.white, child: ListView.builder( itemCount: filtered.length, itemBuilder: (ctx, idx) => _buildRow(filtered[idx], 0), ), ), ), ], ), ); } }