|
|
@@ -0,0 +1,295 @@
|
|
|
+import 'package:chicken_farm/components/vb_app_bar.dart';
|
|
|
+import 'package:chicken_farm/core/config/default_dicts.dart';
|
|
|
+import 'package:chicken_farm/modes/system/dict.dart';
|
|
|
+import 'package:chicken_farm/stores/dict_stroe.dart';
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+
|
|
|
+class DictManagePage extends StatefulWidget {
|
|
|
+ const DictManagePage({super.key});
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<DictManagePage> createState() => _DictManagePageState();
|
|
|
+}
|
|
|
+
|
|
|
+class _DictManagePageState extends State<DictManagePage> {
|
|
|
+ final DictStore _dictStore = DictStore();
|
|
|
+ late Future<Map<String, List<DictDataModel>>> _dictsFuture;
|
|
|
+ final Set<String> _expandedTypes = <String>{};
|
|
|
+
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ super.initState();
|
|
|
+ _loadDicts();
|
|
|
+ }
|
|
|
+
|
|
|
+ void _loadDicts() {
|
|
|
+ setState(() {
|
|
|
+ _dictsFuture = _dictStore.getAllOfflineDicts();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Scaffold(
|
|
|
+ appBar: VberAppBar(title: '字典维护'),
|
|
|
+ body: FutureBuilder<Map<String, List<DictDataModel>>>(
|
|
|
+ future: _dictsFuture,
|
|
|
+ builder: (context, snapshot) {
|
|
|
+ if (snapshot.connectionState == ConnectionState.waiting) {
|
|
|
+ return const Center(child: CircularProgressIndicator());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (snapshot.hasError) {
|
|
|
+ return Center(child: Text('加载失败: ${snapshot.error}'));
|
|
|
+ }
|
|
|
+
|
|
|
+ final dicts = snapshot.data ?? {};
|
|
|
+
|
|
|
+ if (dicts.isEmpty) {
|
|
|
+ return const Center(
|
|
|
+ child: Column(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ Icon(Icons.info, size: 48, color: Colors.grey),
|
|
|
+ SizedBox(height: 16),
|
|
|
+ Text('暂无字典数据', style: TextStyle(fontSize: 16)),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return ListView.builder(
|
|
|
+ itemCount: dicts.length,
|
|
|
+ itemBuilder: (context, index) {
|
|
|
+ final dictType = dicts.keys.elementAt(index);
|
|
|
+ final dictItems = dicts[dictType] ?? [];
|
|
|
+ final dictName = DefaultDicts.getDictName(dictType);
|
|
|
+ return Card(
|
|
|
+ margin: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
|
|
|
+ child: Theme(
|
|
|
+ data: Theme.of(
|
|
|
+ context,
|
|
|
+ ).copyWith(dividerColor: Colors.transparent),
|
|
|
+ child: ExpansionTile(
|
|
|
+ key: Key(dictType),
|
|
|
+ initiallyExpanded: _expandedTypes.contains(dictType),
|
|
|
+ onExpansionChanged: (expanded) {
|
|
|
+ setState(() {
|
|
|
+ if (expanded) {
|
|
|
+ _expandedTypes.add(dictType);
|
|
|
+ } else {
|
|
|
+ _expandedTypes.remove(dictType);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ title: Text('$dictName (${dictItems.length})'),
|
|
|
+ children: [
|
|
|
+ if (dictItems.isEmpty)
|
|
|
+ const ListTile(title: Text('该类型下暂无数据'))
|
|
|
+ else
|
|
|
+ ...dictItems.map(
|
|
|
+ (item) => ListTile(
|
|
|
+ title: Text(item.dictLabel),
|
|
|
+ subtitle: Text('值: ${item.dictValue}'),
|
|
|
+ trailing: Row(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ IconButton(
|
|
|
+ icon: const Icon(Icons.edit, size: 18),
|
|
|
+ onPressed: () =>
|
|
|
+ _editDictItem(dictType, item),
|
|
|
+ ),
|
|
|
+ IconButton(
|
|
|
+ icon: const Icon(Icons.delete, size: 18),
|
|
|
+ onPressed: () =>
|
|
|
+ _deleteDictItem(dictType, item),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ListTile(
|
|
|
+ leading: const Icon(Icons.add, color: Colors.blue),
|
|
|
+ title: const Text('添加新项目'),
|
|
|
+ onTap: () => _addNewDictItem(dictType),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ );
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ void _addNewDictItem(String dictType) async {
|
|
|
+ final labelController = TextEditingController();
|
|
|
+ final valueController = TextEditingController();
|
|
|
+ final sortController = TextEditingController(text: '0');
|
|
|
+
|
|
|
+ final result = await showDialog<bool>(
|
|
|
+ context: context,
|
|
|
+ builder: (context) => AlertDialog(
|
|
|
+ title: const Text('添加字典项'),
|
|
|
+ content: Column(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ TextField(
|
|
|
+ controller: labelController,
|
|
|
+ decoration: const InputDecoration(labelText: '标签'),
|
|
|
+ ),
|
|
|
+ TextField(
|
|
|
+ controller: valueController,
|
|
|
+ decoration: const InputDecoration(labelText: '值'),
|
|
|
+ ),
|
|
|
+ TextField(
|
|
|
+ controller: sortController,
|
|
|
+ decoration: const InputDecoration(labelText: '排序'),
|
|
|
+ keyboardType: TextInputType.number,
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ actions: [
|
|
|
+ TextButton(
|
|
|
+ onPressed: () => Navigator.of(context).pop(false),
|
|
|
+ child: const Text('取消'),
|
|
|
+ ),
|
|
|
+ TextButton(
|
|
|
+ onPressed: () => Navigator.of(context).pop(true),
|
|
|
+ child: const Text('确定'),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+
|
|
|
+ if (result == true) {
|
|
|
+ final dictItems = (await _dictStore.getDictByType(dictType)) ?? [];
|
|
|
+
|
|
|
+ // 生成唯一的dictCode
|
|
|
+ int maxCode = 0;
|
|
|
+ for (final item in dictItems) {
|
|
|
+ if (item.dictCode > maxCode) {
|
|
|
+ maxCode = item.dictCode;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ final newItem = DictDataModel(
|
|
|
+ dictCode: maxCode + 1,
|
|
|
+ dictSort: int.tryParse(sortController.text) ?? 0,
|
|
|
+ dictLabel: labelController.text,
|
|
|
+ dictValue: valueController.text,
|
|
|
+ dictType: dictType,
|
|
|
+ );
|
|
|
+
|
|
|
+ try {
|
|
|
+ await _dictStore.addDictItem(dictType, newItem);
|
|
|
+ _loadDicts(); // 重新加载数据
|
|
|
+ } catch (e) {
|
|
|
+ if (mounted) {
|
|
|
+ ScaffoldMessenger.of(
|
|
|
+ context,
|
|
|
+ ).showSnackBar(SnackBar(content: Text('操作失败: $e')));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void _editDictItem(String dictType, DictDataModel item) async {
|
|
|
+ final labelController = TextEditingController(text: item.dictLabel);
|
|
|
+ final valueController = TextEditingController(text: item.dictValue);
|
|
|
+ final sortController = TextEditingController(
|
|
|
+ text: item.dictSort.toString(),
|
|
|
+ );
|
|
|
+
|
|
|
+ final result = await showDialog<bool>(
|
|
|
+ context: context,
|
|
|
+ builder: (context) => AlertDialog(
|
|
|
+ title: const Text('编辑字典项'),
|
|
|
+ content: Column(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ TextField(
|
|
|
+ controller: labelController,
|
|
|
+ decoration: const InputDecoration(labelText: '标签'),
|
|
|
+ ),
|
|
|
+ TextField(
|
|
|
+ controller: valueController,
|
|
|
+ decoration: const InputDecoration(labelText: '值'),
|
|
|
+ ),
|
|
|
+ TextField(
|
|
|
+ controller: sortController,
|
|
|
+ decoration: const InputDecoration(labelText: '排序'),
|
|
|
+ keyboardType: TextInputType.number,
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ actions: [
|
|
|
+ TextButton(
|
|
|
+ onPressed: () => Navigator.of(context).pop(false),
|
|
|
+ child: const Text('取消'),
|
|
|
+ ),
|
|
|
+ TextButton(
|
|
|
+ onPressed: () => Navigator.of(context).pop(true),
|
|
|
+ child: const Text('确定'),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+
|
|
|
+ if (result == true) {
|
|
|
+ final updatedItem = DictDataModel(
|
|
|
+ dictCode: item.dictCode,
|
|
|
+ dictSort: int.tryParse(sortController.text) ?? item.dictSort,
|
|
|
+ dictLabel: labelController.text,
|
|
|
+ dictValue: valueController.text,
|
|
|
+ dictType: dictType,
|
|
|
+ );
|
|
|
+
|
|
|
+ try {
|
|
|
+ await _dictStore.updateDictItem(dictType, updatedItem);
|
|
|
+ _loadDicts(); // 重新加载数据
|
|
|
+ } catch (e) {
|
|
|
+ if (mounted) {
|
|
|
+ ScaffoldMessenger.of(
|
|
|
+ context,
|
|
|
+ ).showSnackBar(SnackBar(content: Text('操作失败: $e')));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void _deleteDictItem(String dictType, DictDataModel item) async {
|
|
|
+ final confirm = await showDialog<bool>(
|
|
|
+ context: context,
|
|
|
+ builder: (context) => AlertDialog(
|
|
|
+ title: const Text('确认删除'),
|
|
|
+ content: Text('确定要删除 "${item.dictLabel}" 吗?'),
|
|
|
+ actions: [
|
|
|
+ TextButton(
|
|
|
+ onPressed: () => Navigator.of(context).pop(false),
|
|
|
+ child: const Text('取消'),
|
|
|
+ ),
|
|
|
+ TextButton(
|
|
|
+ onPressed: () => Navigator.of(context).pop(true),
|
|
|
+ child: const Text('确定'),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+
|
|
|
+ if (confirm == true) {
|
|
|
+ try {
|
|
|
+ await _dictStore.removeDictItem(dictType, item.dictCode);
|
|
|
+ _loadDicts(); // 重新加载数据
|
|
|
+ } catch (e) {
|
|
|
+ if (mounted) {
|
|
|
+ ScaffoldMessenger.of(
|
|
|
+ context,
|
|
|
+ ).showSnackBar(SnackBar(content: Text('删除失败: $e')));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|