From aa98e217076a1f1a3c6fe6aa366d73f4a79f9052 Mon Sep 17 00:00:00 2001 From: hejl Date: Sat, 21 Jun 2025 15:07:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=85=E5=AD=98=E8=A1=A8=E5=B7=B2=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E4=B8=BA=E5=8D=95=E9=80=89=EF=BC=8C=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=8D=95=E9=80=89=E4=B9=8B=E5=89=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../call_function/models/call_function.dart | 2 + .../memory_table/models/memory_table.dart | 2 +- .../services/memory_table_service.dart | 2 +- .../widgets/memory_table_right_side.dart | 55 ++++--- .../outline/controllers/outline_provider.dart | 24 ++- .../outline/services/functions_service.dart | 5 +- .../outline/services/outline_service.dart | 5 +- .../outline/services/std_field_service.dart | 15 +- .../outline/widgets/outline_explorer.dart | 2 +- .../code_generation_components.dart | 143 ++++++++++++++++++ 10 files changed, 206 insertions(+), 49 deletions(-) create mode 100644 win_text_editor/lib/shared/components/code_generation_components.dart diff --git a/win_text_editor/lib/modules/call_function/models/call_function.dart b/win_text_editor/lib/modules/call_function/models/call_function.dart index 50eb108..1167def 100644 --- a/win_text_editor/lib/modules/call_function/models/call_function.dart +++ b/win_text_editor/lib/modules/call_function/models/call_function.dart @@ -28,6 +28,7 @@ class CallFunction { 'factorParam': factorParam ?? '', 'input': inputParameters + .where((field) => field.isSelected) .map( (field) => { 'id': field.id, @@ -40,6 +41,7 @@ class CallFunction { .toList(), 'output': outputParameters + .where((field) => field.isSelected) .map( (field) => { 'id': field.id, diff --git a/win_text_editor/lib/modules/memory_table/models/memory_table.dart b/win_text_editor/lib/modules/memory_table/models/memory_table.dart index 6117750..9c7408c 100644 --- a/win_text_editor/lib/modules/memory_table/models/memory_table.dart +++ b/win_text_editor/lib/modules/memory_table/models/memory_table.dart @@ -41,7 +41,7 @@ class MemoryTable { //获取主键的字段 List get keyFields { var name = keyName; - if (name!.isEmpty) return []; + if (name == null || name.isEmpty) return []; for (var index in indexes) { if (index.indexName == name) { return index.fields; diff --git a/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart b/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart index 0a1e91e..f78b13a 100644 --- a/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart +++ b/win_text_editor/lib/modules/memory_table/services/memory_table_service.dart @@ -69,7 +69,7 @@ class MemoryTableService { final rule = containerType ?? ''; // Get all index fields - final items = indexNode.findAllElements('items'); + final items = indexNode.findElements('items'); final fieldsList = items .map((item) => item.getAttribute('attrname') ?? '') diff --git a/win_text_editor/lib/modules/memory_table/widgets/memory_table_right_side.dart b/win_text_editor/lib/modules/memory_table/widgets/memory_table_right_side.dart index 8a91318..2614527 100644 --- a/win_text_editor/lib/modules/memory_table/widgets/memory_table_right_side.dart +++ b/win_text_editor/lib/modules/memory_table/widgets/memory_table_right_side.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:win_text_editor/modules/memory_table/controllers/memory_table_controller.dart'; -import 'package:win_text_editor/shared/components/my_checkbox.dart'; class MemoryTableRightSide extends StatefulWidget { final MemoryTableController controller; @@ -14,7 +13,7 @@ class MemoryTableRightSide extends StatefulWidget { } class _MemoryTableRightSideState extends State { - final List _selectedOperations = []; + String? _selectedOperation; // 改为可空的单个字符串 @override void initState() { @@ -30,16 +29,16 @@ class _MemoryTableRightSideState extends State { } void _updateDisplay() { - widget.codeController.text = widget.controller.genCodeString(_selectedOperations)!; + if (_selectedOperation != null) { + widget.codeController.text = widget.controller.genCodeString([_selectedOperation!]) ?? ''; + } else { + widget.codeController.text = ''; + } } - void _toggleOperation(String operation, bool? value) { + void _selectOperation(String operation) { setState(() { - if (value == true) { - _selectedOperations.add(operation); - } else { - _selectedOperations.remove(operation); - } + _selectedOperation = operation; _updateDisplay(); }); } @@ -48,7 +47,7 @@ class _MemoryTableRightSideState extends State { Widget build(BuildContext context) { return Column( children: [ - _buildCheckboxSection(), + _buildRadioSection(), Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0), child: Row( @@ -75,21 +74,21 @@ class _MemoryTableRightSideState extends State { ); } - Widget _buildCheckboxSection() { + Widget _buildRadioSection() { final operations = ['获取记录', '获取记录数', '插入记录', '修改记录', '删除记录', '遍历记录']; return SizedBox( width: double.infinity, child: Card( child: Padding( - padding: const EdgeInsets.only(left: 8, top: 4, bottom: 12), + padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Wrap( - spacing: 8, - runSpacing: 8, - children: operations.map((op) => _buildCheckbox(op)).toList(), + spacing: 16, // 水平间距 + runSpacing: 8, // 垂直间距 + children: operations.map((op) => _buildRadioItem(op)).toList(), ), ], ), @@ -98,11 +97,27 @@ class _MemoryTableRightSideState extends State { ); } - Widget _buildCheckbox(String label) => MyCheckbox( - title: label, - value: _selectedOperations.contains(label), - onChanged: (bool? value) => _toggleOperation(label, value), - ); + Widget _buildRadioItem(String label) { + return Row( + mainAxisSize: MainAxisSize.min, // 使Row只占用必要宽度 + children: [ + Transform.scale( + scale: 0.75, + child: Radio( + value: label, + groupValue: _selectedOperation, + onChanged: (String? value) { + if (value != null) { + _selectOperation(value); + } + }, + ), + ), + const SizedBox(width: 4), + Text(label, style: const TextStyle(fontSize: 14)), + ], + ); + } Widget _buildCodeEditor() { return Card( diff --git a/win_text_editor/lib/modules/outline/controllers/outline_provider.dart b/win_text_editor/lib/modules/outline/controllers/outline_provider.dart index 9f3db49..551ef7f 100644 --- a/win_text_editor/lib/modules/outline/controllers/outline_provider.dart +++ b/win_text_editor/lib/modules/outline/controllers/outline_provider.dart @@ -16,15 +16,6 @@ class OutlineProvider with ChangeNotifier { isExpanded: true, ); - static OutlineNode searchNode = OutlineNode( - name: "搜索结果", - title: "搜索结果", - value: 'Query', - isDirectory: true, - isRoot: true, - isExpanded: true, - ); - bool get isLoading => _isLoading; bool get hasRoot => _outlineNode.isNotEmpty && _outlineNode[0].isRoot; @@ -71,7 +62,7 @@ class OutlineProvider with ChangeNotifier { } } - Future loadDirectoryContents(OutlineNode dirNode) async { + Future loadDirectoryContents(OutlineNode dirNode, {bool refresh = false}) async { if (dirNode.children.isNotEmpty) { return; } @@ -86,10 +77,15 @@ class OutlineProvider with ChangeNotifier { notifyListeners(); } - Future refreshOutlineTree({bool loadContent = false}) async { + Future refreshOutlineTree() async { _isLoading = true; notifyListeners(); - Logger().info('正在刷新大纲树...'); + rootNode.isExpanded = false; + rootNode.children.clear(); + final wordNodes = await OutlineService.getWordNodes(_currentRootPath!); + rootNode.title = "所有"; + rootNode.children = wordNodes; + rootNode.isExpanded = true; _isLoading = false; notifyListeners(); } @@ -101,7 +97,7 @@ class OutlineProvider with ChangeNotifier { return [rootNode]; } - OutlineService.applySearchFilter(searchNode, searchQuery); - return [searchNode]; + OutlineService.applySearchFilter(rootNode, searchQuery); + return [rootNode]; } } diff --git a/win_text_editor/lib/modules/outline/services/functions_service.dart b/win_text_editor/lib/modules/outline/services/functions_service.dart index 211a299..0d21d9e 100644 --- a/win_text_editor/lib/modules/outline/services/functions_service.dart +++ b/win_text_editor/lib/modules/outline/services/functions_service.dart @@ -13,7 +13,7 @@ class FunctionsService { static Map> uftatomMap = {}; static Future initFunctionsMap(String rootPath) async { - await _initUftMap('uftbusiness', rootPath, uftbusinessMap, ['.uffunction']); + await _initUftMap('uftbusiness', rootPath, uftbusinessMap, ['.uftfunction']); await _initUftMap('uftatom', rootPath, uftatomMap, ['.uftatomfunction', '.uftatomservice']); } @@ -51,8 +51,7 @@ class FunctionsService { try { final content = await file.readAsString(); final document = XmlDocument.parse(content); - final businessNode = document.findAllElements('business:Function').firstOrNull; - if (businessNode == null) return; + final businessNode = document.rootElement; final chineseName = businessNode.getAttribute('chineseName') ?? '未命名'; targetMap[chineseName] = [file.path]; diff --git a/win_text_editor/lib/modules/outline/services/outline_service.dart b/win_text_editor/lib/modules/outline/services/outline_service.dart index 0cc7140..282c335 100644 --- a/win_text_editor/lib/modules/outline/services/outline_service.dart +++ b/win_text_editor/lib/modules/outline/services/outline_service.dart @@ -309,11 +309,12 @@ class OutlineService { _searchNode?.children.add(virtualNode); } + root.children.clear(); + root.isExpanded = false; + //如果没有子节点,返回空列表 if (_searchNode!.children.isNotEmpty) { root.title = "搜索结果"; - root.children.clear(); - root.isExpanded = false; root.children.add(_searchNode!); root.isExpanded = true; } else { diff --git a/win_text_editor/lib/modules/outline/services/std_field_service.dart b/win_text_editor/lib/modules/outline/services/std_field_service.dart index f2a8f44..59550ed 100644 --- a/win_text_editor/lib/modules/outline/services/std_field_service.dart +++ b/win_text_editor/lib/modules/outline/services/std_field_service.dart @@ -33,9 +33,10 @@ class StdFieldService { for (final item in document.findAllElements('items')) { final chineseName = item.getAttribute('chineseName'); final name = item.getAttribute('name'); + final status = item.getAttribute('status'); - if (chineseName != null && name != null) { - stdfieldMap[chineseName] = name; + if (chineseName != null && name != null && status != '删除') { + stdfieldMap[name] = chineseName; } } } @@ -66,11 +67,11 @@ class StdFieldService { Logger().info('搜索标准字段:${dirNode.name}'); stdfieldMap.forEach((key, value) { - if (key.contains(dirNode.name)) { + if (value.contains(dirNode.name)) { final fieldNode = OutlineNode( name: key, - title: '$key($value)', - value: value, + title: '$value($key)', + value: key, isDirectory: true, depth: 2, ); @@ -116,8 +117,8 @@ class StdFieldService { value.contains(searchQuery)) { final fieldNode = OutlineNode( name: key, - title: '$key($value)', - value: value, + title: '$value($key)', + value: key, isDirectory: false, depth: 2, ); diff --git a/win_text_editor/lib/modules/outline/widgets/outline_explorer.dart b/win_text_editor/lib/modules/outline/widgets/outline_explorer.dart index 93ef6e5..aab2ba2 100644 --- a/win_text_editor/lib/modules/outline/widgets/outline_explorer.dart +++ b/win_text_editor/lib/modules/outline/widgets/outline_explorer.dart @@ -125,7 +125,7 @@ class _OutlineExplorerState extends State { (node) => _handleNodeDoubleTap(node as OutlineNode, fileProvider), onRefresh: () async { await outlineProvider.refreshOutlineTree(); - setState(() {}); + setState(() => _searchController.text = ''); }, ), ), diff --git a/win_text_editor/lib/shared/components/code_generation_components.dart b/win_text_editor/lib/shared/components/code_generation_components.dart new file mode 100644 index 0000000..fdc17ab --- /dev/null +++ b/win_text_editor/lib/shared/components/code_generation_components.dart @@ -0,0 +1,143 @@ +// shared/components/code_generation_components.dart +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class CodeGenerationRadioItem extends StatelessWidget { + final String label; + final String? groupValue; + final ValueChanged onChanged; + + const CodeGenerationRadioItem({ + super.key, + required this.label, + required this.groupValue, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Transform.scale( + scale: 0.75, + child: Radio(value: label, groupValue: groupValue, onChanged: onChanged), + ), + const SizedBox(width: 4), + Text(label, style: const TextStyle(fontSize: 14)), + ], + ); + } +} + +class CodeGenerationSection extends StatelessWidget { + final String title; + final Widget child; + final TextEditingController codeController; + + const CodeGenerationSection({ + super.key, + required this.title, + required this.child, + required this.codeController, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + child, + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('$title:', style: const TextStyle(fontWeight: FontWeight.bold)), + IconButton( + icon: const Icon(Icons.content_copy, size: 20), + tooltip: '复制代码', + onPressed: () { + if (codeController.text.isNotEmpty) { + Clipboard.setData(ClipboardData(text: codeController.text)); + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('已复制到剪贴板'))); + } + }, + ), + ], + ), + ), + Flexible(child: _buildCodeEditor(codeController)), + ], + ); + } + + Widget _buildCodeEditor(TextEditingController controller) { + return Card( + child: Padding( + padding: const EdgeInsets.all(8), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(4), + ), + child: TextField( + controller: controller, + maxLines: null, + expands: true, + decoration: const InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.all(8), + ), + style: const TextStyle(fontFamily: 'monospace', color: Colors.blueAccent), + ), + ), + ), + ); + } +} + +class OperationRadioSection extends StatelessWidget { + final List operations; + final String? selectedOperation; + final ValueChanged onOperationSelected; + + const OperationRadioSection({ + super.key, + required this.operations, + required this.selectedOperation, + required this.onOperationSelected, + }); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + child: Card( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + spacing: 16, + runSpacing: 8, + children: + operations + .map( + (op) => CodeGenerationRadioItem( + label: op, + groupValue: selectedOperation, + onChanged: onOperationSelected, + ), + ) + .toList(), + ), + ], + ), + ), + ), + ); + } +}