import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; import 'package:qhd_prevention/http/ApiService.dart'; import 'package:qhd_prevention/services/SessionService.dart'; import '../tools/tools.dart'; // 包含 SessionService // 数据模型 class Category { final String id; final String name; final Map extValues; final String departmentId; final String parentId; final String corpinfoId; // 新增:和 departmentId 同层级 final List childrenList; Category({ required this.id, required this.name, required this.childrenList, required this.extValues, required this.departmentId, required this.parentId, required this.corpinfoId, }); factory Category.fromJson(Map json) { // 安全读取并兼容字符串或数字类型的 id String parseString(dynamic v) { if (v == null) return ''; if (v is String) return v; return v.toString(); } final rawChildren = json['childrenList']; List children = []; if (rawChildren is List) { try { children = rawChildren .where((e) => e != null) .map((e) => Category.fromJson(Map.from(e as Map))) .toList(); } catch (e) { // 如果内部解析出错,保持 children 为空并继续 children = []; } } // extValues 有可能为 null 或不是 Map final extRaw = json['extValues']; Map extMap = {}; if (extRaw is Map) { extMap = Map.from(extRaw); } return Category( id: parseString(json['id']), name: parseString(json['name']), childrenList: children, extValues: extMap, departmentId: parseString(json['departmentId']), parentId: parseString(json['parentId']), corpinfoId: parseString(json['corpinfoId']), // 从 JSON 同层级读取 ); } } /// 弹窗回调签名:返回选中项的 id 和 name (保持原样,兼容旧代码) typedef DeptSelectCallback = void Function(String id, String name); class DepartmentPickerHidden extends StatefulWidget { /// 原回调,返回选中部门 id 与 name(保持不变) final DeptSelectCallback onSelected; /// 新增可选扩展回调:当需要 corpinfoId 时使用(不影响原有调用) final void Function(String id, String name, String? corpinfoId)? onSelectedWithCorp; /// 是否包含所有公司 final bool includeAllFirm; final Map? data; const DepartmentPickerHidden({ Key? key, required this.onSelected, this.onSelectedWithCorp, this.includeAllFirm = false, this.data, }) : super(key: key); @override _DepartmentPickerHiddenState createState() => _DepartmentPickerHiddenState(); } class _DepartmentPickerHiddenState extends State { String selectedId = ''; String selectedName = ''; String? selectedCorpinfoId; // 记录选中项的 corpinfoId(可为 null) Set expandedSet = {}; List original = []; List filtered = []; bool loading = true; final TextEditingController _searchController = TextEditingController(); @override void initState() { super.initState(); // 初始均为空 selectedId = ''; selectedName = ''; selectedCorpinfoId = null; expandedSet = {}; _searchController.addListener(_onSearchChanged); _loadData(); } @override void dispose() { _searchController.removeListener(_onSearchChanged); _searchController.dispose(); super.dispose(); } Future _loadData() async { try { final result = await BasicInfoApi.getDeptFour(widget.includeAllFirm, data: widget.data); final raw = result['data'] as List; print(raw); setState(() { original = raw.map((e) => Category.fromJson(e as Map)).toList(); filtered = original; loading = false; }); } catch (e) { setState(() => loading = false); } } 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.childrenList, query); if (cat.name.toLowerCase().contains(query) || children.isNotEmpty) { result.add( Category( id: cat.id, name: cat.name, childrenList: children, extValues: cat.extValues, departmentId: cat.departmentId, parentId: cat.parentId, corpinfoId: cat.corpinfoId, // 保持 corpinfoId 传递 ), ); } } return result; } Widget _buildRow(Category cat, int indent) { final hasChildren = cat.childrenList.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); } selectedId = cat.id; selectedName = cat.name; selectedCorpinfoId = cat.corpinfoId.isEmpty ? null : cat.corpinfoId; }); }, 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.childrenList.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: () { // 关闭弹窗并回调:优先调用扩展回调(带 corpinfoId),否则调用原回调 Navigator.of(context).pop(); if (widget.onSelectedWithCorp != null) { widget.onSelectedWithCorp!( selectedId, selectedName, selectedCorpinfoId, ); } else { widget.onSelected(selectedId, selectedName); } }, 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), ), ), ), ], ), ); } }