Browse Source

修复版本覆盖引起的目录错乱

master
hejl 1 month ago
parent
commit
751c17449c
  1. 104
      win_text_editor/lib/app/app.dart
  2. 2
      win_text_editor/lib/app/menus/app_menu.dart
  3. 4
      win_text_editor/lib/app/menus/menu_actions.dart
  4. 0
      win_text_editor/lib/app/menus/menu_constants.dart
  5. 0
      win_text_editor/lib/app/models/file_node.dart
  6. 0
      win_text_editor/lib/app/models/tab_model.dart
  7. 4
      win_text_editor/lib/app/providers/file_provider.dart
  8. 0
      win_text_editor/lib/app/providers/logger.dart
  9. 10
      win_text_editor/lib/app/providers/tab_provider.dart
  10. 31
      win_text_editor/lib/app/services/syntax_service.dart
  11. 59
      win_text_editor/lib/app/utils/file_utils.dart
  12. 2
      win_text_editor/lib/app/widgets/console_panel.dart
  13. 84
      win_text_editor/lib/app/widgets/editor_pane.dart
  14. 144
      win_text_editor/lib/app/widgets/template_parser_tab.dart
  15. 328
      win_text_editor/lib/app/widgets/text_editor.dart
  16. 4
      win_text_editor/lib/framework/controllers/tab_items_controller.dart
  17. 2
      win_text_editor/lib/framework/services/file_path_manager.dart
  18. 4
      win_text_editor/lib/framework/services/file_service.dart
  19. 2
      win_text_editor/lib/framework/services/macro_template_service.dart
  20. 36
      win_text_editor/lib/framework/widgets/app_scaffold.dart
  21. 24
      win_text_editor/lib/framework/widgets/file_explorer_pane.dart
  22. 2
      win_text_editor/lib/framework/widgets/tab_view.dart
  23. 2
      win_text_editor/lib/main.dart
  24. 2
      win_text_editor/lib/modules/call_function/controllers/call_function_controller.dart
  25. 2
      win_text_editor/lib/modules/call_function/services/call_function_service.dart
  26. 2
      win_text_editor/lib/modules/code_creater/controllers/code_creater_controller.dart
  27. 2
      win_text_editor/lib/modules/code_creater/widgets/code_creater_view.dart
  28. 2
      win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart
  29. 2
      win_text_editor/lib/modules/content_search/services/custom_search_service.dart
  30. 2
      win_text_editor/lib/modules/content_search/widgets/results_view.dart
  31. 2
      win_text_editor/lib/modules/data_compare/controllers/data_compare_controller.dart
  32. 2
      win_text_editor/lib/modules/data_compare/widgets/data_compare_view.dart
  33. 2
      win_text_editor/lib/modules/data_extract/controllers/data_extract_controller.dart
  34. 2
      win_text_editor/lib/modules/data_extract/services/xml_extract_service.dart
  35. 2
      win_text_editor/lib/modules/data_format/controllers/data_format_controller.dart
  36. 2
      win_text_editor/lib/modules/memory_table/controllers/memory_table_controller.dart
  37. 2
      win_text_editor/lib/modules/memory_table/services/memory_table_service.dart
  38. 2
      win_text_editor/lib/modules/module_router.dart
  39. 2
      win_text_editor/lib/modules/outline/controllers/outline_provider.dart
  40. 2
      win_text_editor/lib/modules/outline/services/component_service.dart
  41. 2
      win_text_editor/lib/modules/outline/services/functions_service.dart
  42. 2
      win_text_editor/lib/modules/outline/services/outline_service.dart
  43. 2
      win_text_editor/lib/modules/outline/services/std_field_service.dart
  44. 2
      win_text_editor/lib/modules/outline/services/uft_object_service.dart
  45. 2
      win_text_editor/lib/modules/outline/widgets/outline_explorer.dart
  46. 80
      win_text_editor/lib/modules/pdf_parse/controllers/pdf_parse_controller.dart
  47. 2
      win_text_editor/lib/modules/template_parser/controllers/filter_controller.dart
  48. 2
      win_text_editor/lib/modules/template_parser/controllers/template_parser_controller.dart
  49. 2
      win_text_editor/lib/modules/uft_component/controllers/uft_component_controller.dart
  50. 2
      win_text_editor/lib/modules/uft_component/services/uft_component_service.dart
  51. 2
      win_text_editor/lib/modules/xml_search/controllers/xml_search_controller.dart
  52. 2
      win_text_editor/lib/modules/xml_search/services/xml_search_service.dart
  53. 2
      win_text_editor/lib/modules/xml_search/widgets/results_view.dart
  54. 4
      win_text_editor/lib/shared/components/file_explorer.dart
  55. 2
      win_text_editor/lib/shared/data/std_fields_cache.dart
  56. 2
      win_text_editor/lib/shared/utils/file_utils.dart
  57. 2
      win_text_editor/备忘.txt

104
win_text_editor/lib/app/app.dart

@ -0,0 +1,104 @@ @@ -0,0 +1,104 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/app/menus/app_menu.dart';
import 'package:win_text_editor/app/providers/tab_provider.dart';
import 'package:win_text_editor/app/providers/file_provider.dart';
import 'package:win_text_editor/app/widgets/editor_pane.dart';
import 'package:win_text_editor/app/widgets/file_explorer.dart';
import 'package:win_text_editor/app/widgets/console_panel.dart'; //
class AppScaffold extends StatelessWidget {
const AppScaffold({super.key});
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => FileProvider()),
ChangeNotifierProvider(create: (_) => TabProvider()),
],
child: const Scaffold(
body: Column(
children: [
//
AppMenu(),
//
Expanded(child: _ResizablePanel()),
],
),
),
);
}
}
class _ResizablePanel extends StatefulWidget {
const _ResizablePanel();
@override
State<_ResizablePanel> createState() => _ResizablePanelState();
}
class _ResizablePanelState extends State<_ResizablePanel> {
double _leftWidth = 0.2; // 20%
final double _minWidth = 100; //
final double _maxWidth = 400; //
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return LayoutBuilder(
builder: (context, constraints) {
//
final leftPanelWidth = (_leftWidth * screenWidth).clamp(_minWidth, _maxWidth);
return Column(
children: [
Expanded(
child: Row(
children: [
// - Material小部件包裹
Material(
elevation: 1, //
child: SizedBox(
width: leftPanelWidth,
child: const ClipRect(
//
child: FileExplorer(),
),
),
),
//
GestureDetector(
behavior: HitTestBehavior.translucent,
onPanUpdate: (details) {
setState(() {
_leftWidth = ((leftPanelWidth + details.delta.dx) / screenWidth).clamp(
_minWidth / screenWidth,
_maxWidth / screenWidth,
);
});
},
child: MouseRegion(
cursor: SystemMouseCursors.resizeLeftRight,
child: Container(width: 4, color: Colors.grey[300]),
),
),
// - Material背景
const Expanded(
child: Material(
color: Colors.white,
child: Column(children: [Expanded(child: EditorPane())]),
),
),
],
),
),
//
const ConsolePanel(),
],
);
},
);
}
}

2
win_text_editor/lib/menus/app_menu.dart → win_text_editor/lib/app/menus/app_menu.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:win_text_editor/menus/menu_constants.dart';
import 'package:win_text_editor/app/menus/menu_constants.dart';
import 'menu_actions.dart';

4
win_text_editor/lib/menus/menu_actions.dart → win_text_editor/lib/app/menus/menu_actions.dart

@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; @@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/menus/menu_constants.dart';
import 'package:win_text_editor/framework/controllers/file_provider.dart';
import 'package:win_text_editor/app/menus/menu_constants.dart';
import 'package:win_text_editor/app/providers/file_provider.dart';
import 'dart:io';
import 'package:win_text_editor/modules/module_router.dart';

0
win_text_editor/lib/menus/menu_constants.dart → win_text_editor/lib/app/menus/menu_constants.dart

0
win_text_editor/lib/framework/models/file_node.dart → win_text_editor/lib/app/models/file_node.dart

0
win_text_editor/lib/framework/models/tab_model.dart → win_text_editor/lib/app/models/tab_model.dart

4
win_text_editor/lib/framework/controllers/file_provider.dart → win_text_editor/lib/app/providers/file_provider.dart

@ -2,8 +2,8 @@ import 'dart:io'; @@ -2,8 +2,8 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:win_text_editor/framework/models/file_node.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/models/file_node.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/framework/services/file_service.dart';
class FileProvider with ChangeNotifier {

0
win_text_editor/lib/framework/controllers/logger.dart → win_text_editor/lib/app/providers/logger.dart

10
win_text_editor/lib/app/providers/tab_provider.dart

@ -4,10 +4,10 @@ import 'package:win_text_editor/app/providers/logger.dart'; @@ -4,10 +4,10 @@ import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/app/widgets/template_parser_tab.dart';
class TabProvider with ChangeNotifier {
final List<ContentTab> _tabs = [];
final List<AppTab> _tabs = [];
String? _activeTabId;
List<ContentTab> get tabs => _tabs;
List<AppTab> get tabs => _tabs;
String? get activeTabId => _activeTabId;
final Map<String, TemplateParserTabState> _tabControllers = {};
@ -20,7 +20,7 @@ class TabProvider with ChangeNotifier { @@ -20,7 +20,7 @@ class TabProvider with ChangeNotifier {
_tabControllers.remove(tabId);
}
ContentTab? get activeTab {
AppTab? get activeTab {
if (_activeTabId == null) return null;
try {
return _tabs.firstWhere((tab) => tab.id == _activeTabId);
@ -36,7 +36,7 @@ class TabProvider with ChangeNotifier { @@ -36,7 +36,7 @@ class TabProvider with ChangeNotifier {
IconData? icon,
String content = '',
}) async {
final newTab = ContentTab(
final newTab = AppTab(
id: DateTime.now().millisecondsSinceEpoch.toString(),
title: title,
type: type,
@ -49,7 +49,7 @@ class TabProvider with ChangeNotifier { @@ -49,7 +49,7 @@ class TabProvider with ChangeNotifier {
notifyListeners();
}
ContentTab? getTabById(String tabId) {
AppTab? getTabById(String tabId) {
try {
return _tabs.firstWhere((tab) => tab.id == tabId);
} catch (e) {

31
win_text_editor/lib/app/services/syntax_service.dart

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
class SyntaxService {
static String detectFileType(String fileName) {
final extension = fileName.split('.').last.toLowerCase();
switch (extension) {
case 'dart':
return 'dart';
case 'java':
return 'java';
case 'js':
return 'javascript';
case 'py':
return 'python';
case 'html':
return 'html';
case 'css':
return 'css';
case 'json':
return 'json';
case 'xml':
return 'xml';
case 'md':
return 'markdown';
case 'yaml':
case 'yml':
return 'yaml';
default:
return 'text';
}
}
}

59
win_text_editor/lib/app/utils/file_utils.dart

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
// file_utils.dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class FileUtils {
static Future<String?> pickFile(BuildContext context) async {
try {
final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: false);
return result?.files.single.path;
} catch (e) {
Logger().error('选择文件失败: ${e.toString()}');
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('选择文件失败: ${e.toString()}')));
}
return null;
}
}
static Future<String?> readFileContent(
BuildContext context,
String filePath, {
Duration timeout = const Duration(seconds: 30),
}) async {
try {
final content = await File(filePath).readAsString().timeout(
timeout,
onTimeout: () {
throw TimeoutException('文件加载超时,可能文件过大');
},
);
return content;
} on FormatException {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('这不是可读的文本文件')));
}
return null;
} on FileSystemException catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('文件访问错误: ${e.message}')));
}
return null;
} catch (e) {
Logger().error('读取文件失败: ${e.toString()}');
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('读取失败: ${e.toString()}')));
}
return null;
}
}
// showLoadingDialog方法
}

2
win_text_editor/lib/framework/widgets/console_panel.dart → win_text_editor/lib/app/widgets/console_panel.dart

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart'; //
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class ConsolePanel extends StatefulWidget {
const ConsolePanel({super.key});

84
win_text_editor/lib/app/widgets/editor_pane.dart

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/app/providers/tab_provider.dart';
import 'template_parser_tab.dart';
class EditorPane extends StatelessWidget {
const EditorPane({super.key});
@override
Widget build(BuildContext context) {
final provider = Provider.of<TabProvider>(context);
return Column(
children: [
//
SizedBox(
height: 40,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: provider.tabs.length,
itemBuilder: (ctx, index) {
final tab = provider.tabs[index];
return _TabItem(
title: tab.title,
icon: tab.icon, //
isActive: tab.id == provider.activeTabId,
onClose: () => provider.closeTab(tab.id),
onTap: () => provider.setActiveTab(tab.id),
);
},
),
),
//
Expanded(
child:
provider.activeTabId != null && provider.tabs.any((t) => t.id == provider.activeTabId)
? TemplateParserTab(tabId: provider.activeTabId!)
: const Center(child: Text('无活动标签页')),
),
],
);
}
}
class _TabItem extends StatelessWidget {
final String title;
final IconData? icon; //
final bool isActive;
final VoidCallback onClose;
final VoidCallback onTap;
const _TabItem({
required this.title,
this.icon,
required this.isActive,
required this.onClose,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: isActive ? Colors.blue[100] : Colors.grey[200],
border: Border(
bottom: BorderSide(color: isActive ? Colors.blue : Colors.transparent, width: 2),
),
),
child: Row(
children: [
if (icon != null) Icon(icon, size: 16),
if (icon != null) const SizedBox(width: 4),
Text(title),
const SizedBox(width: 8),
IconButton(icon: const Icon(Icons.close, size: 16), onPressed: onClose),
],
),
),
);
}
}

144
win_text_editor/lib/app/widgets/template_parser_tab.dart

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/app/providers/tab_provider.dart';
import 'package:win_text_editor/app/widgets/text_editor.dart';
class TemplateParserTab extends StatefulWidget {
final String tabId;
const TemplateParserTab({super.key, required this.tabId});
@override
State<TemplateParserTab> createState() => TemplateParserTabState();
}
class TemplateParserTabState extends State<TemplateParserTab> {
late TabProvider _provider;
String? _editor1FileName;
String? _editor2FileName;
String _editor1Content = '';
String _editor2Content = '';
int _activeEditorIndex = 0; // 01
final GlobalKey<TextEditorState> _editor1Key = GlobalKey();
final GlobalKey<TextEditorState> _editor2Key = GlobalKey();
//
void _setupFocusListeners() {
_editor1Key.currentState?.focusNode.addListener(() {
if (_editor1Key.currentState?.hasFocus ?? false) {
setState(() => _activeEditorIndex = 0);
}
});
_editor2Key.currentState?.focusNode.addListener(() {
if (_editor2Key.currentState?.hasFocus ?? false) {
setState(() => _activeEditorIndex = 1);
}
});
}
@override
void initState() {
super.initState();
_provider = Provider.of<TabProvider>(context, listen: false);
_provider.registerTextTabController(widget.tabId, this);
final tab = _provider.getTabById(widget.tabId);
if (tab != null) {
_editor1Content = tab.content;
_editor2Content = tab.content;
_editor1FileName = tab.fileName;
_editor2FileName = tab.fileName;
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_setupFocusListeners();
});
}
// loadFile方法使用_activeEditorIndex
Future<void> loadFile(BuildContext context, String filePath) async {
if (_activeEditorIndex == 0) {
_editor1Key.currentState?.loadFile(context, filePath);
} else {
_editor2Key.currentState?.loadFile(context, filePath);
}
}
@override
Widget build(BuildContext context) {
final tab = _provider.getTabById(widget.tabId);
if (tab == null) {
return const Center(child: Text('选项卡不存在'));
}
return SingleChildScrollView(
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 400),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: SizedBox(
height: MediaQuery.of(context).size.height / 2 - 100,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: _activeEditorIndex == 0 ? Colors.blue : Colors.transparent,
width: 2.0,
),
),
child: TextEditor(
key: _editor1Key,
tabId: '${widget.tabId}_1',
title: '源文本', //
initialContent: _editor1Content,
fileName: _editor1FileName,
onContentChanged: (content, fileName) {
setState(() {
_editor1Content = content;
_editor1FileName = fileName;
});
_provider.updateContent(widget.tabId, content, fileName);
},
onFileLoaded: (filePath) {
//
},
),
),
),
),
Flexible(
child: SizedBox(
height: MediaQuery.of(context).size.height / 2 - 100,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: _activeEditorIndex == 1 ? Colors.blue : Colors.transparent,
width: 2.0,
),
),
child: TextEditor(
key: _editor2Key,
tabId: '${widget.tabId}_2',
title: '目标文本', //
initialContent: _editor2Content,
fileName: _editor2FileName,
onContentChanged: (content, fileName) {
setState(() {
_editor2Content = content;
_editor2FileName = fileName;
});
_provider.updateContent(widget.tabId, content, fileName);
},
onFileLoaded: (filePath) {
//
},
),
),
),
),
],
),
),
);
}
}

328
win_text_editor/lib/app/widgets/text_editor.dart

@ -0,0 +1,328 @@ @@ -0,0 +1,328 @@
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:file_picker/file_picker.dart';
class TextEditor extends StatefulWidget {
final String tabId;
final String? initialContent;
final String? fileName;
final String title;
final Function(String, String?)? onContentChanged;
final Function(String)? onFileLoaded;
const TextEditor({
super.key,
required this.tabId,
this.initialContent,
this.fileName,
this.title = '未命名',
this.onContentChanged,
this.onFileLoaded,
});
@override
State<TextEditor> createState() => TextEditorState();
}
class TextEditorState extends State<TextEditor> {
late TextEditingController _controller;
late ScrollController _scrollController;
bool _isLoading = false;
static const int maxFileSize = 1024 * 1024; // 1MB
bool get hasFocus => _focusNode.hasFocus;
FocusNode get _focusNode => focusNode; // _focusNode改为focusNode
late FocusNode focusNode = FocusNode(); //
void loadFile(BuildContext context, String filePath) async {
await _loadFile(context, filePath);
}
@override
void initState() {
super.initState();
_controller = TextEditingController(text: widget.initialContent ?? '');
focusNode = FocusNode();
_scrollController = ScrollController();
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(focusNode);
});
}
@override
void didUpdateWidget(TextEditor oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.initialContent != widget.initialContent) {
_controller.text = widget.initialContent ?? '';
}
}
@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: 40,
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: hasFocus ? Colors.blue[50] : Colors.grey[100],
border: Border(
bottom: BorderSide(
color: hasFocus ? Colors.blue : Colors.grey[300]!,
width: hasFocus ? 2.0 : 1.0,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${widget.title}${_controller.text.isEmpty ? '' : ' (${widget.fileName ?? ''}${_controller.text.length}字符)'}',
style: const TextStyle(fontWeight: FontWeight.bold),
),
Row(
children: [
IconButton(
icon: const Icon(Icons.folder_open, size: 20),
tooltip: '打开文件',
onPressed: _isLoading ? null : () => _openFile(context),
),
IconButton(
icon: const Icon(Icons.content_copy, size: 20),
tooltip: '复制内容',
onPressed:
_controller.text.isEmpty
? null
: () => _copyToClipboard(context, _controller.text),
),
IconButton(
icon: const Icon(Icons.save, size: 20),
tooltip: '保存到文件',
onPressed:
_controller.text.isEmpty
? null
: () => _saveFile(context, _controller.text),
),
if (_isLoading)
const Padding(
padding: EdgeInsets.only(left: 8),
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
),
],
),
],
),
),
Expanded(
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(
scrollbars: true,
dragDevices: {PointerDeviceKind.touch, PointerDeviceKind.mouse},
),
child: SingleChildScrollView(
controller: _scrollController,
child: Stack(
children: [
TextField(
controller: _controller,
focusNode: _focusNode,
maxLines: null,
onChanged: (text) {
widget.onContentChanged?.call(text, widget.fileName);
},
decoration: const InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.all(16),
),
style: const TextStyle(
fontFamily: 'Courier New',
fontSize: 16,
color: Colors.black,
),
),
],
),
),
),
),
],
);
}
Future<void> _openFile(BuildContext context) async {
final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: false);
if (result != null && result.files.single.path != null) {
await _loadFile(context, result.files.single.path!);
}
}
Future<void> _copyToClipboard(BuildContext context, String content) async {
await Clipboard.setData(ClipboardData(text: content));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已复制到剪贴板')));
}
}
Future<void> _saveFile(BuildContext context, String content) async {
try {
String? outputPath = await FilePicker.platform.saveFile(
dialogTitle: '保存文件',
fileName: 'untitled.txt',
allowedExtensions: ['txt'],
type: FileType.any,
);
if (outputPath == null) return;
final file = File(outputPath);
if (await file.exists()) {
final shouldOverwrite = await showDialog<bool>(
context: context,
builder:
(context) => AlertDialog(
title: const Text('文件已存在'),
content: const Text('要覆盖现有文件吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('取消'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('覆盖'),
),
],
),
);
if (shouldOverwrite != true) return;
}
await file.writeAsString(content);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已保存到: ${file.path}')));
}
} on FileSystemException catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('保存失败: ${e.message}')));
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('保存失败: ${e.toString()}')));
}
}
}
Future<void> _loadFile(BuildContext context, String filePath) async {
try {
setState(() => _isLoading = true);
final file = File(filePath);
final fileSize = await file.length();
//
if (fileSize > maxFileSize) {
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('文件过大(超过1MB),无法处理')));
}
return;
}
//
if (_controller.text.isNotEmpty) {
final confirm = await showDialog<bool>(
context: context,
builder:
(context) => AlertDialog(
title: const Text('确认提示'),
content: const Text('确认是否打开新的文件?打开后将覆盖当前内容'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('取消'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('确认'),
),
],
),
);
if (confirm != true) {
return;
}
}
final fileName = file.path.split('\\').last;
//
_controller.text = '';
widget.onContentChanged?.call('', fileName);
//
final stream = file.openRead();
final lines = stream.transform(utf8.decoder).transform(const LineSplitter());
await for (final line in lines) {
if (!mounted) break;
setState(() {
_controller.text += '$line\n';
widget.onContentChanged?.call(_controller.text, fileName);
});
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
await Future.delayed(const Duration(milliseconds: 10));
}
widget.onFileLoaded?.call(file.path);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已加载: ${file.path}')));
}
} on FormatException {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('这不是可读的文本文件')));
}
} on FileSystemException catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('文件访问错误: ${e.message}')));
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('读取失败: ${e.toString()}')));
}
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
}

4
win_text_editor/lib/framework/controllers/tab_items_controller.dart

@ -2,10 +2,10 @@ import 'dart:io'; @@ -2,10 +2,10 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_js/quickjs/ffi.dart';
import 'package:win_text_editor/framework/models/tab_model.dart';
import 'package:win_text_editor/app/models/tab_model.dart';
import 'package:win_text_editor/modules/module_router.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class TabItemsController with ChangeNotifier {
final List<AppTab> _tabs = [];

2
win_text_editor/lib/framework/services/file_path_manager.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:shared_preferences/shared_preferences.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class FilePathManager {
static const String _lastOpenedFolderKey = 'last_opened_folder';

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

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
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/app/providers/logger.dart';
import 'package:win_text_editor/app/models/file_node.dart';
import 'package:win_text_editor/framework/services/fast_xml_parser.dart';
import 'package:xml/xml.dart';

2
win_text_editor/lib/framework/services/macro_template_service.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:flutter/services.dart' show rootBundle;
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:yaml/yaml.dart';
import 'package:mustache_template/mustache_template.dart' as mustache;

36
win_text_editor/lib/framework/widgets/app_scaffold.dart

@ -3,9 +3,9 @@ import 'package:provider/provider.dart'; @@ -3,9 +3,9 @@ import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/framework/widgets/file_explorer_pane.dart';
import 'package:win_text_editor/framework/widgets/tab_view.dart';
import 'package:win_text_editor/menus/app_menu.dart';
import 'package:win_text_editor/framework/controllers/file_provider.dart';
import 'package:win_text_editor/framework/widgets/console_panel.dart';
import 'package:win_text_editor/app/menus/app_menu.dart';
import 'package:win_text_editor/app/providers/file_provider.dart';
import 'package:win_text_editor/app/widgets/console_panel.dart';
import 'package:win_text_editor/modules/outline/controllers/outline_provider.dart';
import 'package:win_text_editor/modules/outline/widgets/outline_explorer.dart';
@ -43,21 +43,21 @@ class _AppScaffoldState extends State<AppScaffold> { @@ -43,21 +43,21 @@ class _AppScaffoldState extends State<AppScaffold> {
elevation: 2,
child: Column(
children: [
//
if (_isFileExplorerCollapsed)
InkWell(
onTap: () {
setState(() {
_isFileExplorerCollapsed = false;
});
},
child: Container(
height: 40,
alignment: Alignment.center,
child: const Icon(Icons.chevron_right, size: 20),
),
),
//
//
if (_isFileExplorerCollapsed)
InkWell(
onTap: () {
setState(() {
_isFileExplorerCollapsed = false;
});
},
child: Container(
height: 40,
alignment: Alignment.center,
child: const Icon(Icons.chevron_right, size: 20),
),
),
//
if (!_isFileExplorerCollapsed)
Expanded(
child: Consumer<TabItemsController>(

24
win_text_editor/lib/framework/widgets/file_explorer_pane.dart

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/controllers/file_provider.dart';
import 'package:win_text_editor/app/providers/file_provider.dart';
import 'package:win_text_editor/framework/services/file_path_manager.dart';
import 'package:win_text_editor/shared/components/file_explorer.dart';
@ -49,17 +49,17 @@ class FileExplorerPane extends StatelessWidget { @@ -49,17 +49,17 @@ class FileExplorerPane extends StatelessWidget {
),
child: Row(
children: [
//
IconButton(
icon: const Icon(Icons.chevron_left, size: 20),
tooltip: '折叠',
onPressed: () {
//
if (onFolderDoubleTap != null) {
onFolderDoubleTap!('toggle_collapse');
}
},
),
//
IconButton(
icon: const Icon(Icons.chevron_left, size: 20),
tooltip: '折叠',
onPressed: () {
//
if (onFolderDoubleTap != null) {
onFolderDoubleTap!('toggle_collapse');
}
},
),
const Text('项目资源管理器', style: TextStyle(fontWeight: FontWeight.bold)),
const Spacer(),
IconButton(

2
win_text_editor/lib/framework/widgets/tab_view.dart

@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; @@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/modules/module_router.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/framework/models/tab_model.dart';
import 'package:win_text_editor/app/models/tab_model.dart';
class TabView extends StatefulWidget {
final List<AppTab> tabs;

2
win_text_editor/lib/main.dart

@ -5,7 +5,7 @@ import 'package:provider/provider.dart'; @@ -5,7 +5,7 @@ import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/widgets/app_scaffold.dart';
import 'package:win_text_editor/shared/data/std_fields_cache.dart';
import 'package:window_manager/window_manager.dart';
import 'framework/controllers/logger.dart'; //
import 'app/providers/logger.dart'; //
void main() async {
WidgetsFlutterBinding.ensureInitialized();

2
win_text_editor/lib/modules/call_function/controllers/call_function_controller.dart

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import 'package:collection/collection.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/framework/services/macro_template_service.dart';
import 'package:win_text_editor/modules/call_function/models/call_function.dart';
import 'package:win_text_editor/modules/call_function/services/call_function_service.dart';

2
win_text_editor/lib/modules/call_function/services/call_function_service.dart

@ -8,7 +8,7 @@ import 'package:win_text_editor/modules/uft_component/services/uft_component_ser @@ -8,7 +8,7 @@ import 'package:win_text_editor/modules/uft_component/services/uft_component_ser
import 'package:win_text_editor/shared/data/std_fields_cache.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
import 'package:xml/xml.dart' as xml;
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class CallFunctionService {
static const Map<String, String> _functionRootTypeMap = {

2
win_text_editor/lib/modules/code_creater/controllers/code_creater_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:win_text_editor/framework/common/constants.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/code_creater/services/code_create_service.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';

2
win_text_editor/lib/modules/code_creater/widgets/code_creater_view.dart

@ -2,7 +2,7 @@ import 'dart:ui'; @@ -2,7 +2,7 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/modules/code_creater/controllers/code_creater_controller.dart';
import 'package:win_text_editor/modules/code_creater/widgets/node_table.dart';

2
win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart

@ -4,7 +4,7 @@ import 'dart:async'; @@ -4,7 +4,7 @@ import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/content_search/models/search_mode.dart';
import 'package:win_text_editor/modules/content_search/models/search_result.dart';
import 'package:win_text_editor/modules/content_search/services/count_search_service.dart';

2
win_text_editor/lib/modules/content_search/services/custom_search_service.dart

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter_js/flutter_js.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/content_search/models/search_mode.dart';
import 'package:win_text_editor/modules/content_search/models/search_result.dart';
import 'package:win_text_editor/shared/utils/file_utils.dart';

2
win_text_editor/lib/modules/content_search/widgets/results_view.dart

@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; @@ -3,7 +3,7 @@ import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:path/path.dart' as path;
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/content_search/controllers/content_search_controller.dart';
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/modules/content_search/models/count_result.dart';

2
win_text_editor/lib/modules/data_compare/controllers/data_compare_controller.dart

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';

2
win_text_editor/lib/modules/data_compare/widgets/data_compare_view.dart

@ -4,7 +4,7 @@ import 'package:file_picker/file_picker.dart'; @@ -4,7 +4,7 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/modules/data_compare/controllers/data_compare_controller.dart';
import 'package:win_text_editor/modules/data_compare/widgets/data_compare_data_source.dart';

2
win_text_editor/lib/modules/data_extract/controllers/data_extract_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/data_extract/models/search_result.dart';
import 'package:win_text_editor/modules/data_extract/models/xml_rule.dart';
import 'package:win_text_editor/modules/data_extract/services/xml_extract_service.dart';

2
win_text_editor/lib/modules/data_extract/services/xml_extract_service.dart

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
// xml_extract_service.dart
import 'dart:io';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/shared/utils/file_utils.dart';
import 'package:xml/xml.dart' as xml;
import 'package:win_text_editor/modules/data_extract/models/search_result.dart';

2
win_text_editor/lib/modules/data_format/controllers/data_format_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/data_format/services/mustache_service.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';

2
win_text_editor/lib/modules/memory_table/controllers/memory_table_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/framework/services/macro_template_service.dart';
import 'package:win_text_editor/modules/outline/models/code_partner.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';

2
win_text_editor/lib/modules/memory_table/services/memory_table_service.dart

@ -6,7 +6,7 @@ import 'package:win_text_editor/shared/data/std_fields_cache.dart'; @@ -6,7 +6,7 @@ import 'package:win_text_editor/shared/data/std_fields_cache.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
import 'package:xml/xml.dart' as xml;
import 'package:path/path.dart' as path;
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class MemoryTableService {
static Future<TableData> parseStructureFile(String filePath) async {

2
win_text_editor/lib/modules/module_router.dart

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
// modules/tab_content_registry.dart
import 'package:flutter/material.dart';
import 'package:win_text_editor/framework/models/tab_model.dart';
import 'package:win_text_editor/app/models/tab_model.dart';
import 'package:win_text_editor/modules/call_function/controllers/call_function_controller.dart';
import 'package:win_text_editor/modules/call_function/widgets/call_function_view.dart';
import 'package:win_text_editor/modules/code_creater/controllers/code_creater_controller.dart';

2
win_text_editor/lib/modules/outline/controllers/outline_provider.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/modules/outline/services/outline_service.dart';

2
win_text_editor/lib/modules/outline/services/component_service.dart

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import 'dart:io';
import 'package:win_text_editor/framework/common/constants.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:xml/xml.dart';

2
win_text_editor/lib/modules/outline/services/functions_service.dart

@ -2,7 +2,7 @@ import 'dart:io'; @@ -2,7 +2,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:win_text_editor/framework/common/constants.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/modules/outline/services/component_service.dart';
import 'package:xml/xml.dart';

2
win_text_editor/lib/modules/outline/services/outline_service.dart

@ -10,7 +10,7 @@ import 'package:win_text_editor/modules/outline/services/std_field_service.dart' @@ -10,7 +10,7 @@ import 'package:win_text_editor/modules/outline/services/std_field_service.dart'
import 'package:win_text_editor/modules/outline/services/uft_object_service.dart';
import 'package:xml/xml.dart';
import 'package:yaml/yaml.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class OutlineService {
//

2
win_text_editor/lib/modules/outline/services/std_field_service.dart

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import 'dart:io';
import 'package:win_text_editor/framework/common/constants.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/modules/outline/services/component_service.dart';
import 'package:win_text_editor/modules/outline/services/functions_service.dart';

2
win_text_editor/lib/modules/outline/services/uft_object_service.dart

@ -2,7 +2,7 @@ import 'dart:io'; @@ -2,7 +2,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:win_text_editor/framework/common/constants.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:xml/xml.dart';

2
win_text_editor/lib/modules/outline/widgets/outline_explorer.dart

@ -3,7 +3,7 @@ import 'dart:async'; @@ -3,7 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/common/constants.dart';
import 'package:win_text_editor/framework/controllers/file_provider.dart';
import 'package:win_text_editor/app/providers/file_provider.dart';
import 'package:win_text_editor/framework/services/file_path_manager.dart';
import 'package:win_text_editor/modules/outline/controllers/outline_provider.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';

80
win_text_editor/lib/modules/pdf_parse/controllers/pdf_parse_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';
@ -51,6 +51,7 @@ class PdfParseController extends BaseContentController { @@ -51,6 +51,7 @@ class PdfParseController extends BaseContentController {
final dayStartPattern = RegExp(r'^Day');
final weekDays = ['M', 'T', 'W', 'T', 'F', 'S', 'S']; //
int weekDayIndex = 0;
int monthIndex = 0; //
int lineNumber = 0; // 1
for (final line in lines) {
@ -62,17 +63,20 @@ class PdfParseController extends BaseContentController { @@ -62,17 +63,20 @@ class PdfParseController extends BaseContentController {
// Day段落
if (dayStartPattern.hasMatch(line.trim())) {
inDaySection = true;
monthIndex++;
} else {
inDaySection = false;
}
if (inDaySection) {
// Day段落内的行处理
buffer.write("Month,");
buffer.writeln(line.replaceAll(RegExp(r'\s+'), ','));
} else {
// Day段落的行处理
lineNumber++;
final csvLine = _parseNormalLine(line, weekDays[weekDayIndex % 7], lineNumber);
buffer.write('$monthIndex,');
buffer.writeln(csvLine);
weekDayIndex++;
}
@ -82,67 +86,69 @@ class PdfParseController extends BaseContentController { @@ -82,67 +86,69 @@ class PdfParseController extends BaseContentController {
}
String _parseNormalLine(String line, String weekDay, int lineNumber) {
if (lineNumber < 2) Logger().debug('[$_logTag] 开始解析行: "$line"', source: _logTag);
final cells = <String>[];
var remainingLine = line.trim();
// 1.
if (lineNumber < 2) Logger().debug('[$_logTag] 正在解析第一列...', source: _logTag);
var firstCellMatch = RegExp(r'^([A-Za-z]\d{1,2})\b').firstMatch(remainingLine);
if (firstCellMatch == null) {
if (lineNumber < 2) Logger().debug('[$_logTag] 紧凑格式匹配失败,尝试宽松匹配', source: _logTag);
firstCellMatch = RegExp(r'^([A-Za-z])\s*(\d{1,2})\b').firstMatch(remainingLine);
if (firstCellMatch != null) {
final mergedCell = '${firstCellMatch.group(1)}${firstCellMatch.group(2)}';
if (lineNumber < 2) Logger().debug('[$_logTag] 合并后第一列: "$mergedCell"', source: _logTag);
cells.add(mergedCell);
remainingLine = remainingLine.substring(firstCellMatch.end).trim();
if (lineNumber < 2) Logger().debug('[$_logTag] 剩余内容: "$remainingLine"', source: _logTag);
} else {
if (lineNumber < 2)
Logger().debug('[$_logTag] 无法识别第一列格式,使用默认星期: "$weekDay"', source: _logTag);
cells.add(weekDay);
}
} else {
if (lineNumber < 2)
Logger().debug('[$_logTag] 匹配到紧凑格式第一列: "${firstCellMatch.group(1)}"', source: _logTag);
cells.add('$weekDay${firstCellMatch.group(1)!.substring(1)}');
remainingLine = remainingLine.substring(firstCellMatch.end).trim();
if (lineNumber < 2) Logger().debug('[$_logTag] 剩余内容: "$remainingLine"', source: _logTag);
}
// 2.
if (lineNumber < 2) Logger().debug('[$_logTag] 正在解析第二列...', source: _logTag);
final secondCell = _parseThreeNumbersCell(remainingLine);
if (secondCell != null) {
if (lineNumber < 2) Logger().debug('[$_logTag] 第二列内容: "$secondCell"', source: _logTag);
cells.add(secondCell);
remainingLine = remainingLine.substring(secondCell.length).trim();
if (lineNumber < 2) Logger().debug('[$_logTag] 剩余内容: "$remainingLine"', source: _logTag);
}
// 3.
if (lineNumber < 2) Logger().debug('[$_logTag] 正在解析第三列...', source: _logTag);
final thirdCell = _parseThreeSymbolsCell(remainingLine);
if (thirdCell != null) {
if (lineNumber < 2) Logger().debug('[$_logTag] 第三列内容: "$thirdCell"', source: _logTag);
cells.add(thirdCell);
cells.add(_replaceZodiacLetters(thirdCell));
remainingLine = remainingLine.substring(thirdCell.length).trim();
if (lineNumber < 2) Logger().debug('[$_logTag] 剩余内容: "$remainingLine"', source: _logTag);
}
// 4.
if (lineNumber < 2) Logger().debug('[$_logTag] 开始解析后续列...', source: _logTag);
while (remainingLine.isNotEmpty) {
int columnNumber = 4;
while (remainingLine.isNotEmpty && columnNumber++ <= 16) {
final match = _parseTwoSymbolsCell(remainingLine);
if (match == null) break;
if (match == null) {
Logger().error('[$_logTag] 无法匹配后续单元格,剩余内容: "$remainingLine"', source: _logTag);
break; // 退
}
cells.add(match.cellText);
cells.add(_replaceZodiacLetters(match.cellText));
remainingLine = remainingLine.substring(match.matchLength).trim();
}
var lastCellMatch = RegExp(r'^([A-Za-z]\d{1,2})\b').firstMatch(remainingLine);
if (lastCellMatch == null) {
lastCellMatch = RegExp(r'^([A-Za-z])\s*(\d{1,2})\b').firstMatch(remainingLine);
if (lastCellMatch != null) {
final mergedCell = '${lastCellMatch.group(1)}${lastCellMatch.group(2)}';
cells.add(mergedCell);
remainingLine = remainingLine.substring(lastCellMatch.end).trim();
} else {
cells.add(weekDay);
}
} else {
cells.add('$weekDay${lastCellMatch.group(1)!.substring(1)}');
remainingLine = remainingLine.substring(lastCellMatch.end).trim();
}
final result = cells.join(',');
if (lineNumber < 2) Logger().debug('[$_logTag] 最终解析结果: "$result"', source: _logTag);
return result;
}
@ -154,7 +160,8 @@ class PdfParseController extends BaseContentController { @@ -154,7 +160,8 @@ class PdfParseController extends BaseContentController {
// "12°34'56"
String? _parseThreeSymbolsCell(String input) {
final match = RegExp(r'^(\d+[^\d\s]\d+[^\d\s]\d+)').firstMatch(input);
// Updated to handle spaces before single digits (like "21° 0'22")
final match = RegExp(r'^(\d+[^\d\s]\s*\d+[^\d\s]\s*\d+)').firstMatch(input);
return match?.group(0);
}
@ -169,7 +176,7 @@ class PdfParseController extends BaseContentController { @@ -169,7 +176,7 @@ class PdfParseController extends BaseContentController {
}
// 2+1-2+ "1k4"
match = RegExp(r'^(\d+[^\d\s]{1,2}\d+)').firstMatch(input);
match = RegExp(r'^(\d+[^\d\s]{1,2}\s*\d+)').firstMatch(input); // Added \s*
if (match != null) {
return _CellMatch(match.group(0)!, match.group(0)!.length);
}
@ -210,7 +217,7 @@ class PdfParseController extends BaseContentController { @@ -210,7 +217,7 @@ class PdfParseController extends BaseContentController {
var processedLine = line;
// Day段落
if (line.trim().startsWith('Day') && line.trim().endsWith('Day')) {
if (line.trim().startsWith('Month') && line.trim().endsWith('Day')) {
inDaySection = true;
} else {
// Day段落
@ -235,6 +242,27 @@ class PdfParseController extends BaseContentController { @@ -235,6 +242,27 @@ class PdfParseController extends BaseContentController {
return buffer.toString().trim();
}
String _replaceZodiacLetters(String text) {
// Define the replacement mapping (case sensitive)
const replacementMap = {
'a': '',
'b': '',
'c': '',
'd': '',
'e': '',
'f': '',
'g': '',
'h': '',
'i': '',
'j': '',
'k': '',
'l': '',
};
// Replace each character in the input text
return text.split('').map((char) => replacementMap[char] ?? char).join('');
}
String _removeNonTableContent(String rawText) {
final lines = rawText.split('\n');
final buffer = StringBuffer();

2
win_text_editor/lib/modules/template_parser/controllers/filter_controller.dart

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
// filter_controller.dart
import 'package:flutter/foundation.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/shared/models/template_node.dart';
import '../../../shared/base/safe_notifier.dart';

2
win_text_editor/lib/modules/template_parser/controllers/template_parser_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/shared/models/template_node.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';

2
win_text_editor/lib/modules/uft_component/controllers/uft_component_controller.dart

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/framework/services/macro_template_service.dart';
import 'package:win_text_editor/modules/outline/models/code_partner.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';

2
win_text_editor/lib/modules/uft_component/services/uft_component_service.dart

@ -8,7 +8,7 @@ import 'package:win_text_editor/modules/uft_component/models/uft_component.dart' @@ -8,7 +8,7 @@ import 'package:win_text_editor/modules/uft_component/models/uft_component.dart'
import 'package:win_text_editor/shared/data/std_fields_cache.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:xml/xml.dart' as xml;
class UftComponentService {

2
win_text_editor/lib/modules/xml_search/controllers/xml_search_controller.dart

@ -2,7 +2,7 @@ import 'dart:async'; @@ -2,7 +2,7 @@ import 'dart:async';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/outline/models/outline_node.dart';
import 'package:win_text_editor/modules/xml_search/models/search_result.dart';
import 'package:win_text_editor/modules/xml_search/services/xml_search_service.dart';

2
win_text_editor/lib/modules/xml_search/services/xml_search_service.dart

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
// xml_search_service.dart
import 'dart:io';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:xml/xml.dart' as xml;
import 'package:win_text_editor/modules/xml_search/models/search_result.dart';

2
win_text_editor/lib/modules/xml_search/widgets/results_view.dart

@ -4,7 +4,7 @@ import 'package:pluto_grid/pluto_grid.dart'; @@ -4,7 +4,7 @@ import 'package:pluto_grid/pluto_grid.dart';
import 'package:path/path.dart' as path;
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/modules/xml_search/models/search_result.dart';
import 'dart:io';

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

@ -2,8 +2,8 @@ import 'dart:math'; @@ -2,8 +2,8 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/controllers/file_provider.dart';
import 'package:win_text_editor/framework/models/file_node.dart';
import 'package:win_text_editor/app/providers/file_provider.dart';
import 'package:win_text_editor/app/models/file_node.dart';
import 'tree_view.dart';

2
win_text_editor/lib/shared/data/std_fields_cache.dart

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
import 'package:xml/xml.dart' as xml;

2
win_text_editor/lib/shared/utils/file_utils.dart

@ -5,7 +5,7 @@ import 'dart:io'; @@ -5,7 +5,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:path/path.dart' as path;
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/app/providers/logger.dart';
class FileUtils {
static Future<String?> pickFile(BuildContext context) async {

2
win_text_editor/备忘.txt

@ -10,4 +10,4 @@ $env:PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub" @@ -10,4 +10,4 @@ $env:PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
境外镜像
$env:PUB_HOSTED_URL="https://pub.dartlang.org"
$env:FLUTTER_STORAGE_BASE_URL=https://storage.googleapis.com
$env:FLUTTER_STORAGE_BASE_URL="https://storage.googleapis.com"
Loading…
Cancel
Save