QinGang_interested/lib/customWidget/department_picker_two.dart

252 lines
7.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 CategoryType {
final String id;
final String name;
final String pdId;
final List<CategoryType> children;
CategoryType({
required this.id,
required this.name,
required this.pdId,
this.children = const [],
});
factory CategoryType.fromJson(Map<String, dynamic> json) {
return CategoryType(
id: json['id'] != null ? json['id'].toString() : "",
name: json['name'] != null ? json['name'].toString() : "",
pdId: json['parentId'] != null ? json['parentId'].toString() : "",
children: _safeParseChildren(json['childrenList']),
);
}
static List<CategoryType> _safeParseChildren(dynamic childrenData) {
if (childrenData == null) return [];
if (childrenData is! List) return [];
final List<CategoryType> children = [];
for (var item in childrenData) {
if (item is Map<String, dynamic>) {
try {
children.add(CategoryType.fromJson(item));
} catch (e) {
print('解析子项失败: $e');
}
}
}
return children;
}
}
/// 弹窗回调签名:返回选中项的 id 和 name
typedef DeptSelectCallback = void Function(String id, String name,String pdId);
class DepartmentPickerTwo extends StatefulWidget {
/// 回调,返回选中部门 id 与 name
final DeptSelectCallback onSelected;
/// 预选企业ID非必填
final String id;
const DepartmentPickerTwo({Key? key, required this.onSelected, this.id = '', }) : super(key: key);
@override
_DepartmentPickerTwoState createState() => _DepartmentPickerTwoState();
}
class _DepartmentPickerTwoState extends State<DepartmentPickerTwo> {
String selectedId = '';
String selectedPDId = '';
String selectedName = '';
Set<String> expandedSet = {};
List<CategoryType> original = [];
List<CategoryType> filtered = [];
bool loading = true;
final TextEditingController _searchController = TextEditingController();
@override
void initState() {
super.initState();
// 初始均为空
selectedId = '';
selectedName = '';
selectedPDId = '';
expandedSet = {};
_searchController.addListener(_onSearchChanged);
_loadData();
}
@override
void dispose() {
_searchController.removeListener(_onSearchChanged);
_searchController.dispose();
super.dispose();
}
Future<void> _loadData() async {
try {
List<dynamic> raw;
// if (SessionService.instance.departmentJsonStr?.isNotEmpty ?? false) {
// raw = json.decode(SessionService.instance.departmentJsonStr!) as List<dynamic>;
// } else {
// final result = await HiddenDangerApi.getHiddenTreatmentListTree();
// final String nodes = result['data'] as String;
// SessionService.instance.departmentJsonStr = nodes;
// raw = result['data'];
// }
final result = await HiddenDangerApi.getHiddenTreatmentListTree(widget.id);
raw = result['data'];
setState(() {
original = raw.map((e) => CategoryType.fromJson(e as Map<String, dynamic>)).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<CategoryType> _filterCategories(List<CategoryType> list, String query) {
List<CategoryType> result = [];
for (var cat in list) {
final children = _filterCategories(cat.children, query);
if (cat.name.toLowerCase().contains(query) || children.isNotEmpty) {
result.add(CategoryType(id: cat.id, name: cat.name,pdId:cat.pdId, children: children));
}
}
return result;
}
Widget _buildRow(CategoryType 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),
),
),
),
],
),
);
}
}