import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/http/ApiService.dart'; import 'package:qhd_prevention/tools/tools.dart'; /// 数据模型 class CategoryTypeThree { final String id; final String name; final String pdId; final Map rawJson; final List children; CategoryTypeThree({ required this.id, required this.name, required this.pdId, required this.rawJson, this.children = const [], }); factory CategoryTypeThree.fromJson(Map json) { return CategoryTypeThree( id: json['id'] != null ? json['id'].toString() : "", name: json['projectName'] != null ? json['projectName'].toString() : "", pdId: json['parentId'] != null ? json['parentId'].toString() : "", rawJson: Map.from(json), 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(); } } /// 原来的回调保持不变 typedef DeptSelectCallback = void Function(String id, String name, String pdId); /// 新增:整条 JSON 回调(可选,不影响旧调用) typedef DeptSelectJsonCallback = void Function( String id, String name, String pdId, Map selectedJson, ); class RelatedPartiesPicker extends StatefulWidget { /// 原来的回调,保留不变 final DeptSelectCallback onSelected; /// 新增:可选回调,回传整条 JSON final DeptSelectJsonCallback? onSelectedJson; final listdata; const RelatedPartiesPicker({ Key? key, required this.onSelected, required this.listdata, this.onSelectedJson, }) : super(key: key); @override _RelatedPartiesPickerState createState() => _RelatedPartiesPickerState(); } class _RelatedPartiesPickerState extends State { String selectedId = ''; String selectedPDId = ''; String selectedName = ''; Map selectedJson = {}; Set expandedSet = {}; List original = []; List filtered = []; bool loading = true; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); selectedId = ''; selectedName = ''; selectedPDId = ''; selectedJson = {}; expandedSet = {}; _searchController.addListener(_onSearchChanged); _getRelatedPartiesList(); } Future _getRelatedPartiesList() async { try { final raw = await HiddenDangerApi.getRelatedPartiesList(); if (raw['success']) { final newList = raw['data'] ?? []; setState(() { original = (newList as List) .whereType>() .map((json) => CategoryTypeThree.fromJson(json)) .toList(); filtered = original; loading = false; }); } else { ToastUtil.showNormal(context, "获取列表失败"); setState(() { original = []; filtered = original; loading = false; }); } } catch (e) { print('获取数据失败:$e'); setState(() { original = []; 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, rawJson: cat.rawJson, 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; selectedJson = cat.rawJson; }); }, 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)), ], ); } void _confirm() { Navigator.of(context).pop(); widget.onSelected(selectedId, selectedName, selectedPDId); // 新增回调:不影响旧调用 widget.onSelectedJson?.call( selectedId, selectedName, selectedPDId, selectedJson, ); } @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: _confirm, child: const Text( '确定', style: TextStyle(fontSize: 16, color: Colors.blue), ), ), ], ), ), const 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), ), ), ), ], ), ); } }