Browse Source

文件夹名称解析OK

master
hejl 2 months ago
parent
commit
289f22ec2c
  1. 4
      win_text_editor/assets/config/uft_macro_list.yaml
  2. 24
      win_text_editor/lib/framework/controllers/file_provider.dart
  3. 8
      win_text_editor/lib/framework/models/file_node.dart
  4. 60
      win_text_editor/lib/framework/services/file_service.dart
  5. 65
      win_text_editor/lib/shared/components/file_explorer.dart
  6. 48
      win_text_editor/lib/shared/components/tree_view.dart

4
win_text_editor/assets/config/uft_macro_list.yaml

@ -35,13 +35,13 @@ templates: @@ -35,13 +35,13 @@ templates:
[获取记录][{{tableName}}({{keyName}})][
{{#keyFields}}
{{value}} = @{{value}} {{^isLast}}, {{/isLast}}
{{value}} = @{{value}}
{{/keyFields}}
]
[修改记录][{{tableName}}][
{{#fields}}
{{value}} = @{{value}} {{^isLast}}, {{/isLast}}
{{value}} = @{{value}}
{{/fields}}
]
}

24
win_text_editor/lib/framework/controllers/file_provider.dart

@ -60,14 +60,15 @@ class FileProvider with ChangeNotifier { @@ -60,14 +60,15 @@ class FileProvider with ChangeNotifier {
try {
final directory = Directory(path);
final displayName = await FileService.getModuleDisplayName(directory.path);
final rootNode = FileNode(
name: directory.path.split(Platform.pathSeparator).last,
name: displayName ?? directory.path.split(Platform.pathSeparator).last,
path: directory.path,
isDirectory: true,
isRoot: true, //
isRoot: true,
children: await FileService.buildFileTree(directory.path),
);
_fileNodes = [rootNode]; //
_fileNodes = [rootNode];
} catch (e) {
Logger().error('Error loading directory: $e');
_fileNodes = [];
@ -84,9 +85,10 @@ class FileProvider with ChangeNotifier { @@ -84,9 +85,10 @@ class FileProvider with ChangeNotifier {
notifyListeners();
try {
final displayName = await FileService.getModuleDisplayName(_currentRootPath!);
_fileNodes = [
FileNode(
name: _currentRootPath!.split(Platform.pathSeparator).last,
name: displayName ?? _currentRootPath!.split(Platform.pathSeparator).last,
path: _currentRootPath!,
isDirectory: true,
isRoot: true,
@ -108,9 +110,10 @@ class FileProvider with ChangeNotifier { @@ -108,9 +110,10 @@ class FileProvider with ChangeNotifier {
notifyListeners();
try {
final displayName = await FileService.getModuleDisplayName(path);
_fileNodes = [
FileNode(
name: path.split(Platform.pathSeparator).last,
name: displayName ?? path.split(Platform.pathSeparator).last,
path: path,
isDirectory: true,
isRoot: true,
@ -161,16 +164,9 @@ class FileProvider with ChangeNotifier { @@ -161,16 +164,9 @@ class FileProvider with ChangeNotifier {
notifyListeners();
try {
final contents = await FileService.listDirectory(
dirNode.path,
parentDepth: dirNode.depth, //
);
final contents = await FileService.listDirectory(dirNode.path, parentDepth: dirNode.depth);
final updatedNode = dirNode.copyWith(
children: contents,
isExpanded: true,
// depth copyWith
);
final updatedNode = dirNode.copyWith(children: contents, isExpanded: true);
_replaceNodeInTree(dirNode, updatedNode);
} catch (e) {

8
win_text_editor/lib/framework/models/file_node.dart

@ -97,19 +97,19 @@ class FileNode implements TreeNode { @@ -97,19 +97,19 @@ class FileNode implements TreeNode {
String? name,
String? path,
bool? isDirectory,
bool? isExpanded,
bool? isRoot,
int? depth, // depth参数
List<FileNode>? children,
bool? isExpanded,
int? depth,
}) {
return FileNode(
name: name ?? this.name,
path: path ?? this.path,
isDirectory: isDirectory ?? this.isDirectory,
isExpanded: isExpanded ?? this.isExpanded,
isRoot: isRoot ?? this.isRoot,
depth: depth ?? this.depth, // depth或使用新值
children: children ?? this.children,
isExpanded: isExpanded ?? this.isExpanded,
depth: depth ?? this.depth,
);
}

60
win_text_editor/lib/framework/services/file_service.dart

@ -1,42 +1,46 @@ @@ -1,42 +1,46 @@
import 'dart:io';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/framework/models/file_node.dart';
import 'package:xml/xml.dart';
class FileService {
///
static Future<List<FileNode>> listDirectory(String path, {int parentDepth = 0}) async {
final directory = Directory(path);
final dir = Directory(path);
final List<FileSystemEntity> entities = await dir.list().toList();
final List<FileNode> nodes = [];
if (await directory.exists()) {
final entities = directory.listSync();
// FileNode
for (final entity in entities) {
nodes.add(
FileNode(
name: entity.path.split(Platform.pathSeparator).last,
path: entity.path,
isDirectory: entity is Directory,
depth: parentDepth + 1,
children: [],
),
);
}
final isDirectory = await FileSystemEntity.isDirectory(entity.path);
final displayName = isDirectory
? await getModuleDisplayName(entity.path)
: null;
nodes.add(FileNode(
name: displayName ?? entity.path.split(Platform.pathSeparator).last,
path: entity.path,
isDirectory: isDirectory,
depth: parentDepth + 1,
));
}
//
nodes.sort((a, b) {
if (a.isDirectory && !b.isDirectory) {
return -1; // a是文件夹b是文件a排在前面
} else if (!a.isDirectory && b.isDirectory) {
return 1; // a是文件b是文件夹b排在前面
} else {
//
return a.name.compareTo(b.name);
}
});
}
return nodes;
}
return nodes;
static Future<String?> getModuleDisplayName(String dirPath) async {
try {
final moduleFile = File('$dirPath${Platform.pathSeparator}module.xml');
if (await moduleFile.exists()) {
final content = await moduleFile.readAsString();
final xmlDoc = XmlDocument.parse(content);
final infoNode = xmlDoc.findAllElements('info').firstOrNull;
return infoNode?.getAttribute('cname');
}
} catch (e) {
Logger().debug('Error reading module.xml: $e');
}
return null;
}
///

65
win_text_editor/lib/shared/components/file_explorer.dart

@ -1,9 +1,7 @@ @@ -1,9 +1,7 @@
import 'dart:math';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/services/file_path_manager.dart';
import '../../framework/models/file_node.dart';
import '../../framework/controllers/file_provider.dart';
@ -20,32 +18,18 @@ class FileExplorer extends StatefulWidget { @@ -20,32 +18,18 @@ class FileExplorer extends StatefulWidget {
}
class _FileExplorerState extends State<FileExplorer> {
// ScrollController
final ScrollController _scrollController = ScrollController(); // ScrollController
Future<void> _promptForDirectory(BuildContext context) async {
final fileProvider = Provider.of<FileProvider>(context, listen: false);
final String? selectedDirectory = await FilePicker.platform.getDirectoryPath();
if (selectedDirectory != null) {
await FilePathManager.saveLastOpenedFolder(selectedDirectory);
await fileProvider.setRootPath(selectedDirectory);
}
}
Widget _buildEmptyPrompt(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('没有文件可显示'),
TextButton(onPressed: () => _promptForDirectory(context), child: const Text('打开目录')),
],
);
@override
void dispose() {
_scrollController.dispose(); // controller
super.dispose();
}
//
double calculateTotalWidth(BuildContext context, FileProvider fileProvider) {
final maxDepth = _getMaxDepth(fileProvider.fileNodes);
return maxDepth * 200 + MediaQuery.of(context).size.width * 0.5;
return maxDepth * 60 + MediaQuery.of(context).size.width * 0.2;
}
int _getMaxDepth(List<FileNode> nodes) {
@ -62,29 +46,24 @@ class _FileExplorerState extends State<FileExplorer> { @@ -62,29 +46,24 @@ class _FileExplorerState extends State<FileExplorer> {
Widget build(BuildContext context) {
final fileProvider = Provider.of<FileProvider>(context);
return Container(
color: Colors.white,
child: Column(
children: [
Expanded(
child: ClipRect(
child:
fileProvider.isLoading
? const Center(child: CircularProgressIndicator())
: fileProvider.fileNodes.isEmpty
? Center(child: _buildEmptyPrompt(context))
: SizedBox(
width: calculateTotalWidth(context, fileProvider),
child: TreeView(
nodes: fileProvider.fileNodes,
config: const TreeViewConfig(showIcons: true, lazyLoad: true),
onNodeTap: (node) => _handleNodeTap(context, node as FileNode),
onNodeDoubleTap: (node) => _handleNodeDoubleTap(node as FileNode),
),
),
return Scrollbar(
controller: _scrollController, // controller
thumbVisibility: true,
child: SingleChildScrollView(
controller: _scrollController, // 使controller
scrollDirection: Axis.horizontal,
child: Container(
color: Colors.white,
child: SizedBox(
width: calculateTotalWidth(context, fileProvider),
child: TreeView(
nodes: fileProvider.fileNodes,
config: const TreeViewConfig(showIcons: true, lazyLoad: true),
onNodeTap: (node) => _handleNodeTap(context, node as FileNode),
onNodeDoubleTap: (node) => _handleNodeDoubleTap(node as FileNode),
),
),
],
),
),
);
}

48
win_text_editor/lib/shared/components/tree_view.dart

@ -89,37 +89,33 @@ class _TreeViewState extends State<TreeView> { @@ -89,37 +89,33 @@ class _TreeViewState extends State<TreeView> {
@override
Widget build(BuildContext context) {
return Scrollbar(
return ListView.builder(
controller: _effectiveController,
thumbVisibility: true,
notificationPredicate: (_) => true, //
child: ListView.builder(
controller: _effectiveController,
physics: const ClampingScrollPhysics(),
itemCount: _countVisibleNodes(widget.nodes),
itemBuilder: (context, index) {
final node = _getVisibleNode(widget.nodes, index);
final isSelected = _selectedIds.contains(node.id);
// 使
return widget.nodeBuilder != null
? widget.nodeBuilder!(context, node, isSelected, () => _handleNodeTap(node))
: TreeNodeWidget(
node: node,
config: widget.config,
isSelected: isSelected,
isChecked: _checkedIds.contains(node.id),
onTap: () => _handleNodeTap(node),
onDoubleTap: () => widget.onNodeDoubleTap?.call(node),
onCheckChanged: (value) => _handleNodeCheckChanged(node, value),
);
},
),
physics: const ClampingScrollPhysics(),
itemCount: _countVisibleNodes(widget.nodes),
itemBuilder: (context, index) {
final node = _getVisibleNode(widget.nodes, index);
final isSelected = _selectedIds.contains(node.id);
// 使
return widget.nodeBuilder != null
? widget.nodeBuilder!(context, node, isSelected, () => _handleNodeTap(node))
: TreeNodeWidget(
node: node,
config: widget.config,
isSelected: isSelected,
isChecked: _checkedIds.contains(node.id),
onTap: () => _handleNodeTap(node),
onDoubleTap: () => widget.onNodeDoubleTap?.call(node),
onCheckChanged: (value) => _handleNodeCheckChanged(node, value),
);
},
);
}
void _handleNodeTap(TreeNode node) {
if (widget.config.singleSelect && !node.isDirectory) { //
if (widget.config.singleSelect && !node.isDirectory) {
//
setState(() {
_selectedIds.clear();
_selectedIds.add(node.id);

Loading…
Cancel
Save