Browse Source

组件列表展示OK

master
hejl 2 months ago
parent
commit
086f9ae021
  1. 68
      win_text_editor/lib/modules/memory_table/services/memory_table_service.dart
  2. 51
      win_text_editor/lib/modules/uft_component/controllers/component_source.dart
  3. 57
      win_text_editor/lib/modules/uft_component/controllers/uft_component_controller.dart
  4. 28
      win_text_editor/lib/modules/uft_component/models/uft_component.dart
  5. 76
      win_text_editor/lib/modules/uft_component/services/uft_component_service.dart
  6. 106
      win_text_editor/lib/modules/uft_component/widgets/component_grid.dart
  7. 37
      win_text_editor/lib/modules/uft_component/widgets/uft_component_left_side.dart
  8. 18
      win_text_editor/lib/shared/uft_std_fields/field_data_service.dart

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

@ -4,6 +4,7 @@ import 'dart:io'; @@ -4,6 +4,7 @@ import 'dart:io';
import 'package:win_text_editor/modules/memory_table/models/memory_table.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/shared/uft_std_fields/field_data_service.dart';
import 'package:xml/xml.dart' as xml;
import 'package:path/path.dart' as path;
import 'package:win_text_editor/framework/controllers/logger.dart';
@ -23,9 +24,9 @@ class MemoryTableService { @@ -23,9 +24,9 @@ class MemoryTableService {
// 2. metadata stdfield.stfield
if (await StdFieldsCache.getLength() == 0) {
_logger.info("加载标准字段缓存");
final metadataFile = await _findMetadataFile(filePath);
final metadataFile = await FieldDataService.findMetadataFile(filePath);
if (metadataFile != null) {
await _processStdFieldFile(metadataFile);
await FieldDataService.processStdFieldFile(metadataFile);
}
}
@ -97,8 +98,8 @@ class MemoryTableService { @@ -97,8 +98,8 @@ class MemoryTableService {
tableName: fileNameWithoutExt,
chineseName: chineseName,
objectId: objectId,
fields: fields.isNotEmpty ? fields : _getDefaultFields(),
indexes: indexList.isNotEmpty ? indexList : _getDefaultIndexes(),
fields: fields.isNotEmpty ? fields : FieldDataService.getDefaultFields(),
indexes: indexList.isNotEmpty ? indexList : FieldDataService.getDefaultIndexes(),
);
} on xml.XmlParserException catch (e) {
_logger.error("XML解析错误: ${e.message}");
@ -108,65 +109,6 @@ class MemoryTableService { @@ -108,65 +109,6 @@ class MemoryTableService {
rethrow;
}
}
// metadata stdfield.stfield
Future<File?> _findMetadataFile(String filePath) async {
Directory currentDir = File(filePath).parent;
const targetDirName = 'metadata';
const targetFileName = 'stdfield.stdfield';
// metadata
while (true) {
final metadataDir = Directory('${currentDir.path}/$targetDirName');
if (await metadataDir.exists()) {
final stdFieldFile = File('${metadataDir.path}/$targetFileName');
if (await stdFieldFile.exists()) {
return stdFieldFile;
} else {
_logger.error("没找到标准字段文件 $targetFileName");
return null;
}
}
//
if (currentDir.path == currentDir.parent.path) {
_logger.error("没有找到元数据目录 $targetDirName");
return null;
}
currentDir = currentDir.parent;
}
}
//
Future<void> _processStdFieldFile(File stdFieldFile) async {
try {
final content = await stdFieldFile.readAsString();
final document = xml.XmlDocument.parse(content);
final items = document.findAllElements('items');
for (final item in items) {
final name = item.getAttribute('name') ?? '';
final chineseName = item.getAttribute('chineseName') ?? '';
final dataType = item.getAttribute('dataType') ?? '';
if (name.isNotEmpty) {
final stdField = StdField(name: name, chineseName: chineseName, dateType: dataType);
await StdFieldsCache.setData(name, stdField);
}
}
} catch (e) {
_logger.error("处理标准字段文件时出错: $e");
}
}
List<Field> _getDefaultFields() {
return [Field('1', '', '', ''), Field('2', '', '', ''), Field('3', '', '', '')];
}
List<Index> _getDefaultIndexes() {
return [Index('', false, '', ''), Index('', false, '', '')];
}
}
class TableData {

51
win_text_editor/lib/modules/uft_component/controllers/component_source.dart

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/modules/uft_component/models/uft_component.dart';
import 'package:win_text_editor/shared/base/base_data_source.dart';
class ComponentSource extends SelectableDataSource<UftComponent> {
ComponentSource(
List<UftComponent> uftComponents, {
required Null Function(dynamic index, dynamic isSelected) onSelectionChanged,
}) : super(uftComponents, onSelectionChanged: onSelectionChanged);
@override
List<DataGridRow> get rows =>
items
.map(
(component) => DataGridRow(
cells: [
DataGridCell<bool>(columnName: 'select', value: component.isSelected),
DataGridCell<int>(columnName: 'id', value: component.id),
DataGridCell<String>(columnName: 'name', value: component.name),
DataGridCell<String>(columnName: 'chineseName', value: component.chineseName),
],
),
)
.toList();
get data => items;
@override
DataGridRowAdapter buildRow(DataGridRow row) {
final rowIndex = effectiveRows.indexOf(row);
return DataGridRowAdapter(
cells:
row.getCells().map<Widget>((cell) {
if (cell.columnName == 'select') {
return Center(
child: Checkbox(
value: items[rowIndex].isSelected,
onChanged: (value) => toggleRowSelection(rowIndex, value),
),
);
}
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(cell.value.toString(), overflow: TextOverflow.ellipsis),
);
}).toList(),
);
}
}

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

@ -1,30 +1,41 @@ @@ -1,30 +1,41 @@
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/framework/services/macro_template_service.dart';
import 'package:win_text_editor/modules/uft_component/controllers/component_source.dart';
import 'package:win_text_editor/modules/uft_component/models/uft_component.dart';
import 'package:win_text_editor/modules/uft_component/services/uft_component_service.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
import 'package:win_text_editor/shared/uft_std_fields/field_data_source.dart';
import 'package:win_text_editor/modules/memory_table/models/memory_table.dart';
import 'package:win_text_editor/modules/memory_table/services/memory_table_service.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';
class UftComponentController extends BaseContentController {
String? _errorMessage;
String tableName = "";
String objectId = "";
String componentName = "";
String chineseName = "";
late DataGridSource fieldsSource;
final MemoryTableService _service;
late DataGridSource componentsSource;
final UftComponentService _service;
final MacroTemplateService templateService = MacroTemplateService();
// MemoryTable对
late MemoryTable _memoryTable;
//
late UftComponent _currentUftComponent;
UftComponentController() : _service = MemoryTableService(Logger()) {
UftComponentController() : _service = UftComponentService(Logger()) {
//
final initialFields = [Field('1', '', '', '', false), Field('2', '', '', '', false)];
final initialIndexes = [Index('', false, '', '', false)];
final initalComponents = [
UftComponent(id: 1, name: '', chineseName: '', fields: initialFields),
];
componentsSource = ComponentSource(
initalComponents,
onSelectionChanged: (index, isSelected) {
updateComponentSelection(index, isSelected);
},
);
fieldsSource = FieldsDataSource(
initialFields,
@ -33,14 +44,14 @@ class UftComponentController extends BaseContentController { @@ -33,14 +44,14 @@ class UftComponentController extends BaseContentController {
},
);
// MemoryTable
_memoryTable = MemoryTable(tableName: '', columns: initialFields, indexes: initialIndexes);
// uftComponent
_currentUftComponent = UftComponent(id: 0, name: '', chineseName: '', fields: initialFields);
}
String? get errorMessage => _errorMessage;
// MemoryTable
MemoryTable get memoryTable => _memoryTable;
// UftComponent
UftComponent get currentUftComponent => _currentUftComponent;
void initTemplateService() {
if (!templateService.inited) {
@ -50,29 +61,17 @@ class UftComponentController extends BaseContentController { @@ -50,29 +61,17 @@ class UftComponentController extends BaseContentController {
String? genCodeString(List<String> macroList) {
initTemplateService();
return templateService.renderTemplate(macroList, _memoryTable.toMap());
return templateService.renderTemplate(macroList, _currentUftComponent.toMap());
}
@override
Future<void> onOpenFile(String filePath) async {
Logger().info("Opening file: $filePath");
try {
final tableData = await _service.parseStructureFile(filePath);
// Update controller state
tableName = tableData.tableName;
chineseName = tableData.chineseName;
objectId = tableData.objectId;
final components = await _service.parseComponentFile(filePath);
// Update data sources
(fieldsSource as FieldsDataSource).updateData(tableData.fields);
// MemoryTable对象
_memoryTable = MemoryTable(
tableName: tableName,
columns: tableData.fields,
indexes: tableData.indexes,
);
(componentsSource as ComponentSource).updateData(components);
// Clear any previous error
_errorMessage = null;
@ -94,7 +93,7 @@ class UftComponentController extends BaseContentController { @@ -94,7 +93,7 @@ class UftComponentController extends BaseContentController {
fieldsSource.notifyListeners();
// MemoryTable
_memoryTable.columns[index].isSelected = isSelected;
_currentUftComponent.fields[index].isSelected = isSelected;
notifyListeners();
}
}
@ -110,4 +109,6 @@ class UftComponentController extends BaseContentController { @@ -110,4 +109,6 @@ class UftComponentController extends BaseContentController {
void dispose() {
super.dispose();
}
void updateComponentSelection(index, isSelected) {}
}

28
win_text_editor/lib/modules/uft_component/models/uft_component.dart

@ -1,25 +1,37 @@ @@ -1,25 +1,37 @@
import 'package:win_text_editor/shared/models/std_filed.dart';
class UftComponent {
final String componentName;
final List<Field> columns;
class UftComponent implements SelectableItem {
final int id;
final String name;
final String chineseName;
final List<Field> fields;
@override
bool isSelected;
UftComponent({required this.componentName, required this.columns});
UftComponent({
required this.id,
required this.name,
required this.chineseName,
required this.fields,
this.isSelected = false,
});
List<Field> get selectFields => columns.where((field) => field.isSelected).toList();
List<Field> get selectFields => fields.where((field) => field.isSelected).toList();
Map<String, dynamic> toMap() {
return {
'componentName': componentName,
'id': id,
'name': name,
'chineseName': chineseName,
'fields':
columns
fields
.map(
(field) => {
'id': field.id,
'name': field.name,
'chineseName': field.chineseName,
'type': field.type,
'isLast': columns.indexOf(field) == columns.length - 1,
'isLast': fields.indexOf(field) == fields.length - 1,
},
)
.toList(),

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

@ -1,19 +1,85 @@ @@ -1,19 +1,85 @@
// memory_table_service.dart
import 'dart:io';
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/shared/uft_std_fields/field_data_service.dart';
import 'package:xml/xml.dart' as xml;
class UftComponentService {
final Logger _logger;
UftComponentService(this._logger);
Future<List<UftComponent>> parseComponentFile(String filePath) async {
try {
// 1. Check file extension
if (!filePath.toLowerCase().endsWith('component.xml')) {
throw const FormatException("文件名必须是component.xml");
}
// 2. metadata stdfield.stfield
if (await StdFieldsCache.getLength() == 0) {
_logger.info("加载标准字段缓存");
final metadataFile = await FieldDataService.findMetadataFile(filePath);
if (metadataFile != null) {
await FieldDataService.processStdFieldFile(metadataFile);
}
}
// 3. Read and parse structure file content
final file = File(filePath);
final content = await file.readAsString();
final document = xml.XmlDocument.parse(content);
final componentNodes = document.findAllElements('items');
if (componentNodes.isEmpty) {
throw const FormatException("文件格式错误:缺少items节点");
}
// 4.
final components = <UftComponent>[];
int id = 0;
for (var node in componentNodes) {
if (node.findElements("items").isEmpty) continue;
id++;
final name = node.getAttribute('name') ?? '';
final chineseName = node.getAttribute('chineseName') ?? '';
// 5. Process properties (fields)
final childNodes = node.children;
final fields = <Field>[];
int index = 1;
for (final childNode in childNodes) {
final name = childNode.getAttribute('name') ?? '';
//
final stdField = StdFieldsCache.getData(name);
fields.add(
Field(
(index++).toString(), //
name, //
stdField?.chineseName ?? '', //
stdField?.dateType ?? '', //
),
);
}
class ComponentData {
final String name;
final String chineseName;
final List<Field> fields;
components.add(UftComponent(id: id, name: name, chineseName: chineseName, fields: fields));
}
ComponentData({required this.name, required this.chineseName, required this.fields});
return components;
} on xml.XmlParserException catch (e) {
_logger.error("XML解析错误: ${e.message}");
rethrow;
} catch (e) {
_logger.error("处理文件时发生错误: $e");
rethrow;
}
}
}

106
win_text_editor/lib/modules/uft_component/widgets/component_grid.dart

@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:win_text_editor/modules/uft_component/controllers/component_source.dart';
import 'package:win_text_editor/shared/base/base_data_source.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
class ComponentGrid extends StatelessWidget {
final ComponentSource componentsSource;
final Function(int index, bool isSelected)? onSelectionChanged;
const ComponentGrid({super.key, required this.componentsSource, this.onSelectionChanged});
Container _buildGridHeader(String text) {
return Container(
alignment: Alignment.center,
color: Colors.grey[200],
child: Text(text, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
);
}
Widget _buildCheckboxHeader<T extends SelectableItem>(
BuildContext context,
SelectableDataSource<T> dataSource,
) {
final allSelected =
dataSource.items.isNotEmpty && dataSource.items.every((item) => item.isSelected);
final someSelected =
dataSource.items.isNotEmpty &&
dataSource.items.any((item) => item.isSelected) &&
!allSelected;
return Container(
alignment: Alignment.center,
color: Colors.grey[200],
child: Checkbox(
value: allSelected,
tristate: someSelected,
onChanged: (value) => dataSource.toggleAllSelection(value ?? false),
),
);
}
@override
Widget build(BuildContext context) {
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
width: constraints.maxWidth,
child: SfDataGrid(
source: componentsSource,
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
columnWidthMode: ColumnWidthMode.fitByCellValue,
selectionMode: SelectionMode.none,
columns: [
GridColumn(
columnName: 'select',
label: ValueListenableBuilder<bool>(
valueListenable: componentsSource.selectionNotifier,
builder:
(context, _, __) => _buildCheckboxHeader(context, componentsSource),
),
width: 60,
),
GridColumn(columnName: 'id', label: _buildGridHeader('序号'), minimumWidth: 80),
GridColumn(
columnName: 'name',
label: _buildGridHeader('名称'),
minimumWidth: 120,
),
GridColumn(
columnName: 'chineseName',
label: _buildGridHeader('中文名'),
minimumWidth: 120,
),
],
onCellTap: (details) {
if (details.column.columnName == 'select') {
final rowIndex = details.rowColumnIndex.rowIndex - 1;
if (rowIndex >= 0 && rowIndex < componentsSource.items.length) {
componentsSource.toggleRowSelection(
rowIndex,
!componentsSource.items[rowIndex].isSelected,
);
onSelectionChanged?.call(
rowIndex,
componentsSource.items[rowIndex].isSelected,
);
}
}
},
),
);
},
),
),
],
),
);
}
}

37
win_text_editor/lib/modules/uft_component/widgets/uft_component_left_side.dart

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:win_text_editor/modules/uft_component/controllers/component_source.dart';
import 'package:win_text_editor/modules/uft_component/controllers/uft_component_controller.dart';
import 'package:win_text_editor/modules/uft_component/widgets/component_grid.dart';
import 'package:win_text_editor/shared/uft_std_fields/field_data_source.dart';
import 'package:win_text_editor/shared/uft_std_fields/fields_data_grid.dart';
@ -13,7 +15,7 @@ class UftComponentLeftSide extends StatelessWidget { @@ -13,7 +15,7 @@ class UftComponentLeftSide extends StatelessWidget {
children: [
Text('$label:'),
SizedBox(
width: 200,
width: 150,
child: TextField(
controller: TextEditingController(text: value),
readOnly: true,
@ -29,30 +31,25 @@ class UftComponentLeftSide extends StatelessWidget { @@ -29,30 +31,25 @@ class UftComponentLeftSide extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: double.infinity,
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 16,
runSpacing: 8,
const SizedBox(height: 8),
Row(
children: [
_buildTextFieldRow('名称', controller.tableName),
const SizedBox(width: 8),
_buildTextFieldRow('名称', controller.componentName),
_buildTextFieldRow('中文名', controller.chineseName),
_buildTextFieldRow('对象编号', controller.objectId),
],
),
Expanded(
flex: 6,
child: ComponentGrid(
componentsSource: controller.componentsSource as ComponentSource,
onSelectionChanged: (index, isSelected) {
controller.updateFieldSelection(index, isSelected);
},
),
),
),
const SizedBox(height: 8),
const Padding(
padding: EdgeInsets.all(8.0),
child: Text('字段列表', style: TextStyle(fontWeight: FontWeight.bold)),
),
Expanded(
flex: 6,
flex: 3,
child: FieldsDataGrid(
fieldsSource: controller.fieldsSource as FieldsDataSource,
onSelectionChanged: (index, isSelected) {
@ -60,10 +57,6 @@ class UftComponentLeftSide extends StatelessWidget { @@ -60,10 +57,6 @@ class UftComponentLeftSide extends StatelessWidget {
},
),
),
const Padding(
padding: EdgeInsets.all(8.0),
child: Text('索引列表', style: TextStyle(fontWeight: FontWeight.bold)),
),
],
);
}

18
win_text_editor/lib/shared/uft_std_fields/field_data_service.dart

@ -7,11 +7,7 @@ import 'package:win_text_editor/shared/models/std_filed.dart'; @@ -7,11 +7,7 @@ import 'package:win_text_editor/shared/models/std_filed.dart';
import 'package:xml/xml.dart' as xml;
class FieldDataService {
final Logger _logger;
FieldDataService(this._logger);
Future<File?> findMetadataFile(String filePath) async {
static Future<File?> findMetadataFile(String filePath) async {
Directory currentDir = File(filePath).parent;
const targetDirName = 'metadata';
const targetFileName = 'stdfield.stdfield';
@ -24,14 +20,14 @@ class FieldDataService { @@ -24,14 +20,14 @@ class FieldDataService {
if (await stdFieldFile.exists()) {
return stdFieldFile;
} else {
_logger.error("没找到标准字段文件 $targetFileName");
Logger().error("没找到标准字段文件 $targetFileName");
return null;
}
}
//
if (currentDir.path == currentDir.parent.path) {
_logger.error("没有找到元数据目录 $targetDirName");
Logger().error("没有找到元数据目录 $targetDirName");
return null;
}
@ -40,7 +36,7 @@ class FieldDataService { @@ -40,7 +36,7 @@ class FieldDataService {
}
//
Future<void> processStdFieldFile(File stdFieldFile) async {
static Future<void> processStdFieldFile(File stdFieldFile) async {
try {
final content = await stdFieldFile.readAsString();
final document = xml.XmlDocument.parse(content);
@ -57,15 +53,15 @@ class FieldDataService { @@ -57,15 +53,15 @@ class FieldDataService {
}
}
} catch (e) {
_logger.error("处理标准字段文件时出错: $e");
Logger().error("处理标准字段文件时出错: $e");
}
}
List<Field> getDefaultFields() {
static List<Field> getDefaultFields() {
return [Field('1', '', '', ''), Field('2', '', '', ''), Field('3', '', '', '')];
}
List<Index> getDefaultIndexes() {
static List<Index> getDefaultIndexes() {
return [Index('', false, '', ''), Index('', false, '', '')];
}
}

Loading…
Cancel
Save