Browse Source

组件代码生成完成。

master
hejl 2 months ago
parent
commit
fadd59d1dc
  1. 85
      win_text_editor/assets/config/uft_macro_list.yaml
  2. 8
      win_text_editor/lib/framework/services/macro_template_service.dart
  3. 33
      win_text_editor/lib/modules/uft_component/controllers/component_source.dart
  4. 14
      win_text_editor/lib/modules/uft_component/controllers/uft_component_controller.dart
  5. 16
      win_text_editor/lib/modules/uft_component/models/uft_component.dart
  6. 45
      win_text_editor/lib/modules/uft_component/services/uft_component_service.dart
  7. 73
      win_text_editor/lib/modules/uft_component/widgets/component_grid.dart
  8. 101
      win_text_editor/lib/modules/uft_component/widgets/uft_component_left_side.dart
  9. 2
      win_text_editor/lib/modules/uft_component/widgets/uft_component_right_side.dart

85
win_text_editor/assets/config/uft_macro_list.yaml

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
templates:
获取记录:
header: "<M>[获取记录][{{tableName}}({{keyName}})"
body: |
][
<M>[获取记录][{{tableName}}({{keyName}})][
{{#keyFields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/keyFields}}
@ -12,7 +11,6 @@ templates: @@ -12,7 +11,6 @@ templates:
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/selectedFields}}
]
footer: |
[继续执行]
[记录为空][{{tableName}}]
{
@ -23,19 +21,15 @@ templates: @@ -23,19 +21,15 @@ templates:
获取记录数:
header: "[获取记录数][{{tableName}}][@count]"
body: ""
footer: ""
body: "[获取记录数][{{tableName}}][@count]"
插入记录:
header: "<C>[插入记录][{{tableName}}]["
body: |
][
<C>[插入记录][{{tableName}}][
{{#fields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/fields}}
]
footer: |
[索引冲突]
{
[继续执行]
@ -60,14 +54,12 @@ templates: @@ -60,14 +54,12 @@ templates:
}
修改记录:
header: "<M>[获取记录][{{tableName}}({{keyName}})"
body: |
][
<M>[获取记录][{{tableName}}({{keyName}})][
{{#keyFields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/keyFields}}
]
footer: |
[继续执行]
[记录不为空][{{tableName}}]
{
@ -85,14 +77,12 @@ templates: @@ -85,14 +77,12 @@ templates:
}
删除记录:
header: "<M>[获取记录][{{tableName}}({{keyName}})"
body: |
][
<M>[获取记录][{{tableName}}({{keyName}})][
{{#keyFields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/keyFields}}
]
footer: |
[继续执行]
[记录不为空][{{tableName}}]
{
@ -100,9 +90,8 @@ templates: @@ -100,9 +90,8 @@ templates:
}
遍历记录:
header: "<M>[遍历记录开始][{{tableName}}({{selectIndexOrKey.name}})"
body: |
][
<M>[遍历记录开始][{{tableName}}({{selectIndexOrKey.name}})][
{{#selectIndexOrKey.fields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/selectIndexOrKey.fields}}
@ -111,8 +100,68 @@ templates: @@ -111,8 +100,68 @@ templates:
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/selectedFields}}
]
footer: |
{
//balabala
}
[遍历记录结束]
插入组件:
body: |
[插入组件][{{name}}][0][
{{#fields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/fields}}
]
修改组件:
body: |
[修改组件][{{name}}][@num][
{{#selectedFields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/selectedFields}}
]
获取组件:
body: |
{{#hasIndex}}[组件排序][{{name}}(index.name)]{{/hasIndex}}
[获取组件][{{name}}{{#hasIndex}}({{index.name}}){{/hasIndex}}][{{^hasIndex}}[@num][{{/hasIndex}}
{{#hasIndex}}
{{#index.fields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/index.fields}}
][
{{/hasIndex}}
{{#selectedFields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/selectedFields}}
]
遍历组件:
body: |
{{#hasIndex}}[组件排序][{{name}}({{index.name}})]{{/hasIndex}}
[遍历组件开始][{{name}}{{#hasIndex}}({{index.name}}){{/hasIndex}}][
{{#hasIndex}}
{{#index.fields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/index.fields}}
{{/hasIndex}}
][
{{#selectedFields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/selectedFields}}
]
{
}
"[遍历组件结束]"
组件大小:
body: "[组件大小][{{name}}][@num]"
尾部插入组件:
body: |
[插入组件][{{name}}][
{{#fields}}
{{name}} = @{{name}} {{^isLast}}, {{/isLast}}
{{/fields}}
]

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

@ -47,13 +47,7 @@ class MacroTemplateService { @@ -47,13 +47,7 @@ class MacroTemplateService {
final template = getTemplate(templateName);
if (template == null) throw Exception('Template $templateName not found');
buffer.writeln(
[
_render(template['header'], context),
_render(template['body'], context),
_render(template['footer'], context),
].join('\n'),
);
buffer.writeln(_render(template['body'], context));
buffer.writeln();
}

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

@ -15,7 +15,6 @@ class ComponentSource extends SelectableDataSource<UftComponent> { @@ -15,7 +15,6 @@ class ComponentSource extends SelectableDataSource<UftComponent> {
.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),
@ -24,28 +23,30 @@ class ComponentSource extends SelectableDataSource<UftComponent> { @@ -24,28 +23,30 @@ class ComponentSource extends SelectableDataSource<UftComponent> {
)
.toList();
get data => items;
@override
DataGridRowAdapter buildRow(DataGridRow row) {
final rowIndex = effectiveRows.indexOf(row);
final isSelected = items[rowIndex].isSelected;
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),
color: isSelected ? Colors.lightBlue.withOpacity(0.3) : null,
cells: [
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(row.getCells()[0].value.toString(), overflow: TextOverflow.ellipsis),
),
);
}
return Container(
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(cell.value.toString(), overflow: TextOverflow.ellipsis),
);
}).toList(),
child: Text(row.getCells()[1].value.toString(), overflow: TextOverflow.ellipsis),
),
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(row.getCells()[2].value.toString(), overflow: TextOverflow.ellipsis),
),
],
);
}
}

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

@ -6,7 +6,6 @@ import 'package:win_text_editor/modules/uft_component/models/uft_component.dart' @@ -6,7 +6,6 @@ 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/shared/base/base_content_controller.dart';
class UftComponentController extends BaseContentController {
@ -110,5 +109,16 @@ class UftComponentController extends BaseContentController { @@ -110,5 +109,16 @@ class UftComponentController extends BaseContentController {
super.dispose();
}
void updateComponentSelection(index, isSelected) {}
void updateComponentSelection(int index, bool isSelected) {
if (index >= 0 && index < (componentsSource as ComponentSource).items.length) {
//
_currentUftComponent = (componentsSource as ComponentSource).items[index];
//
(fieldsSource as FieldsDataSource).updateData(_currentUftComponent.fields);
// UI更新
notifyListeners();
}
}
}

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

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
import 'package:win_text_editor/modules/memory_table/models/memory_table.dart';
import 'package:win_text_editor/shared/models/std_filed.dart';
class UftComponent implements SelectableItem {
@ -5,6 +6,7 @@ class UftComponent implements SelectableItem { @@ -5,6 +6,7 @@ class UftComponent implements SelectableItem {
final String name;
final String chineseName;
final List<Field> fields;
List<Index>? indexes;
@override
bool isSelected;
@ -14,11 +16,13 @@ class UftComponent implements SelectableItem { @@ -14,11 +16,13 @@ class UftComponent implements SelectableItem {
required this.chineseName,
required this.fields,
this.isSelected = false,
this.indexes,
});
List<Field> get selectFields => fields.where((field) => field.isSelected).toList();
Map<String, dynamic> toMap() {
var index = indexes?.firstOrNull;
return {
'id': id,
'name': name,
@ -47,6 +51,18 @@ class UftComponent implements SelectableItem { @@ -47,6 +51,18 @@ class UftComponent implements SelectableItem {
},
)
.toList(),
'hasIndex': indexes?.isNotEmpty ?? false,
'index':
index == null
? null
: {
'name': index.indexName,
'fields':
index.fields.asMap().entries.map((entry) {
return {'name': entry.value, 'isLast': entry.key == index.fields.length - 1};
}).toList(),
'rule': index.rule,
},
};
}
}

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

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
import 'dart:io';
import 'package:win_text_editor/modules/memory_table/models/memory_table.dart';
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';
@ -44,20 +45,48 @@ class UftComponentService { @@ -44,20 +45,48 @@ class UftComponentService {
// 4.
final components = <UftComponent>[];
int id = 0;
int id = 1;
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>[];
List<Index>? indexes = [];
int index = 1;
// 5.
final indexNodes = node.findElements('indexs');
if (indexNodes.isNotEmpty) {
final attrnames = <String>[];
for (final indexNode in indexNodes) {
final indexName = indexNode.getAttribute('name') ?? '';
//5.1
final indexFieldNodes = indexNode.findElements('items');
for (final fieldNode in indexFieldNodes) {
final fieldName = fieldNode.getAttribute('attrname') ?? '';
if (fieldName.isEmpty) continue; //
attrnames.add(fieldName);
}
indexes.add(Index(indexName, true, attrnames.join(','), '', false));
//
// fields.add(Field((index++).toString(), indexName, '索引', 'COMPONENT_INDEX'));
}
}
// 6.
final childNodes = node.children;
for (final childNode in childNodes) {
if (childNode is xml.XmlElement) {
if (childNode.name.local != 'items') continue; // items节点
}
final name = childNode.getAttribute('name') ?? '';
if (name.isEmpty) continue; //
//
final stdField = StdFieldsCache.getData(name);
fields.add(
@ -70,7 +99,15 @@ class UftComponentService { @@ -70,7 +99,15 @@ class UftComponentService {
);
}
components.add(UftComponent(id: id, name: name, chineseName: chineseName, fields: fields));
components.add(
UftComponent(
id: id,
name: name,
chineseName: chineseName,
fields: fields,
indexes: indexes,
),
);
}
return components;

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

@ -1,15 +1,20 @@ @@ -1,15 +1,20 @@
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 {
class ComponentGrid extends StatefulWidget {
final ComponentSource componentsSource;
final Function(int index, bool isSelected)? onSelectionChanged;
const ComponentGrid({super.key, required this.componentsSource, this.onSelectionChanged});
@override
State<ComponentGrid> createState() => ComponentGridState();
}
class ComponentGridState extends State<ComponentGrid> {
final DataGridController _dataGridController = DataGridController();
Container _buildGridHeader(String text) {
return Container(
alignment: Alignment.center,
@ -18,26 +23,9 @@ class ComponentGrid extends StatelessWidget { @@ -18,26 +23,9 @@ class ComponentGrid extends StatelessWidget {
);
}
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),
),
);
void scrollToIndex(int index) {
_dataGridController.scrollToRow(index.toDouble());
_dataGridController.selectedIndex = index;
}
@override
@ -52,21 +40,13 @@ class ComponentGrid extends StatelessWidget { @@ -52,21 +40,13 @@ class ComponentGrid extends StatelessWidget {
return SizedBox(
width: constraints.maxWidth,
child: SfDataGrid(
source: componentsSource,
controller: _dataGridController,
source: widget.componentsSource,
gridLinesVisibility: GridLinesVisibility.both,
headerGridLinesVisibility: GridLinesVisibility.both,
columnWidthMode: ColumnWidthMode.fitByCellValue,
selectionMode: SelectionMode.none,
selectionMode: SelectionMode.single,
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',
@ -79,18 +59,19 @@ class ComponentGrid extends StatelessWidget { @@ -79,18 +59,19 @@ class ComponentGrid extends StatelessWidget {
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,
);
onSelectionChanged: (addedRows, removedRows) {
if (addedRows.isNotEmpty) {
//
final rowIndex = widget.componentsSource.effectiveRows
.indexOf(addedRows.first);
if (rowIndex >= 0 && rowIndex < widget.componentsSource.items.length) {
//
for (var i = 0; i < widget.componentsSource.items.length; i++) {
widget.componentsSource.items[i].isSelected = (i == rowIndex);
}
widget.componentsSource.notifyListeners();
widget.onSelectionChanged?.call(rowIndex, true);
}
}
},

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

@ -5,59 +5,118 @@ import 'package:win_text_editor/modules/uft_component/widgets/component_grid.dar @@ -5,59 +5,118 @@ import 'package:win_text_editor/modules/uft_component/widgets/component_grid.dar
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';
class UftComponentLeftSide extends StatelessWidget {
class UftComponentLeftSide extends StatefulWidget {
final UftComponentController controller;
const UftComponentLeftSide({super.key, required this.controller});
Widget _buildTextFieldRow(String label, String value) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('$label:'),
SizedBox(
width: 150,
@override
State<UftComponentLeftSide> createState() => _UftComponentLeftSideState();
}
class _UftComponentLeftSideState extends State<UftComponentLeftSide> {
final TextEditingController _searchController = TextEditingController();
final GlobalKey<ComponentGridState> _gridKey = GlobalKey();
final FocusNode _searchFocusNode = FocusNode(); //
Widget _buildSearchField() {
return SizedBox(
width: 400,
child: TextField(
controller: TextEditingController(text: value),
readOnly: true,
decoration: const InputDecoration(isDense: true, contentPadding: EdgeInsets.all(8)),
controller: _searchController,
focusNode: _searchFocusNode, //
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.all(8),
hintText: '输入名称或中文名查找',
suffixIcon: IconButton(icon: const Icon(Icons.search), onPressed: _handleSearch),
),
onSubmitted: (_) => _handleSearch(), //
),
],
);
}
void _handleSearch() {
final searchText = _searchController.text.trim();
if (searchText.isEmpty) return;
final source = widget.controller.componentsSource as ComponentSource;
final items = source.items;
//
int? foundIndex;
for (var i = 0; i < items.length; i++) {
if (items[i].chineseName.contains(searchText)) {
foundIndex = i;
break;
}
}
if (foundIndex == null) {
for (var i = 0; i < items.length; i++) {
if (items[i].name.contains(searchText)) {
foundIndex = i;
break;
}
}
}
if (foundIndex != null) {
//
for (var i = 0; i < items.length; i++) {
items[i].isSelected = (i == foundIndex);
}
source.notifyListeners();
//
_gridKey.currentState?.scrollToIndex(foundIndex);
//
widget.controller.updateComponentSelection(foundIndex, true);
} else {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('未找到匹配的记录')));
}
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const SizedBox(width: 8),
_buildTextFieldRow('名称', controller.componentName),
_buildTextFieldRow('中文名', controller.chineseName),
const Text(' 标准组件', style: TextStyle(fontWeight: FontWeight.bold)),
_buildSearchField(),
],
),
Expanded(
flex: 6,
flex: 3,
child: ComponentGrid(
componentsSource: controller.componentsSource as ComponentSource,
key: _gridKey,
componentsSource: widget.controller.componentsSource as ComponentSource,
onSelectionChanged: (index, isSelected) {
controller.updateFieldSelection(index, isSelected);
widget.controller.updateComponentSelection(index, isSelected);
},
),
),
Expanded(
flex: 3,
child: FieldsDataGrid(
fieldsSource: controller.fieldsSource as FieldsDataSource,
fieldsSource: widget.controller.fieldsSource as FieldsDataSource,
onSelectionChanged: (index, isSelected) {
controller.updateFieldSelection(index, isSelected);
widget.controller.updateFieldSelection(index, isSelected);
},
),
),
],
);
}
@override
void dispose() {
_searchController.dispose();
_searchFocusNode.dispose(); //
super.dispose();
}
}

2
win_text_editor/lib/modules/uft_component/widgets/uft_component_right_side.dart

@ -75,7 +75,7 @@ class _UftComponentRightSideState extends State<UftComponentRightSide> { @@ -75,7 +75,7 @@ class _UftComponentRightSideState extends State<UftComponentRightSide> {
}
Widget _buildCheckboxSection() {
final operations = ['获取记录', '获取记录数', '插入记录', '修改记录', '删除记录', '遍历记录'];
final operations = ['插入组件', '修改组件', '获取组件', '遍历组件', '组件大小', '尾部插入组件'];
return SizedBox(
width: double.infinity,

Loading…
Cancel
Save