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. 52
      win_text_editor/lib/framework/services/file_service.dart
  5. 49
      win_text_editor/lib/shared/components/file_explorer.dart
  6. 10
      win_text_editor/lib/shared/components/tree_view.dart

4
win_text_editor/assets/config/uft_macro_list.yaml

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

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

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

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

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

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

@ -1,42 +1,46 @@
import 'dart:io'; import 'dart:io';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/framework/models/file_node.dart'; import 'package:win_text_editor/framework/models/file_node.dart';
import 'package:xml/xml.dart';
class FileService { class FileService {
/// ///
static Future<List<FileNode>> listDirectory(String path, {int parentDepth = 0}) async { 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 = []; final List<FileNode> nodes = [];
if (await directory.exists()) {
final entities = directory.listSync();
// FileNode
for (final entity in entities) { for (final entity in entities) {
nodes.add( final isDirectory = await FileSystemEntity.isDirectory(entity.path);
FileNode( final displayName = isDirectory
name: entity.path.split(Platform.pathSeparator).last, ? await getModuleDisplayName(entity.path)
: null;
nodes.add(FileNode(
name: displayName ?? entity.path.split(Platform.pathSeparator).last,
path: entity.path, path: entity.path,
isDirectory: entity is Directory, isDirectory: isDirectory,
depth: parentDepth + 1, depth: parentDepth + 1,
children: [], ));
),
);
} }
// return nodes;
nodes.sort((a, b) { }
if (a.isDirectory && !b.isDirectory) {
return -1; // a是文件夹b是文件a排在前面
} else if (!a.isDirectory && b.isDirectory) { static Future<String?> getModuleDisplayName(String dirPath) async {
return 1; // a是文件b是文件夹b排在前面 try {
} else { final moduleFile = File('$dirPath${Platform.pathSeparator}module.xml');
// if (await moduleFile.exists()) {
return a.name.compareTo(b.name); 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;
return nodes;
} }
/// ///

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

@ -1,9 +1,7 @@
import 'dart:math'; import 'dart:math';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.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/models/file_node.dart';
import '../../framework/controllers/file_provider.dart'; import '../../framework/controllers/file_provider.dart';
@ -20,32 +18,18 @@ class FileExplorer extends StatefulWidget {
} }
class _FileExplorerState extends State<FileExplorer> { class _FileExplorerState extends State<FileExplorer> {
// ScrollController final ScrollController _scrollController = ScrollController(); // ScrollController
Future<void> _promptForDirectory(BuildContext context) async { @override
final fileProvider = Provider.of<FileProvider>(context, listen: false); void dispose() {
final String? selectedDirectory = await FilePicker.platform.getDirectoryPath(); _scrollController.dispose(); // controller
super.dispose();
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('打开目录')),
],
);
} }
// //
double calculateTotalWidth(BuildContext context, FileProvider fileProvider) { double calculateTotalWidth(BuildContext context, FileProvider fileProvider) {
final maxDepth = _getMaxDepth(fileProvider.fileNodes); 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) { int _getMaxDepth(List<FileNode> nodes) {
@ -62,18 +46,15 @@ class _FileExplorerState extends State<FileExplorer> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final fileProvider = Provider.of<FileProvider>(context); final fileProvider = Provider.of<FileProvider>(context);
return Container( return Scrollbar(
controller: _scrollController, // controller
thumbVisibility: true,
child: SingleChildScrollView(
controller: _scrollController, // 使controller
scrollDirection: Axis.horizontal,
child: Container(
color: Colors.white, color: Colors.white,
child: Column( child: SizedBox(
children: [
Expanded(
child: ClipRect(
child:
fileProvider.isLoading
? const Center(child: CircularProgressIndicator())
: fileProvider.fileNodes.isEmpty
? Center(child: _buildEmptyPrompt(context))
: SizedBox(
width: calculateTotalWidth(context, fileProvider), width: calculateTotalWidth(context, fileProvider),
child: TreeView( child: TreeView(
nodes: fileProvider.fileNodes, nodes: fileProvider.fileNodes,
@ -84,8 +65,6 @@ class _FileExplorerState extends State<FileExplorer> {
), ),
), ),
), ),
],
),
); );
} }

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

@ -89,11 +89,7 @@ class _TreeViewState extends State<TreeView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scrollbar( return ListView.builder(
controller: _effectiveController,
thumbVisibility: true,
notificationPredicate: (_) => true, //
child: ListView.builder(
controller: _effectiveController, controller: _effectiveController,
physics: const ClampingScrollPhysics(), physics: const ClampingScrollPhysics(),
itemCount: _countVisibleNodes(widget.nodes), itemCount: _countVisibleNodes(widget.nodes),
@ -114,12 +110,12 @@ class _TreeViewState extends State<TreeView> {
onCheckChanged: (value) => _handleNodeCheckChanged(node, value), onCheckChanged: (value) => _handleNodeCheckChanged(node, value),
); );
}, },
),
); );
} }
void _handleNodeTap(TreeNode node) { void _handleNodeTap(TreeNode node) {
if (widget.config.singleSelect && !node.isDirectory) { // if (widget.config.singleSelect && !node.isDirectory) {
//
setState(() { setState(() {
_selectedIds.clear(); _selectedIds.clear();
_selectedIds.add(node.id); _selectedIds.add(node.id);

Loading…
Cancel
Save