添加ioc和自动任务

This commit is contained in:
2026-02-03 21:21:20 +08:00
parent 4a3e0d8391
commit 21052cf0a7
9 changed files with 2034 additions and 2 deletions

View File

@@ -1,7 +1,7 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QWidget, QScrollArea
from qfluentwidgets import (
BodyLabel, TitleLabel, HorizontalSeparator, PushButton, PrimaryPushButton,
LineEdit, SpinBox, DoubleSpinBox, CheckBox, TextEdit
LineEdit, SpinBox, DoubleSpinBox, CheckBox, TextEdit, ComboBox
)
from qfluentwidgets import theme, Theme
import yaml
@@ -76,12 +76,20 @@ class TaskConfigDialog(QDialog):
self.add_btn = PrimaryPushButton("创建新任务")
self.add_btn.setAutoDefault(False) # 禁止回车触发
self.add_btn.setDefault(False)
# 新增:预设任务按钮
self.preset_btn = PushButton("使用预设任务")
self.preset_btn.setAutoDefault(False)
self.preset_btn.setDefault(False)
self.del_btn = PushButton("删除当前任务")
self.del_btn.setAutoDefault(False) # 禁止回车触发
self.del_btn.setDefault(False)
self.add_btn.clicked.connect(self.add_task)
self.preset_btn.clicked.connect(self.add_preset_task)
self.del_btn.clicked.connect(self.delete_current_task)
btn_layout.addWidget(self.add_btn)
btn_layout.addWidget(self.preset_btn)
btn_layout.addWidget(self.del_btn)
btn_layout.addStretch() # 添加/删除靠左stretch在中间
@@ -135,6 +143,274 @@ class TaskConfigDialog(QDialog):
self.task_btn_layout.addWidget(btn)
self.task_btn_layout.addStretch()
def get_preset_tasks(self):
"""获取所有可用的预设任务"""
from app.tools.code_generator import CodeGenerator
task_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
preset_tasks = []
if not os.path.exists(task_dir):
return preset_tasks
for filename in os.listdir(task_dir):
if filename.endswith('.c') and not filename.endswith('.template'):
task_name = os.path.splitext(filename)[0]
preset_tasks.append(task_name)
return preset_tasks
def load_preset_task_config(self, task_name):
"""从 yaml 配置文件中加载预设任务的配置"""
try:
from app.tools.code_generator import CodeGenerator
template_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
config_file = os.path.join(template_dir, "task.yaml")
if not os.path.exists(config_file):
return None
with open(config_file, 'r', encoding='utf-8') as f:
config_data = yaml.safe_load(f)
if config_data and task_name in config_data:
return config_data[task_name]
return None
except Exception as e:
print(f"加载预设任务配置失败: {e}")
return None
def load_preset_task_code(self, task_name):
"""加载预设任务的代码内容"""
from app.tools.code_generator import CodeGenerator
task_dir = CodeGenerator.get_assets_dir("User_code/task/template_task")
task_file = os.path.join(task_dir, f"{task_name}.c")
if os.path.exists(task_file):
with open(task_file, 'r', encoding='utf-8') as f:
return f.read()
return None
def add_preset_task(self):
"""添加预设任务"""
preset_tasks = self.get_preset_tasks()
if not preset_tasks:
InfoBar.warning(
title="无预设任务",
content="未找到可用的预设任务模板",
parent=self,
duration=2000
)
return
# 创建自适应主题的对话框
dialog = QDialog(self)
dialog.setWindowTitle("选择预设任务")
dialog.resize(600, 500)
dialog.setModal(True)
layout = QVBoxLayout(dialog)
layout.setContentsMargins(24, 24, 24, 24)
layout.setSpacing(18)
# 固定内容区域
fixed_content = QWidget()
fixed_content.setFixedHeight(180) # 减少固定高度
fixed_layout = QVBoxLayout(fixed_content)
fixed_layout.setContentsMargins(0, 0, 0, 0)
fixed_layout.setSpacing(18)
# 标题
title_label = TitleLabel("选择预设任务模板")
fixed_layout.addWidget(title_label)
# 说明文字
desc_label = BodyLabel("选择一个预设任务模板,系统将自动复制相应的代码和配置")
fixed_layout.addWidget(desc_label)
fixed_layout.addWidget(HorizontalSeparator())
# 任务选择
select_layout = QHBoxLayout()
select_layout.setSpacing(12)
select_label = BodyLabel("预设任务:")
preset_combo = ComboBox()
preset_combo.addItems(preset_tasks)
preset_combo.setCurrentIndex(0)
preset_combo.setMinimumWidth(160)
select_layout.addWidget(select_label)
select_layout.addWidget(preset_combo)
select_layout.addStretch()
fixed_layout.addLayout(select_layout)
# 参数信息 - 单行显示
params_layout = QHBoxLayout()
params_layout.setSpacing(24) # 适中的间距
self.info_freq = BodyLabel("")
self.info_delay = BodyLabel("")
self.info_stack = BodyLabel("")
self.info_ctrl = BodyLabel("")
self.info_freq.setMinimumWidth(120)
self.info_delay.setMinimumWidth(100)
self.info_stack.setMinimumWidth(120)
self.info_ctrl.setMinimumWidth(100)
params_layout.addWidget(self.info_freq)
params_layout.addWidget(self.info_delay)
params_layout.addWidget(self.info_stack)
params_layout.addWidget(self.info_ctrl)
params_layout.addStretch()
fixed_layout.addLayout(params_layout)
fixed_layout.addStretch() # 在固定区域内保持紧凑
layout.addWidget(fixed_content)
# 弹性描述区域
desc_layout = QVBoxLayout()
desc_layout.setSpacing(8)
desc_title = BodyLabel("描述:")
desc_title.setStyleSheet("font-weight: bold;")
desc_layout.addWidget(desc_title)
self.preview_desc = TextEdit()
self.preview_desc.setReadOnly(True)
self.preview_desc.setMinimumHeight(60) # 最小高度
desc_layout.addWidget(self.preview_desc)
layout.addLayout(desc_layout, stretch=1) # 弹性伸缩
# 按钮区域
layout.addWidget(HorizontalSeparator())
btn_layout = QHBoxLayout()
btn_layout.addStretch()
cancel_btn = PushButton("取消")
ok_btn = PrimaryPushButton("确定添加")
cancel_btn.clicked.connect(dialog.reject)
ok_btn.clicked.connect(dialog.accept)
btn_layout.addWidget(cancel_btn)
btn_layout.addWidget(ok_btn)
layout.addLayout(btn_layout)
# 预览更新函数
def update_preview():
selected = preset_combo.currentText()
self.update_preset_preview(selected)
preset_combo.currentTextChanged.connect(update_preview)
# 存储对话框状态
self.current_preview_dialog = dialog
self.preview_combo = preset_combo
# 初始化预览
if preset_tasks:
update_preview()
# 显示对话框
if dialog.exec() == QDialog.Accepted:
selected_task = preset_combo.currentText()
self.save_form()
new_idx = len(self.tasks)
# 从配置文件加载预设任务参数
config = self.load_preset_task_config(selected_task)
if config:
new_task = self._make_task_obj({
"name": config.get("name", selected_task),
"frequency": config.get("frequency", 500),
"delay": config.get("delay", 0),
"stack": config.get("stack", 256),
"description": config.get("description", ""),
"freq_control": config.get("freq_control", True)
})
else:
new_task = self._make_task_obj({"name": selected_task})
new_task["preset_task"] = selected_task
self.tasks.append(new_task)
self.current_index = new_idx
self.refresh_task_btns()
self.show_task_form(self.tasks[self.current_index])
InfoBar.success(
title="添加成功",
content=f"已添加预设任务:{selected_task}",
parent=self,
duration=2000
)
def update_preset_preview(self, task_name):
"""更新预设任务预览信息"""
# 从配置加载信息
config = self.load_preset_task_config(task_name)
if config:
self.info_freq.setText(f"频率: {config.get('frequency', 500)} Hz")
self.info_delay.setText(f"延时: {config.get('delay', 0)} ms")
self.info_stack.setText(f"堆栈: {config.get('stack', 256)} Bytes")
freq_ctrl = "启用" if config.get('freq_control', True) else "禁用"
self.info_ctrl.setText(f"频率控制: {freq_ctrl}")
description = config.get('description', f'预设任务:{task_name}')
self.preview_desc.setText(description)
else:
self.info_freq.setText("频率: 500 Hz")
self.info_delay.setText("延时: 0 ms")
self.info_stack.setText("堆栈: 256 Bytes")
self.info_ctrl.setText("频率控制: 启用")
self.preview_desc.setText(f"预设任务:{task_name}")
def on_preset_task_selected(self, task_name):
"""预设任务选择事件(向后兼容)"""
pass
def get_preset_task_description(self, task_name):
"""获取预设任务的描述信息"""
# 首先尝试从 yaml 配置中获取描述
config = self.load_preset_task_config(task_name)
if config and 'description' in config:
return f"预设任务:{task_name}\n\n{config['description']}\n\n频率控制:{'启用' if config.get('freq_control', True) else '禁用'}\n运行频率:{config.get('frequency', 500)} Hz\n堆栈大小:{config.get('stack', 256)} Bytes\n初始延时:{config.get('delay', 0)} ms"
# 如果没有配置文件,则从代码注释中提取
try:
task_code = self.load_preset_task_code(task_name)
if task_code:
# 尝试从注释中提取描述
lines = task_code.split('\n')
description_lines = []
in_comment = False
for line in lines[:20]: # 只检查前20行
line = line.strip()
if line.startswith('/*'):
in_comment = True
if 'Task' in line and line != '/*':
description_lines.append(line.replace('/*', '').strip())
continue
elif line.endswith('*/'):
in_comment = False
break
elif in_comment and line and not line.startswith('*'):
description_lines.append(line)
if description_lines:
return '\n'.join(description_lines)
else:
return f"预设任务:{task_name}\n这是一个预定义的任务模板,包含完整的实现代码。"
else:
return f"预设任务:{task_name}\n无法读取任务描述。"
except Exception as e:
return f"预设任务:{task_name}\n读取描述时出现错误:{str(e)}"
def add_task(self):
self.save_form()
new_idx = len(self.tasks)
@@ -302,5 +578,10 @@ class TaskConfigDialog(QDialog):
}
if freq_ctrl:
task["frequency"] = freq
# 保留预设任务信息
if "preset_task" in t:
task["preset_task"] = t["preset_task"]
tasks.append(task)
return tasks