commit b16661ac91bf7005f8df4f3b511c9990cf2a9e05 Author: sonto lau Date: Sat Jan 31 17:32:00 2026 +0800 create project diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000..11b48e1 --- /dev/null +++ b/config/__init__.py @@ -0,0 +1,6 @@ +""" +配置模块 +""" +from .styles import DARK_THEME + +__all__ = ['DARK_THEME'] diff --git a/config/styles.py b/config/styles.py new file mode 100644 index 0000000..414c804 --- /dev/null +++ b/config/styles.py @@ -0,0 +1,363 @@ +# """ +# 样式定义模块 +# 包含深色主题样式 +# """ +# +DARK_THEME = """""" +# DARK_THEME = """ +# /* ==================== 全局样式 ==================== */ +# QMainWindow, QDialog { +# background: qlineargradient(x1:0, y1:0, x2:1, y2:1, +# stop:0 #0a0e27, stop:1 #1a1f3a); +# color: #e0e6ed; +# } +# +# QWidget { +# background-color: transparent; +# color: #e0e6ed; +# font-family: "Microsoft YaHei", "SimHei", Arial; +# font-size: 13px; +# } +# +# /* ==================== 面板样式 ==================== */ +# QFrame[frameShape="4"], +# QFrame[frameShape="5"] { +# background: rgba(30, 41, 59, 0.6); +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 12px; +# } +# +# /* ==================== 按钮样式 ==================== */ +# QPushButton { +# background: qlineargradient(x1:0, y1:0, x2:0, y2:1, +# stop:0 #3b82f6, stop:1 #2563eb); +# color: white; +# border: none; +# border-radius: 6px; +# padding: 8px 16px; +# font-weight: bold; +# min-height: 30px; +# } +# +# QPushButton:hover { +# background: qlineargradient(x1:0, y1:0, x2:0, y2:1, +# stop:0 #60a5fa, stop:1 #3b82f6); +# } +# +# QPushButton:pressed { +# background: #2563eb; +# } +# +# QPushButton:disabled { +# background: rgba(51, 65, 85, 0.5); +# color: #64748b; +# } +# +# /* ==================== 输入框样式 ==================== */ +# QLineEdit, QTextEdit, QPlainTextEdit { +# background: rgba(51, 65, 85, 0.5); +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 6px; +# padding: 8px; +# color: #e0e6ed; +# selection-background-color: #3b82f6; +# } +# +# QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus { +# border: 1px solid #3b82f6; +# background: rgba(51, 65, 85, 0.7); +# } +# +# /* ==================== 下拉框样式 ==================== */ +# QComboBox { +# background: rgba(51, 65, 85, 0.5); +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 6px; +# padding: 6px; +# color: #e0e6ed; +# min-height: 30px; +# } +# +# QComboBox:hover { +# border: 1px solid rgba(59, 130, 246, 0.4); +# } +# +# QComboBox::drop-down { +# border: none; +# width: 30px; +# } +# +# QComboBox QAbstractItemView { +# background: rgba(30, 41, 59, 0.95); +# border: 1px solid rgba(59, 130, 246, 0.3); +# border-radius: 6px; +# selection-background-color: rgba(59, 130, 246, 0.3); +# color: #e0e6ed; +# } +# +# /* ==================== 列表样式 ==================== */ +# QListWidget, QTreeWidget { +# background: rgba(30, 41, 59, 0.4); +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 8px; +# color: #e0e6ed; +# outline: none; +# } +# +# QListWidget::item, QTreeWidget::item { +# padding: 8px; +# border-radius: 4px; +# border: none; +# } +# +# QListWidget::item:hover, QTreeWidget::item:hover { +# background: rgba(59, 130, 246, 0.15); +# } +# +# QListWidget::item:selected, QTreeWidget::item:selected { +# background: rgba(59, 130, 246, 0.3); +# border-left: 3px solid #3b82f6; +# } +# +# /* ==================== 标签页样式 ==================== */ +# QTabWidget::pane { +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 8px; +# background: rgba(30, 41, 59, 0.4); +# top: -1px; +# } +# +# QTabBar::tab { +# background: rgba(51, 65, 85, 0.4); +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-bottom: none; +# border-radius: 6px 6px 0 0; +# padding: 8px 16px; +# margin-right: 4px; +# color: #94a3b8; +# min-width: 80px; +# } +# +# QTabBar::tab:hover { +# background: rgba(59, 130, 246, 0.15); +# color: #e0e6ed; +# } +# +# QTabBar::tab:selected { +# background: qlineargradient(x1:0, y1:0, x2:0, y2:1, +# stop:0 #3b82f6, stop:1 #2563eb); +# color: white; +# border-color: #3b82f6; +# } +# +# /* ==================== 进度条样式 ==================== */ +# QProgressBar { +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 4px; +# background: rgba(51, 65, 85, 0.5); +# text-align: center; +# color: #e0e6ed; +# height: 20px; +# } +# +# QProgressBar::chunk { +# background: qlineargradient(x1:0, y1:0, x2:1, y2:0, +# stop:0 #3b82f6, stop:1 #06b6d4); +# border-radius: 3px; +# } +# +# /* ==================== 复选框样式 ==================== */ +# QCheckBox { +# color: #e0e6ed; +# spacing: 8px; +# } +# +# QCheckBox::indicator { +# width: 18px; +# height: 18px; +# border: 2px solid rgba(59, 130, 246, 0.4); +# border-radius: 4px; +# background: rgba(51, 65, 85, 0.5); +# } +# +# QCheckBox::indicator:hover { +# border-color: rgba(59, 130, 246, 0.6); +# } +# +# QCheckBox::indicator:checked { +# background: #3b82f6; +# border-color: #3b82f6; +# } +# +# /* ==================== 单选框样式 ==================== */ +# QRadioButton { +# color: #e0e6ed; +# spacing: 8px; +# } +# +# QRadioButton::indicator { +# width: 18px; +# height: 18px; +# border: 2px solid rgba(59, 130, 246, 0.4); +# border-radius: 9px; +# background: rgba(51, 65, 85, 0.5); +# } +# +# QRadioButton::indicator:hover { +# border-color: rgba(59, 130, 246, 0.6); +# } +# +# QRadioButton::indicator:checked { +# background: #3b82f6; +# border-color: #3b82f6; +# } +# +# /* ==================== 滚动条样式 ==================== */ +# QScrollBar:vertical { +# border: none; +# background: rgba(30, 41, 59, 0.3); +# width: 10px; +# border-radius: 5px; +# margin: 0; +# } +# +# QScrollBar::handle:vertical { +# background: rgba(59, 130, 246, 0.4); +# border-radius: 5px; +# min-height: 30px; +# } +# +# QScrollBar::handle:vertical:hover { +# background: rgba(59, 130, 246, 0.6); +# } +# +# QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { +# height: 0px; +# } +# +# QScrollBar:horizontal { +# border: none; +# background: rgba(30, 41, 59, 0.3); +# height: 10px; +# border-radius: 5px; +# margin: 0; +# } +# +# QScrollBar::handle:horizontal { +# background: rgba(59, 130, 246, 0.4); +# border-radius: 5px; +# min-width: 30px; +# } +# +# QScrollBar::handle:horizontal:hover { +# background: rgba(59, 130, 246, 0.6); +# } +# +# QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { +# width: 0px; +# } +# +# /* ==================== 分组框样式 ==================== */ +# QGroupBox { +# border: 1px solid rgba(59, 130, 246, 0.2); +# border-radius: 8px; +# margin-top: 12px; +# padding-top: 12px; +# color: #60a5fa; +# font-weight: bold; +# } +# +# QGroupBox::title { +# subcontrol-origin: margin; +# subcontrol-position: top left; +# padding: 0 8px; +# } +# +# /* ==================== 工具栏样式 ==================== */ +# QToolBar { +# background: rgba(15, 23, 42, 0.8); +# border: none; +# border-bottom: 2px solid rgba(59, 130, 246, 0.3); +# spacing: 8px; +# padding: 8px; +# } +# +# QToolBar::separator { +# background: rgba(59, 130, 246, 0.3); +# width: 1px; +# margin: 0 8px; +# } +# +# QToolButton { +# background: transparent; +# border: none; +# border-radius: 4px; +# padding: 6px; +# color: #e0e6ed; +# } +# +# QToolButton:hover { +# background: rgba(59, 130, 246, 0.2); +# } +# +# QToolButton:pressed { +# background: rgba(59, 130, 246, 0.3); +# } +# +# /* ==================== 状态栏样式 ==================== */ +# QStatusBar { +# background: rgba(15, 23, 42, 0.8); +# border-top: 1px solid rgba(59, 130, 246, 0.2); +# color: #94a3b8; +# } +# +# /* ==================== 菜单样式 ==================== */ +# QMenu { +# background: rgba(30, 41, 59, 0.95); +# border: 1px solid rgba(59, 130, 246, 0.3); +# border-radius: 8px; +# padding: 5px; +# } +# +# QMenu::item { +# padding: 8px 30px 8px 20px; +# border-radius: 4px; +# color: #e0e6ed; +# } +# +# QMenu::item:selected { +# background: rgba(59, 130, 246, 0.3); +# } +# +# QMenu::separator { +# height: 1px; +# background: rgba(59, 130, 246, 0.2); +# margin: 5px 10px; +# } +# +# /* ==================== 分割器样式 ==================== */ +# QSplitter::handle { +# background: rgba(59, 130, 246, 0.2); +# } +# +# QSplitter::handle:hover { +# background: rgba(59, 130, 246, 0.4); +# } +# +# QSplitter::handle:horizontal { +# width: 2px; +# } +# +# QSplitter::handle:vertical { +# height: 2px; +# } +# +# /* ==================== 工具提示样式 ==================== */ +# QToolTip { +# background: rgba(30, 41, 59, 0.95); +# border: 1px solid rgba(59, 130, 246, 0.3); +# border-radius: 6px; +# padding: 5px; +# color: #e0e6ed; +# } +# """ diff --git a/dialogs/__init__.py b/dialogs/__init__.py new file mode 100644 index 0000000..00474f1 --- /dev/null +++ b/dialogs/__init__.py @@ -0,0 +1,14 @@ +""" +对话框模块 +""" +from .new_project_dialog import NewProjectDialog +from .code_view_dialog import CodeViewDialog +from .module_detail_dialog import ModuleDetailDialog +from .pipeline_dialog import PipelineDialog + +__all__ = [ + 'NewProjectDialog', + 'CodeViewDialog', + 'ModuleDetailDialog', + 'PipelineDialog' +] diff --git a/dialogs/code_view_dialog.py b/dialogs/code_view_dialog.py new file mode 100644 index 0000000..fced676 --- /dev/null +++ b/dialogs/code_view_dialog.py @@ -0,0 +1,351 @@ +""" +代码查看对话框 +""" +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QHBoxLayout, QLabel, + QTextEdit, QPushButton, QMessageBox, QFileDialog, QApplication +) +from PyQt5.QtCore import Qt + + +class CodeViewDialog(QDialog): + """代码查看对话框""" + + def __init__(self, file_name: str, parent=None): + """ + 初始化对话框 + + Args: + file_name: 文件名 + parent: 父窗口 + """ + super().__init__(parent) + self.file_name = file_name + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + self.setWindowTitle(f"代码查看 - {self.file_name}") + self.resize(900, 600) + + layout = QVBoxLayout(self) + layout.setSpacing(10) + + # 工具栏 + toolbar = QHBoxLayout() + + file_label = QLabel(f"📄 {self.file_name}") + file_label.setStyleSheet(""" + font-weight: bold; + color: #60a5fa; + font-size: 14px; + """) + toolbar.addWidget(file_label) + + toolbar.addStretch() + + copy_btn = QPushButton("📋 复制代码") + copy_btn.clicked.connect(self._copy_code) + toolbar.addWidget(copy_btn) + + download_btn = QPushButton("⬇ 下载") + download_btn.clicked.connect(self._download_code) + toolbar.addWidget(download_btn) + + layout.addLayout(toolbar) + + # 代码编辑器 + self.code_editor = QTextEdit() + self.code_editor.setReadOnly(True) + self.code_editor.setStyleSheet(""" + QTextEdit { + background: #1e293b; + color: #e0e6ed; + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; + font-size: 13px; + border: 1px solid rgba(59, 130, 246, 0.2); + border-radius: 8px; + padding: 15px; + line-height: 1.5; + } + """) + + # 生成示例代码 + sample_code = self._generate_sample_code() + self.code_editor.setPlainText(sample_code) + + layout.addWidget(self.code_editor) + + # 关闭按钮 + close_btn = QPushButton("关闭") + close_btn.clicked.connect(self.accept) + layout.addWidget(close_btn) + + def _generate_sample_code(self) -> str: + """生成示例代码""" + if self.file_name.endswith('.java'): + return self._get_java_sample() + elif self.file_name.endswith('.py'): + return self._get_python_sample() + elif self.file_name.endswith('.xml'): + return self._get_xml_sample() + else: + return f"# {self.file_name}\n\n这是一个示例文件的内容。" + + def _get_java_sample(self) -> str: + """获取Java示例代码""" + return '''package com.example.project; + +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; + +/** + * 示例控制器 + * + * @author AI Generator + * @version 1.0 + * @date 2024-01-15 + */ +@RestController +@RequestMapping("/api/v1") +public class ExampleController { + + @Autowired + private ExampleService exampleService; + + /** + * 获取数据 + * + * @param id 数据ID + * @return 响应结果 + */ + @GetMapping("/data/{id}") + public ResponseEntity getData(@PathVariable Long id) { + try { + DataResponse data = exampleService.getDataById(id); + return ResponseEntity.ok(data); + } catch (Exception e) { + return ResponseEntity.internalServerError().build(); + } + } + + /** + * 创建数据 + * + * @param request 请求参数 + * @return 响应结果 + */ + @PostMapping("/data") + public ResponseEntity createData(@RequestBody DataRequest request) { + DataResponse data = exampleService.createData(request); + return ResponseEntity.ok(data); + } + + /** + * 更新数据 + * + * @param id 数据ID + * @param request 请求参数 + * @return 响应结果 + */ + @PutMapping("/data/{id}") + public ResponseEntity updateData( + @PathVariable Long id, + @RequestBody DataRequest request) { + DataResponse data = exampleService.updateData(id, request); + return ResponseEntity.ok(data); + } + + /** + * 删除数据 + * + * @param id 数据ID + * @return 响应结果 + */ + @DeleteMapping("/data/{id}") + public ResponseEntity deleteData(@PathVariable Long id) { + exampleService.deleteData(id); + return ResponseEntity.ok().build(); + } +}''' + + def _get_python_sample(self) -> str: + """获取Python示例代码""" + return '''#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +示例模块 + +Author: AI Generator +Version: 1.0 +Date: 2024-01-15 +""" + +from flask import Flask, jsonify, request +from typing import Dict, Any + +app = Flask(__name__) + + +@app.route('/api/v1/data/', methods=['GET']) +def get_data(data_id: int) -> Dict[str, Any]: + """ + 获取数据 + + Args: + data_id: 数据ID + + Returns: + 响应数据 + """ + try: + # 实现逻辑 + return jsonify({ + 'id': data_id, + 'status': 'success', + 'data': {} + }) + except Exception as e: + return jsonify({ + 'status': 'error', + 'message': str(e) + }), 500 + + +@app.route('/api/v1/data', methods=['POST']) +def create_data() -> Dict[str, Any]: + """ + 创建数据 + + Returns: + 响应数据 + """ + data = request.get_json() + + # 实现逻辑 + return jsonify({ + 'status': 'success', + 'data': data + }) + + +@app.route('/api/v1/data/', methods=['PUT']) +def update_data(data_id: int) -> Dict[str, Any]: + """ + 更新数据 + + Args: + data_id: 数据ID + + Returns: + 响应数据 + """ + data = request.get_json() + + # 实现逻辑 + return jsonify({ + 'id': data_id, + 'status': 'success', + 'data': data + }) + + +@app.route('/api/v1/data/', methods=['DELETE']) +def delete_data(data_id: int) -> Dict[str, Any]: + """ + 删除数据 + + Args: + data_id: 数据ID + + Returns: + 响应数据 + """ + # 实现逻辑 + return jsonify({ + 'status': 'success', + 'message': 'Data deleted' + }) + + +if __name__ == '__main__': + app.run(debug=True, host='0.0.0.0', port=5000)''' + + def _get_xml_sample(self) -> str: + """获取XML示例代码""" + return ''' + + 4.0.0 + + com.example + lowcode-project + 1.0.0 + jar + + LowCode Project + AI Generated Project + + + org.springframework.boot + spring-boot-starter-parent + 2.7.0 + + + + 17 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + +''' + + def _copy_code(self): + """复制代码""" + clipboard = QApplication.clipboard() + clipboard.setText(self.code_editor.toPlainText()) + QMessageBox.information(self, "复制", "代码已复制到剪贴板") + + def _download_code(self): + """下载代码""" + file_path, _ = QFileDialog.getSaveFileName( + self, + "保存代码", + self.file_name + ) + + if file_path: + try: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(self.code_editor.toPlainText()) + QMessageBox.information(self, "下载", f"代码已保存到:\n{file_path}") + except Exception as e: + QMessageBox.critical(self, "错误", f"保存失败:\n{str(e)}") diff --git a/dialogs/module_detail_dialog.py b/dialogs/module_detail_dialog.py new file mode 100644 index 0000000..d509af4 --- /dev/null +++ b/dialogs/module_detail_dialog.py @@ -0,0 +1,167 @@ +""" +模块详情对话框 +""" +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QHBoxLayout, QLabel, + QPushButton, QProgressBar, QGroupBox +) +from PyQt5.QtCore import Qt + + +class ModuleDetailDialog(QDialog): + """模块详情对话框""" + + def __init__(self, module, parent=None): + """ + 初始化对话框 + + Args: + module: 模块对象 + parent: 父窗口 + """ + super().__init__(parent) + self.module = module + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + self.setWindowTitle(f"模块详情 - {self.module.name}") + self.resize(600, 500) + + layout = QVBoxLayout(self) + layout.setSpacing(20) + + # 模块标题 + title_label = QLabel(f"

{self.module.icon} {self.module.name}

") + layout.addWidget(title_label) + + # 基本信息组 + basic_group = self._create_basic_info_group() + layout.addWidget(basic_group) + + # 关联需求组 + req_group = self._create_requirements_group() + layout.addWidget(req_group) + + # 技术栈组 + tech_group = self._create_tech_stack_group() + layout.addWidget(tech_group) + + # 开发进度组 + progress_group = self._create_progress_group() + layout.addWidget(progress_group) + + layout.addStretch() + + # 关闭按钮 + button_layout = QHBoxLayout() + button_layout.addStretch() + + close_btn = QPushButton("关闭") + close_btn.setMinimumWidth(100) + close_btn.clicked.connect(self.accept) + button_layout.addWidget(close_btn) + + layout.addLayout(button_layout) + + def _create_basic_info_group(self) -> QGroupBox: + """创建基本信息组""" + group = QGroupBox("基本信息") + layout = QVBoxLayout(group) + + # 描述 + desc_label = QLabel(f"描述:
{self.module.description}") + desc_label.setWordWrap(True) + desc_label.setStyleSheet("color: #e0e6ed; padding: 5px;") + layout.addWidget(desc_label) + + return group + + def _create_requirements_group(self) -> QGroupBox: + """创建关联需求组""" + group = QGroupBox("关联需求") + layout = QVBoxLayout(group) + + if self.module.requirements: + req_layout = QHBoxLayout() + req_layout.setSpacing(8) + + for req_id in self.module.requirements: + req_label = QLabel(req_id) + req_label.setStyleSheet(""" + background: #3b82f633; + color: #3b82f6; + border: 1px solid #3b82f6; + border-radius: 4px; + padding: 4px 10px; + font-size: 12px; + """) + req_layout.addWidget(req_label) + + req_layout.addStretch() + layout.addLayout(req_layout) + else: + no_req_label = QLabel("暂无关联需求") + no_req_label.setStyleSheet("color: #94a3b8;") + layout.addWidget(no_req_label) + + return group + + def _create_tech_stack_group(self) -> QGroupBox: + """创建技术栈组""" + group = QGroupBox("技术栈") + layout = QVBoxLayout(group) + + if self.module.tech_stack: + tech_layout = QHBoxLayout() + tech_layout.setSpacing(8) + + for tech in self.module.tech_stack: + tech_label = QLabel(tech) + tech_label.setStyleSheet(""" + background: rgba(100, 116, 139, 0.3); + color: #94a3b8; + border: 1px solid rgba(100, 116, 139, 0.5); + border-radius: 4px; + padding: 4px 10px; + font-size: 12px; + """) + tech_layout.addWidget(tech_label) + + tech_layout.addStretch() + layout.addLayout(tech_layout) + else: + no_tech_label = QLabel("暂无技术栈信息") + no_tech_label.setStyleSheet("color: #94a3b8;") + layout.addWidget(no_tech_label) + + return group + + def _create_progress_group(self) -> QGroupBox: + """创建开发进度组""" + group = QGroupBox("开发进度") + layout = QVBoxLayout(group) + + # 进度条 + progress = QProgressBar() + progress.setValue(self.module.progress) + progress.setTextVisible(True) + progress.setFormat(f"{self.module.progress}%") + layout.addWidget(progress) + + # 状态说明 + if self.module.progress == 0: + status_text = "尚未开始" + status_color = "#94a3b8" + elif self.module.progress < 100: + status_text = "开发中" + status_color = "#3b82f6" + else: + status_text = "已完成" + status_color = "#10b981" + + status_label = QLabel(f"状态: {status_text}") + status_label.setStyleSheet(f"color: {status_color}; font-weight: bold;") + layout.addWidget(status_label) + + return group diff --git a/dialogs/new_project_dialog.py b/dialogs/new_project_dialog.py new file mode 100644 index 0000000..8b5e994 --- /dev/null +++ b/dialogs/new_project_dialog.py @@ -0,0 +1,153 @@ +""" +新建项目对话框 +""" +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QHBoxLayout, QLabel, + QLineEdit, QTextEdit, QPushButton, QMessageBox +) +from PyQt5.QtCore import Qt +from models import Project, Requirement, Module, Document + + +class NewProjectDialog(QDialog): + """新建项目对话框""" + + def __init__(self, parent=None): + """ + 初始化对话框 + + Args: + parent: 父窗口 + """ + super().__init__(parent) + self.project = None + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + self.setWindowTitle("新建项目") + self.setModal(True) + self.resize(700, 500) + + layout = QVBoxLayout(self) + layout.setSpacing(15) + + # 标题 + title_label = QLabel("

📁 新建项目

") + layout.addWidget(title_label) + + # 项目名称 + layout.addWidget(QLabel("项目名称 *")) + self.name_edit = QLineEdit() + self.name_edit.setPlaceholderText("请输入项目名称") + layout.addWidget(self.name_edit) + + # 项目描述 + layout.addWidget(QLabel("项目描述")) + self.desc_edit = QTextEdit() + self.desc_edit.setPlaceholderText("请输入项目描述(可选)") + self.desc_edit.setMaximumHeight(80) + layout.addWidget(self.desc_edit) + + # 需求描述 + layout.addWidget(QLabel("需求描述 *")) + self.req_edit = QTextEdit() + self.req_edit.setPlaceholderText( + "请输入项目需求...\n\n" + "建议格式:\n" + "1. 功能描述\n" + "2. 性能要求\n" + "3. 安全要求" + ) + layout.addWidget(self.req_edit) + + # 按钮区域 + button_layout = QHBoxLayout() + button_layout.addStretch() + + cancel_btn = QPushButton("取消") + cancel_btn.setStyleSheet(""" + QPushButton { + background: rgba(51, 65, 85, 0.5); + border: 1px solid rgba(59, 130, 246, 0.2); + } + """) + cancel_btn.clicked.connect(self.reject) + button_layout.addWidget(cancel_btn) + + create_btn = QPushButton("创建项目") + create_btn.clicked.connect(self._create_project) + button_layout.addWidget(create_btn) + + layout.addLayout(button_layout) + + def _create_project(self): + """创建项目""" + # 验证输入 + name = self.name_edit.text().strip() + if not name: + QMessageBox.warning(self, "提示", "请输入项目名称") + return + + req_text = self.req_edit.toPlainText().strip() + if not req_text: + QMessageBox.warning(self, "提示", "请输入需求描述") + return + + # 创建项目对象 + self.project = Project( + name=name, + description=self.desc_edit.toPlainText().strip() + ) + self.project.original_requirement = req_text + + # 模拟生成需求 + self._generate_requirements() + + # 模拟生成模块 + self._generate_modules() + + # 模拟生成文档 + self._generate_documents() + + self.accept() + + def _generate_requirements(self): + """生成需求(模拟AI分析)""" + requirements = [ + Requirement("REQ-001", "核心功能", "从需求文本提取的核心功能", 90, "高"), + Requirement("REQ-002", "数据管理", "数据的增删改查功能", 85, "中"), + Requirement("REQ-003", "用户管理", "用户认证和权限管理", 88, "高") + ] + + for req in requirements: + self.project.add_requirement(req) + + def _generate_modules(self): + """生成模块(模拟AI生成)""" + modules = [ + Module("核心业务模块", "实现主要业务逻辑", ["REQ-001"]), + Module("数据管理模块", "数据存储和查询", ["REQ-002"]), + Module("用户认证模块", "用户登录和权限控制", ["REQ-003"]) + ] + + for module in modules: + module.add_tech("Spring Boot") + module.add_tech("MySQL") + module.add_tech("Redis") + self.project.add_module(module) + + def _generate_documents(self): + """生成文档""" + documents = [ + Document("需求规格说明书.docx", "SRS", "1.5 MB"), + Document("功能设计文档.docx", "功能设计", "1.2 MB"), + Document("接口文档.pdf", "API", "800 KB") + ] + + for doc in documents: + self.project.add_document(doc) + + def get_project(self): + """获取创建的项目""" + return self.project diff --git a/dialogs/pipeline_dialog.py b/dialogs/pipeline_dialog.py new file mode 100644 index 0000000..8589aca --- /dev/null +++ b/dialogs/pipeline_dialog.py @@ -0,0 +1,300 @@ +""" +流水线执行对话框 +""" +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QHBoxLayout, QLabel, + QTextEdit, QPushButton, QProgressBar, QFrame, QMessageBox +) +from PyQt5.QtCore import Qt, QTimer +from datetime import datetime + + +class PipelineDialog(QDialog): + """流水线执行对话框""" + + def __init__(self, project, parent=None): + """ + 初始化对话框 + + Args: + project: 项目对象 + parent: 父窗口 + """ + super().__init__(parent) + self.project = project + self.current_step = 0 + self.timer = None + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + self.setWindowTitle(f"流水线 - {self.project.name}") + self.resize(1000, 600) + + layout = QVBoxLayout(self) + layout.setSpacing(15) + + # 标题 + title_label = QLabel(f"

🚀 项目流水线 - {self.project.name}

") + layout.addWidget(title_label) + + # 流水线步骤 + steps_layout = QHBoxLayout() + steps_layout.setSpacing(10) + + self.step_widgets = [] + steps = [ + ("🔍", "静态扫描", "SonarQube"), + ("🔨", "编译构建", "Maven"), + ("📦", "打包", "JAR"), + ("🚀", "部署", "测试环境"), + ("✅", "验证测试", "JUnit") + ] + + for icon, name, tool in steps: + step_widget = self._create_step_widget(icon, name, tool) + self.step_widgets.append(step_widget) + steps_layout.addWidget(step_widget) + + layout.addLayout(steps_layout) + + # 日志输出区域 + log_label = QLabel("执行日志:") + layout.addWidget(log_label) + + self.log_text = QTextEdit() + self.log_text.setReadOnly(True) + self.log_text.setStyleSheet(""" + QTextEdit { + background: #1e293b; + color: #10b981; + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; + font-size: 12px; + border: 1px solid rgba(59, 130, 246, 0.2); + border-radius: 8px; + padding: 10px; + } + """) + layout.addWidget(self.log_text) + + # 总体进度条 + self.progress = QProgressBar() + self.progress.setTextVisible(True) + self.progress.setFormat("%p%") + layout.addWidget(self.progress) + + # 按钮区域 + button_layout = QHBoxLayout() + button_layout.addStretch() + + self.start_btn = QPushButton("▶ 启动流水线") + self.start_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #10b981, stop:1 #059669); + } + """) + self.start_btn.setMinimumWidth(120) + self.start_btn.clicked.connect(self._start_pipeline) + button_layout.addWidget(self.start_btn) + + self.stop_btn = QPushButton("⏹ 停止") + self.stop_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #ef4444, stop:1 #dc2626); + } + """) + self.stop_btn.setMinimumWidth(120) + self.stop_btn.setEnabled(False) + self.stop_btn.clicked.connect(self._stop_pipeline) + button_layout.addWidget(self.stop_btn) + + close_btn = QPushButton("关闭") + close_btn.setMinimumWidth(120) + close_btn.clicked.connect(self.accept) + button_layout.addWidget(close_btn) + + layout.addLayout(button_layout) + + def _create_step_widget(self, icon: str, name: str, tool: str) -> QFrame: + """创建步骤组件""" + widget = QFrame() + widget.setFrameShape(QFrame.StyledPanel) + widget.setStyleSheet(""" + QFrame { + background: rgba(51, 65, 85, 0.4); + border: 1px solid rgba(59, 130, 246, 0.2); + border-radius: 8px; + padding: 15px; + } + """) + + layout = QVBoxLayout(widget) + layout.setAlignment(Qt.AlignCenter) + layout.setSpacing(8) + + # 图标 + icon_label = QLabel(icon) + icon_label.setStyleSheet("font-size: 36px;") + icon_label.setAlignment(Qt.AlignCenter) + layout.addWidget(icon_label) + + # 步骤名称 + name_label = QLabel(name) + name_label.setStyleSheet(""" + font-weight: bold; + font-size: 14px; + color: #e0e6ed; + """) + name_label.setAlignment(Qt.AlignCenter) + layout.addWidget(name_label) + + # 工具名称 + tool_label = QLabel(tool) + tool_label.setStyleSheet(""" + color: #94a3b8; + font-size: 11px; + """) + tool_label.setAlignment(Qt.AlignCenter) + layout.addWidget(tool_label) + + # 状态标签 + status_label = QLabel("就绪") + status_label.setObjectName("status_label") + status_label.setStyleSheet(""" + color: #94a3b8; + font-size: 12px; + """) + status_label.setAlignment(Qt.AlignCenter) + layout.addWidget(status_label) + + return widget + + def _start_pipeline(self): + """启动流水线""" + self.start_btn.setEnabled(False) + self.stop_btn.setEnabled(True) + self.current_step = 0 + self.progress.setValue(0) + self.log_text.clear() + + self._add_log("[INFO] ========================================") + self._add_log(f"[INFO] 流水线启动 - 项目: {self.project.name}") + self._add_log("[INFO] ========================================") + + # 使用定时器模拟流水线执行 + self.timer = QTimer() + self.timer.timeout.connect(self._update_pipeline) + self.timer.start(1500) # 每1.5秒执行一步 + + def _update_pipeline(self): + """更新流水线状态""" + if self.current_step < len(self.step_widgets): + widget = self.step_widgets[self.current_step] + + # 更新为进行中状态 + widget.setStyleSheet(""" + QFrame { + background: rgba(59, 130, 246, 0.3); + border: 2px solid #3b82f6; + border-radius: 8px; + padding: 15px; + } + """) + + # 更新状态标签 + status_label = widget.findChild(QLabel, "status_label") + if status_label: + status_label.setText("进行中...") + status_label.setStyleSheet(""" + color: #3b82f6; + font-size: 12px; + font-weight: bold; + """) + + # 添加日志 + step_names = ["静态扫描", "编译构建", "打包", "部署", "验证测试"] + self._add_log(f"[INFO] 开始执行: {step_names[self.current_step]}") + self._add_log(f"[INFO] 步骤 {self.current_step + 1}/{len(self.step_widgets)}") + + # 更新进度条 + progress_value = int((self.current_step + 1) / len(self.step_widgets) * 100) + self.progress.setValue(progress_value) + + # 延迟标记为完成 + QTimer.singleShot(1000, lambda: self._complete_step(self.current_step)) + + self.current_step += 1 + else: + self.timer.stop() + self._finish_pipeline() + + def _complete_step(self, step_index: int): + """完成步骤""" + if step_index < len(self.step_widgets): + widget = self.step_widgets[step_index] + + # 更新为完成状态 + widget.setStyleSheet(""" + QFrame { + background: rgba(16, 185, 129, 0.2); + border: 2px solid #10b981; + border-radius: 8px; + padding: 15px; + } + """) + + # 更新状态标签 + status_label = widget.findChild(QLabel, "status_label") + if status_label: + status_label.setText("✓ 完成") + status_label.setStyleSheet(""" + color: #10b981; + font-size: 12px; + font-weight: bold; + """) + + # 添加完成日志 + step_names = ["静态扫描", "编译构建", "打包", "部署", "验证测试"] + self._add_log(f"[SUCCESS] {step_names[step_index]} 完成") + self._add_log("") + + def _finish_pipeline(self): + """完成流水线""" + self._add_log("[INFO] ========================================") + self._add_log("[SUCCESS] 流水线执行完成!") + self._add_log(f"[INFO] 项目: {self.project.name}") + self._add_log("[INFO] 所有步骤已成功执行") + self._add_log("[INFO] ========================================") + + self.start_btn.setEnabled(True) + self.stop_btn.setEnabled(False) + + QMessageBox.information( + self, + "完成", + f"流水线执行完成!\n\n项目: {self.project.name}\n所有步骤已成功执行。" + ) + + def _stop_pipeline(self): + """停止流水线""" + if self.timer: + self.timer.stop() + + self._add_log("") + self._add_log("[WARNING] ========================================") + self._add_log("[WARNING] 流水线已被用户停止") + self._add_log("[WARNING] ========================================") + + self.start_btn.setEnabled(True) + self.stop_btn.setEnabled(False) + + def _add_log(self, message: str): + """添加日志""" + timestamp = datetime.now().strftime("%H:%M:%S") + self.log_text.append(f"[{timestamp}] {message}") + + # 自动滚动到底部 + scrollbar = self.log_text.verticalScrollBar() + scrollbar.setValue(scrollbar.maximum()) diff --git a/index-3.html b/index-3.html new file mode 100644 index 0000000..1b3008f --- /dev/null +++ b/index-3.html @@ -0,0 +1,3167 @@ + + + + + + 装备履历本全生命周期管理系统 + + + + + + + + + + + + +
+ +
+
+
+

工作台

+

履历本全生命周期管理流程

+
+
+

当前时间

+

+
+
+ + +
+
+
+
+
+

产品总数

+

1,234

+
+
+ +
+
+
+
+
+
+
+
+

履历本总数

+

5,678

+
+
+ +
+
+
+
+
+
+
+
+

待审批

+

23

+

↑ +5

+
+
+ +
+
+
+
+
+
+
+
+

今日制作

+

45

+

↑ +12

+
+
+ +
+
+
+
+
+ + +
+
+
+ 履历本业务流程 +
+
+
+
+
+
+
+
+ +
+ +
+
新本制作
+

装备首次出厂履历本制作

+
    +
  • 产品信息
  • +
  • 数据录入
  • +
  • AI校验
  • +
  • 审批
  • +
  • 套打输出
  • +
+
+
+
+
+
+
+ +
+ +
+
扫描识别
+

纸质履历本数字化

+
    +
  • 放入扫描仪
  • +
  • 自动翻页
  • +
  • OCR识别
  • +
  • 数据提取
  • +
+
+
+
+
+
+
+ +
+ +
+
智能校验
+

AI智能规则校验

+
    +
  • 规则加载
  • +
  • 数据校验
  • +
  • 异常检测
  • +
  • 生成报告
  • +
+
+
+
+
+
+
+ +
+ +
+
版本对比
+

新旧版本差异分析

+
    +
  • 加载版本
  • +
  • 数据对比
  • +
  • 差异标注
  • +
  • 生成报告
  • +
+
+
+
+ +
+
+
+
+
+ +
+ +
+
副本修订
+

返厂修理履历本修订

+
    +
  • 扫描原本
  • +
  • 修订记录
  • +
  • 版本对比
  • +
  • 审批输出
  • +
+
+
+
+
+
+
+ +
+ +
+
审批流程
+

履历本审批管理

+
    +
  • 提交审批
  • +
  • 工艺审核
  • +
  • 技术审核
  • +
  • 质量审核
  • +
+
+
+
+
+
+
+ +
+ +
+
套打输出
+

自动套打打印

+
    +
  • 模板加载
  • +
  • 数据填充
  • +
  • 印章填充
  • +
  • 打印输出
  • +
+
+
+
+
+
+
+ +
+ +
+
数据管理
+

全生命周期数据管理

+
    +
  • 数据存储
  • +
  • 版本管理
  • +
  • 数据查询
  • +
  • 统计分析
  • +
+
+
+
+
+
+ + +
+
+
+
+
+ 待办事项 +
+
+
+
+
+
+
+ + XX-2024-001 履历本待审批 +
+ 2小时前 +
+ +
+
+
+
+
+
+ + XX-2024-002 校验异常待处理 +
+ 5小时前 +
+ +
+
+
+
+
+
+ + XX-2024-003 副本制作中 +
+ 1天前 +
+ +
+
+
+
+
+ +
+
+
+
+ 最近操作 +
+
+
+
+

+ 张三 制作履历本 + XX-2024-005 +

+ 10分钟前 +
+
+

+ 李四 审批通过 + XX-2024-004 +

+ 1小时前 +
+
+

+ 王五 扫描完成 + XX-2024-003 +

+ 2小时前 +
+
+
+
+
+
+ + +
+
+
+

产品管理

+

管理装备产品基本信息

+
+ +
+ +
+
+
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
产品型号产品编号交付主机厂履历本数量状态操作
XX-2024-00120240101001132厂3正常查看详情
XX-2024-00220240101002132厂6正常查看详情
XX-2024-00320240101003132厂9正常查看详情
XX-2024-00420240101004132厂12正常查看详情
XX-2024-00520240101005132厂15正常查看详情
+
+
+
+
+ + +
+
+

履历本制作

+

新本制作与副本修订

+
+ +
+
+
+
+
制作向导
+
+
+
+
+
1
+
+
+
+
2
+
+
+
+
3
+
+
+
+
4
+
+
+ +
+
步骤1:选择产品
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+
+ +
+
+
+
快速操作
+
+
+
+
+
新本制作
+ 装备首次出厂 +
+
+
+
+
副本修订
+ 返厂修理后 +
+
+
+
+ +
+
+
制作进度
+
+
+
+ 当前步骤 +
1/4 - 选择产品
+
+
+
+
+ 25% 完成 +
+
+
+
+
+ +
+
+

扫描管理

+

纸质履历本数字化扫描

+
+ +
+
+
+
+
设备状态
+
+
+
+
+
KABIS V系列扫描仪
+ 设备ID: SCAN-001 +
+ 在线 +
+ +
+
+
+ 今日扫描 +

156页

+
+
+
+
+ 识别率 +

99.2%

+
+
+
+ + + +
+
+
+ +
+
+
+
扫描任务
+
+
+
+
+ XX-2024-001 + 进行中 +
+
+
+
+ 30% 完成 · 已扫描 15/50 页 +
+ +
+
+ XX-2024-002 + 进行中 +
+
+
+
+ 60% 完成 · 已扫描 24/40 页 +
+ +
+
+ XX-2024-003 + 已完成 +
+
+
+
+ 100% 完成 · 已扫描 45/45 页 +
+
+
+
+
+ +
+
+
扫描历史
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
产品编号扫描时间页数识别率状态操作
XX-2024-0032026-01-13 14:30:004599.5%完成查看结果
XX-2024-0022026-01-13 13:20:004098.8%进行中查看进度
XX-2024-0012026-01-13 12:10:005099.2%进行中查看进度
+
+
+
+
+ + +
+
+

智能校验

+

AI智能规则校验与异常检测

+
+ +
+
+
+
+
+

通过

+

156

+
+
+ +
+
+
+
+
+
+
+
+

严重错误

+

3

+
+
+ +
+
+
+
+
+
+
+
+

警告

+

12

+
+
+ +
+
+
+
+
+
+
+
+

提示

+

8

+
+
+ +
+
+
+
+
+ +
+
+
+
校验配置
+ +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
校验详情
+
+
+
+
+
+
+ 严重 + 封面 - 日期逻辑错误 +
+

出厂日期(2026-01-10)早于性能测试日期(2026-01-11)

+

+ + 建议:修正出厂日期为2026-01-12或更晚 +

+
+ +
+
+ +
+
+
+
+ 严重 + 性能指标 - 数据超差 +
+

电压值(25.2V)超出允许范围(24V±0.5V)

+

+ + 建议:重新测试或确认数据准确性 +

+
+ +
+
+ +
+
+
+
+ 警告 + 验收证明 - 印章缺失 +
+

质检印章未填充

+

+ + 建议:补充质检人员印章 +

+
+ +
+
+ +
+
+
+
+ 提示 + 配套页 - 格式建议 +
+

配套件批次号格式建议统一为:YYYYMMDD-XXX

+

+ + 建议:按标准格式填写以便后续管理 +

+
+ +
+
+
+
+
+ + +
+
+

版本对比

+

新旧版本差异分析

+
+ +
+
+
版本选择
+
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+ +
+
+
+
+
对比统计
+
+
+
+
+ +
+

5

+ 修改项 +
+
+
+
+
+ +
+

3

+ 新增项 +
+
+
+
+
+ +
+

15

+ 未变化项 +
+
+
+
+
+
+ +
+
+
+
差异详情
+
+
+
+
+ 修改 +
封面 - 修订次数
+
+
+ 原值: + 0 + + 新值: + 1 +
+
+ +
+
+ 新增 +
修理记录 - 新增记录
+
+
+
+

修理日期:2026-03-10

+

修理内容:更换电源模块

+

修理人员:李四

+
+
+
+ +
+
+ 新增 +
换件记录 - 新增记录
+
+
+
+

换件日期:2026-03-10

+

换件名称:电源模块

+

旧件编号:PM-20240101

+

新件编号:PM-20260310

+
+
+
+ +
+
+ 修改 +
性能检查表 - 性能数据更新
+
+
+ 电压: + 24.2V + + 24.3V +
+
+ 电流: + 1.5A + + 1.6A +
+
+
+
+
+
+
+ + +
+
+

审批管理

+

履历本审批流程管理

+
+ +
+
+
+
+
+

待我审批

+

5

+
+
+ +
+
+
+
+
+
+
+
+

我已审批

+

23

+
+
+ +
+
+
+
+
+
+
+
+

审批中

+

12

+
+
+ +
+
+
+
+
+ +
+
+
待审批列表
+
+
+
+
+
+
XX-2024-001 履历本新本
+
+ 提交人: + 张三 + 提交时间: + 2026-01-12 10:30:00 +
+ 待审批 +
+
+
+ + + +
+
+ +
+
+
+
XX-2024-002 履历本副本
+
+ 提交人: + 李四 + 提交时间: + 2026-01-12 14:20:00 +
+ 待审批 +
+
+
+ + + +
+
+ +
+
+
+
XX-2024-003 履历本新本
+
+ 提交人: + 王五 + 提交时间: + 2026-01-13 09:15:00 +
+ 待审批 +
+
+
+ + + +
+
+
+
+
+ + +
+
+

套打输出

+

自动套打打印管理

+
+ +
+
+
+
+
打印设备
+
+
+
+
+
智能套打打印机
+ 设备ID: PRINT-001 +
+ 就绪 +
+ +
+
+
+ 今日打印 +

45页

+
+
+
+
+ 套打精度 +

±0.3mm

+
+
+
+ +
+ + + +
+ + +
+
+
+ +
+
+
+
打印队列
+
+
+
+
+ XX-2024-001 + 等待中 +
+ 12页 · A4纸 · 双面打印 +
+ +
+
+ XX-2024-002 + 等待中 +
+ 15页 · A4纸 · 双面打印 +
+ +
+
+ XX-2024-003 + 打印中 +
+
+
+
+ 65% 完成 · 已打印 13/20 页 +
+
+
+
+
+ +
+
+
打印历史
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
产品编号打印时间页数纸张状态操作
XX-2024-0052026-01-13 14:30:0018A4 双面完成重新打印
XX-2024-0042026-01-13 13:20:0022A4 双面完成重新打印
XX-2024-0032026-01-13 12:10:0020A4 双面打印中查看进度
+
+
+
+
+ + +
+
+
+

规则管理

+

校验规则配置与管理

+
+ +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
封面日期逻辑校验
+ 技术协议 +
+

+ 适用厂家:132厂 | 适用产品:全部 +

+

+ 封面的开始日期必须在后续页面的日期之前,否则需要提出校验错误的提示 +

+
+
+ 启用 + +
+
+
+ +
+
+
+
+
性能数据超差检查
+ 技术规范 +
+

+ 适用厂家:132厂 | 适用产品:全部 +

+

+ 性能测试数据必须在技术规范规定的范围内,超出范围需要提示错误 +

+
+
+ 启用 + +
+
+
+ +
+
+
+
+
印章完整性检查
+ 通用规则 +
+

+ 适用厂家:全部 | 适用产品:全部 +

+

+ 所有需要签字盖章的位置必须填充完整,不能有空缺 +

+
+
+ 启用 + +
+
+
+ +
+
+
+
+
时间序列逻辑检查
+ 技术协议 +
+

+ 适用厂家:132厂 | 适用产品:全部 +

+

+ 各项操作时间必须符合逻辑顺序,如生产日期应早于测试日期,测试日期应早于出厂日期 +

+
+
+ 启用 + +
+
+
+
+
+
+ + +
+
+
+

模板管理

+

履历本模板配置与管理

+
+ +
+ +
+
+
+
+ + V2.0 +
+
封面模板
+

132厂

+
+ + +
+
+
+ +
+
+
+ + V1.5 +
+
验收证明模板
+

132厂

+
+ + +
+
+
+ +
+
+
+ + V2.1 +
+
性能指标模板
+

132厂

+
+ + +
+
+
+ +
+
+
+ + V1.0 +
+
配套页模板
+

全部

+
+ + +
+
+
+ +
+
+
+ + V1.2 +
+
修理记录模板
+

全部

+
+ + +
+
+
+ +
+
+
+ + V1.0 +
+
重要记事模板
+

全部

+
+ + +
+
+
+
+
+ + +
+
+
+

印章管理

+

履历本印章配置与管理

+
+ +
+ +
+
+
+
+
工艺负责人
+
+
工艺负责人
+

PNG · 200x200

+
+
+ +
+
+
+
技术负责人
+
+
技术负责人
+

PNG · 200x200

+
+
+ +
+
+
+
质量负责人
+
+
质量负责人
+

PNG · 200x200

+
+
+ +
+
+
+
检验员
+
+
检验员
+

PNG · 200x200

+
+
+ +
+
+
+
审核员
+
+
审核员
+

PNG · 200x200

+
+
+ +
+
+
+
批准人
+
+
批准人
+

PNG · 200x200

+
+
+ +
+
+
+
公司公章
+
+
公司公章
+

PNG · 200x200

+
+
+ +
+
+
+
质检章
+
+
质检章
+

PNG · 200x200

+
+
+
+
+ + +
+
+

数据管理

+

全生命周期数据管理与统计

+
+ +
+
+
+
+
+

总数据量

+

2.3TB

+
+
+ +
+
+
+
+
+
+
+
+

履历本文件

+

5,678

+
+
+ +
+
+
+
+
+
+
+
+

今日备份

+

成功

+
+
+ +
+
+
+
+
+
+
+
+

存储使用率

+

68%

+
+
+ +
+
+
+
+
+ +
+
+
数据统计
+
+
+
+
+ +

数据统计图表区域

+
+
+
+
+ +
+
+
+
+
数据备份
+
+
+
+ + +
+ +
+
+
+ +
+
+
+
数据导出
+
+
+
+ + +
+ +
+
+
+
+
+ + +
+
+
+

用户管理

+

系统用户配置与管理

+
+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
用户名姓名部门角色状态操作
admin管理员系统管理部系统管理员启用 + 编辑 + 删除 +
zhangsan张三工艺部编制人启用 + 编辑 + 删除 +
lisi李四技术部审核人启用编辑 删除 +
wangwu王五质量部质量管理员启用编辑 删除 +
zhaoliu赵六生产部编制人停用编辑 删除 +
+
+
+
+
+ +
+
+

权限管理

+

角色与权限配置

+
+ +
+ + +
+
+
+
+
系统管理员 - 权限配置
+ +
+
+
+
+
主要功能
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
系统配置
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+ + +
+
+

系统设置

+

系统参数配置

+
+ +
+
+
基本设置
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
安全设置
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
文件设置
+
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+
备份设置
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+ + +
+
+
+ + + + + \ No newline at end of file diff --git a/index-4.html b/index-4.html new file mode 100644 index 0000000..b2f7e41 --- /dev/null +++ b/index-4.html @@ -0,0 +1,2183 @@ + + + + + + 套打输出模块 + + + + + +
+
+

套打输出

+

履历本物理输出管理 - 新本打印与原本修订

+
+ + + + + +
+ + +
+
+ +
+
+
+
新本打印配置
+
+
+ +
+
+
1
+
+
+
+
2
+
+
+
+
3
+
+
+
+
4
+
+
+ + + + + + + + + + + + +
+
+
+ + +
+
+
+
打印设备状态
+
+
+
+
+
智能套打打印机
+ PRINT-001 +
+ 就绪 +
+ +
+
设备监控
+
+ 设备状态: + ● 在线 +
+
+ 纸张余量: + 85% +
+
+ 黑色墨粉: + 60% +
+
+ 彩色墨粉: + 75% +
+
+ 硒鼓寿命: + 45% +
+
+ 打印速度: + 55页/分钟 +
+
+ 今日打印: + 284页 +
+
+ + +
+
+ +
+
+
打印队列
+
+
+
+
+ XX-2024-005 + 打印中 +
+
+
+
+ 65% 完成 · 已打印 13/20 页 +
+ +
+
+ XX-2024-006 + 等待中 +
+ 18页 · 双面打印 +
+ +
+
+ XX-2024-007 + 等待中 +
+ 15页 · 双面打印 +
+
+
+
+
+
+ + +
+
+ +
+
+
+
原本修订配置
+
+
+ +
+
+
1
+
+
+
+
2
+
+
+
+
3
+
+
+
+
4
+
+
+ + +
+
步骤1:选择产品和修订数据
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + 系统已完成版本对比,共检测到15项修订内容 +
+
+
+
+ + +
+
+ + +
+
步骤2:修订内容确认
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
页码页面类型修订类型修订内容
1封面修改修订次数: 0 → 1
8修理记录新增修理日期: 2026-03-10
8修理记录新增修理内容: 更换电源模块
9换件记录新增换件日期: 2026-03-10
9换件记录新增换件名称: 电源模块
+
+
+
+
+ 修订项总数 +
15项
+
+
+
+
+ 涉及页面 +
5页
+
+
+
+
+ 预计耗时 +
23分钟
+
+
+
+
+ + +
+
+ + +
+
步骤3:写字参数设置
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ 坐标校准参数 + +
+
+
+ X精度 + ±0.09mm +
+
+ Y精度 + ±0.10mm +
+
+ Z精度 + ±0.05mm +
+
+
+
+
+
+ + +
+
+ + +
+
步骤4:确认并开始写字
+
+
修订信息确认
+
+
+ 产品编号 + XX-2023-101 +
+
+ 写字设备 + WRITE-001 +
+
+ 修订项数 + 15项 +
+
+ 涉及页面 + 5页 +
+
+ 预计耗时 + 约23分钟 +
+
+ 笔型 + 黑色中性笔 0.5mm +
+
+
+
+ + 请确认已将原履历本正确放置到写字机器人托盘,并打开到第1页 +
+
+ + +
+
+
+
+ + +
+
+
写字路径预览
+
+
+ +
+ + + 蓝色线条表示笔头移动路径,红色点表示写字位置 + +
+
+
+
+ + +
+
+
+
写字设备状态
+
+
+
+
+
智能写字机器人
+ WRITE-001 +
+ 就绪 +
+ +
+
设备监控
+
+ 设备状态: + ● 在线 +
+
+ 笔芯状态: + ● 正常 +
+
+ 笔芯余量: + 50% +
+
+ 笔压: + 1.5N +
+
+ 定位精度: + ±0.1mm +
+
+ 翻页状态: + ● 正常 +
+
+ 今日修订: + 7份 +
+
+ + +
+
+ +
+
+
写字队列
+
+
+
+
+ XX-2023-105 + 写字中 +
+
+
+
+ 40% 完成 · 已完成 6/15 项修订 +
+ +
+
+ XX-2023-106 + 等待中 +
+ 12项修订 · 预计20分钟 +
+ +
+
+ XX-2023-107 + 等待中 +
+ 18项修订 · 预计28分钟 +
+
+
+
+
+
+ + +
+
+
+
+
+
+
批量输出配置
+ +
+
+
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
产品编号输出类型页数/修订项预计耗时状态
XX-2024-001新本打印20页8分钟就绪
XX-2024-002新本打印18页7分钟就绪
XX-2023-101原本修订15项23分钟就绪
XX-2024-003新本打印22页9分钟就绪
XX-2023-102原本修订12项20分钟就绪
+
+ +
+
+ 已选择 5 项 + 预计总耗时:67分钟 +
+ +
+
+
+ + + +
+ +
+
+
+
批量统计
+
+
+
+
+
+
+
+

今日批量任务

+

8个

+
+
+ +
+
+
+
+
+
+
+
+

今日输出总数

+

156份

+
+
+ +
+
+
+
+
+
+
+
+

平均成功率

+

97.4%

+
+
+ +
+
+
+
+
+
+
+ +
+
+
最近批量任务
+
+
+
+
+ BATCH-20260112-003 + 完成 +
+ 20份 · 新本打印 + 成功率:100% +
+
+
+ BATCH-20260112-002 + 完成 +
+ 15份 · 混合输出 + 成功率:93.3% +
+
+
+ BATCH-20260112-001 + 完成 +
+ 10份 · 原本修订 + 成功率:100% +
+
+
+
+
+
+ + +
+
+
+
+
+
+ 打印机管理 +
+
+
+
+
+
智能套打打印机
+ PRINT-001 · HP LaserJet M607dn +
+ 在线 +
+ +
+
设备信息
+
+ 购置日期: + 2025-06-01 +
+
+ 使用天数: + 212天 +
+
+ 累计打印: + 125,680页 +
+
+ 故障次数: + 3次 +
+
+ 故障率: + 0.002% +
+
+ +
+
耗材状态
+
+
+ 黑色墨粉 + 60% +
+
+
+
+ 剩余约6,000页 +
+
+
+ 彩色墨粉 + 75% +
+
+
+
+ 剩余约7,500页 +
+
+
+ 硒鼓寿命 + 45% +
+
+
+
+ 剩余约45,000页 +
+
+ +
+
维护记录
+
+
+ 定期维护 + 2025-12-15 +
+ 清洁、校准、更换零件 +
+
+
+ 下次维护 + 2026-03-15 +
+ 定期维护(3个月周期) +
+
+ +
+ + +
+
+
+
+ +
+
+
+
+ 写字机器人管理 +
+
+
+
+
+
智能写字机器人
+ WRITE-001 · AutoWriter Pro X1 +
+ 在线 +
+ +
+
设备信息
+
+ 购置日期: + 2025-07-01 +
+
+ 使用天数: + 184天 +
+
+ 累计修订: + 2,156份 +
+
+ 故障次数: + 15次 +
+
+ 翻页成功率: + 96.8% +
+
+ +
+
运动系统状态
+
+
+
+ X轴 + ● 正常 + ±0.10mm +
+
+
+
+ Y轴 + ● 正常 + ±0.11mm +
+
+
+
+ Z轴 + ● 正常 + ±0.05mm +
+
+
+
+ 翻页机构 + ● 正常 + 96.8% +
+
+
+
+ +
+
耗材状态
+
+
+ 当前笔芯 + 黑色中性笔 0.5mm +
+
+ 笔芯余量 + 50% +
+
+
+
+ 累计更换:96次 +
+
+ +
+
维护记录
+
+
+ 定期维护 + 2025-12-15 +
+ 清洁、润滑、更换零件 +
+
+
+ 下次维护 + 2026-02-15 +
+ 定期维护(2个月周期) +
+
+ +
+ + +
+
+
+
+
+ + +
+
+
设备性能统计
+
+
+
+
+
打印机性能趋势
+
+
+ +

性能趋势图表

+
+
+
+
+
写字机器人性能趋势
+
+
+ +

性能趋势图表

+
+
+
+
+
+
+
+ + +
+
+
+
输出历史查询
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+
+
+ + +
+
+
+
+
+

本月输出总数

+

678份

+
+
+ +
+
+
+
+
+
+
+
+

新本打印

+

486份

+
+
+ +
+
+
+
+
+
+
+
+

原本修订

+

192份

+
+
+ +
+
+
+
+
+
+
+
+

成功率

+

97.8%

+
+
+ +
+
+
+
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
产品编号输出类型输出时间耗时使用设备操作人员状态质检结果操作
XX-2024-010新本打印2026-01-12 14:30:008分钟PRINT-001张三成功合格 + 查看详情 +
XX-2023-105原本修订2026-01-12 13:20:0023分钟WRITE-001李四成功合格 + 查看详情 +
XX-2024-009新本打印2026-01-12 12:10:009分钟PRINT-001张三成功合格 + 查看详情 +
XX-2024-008新本打印2026-01-12 11:00:00失败PRINT-001张三失败- + 重新打印 +
XX-2023-104原本修订2026-01-12 10:30:0020分钟WRITE-001李四成功合格 + 查看详情 +
+
+ + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/index-v2.html b/index-v2.html new file mode 100644 index 0000000..794036a --- /dev/null +++ b/index-v2.html @@ -0,0 +1,3300 @@ + + + + + + 智能低代码开发平台 + + + + + + + + + + + +
+
+ +
+
+
项目列表
+ + +
+
+
智能监控系统
+
基于AI的实时监控平台
+
+ 2024-01-15 + 进行中 +
+
+
+
数据分析平台
+
大数据可视化分析工具
+
+ 2024-01-10 + 已完成 +
+
+
+
物联网管理系统
+
设备管理与数据采集
+
+ 2024-01-05 + 进行中 +
+
+
+
电商管理系统
+
订单、库存、用户管理
+
+ 2023-12-28 + 已暂停 +
+
+
+
+
+ + +
+
+ +
+
+
需求管理
+ +
+
+
+
+
+ + 录入方式: + 文本输入 +
+ 2024-01-15 10:30 +
+
+

+ 需要开发一个智能监控系统,该系统应具备以下核心功能:

+ 1. 用户登录认证:支持用户通过用户名和密码进行登录,并集成多因素认证机制,确保账户安全性。
+ 2. 实时数据监控:平台需要实时采集设备数据,并通过可视化图表展示关键指标,支持异常告警。
+ 3. 数据导出功能:支持将监控数据导出为Excel、CSV等格式,便于后续分析和报告生成。
+ 4. 系统日志管理:记录所有系统操作日志,支持日志查询和审计。 +

+
+
+
+
+
+ + +
+
+ + + +
+
+
+
+ +
+
+
REQ-001 用户登录认证
+
+ 高 95% + 高优先级 +
+
+
系统需要支持用户通过用户名和密码进行登录,并集成多因素认证机制,确保账户安全性。
+
+ + +
+
+
+
+
+
+ +
+
+
REQ-002 实时数据监控
+
+ 高 92% + 高优先级 +
+
+
平台需要实时采集设备数据,并通过可视化图表展示关键指标,支持异常告警。
+
+ + +
+
+
+
+
+
+ +
+
+
REQ-003 数据导出功能
+
+ 中 78% + 中优先级 +
+
+
支持将监控数据导出为Excel、CSV等格式,便于后续分析和报告生成。
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+
+
功能模块
+
+ + +
+
+
+
+
+
+
+ +
+
用户认证模块
+
+ REQ-001 +
+
实现登录、注册、密码重置、多因素认证等功能
+
+ Spring Boot + JWT +
+
+
+
+
+ + +
+
+
+
+
+
+ +
+
数据监控模块
+
+ REQ-002 +
+
实时数据采集、可视化展示、告警管理
+
+ ECharts + WebSocket +
+
+
+
+
+ + +
+
+
+
+
+
+ +
+
数据管理模块
+
+ REQ-003 +
+
数据查询、导出、备份与恢复
+
+ POI + MySQL +
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+ + +
+
+ +
+
+
项目文档
+
+
+
+ +
+
需求规格说明书
+
2.3 MB · 2024-01-15
+
+
+
+ + +
+
+
+
+ +
+
功能设计文档
+
1.8 MB · 2024-01-15
+
+
+
+ + +
+
+
+
+ +
+
软件概要设计文档
+
3.1 MB · 2024-01-15
+
+
+
+ + +
+
+
+
+ +
+
软件详细设计文档
+
4.5 MB · 2024-01-15
+
+
+
+ + +
+
+
+
+ +
+
接口文档
+
1.2 MB · 2024-01-15
+
+
+
+ +
+ + +
+
+
+
+
+
+ + +
+
+
+
代码结构
+
+ +
+
+
+
+ + + 智能监控系统 +
+
+
+ + + src +
+
+
+ + + Application.java + +
+
+ + + modules +
+
+
+ + + auth +
+
+
+ + + AuthController.java + +
+
+ + + AuthService.java + +
+
+
+ + + monitor +
+
+
+ + + utils +
+
+ + + config +
+
+
+ + + pom.xml + +
+
+ + + README.md + +
+
+
+
+
+
+
+ + +
+
+
+
流水线操作
+
+ + + +
+
+
+
+
+
静态扫描
+
已完成 · 2分15秒
+ SonarQube +
+
+
+
编译构建
+
进行中 · 65%
+
+
+
+
+
+
+
打包
+
等待中
+ JAR +
+
+
+
部署
+
等待中
+ 测试环境 +
+
+
+
验证测试
+
等待中
+ 0/25 通过 +
+
+
+ 总耗时: 3分42秒 · 预计剩余: 2分18秒 +
+
+
+
+
+ + + + + +
+ + +
+
+ 重命名 +
+
+ 删除 +
+
+ 导出 +
+
+ 复制 +
+
+ + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..6a8892d --- /dev/null +++ b/index.html @@ -0,0 +1,1107 @@ + + + + + + 智能低代码开发平台 + + + + + + + + + + + +
+
+ +
+
+
项目列表
+ +
+
+
智能监控系统
+
基于AI的实时监控平台
+
+
+
数据分析平台
+
大数据可视化分析工具
+
+
+
物联网管理系统
+
设备管理与数据采集
+
+
+
电商管理系统
+
订单、库存、用户管理
+
+
+
+
+ + +
+
+ +
+
+
需求管理
+ +
+
+
+ 原始需求描述:需要开发一个智能监控系统,支持用户登录认证、实时数据监控、数据导出等功能... +
+
+
+
+
+ +
+
REQ-001 用户登录认证
+
系统需要支持用户通过用户名和密码进行登录,并集成多因素认证机制,确保账户安全性。
+
+
+
+
+
+ +
+
REQ-002 实时数据监控
+
平台需要实时采集设备数据,并通过可视化图表展示关键指标,支持异常告警。
+
+
+
+
+
+ +
+
REQ-003 数据导出功能
+
支持将监控数据导出为Excel、CSV等格式,便于后续分析和报告生成。
+
+
+
+
+
+
+
+ + +
+
+
功能模块
+
+
+
+ 用户认证模块 +
+
+ REQ-001 + 实现登录、注册、密码重置、多因素认证等功能 +
+
+
+
+ 数据监控模块 +
+
+ REQ-002 + 实时数据采集、可视化展示、告警管理 +
+
+
+
+ 数据管理模块 +
+
+ REQ-003 + 数据查询、导出、备份与恢复 +
+
+
+
+
+
+
+ + +
+
+ +
+
+
项目文档
+
+
+
+ + 需求规格说明书 +
+
+ + +
+
+
+
+ + 功能设计文档 +
+
+ + +
+
+
+
+ + 软件概要设计文档 +
+
+ + +
+
+
+
+ + 软件详细设计文档 +
+
+ + +
+
+
+
+ + 接口文档 +
+
+ + +
+
+
+
+
+ + +
+
+
代码结构
+
+
+ src +
+
+ main.java +
+
+ modules +
+
+ AuthModule.java +
+
+ MonitorModule.java +
+
+ DataModule.java +
+
+ utils +
+
+ HttpUtil.java +
+
+ DateUtil.java +
+
+ config +
+
+ application.yml +
+
+
+
+
+
+ + +
+
+
流水线操作
+
+
+
+
静态扫描
+
就绪
+
+
+
+
编译构建
+
进行中...
+
+
+
+
打包
+
等待中
+
+
+
+
部署
+
等待中
+
+
+
+
验证
+
等待中
+
+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..8ec220b --- /dev/null +++ b/main.py @@ -0,0 +1,53 @@ +""" +智能低代码开发平台 - 主程序入口 + +使用方法: + python main.py + +依赖: + pip install PyQt5 +""" + +import sys +from PyQt5.QtWidgets import QApplication +from PyQt5.QtGui import QFont +from PyQt5.QtCore import Qt + +from config import DARK_THEME +from windows import MainWindow + + +def main(): + """主函数""" + # 创建应用程序 + app = QApplication(sys.argv) + + # 设置应用程序信息 + app.setApplicationName("智能低代码开发平台") + app.setApplicationVersion("1.0.0") + app.setOrganizationName("AI Development Team") + + # 设置样式 + app.setStyle("Fusion") + + # 应用深色主题 + app.setStyleSheet(DARK_THEME) + + # 设置默认字体 + font = QFont("Microsoft YaHei", 10) + app.setFont(font) + + # 启用高DPI支持 + QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) + QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True) + + # 创建并显示主窗口 + window = MainWindow() + window.show() + + # 运行应用程序 + sys.exit(app.exec_()) + + +if __name__ == "__main__": + main() diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..05bcbc7 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,9 @@ +""" +数据模型模块 +""" +from .project import Project +from .requirement import Requirement +from .module import Module +from .document import Document + +__all__ = ['Project', 'Requirement', 'Module', 'Document'] diff --git a/models/document.py b/models/document.py new file mode 100644 index 0000000..58ad3be --- /dev/null +++ b/models/document.py @@ -0,0 +1,50 @@ +""" +文档模型 +""" +from datetime import datetime +from typing import Dict, Any + + +class Document: + """文档数据模型""" + + def __init__(self, name: str, doc_type: str, size: str = "0 KB"): + """ + 初始化文档 + + Args: + name: 文档名称 + doc_type: 文档类型 + size: 文件大小 + """ + self.name = name + self.doc_type = doc_type + self.size = size + self.created_at = datetime.now() + self.icon = self._get_icon() + + def _get_icon(self) -> str: + """根据文档类型获取图标""" + icon_map = { + 'SRS': '📄', + '功能设计': '📋', + '概要设计': '🏗️', + '详细设计': '📐', + 'API': '📖', + '数据库': '🗄️', + '测试': '✅', + '用户手册': '📚' + } + return icon_map.get(self.doc_type, '📄') + + def to_dict(self) -> Dict[str, Any]: + """转换为字典""" + return { + 'name': self.name, + 'type': self.doc_type, + 'size': self.size, + 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M') + } + + def __str__(self) -> str: + return f"{self.icon} {self.name}" diff --git a/models/module.py b/models/module.py new file mode 100644 index 0000000..b48fed8 --- /dev/null +++ b/models/module.py @@ -0,0 +1,47 @@ +""" +功能模块模型 +""" +from typing import List, Dict, Any + + +class Module: + """功能模块数据模型""" + + def __init__(self, name: str, description: str, requirements: List[str] = None): + """ + 初始化模块 + + Args: + name: 模块名称 + description: 模块描述 + requirements: 关联的需求ID列表 + """ + self.name = name + self.description = description + self.requirements = requirements or [] + self.tech_stack = [] + self.progress = 0 + self.icon = "🔧" + + def add_requirement(self, req_id: str): + """添加关联需求""" + if req_id not in self.requirements: + self.requirements.append(req_id) + + def add_tech(self, tech: str): + """添加技术栈""" + if tech not in self.tech_stack: + self.tech_stack.append(tech) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典""" + return { + 'name': self.name, + 'description': self.description, + 'requirements': self.requirements, + 'tech_stack': self.tech_stack, + 'progress': self.progress + } + + def __str__(self) -> str: + return f"{self.icon} {self.name}" diff --git a/models/project.py b/models/project.py new file mode 100644 index 0000000..052708a --- /dev/null +++ b/models/project.py @@ -0,0 +1,71 @@ +""" +项目模型 +""" +from datetime import datetime +from typing import List, Dict, Any +from .requirement import Requirement +from .module import Module +from .document import Document + + +class Project: + """项目数据模型""" + + def __init__(self, name: str, description: str = "", status: str = "进行中"): + """ + 初始化项目 + + Args: + name: 项目名称 + description: 项目描述 + status: 项目状态 (进行中/已完成/已暂停) + """ + self.name = name + self.description = description + self.status = status + self.created_at = datetime.now() + self.requirements: List[Requirement] = [] + self.modules: List[Module] = [] + self.documents: List[Document] = [] + self.original_requirement = "" + self.project_type = "Java Spring Boot" + + def add_requirement(self, requirement: Requirement): + """添加需求""" + self.requirements.append(requirement) + + def add_module(self, module: Module): + """添加模块""" + self.modules.append(module) + + def add_document(self, document: Document): + """添加文档""" + self.documents.append(document) + + def get_requirement_count(self) -> int: + """获取需求数量""" + return len(self.requirements) + + def get_module_count(self) -> int: + """获取模块数量""" + return len(self.modules) + + def get_document_count(self) -> int: + """获取文档数量""" + return len(self.documents) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典""" + return { + 'name': self.name, + 'description': self.description, + 'status': self.status, + 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M'), + 'requirements': [r.to_dict() for r in self.requirements], + 'modules': [m.to_dict() for m in self.modules], + 'documents': [d.to_dict() for d in self.documents], + 'project_type': self.project_type + } + + def __str__(self) -> str: + return f"Project: {self.name} ({self.status})" diff --git a/models/requirement.py b/models/requirement.py new file mode 100644 index 0000000..c6b62da --- /dev/null +++ b/models/requirement.py @@ -0,0 +1,42 @@ +""" +需求模型 +""" +from typing import Dict, Any + + +class Requirement: + """需求数据模型""" + + def __init__(self, req_id: str, title: str, description: str, + confidence: int = 0, priority: str = "中"): + """ + 初始化需求 + + Args: + req_id: 需求ID + title: 需求标题 + description: 需求描述 + confidence: 置信度 (0-100) + priority: 优先级 (高/中/低) + """ + self.req_id = req_id + self.title = title + self.description = description + self.confidence = confidence + self.priority = priority + self.checked = True + self.req_type = "功能性" + + def to_dict(self) -> Dict[str, Any]: + """转换为字典""" + return { + 'req_id': self.req_id, + 'title': self.title, + 'description': self.description, + 'confidence': self.confidence, + 'priority': self.priority, + 'type': self.req_type + } + + def __str__(self) -> str: + return f"{self.req_id}: {self.title}" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/widgets.py b/widgets.py new file mode 100644 index 0000000..e69de29 diff --git a/widgets/__init__.py b/widgets/__init__.py new file mode 100644 index 0000000..8f54423 --- /dev/null +++ b/widgets/__init__.py @@ -0,0 +1,14 @@ +""" +自定义组件模块 +""" +from .panel_widget import PanelWidget +from .project_item import ProjectItemWidget +from .requirement_item import RequirementItemWidget +from .module_item import ModuleItemWidget + +__all__ = [ + 'PanelWidget', + 'ProjectItemWidget', + 'RequirementItemWidget', + 'ModuleItemWidget' +] diff --git a/widgets/module_item.py b/widgets/module_item.py new file mode 100644 index 0000000..12683b8 --- /dev/null +++ b/widgets/module_item.py @@ -0,0 +1,97 @@ +""" +模块列表项组件 +""" +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel +from PyQt5.QtCore import Qt + + +class ModuleItemWidget(QWidget): + """模块列表项组件""" + + def __init__(self, module, parent=None): + """ + 初始化模块列表项 + + Args: + module: 模块对象 + parent: 父组件 + """ + super().__init__(parent) + self.module = module + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + layout = QVBoxLayout(self) + layout.setContentsMargins(15, 15, 15, 15) + layout.setSpacing(10) + + # 模块标题 + title_label = QLabel(f"{self.module.icon} {self.module.name}") + title_label.setStyleSheet(""" + font-weight: bold; + color: #60a5fa; + font-size: 14px; + """) + layout.addWidget(title_label) + + # 模块描述 + desc_label = QLabel(self.module.description) + desc_label.setStyleSheet(""" + color: #94a3b8; + font-size: 12px; + """) + desc_label.setWordWrap(True) + layout.addWidget(desc_label) + + # 需求标签 + if self.module.requirements: + req_layout = QHBoxLayout() + req_layout.setSpacing(5) + + for req_id in self.module.requirements[:3]: # 最多显示3个 + req_label = QLabel(req_id) + req_label.setStyleSheet(""" + background: #3b82f633; + color: #3b82f6; + border: 1px solid #3b82f6; + border-radius: 4px; + padding: 2px 6px; + font-size: 11px; + """) + req_layout.addWidget(req_label) + + req_layout.addStretch() + layout.addLayout(req_layout) + + # 技术栈标签 + if self.module.tech_stack: + tech_layout = QHBoxLayout() + tech_layout.setSpacing(5) + + for tech in self.module.tech_stack[:3]: # 最多显示3个 + tech_label = QLabel(tech) + tech_label.setStyleSheet(""" + background: rgba(100, 116, 139, 0.3); + color: #94a3b8; + border-radius: 4px; + padding: 2px 6px; + font-size: 11px; + """) + tech_layout.addWidget(tech_label) + + tech_layout.addStretch() + layout.addLayout(tech_layout) + + # 设置整体样式 + self.setStyleSheet(""" + QWidget { + background: rgba(51, 65, 85, 0.3); + border: 1px solid rgba(59, 130, 246, 0.15); + border-radius: 8px; + } + QWidget:hover { + background: rgba(59, 130, 246, 0.1); + border-color: rgba(59, 130, 246, 0.3); + } + """) diff --git a/widgets/panel_widget.py b/widgets/panel_widget.py new file mode 100644 index 0000000..074717a --- /dev/null +++ b/widgets/panel_widget.py @@ -0,0 +1,52 @@ +""" +面板组件 +""" +from PyQt5.QtWidgets import QFrame, QVBoxLayout, QLabel +from PyQt5.QtCore import Qt + + +class PanelWidget(QFrame): + """面板组件 - 带标题的容器""" + + def __init__(self, title: str = "", parent=None): + """ + 初始化面板 + + Args: + title: 面板标题 + parent: 父组件 + """ + super().__init__(parent) + self.title = title + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + # 设置框架样式 + self.setFrameShape(QFrame.StyledPanel) + + # 创建布局 + layout = QVBoxLayout(self) + layout.setContentsMargins(15, 15, 15, 15) + layout.setSpacing(10) + + # 添加标题 + if self.title: + title_label = QLabel(self.title) + title_label.setStyleSheet(""" + font-size: 16px; + font-weight: bold; + color: #60a5fa; + margin-bottom: 5px; + """) + layout.addWidget(title_label) + + # 添加分隔线 + line = QFrame() + line.setFrameShape(QFrame.HLine) + line.setStyleSheet(""" + background: rgba(59, 130, 246, 0.2); + max-height: 1px; + margin-bottom: 10px; + """) + layout.addWidget(line) diff --git a/widgets/project_item.py b/widgets/project_item.py new file mode 100644 index 0000000..251efc7 --- /dev/null +++ b/widgets/project_item.py @@ -0,0 +1,106 @@ +""" +项目列表项组件 +""" +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel +from PyQt5.QtCore import pyqtSignal, Qt + + +class ProjectItemWidget(QWidget): + """项目列表项组件""" + + clicked = pyqtSignal(object) # 点击信号 + + def __init__(self, project, parent=None): + """ + 初始化项目列表项 + + Args: + project: 项目对象 + parent: 父组件 + """ + super().__init__(parent) + self.project = project + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + layout = QVBoxLayout(self) + layout.setContentsMargins(12, 12, 12, 12) + layout.setSpacing(8) + + # 项目名称 + name_label = QLabel(self.project.name) + name_label.setStyleSheet(""" + font-weight: bold; + color: #60a5fa; + font-size: 14px; + """) + layout.addWidget(name_label) + + # 项目描述 + desc_label = QLabel(self.project.description or "暂无描述") + desc_label.setStyleSheet(""" + color: #94a3b8; + font-size: 12px; + """) + desc_label.setWordWrap(True) + layout.addWidget(desc_label) + + # 底部信息 + bottom_layout = QHBoxLayout() + bottom_layout.setSpacing(10) + + # 创建时间 + time_label = QLabel(self.project.created_at.strftime('%Y-%m-%d')) + time_label.setStyleSheet(""" + color: #64748b; + font-size: 11px; + """) + bottom_layout.addWidget(time_label) + + bottom_layout.addStretch() + + # 状态标签 + status_label = self._create_status_label() + bottom_layout.addWidget(status_label) + + layout.addLayout(bottom_layout) + + # 设置整体样式 + self.setStyleSheet(""" + QWidget { + background: rgba(51, 65, 85, 0.4); + border: 1px solid rgba(59, 130, 246, 0.2); + border-radius: 8px; + } + QWidget:hover { + background: rgba(59, 130, 246, 0.15); + border-color: rgba(59, 130, 246, 0.4); + } + """) + + def _create_status_label(self) -> QLabel: + """创建状态标签""" + status_colors = { + "进行中": "#10b981", + "已完成": "#3b82f6", + "已暂停": "#f59e0b" + } + color = status_colors.get(self.project.status, "#94a3b8") + + status_label = QLabel(self.project.status) + status_label.setStyleSheet(f""" + background: {color}33; + color: {color}; + border: 1px solid {color}; + border-radius: 4px; + padding: 2px 8px; + font-size: 10px; + """) + + return status_label + + def mousePressEvent(self, event): + """鼠标点击事件""" + self.clicked.emit(self.project) + super().mousePressEvent(event) diff --git a/widgets/requirement_item.py b/widgets/requirement_item.py new file mode 100644 index 0000000..266db24 --- /dev/null +++ b/widgets/requirement_item.py @@ -0,0 +1,123 @@ +""" +需求列表项组件 +""" +from PyQt5.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QLabel, QCheckBox +from PyQt5.QtCore import Qt + + +class RequirementItemWidget(QWidget): + """需求列表项组件""" + + def __init__(self, requirement, parent=None): + """ + 初始化需求列表项 + + Args: + requirement: 需求对象 + parent: 父组件 + """ + super().__init__(parent) + self.requirement = requirement + self._setup_ui() + + def _setup_ui(self): + """设置UI""" + layout = QHBoxLayout(self) + layout.setContentsMargins(10, 10, 10, 10) + layout.setSpacing(10) + + # 复选框 + checkbox = QCheckBox() + checkbox.setChecked(self.requirement.checked) + checkbox.stateChanged.connect( + lambda state: setattr(self.requirement, 'checked', state == Qt.Checked) + ) + layout.addWidget(checkbox) + + # 内容区域 + content_layout = QVBoxLayout() + content_layout.setSpacing(5) + + # 标题行 + title_layout = QHBoxLayout() + title_layout.setSpacing(10) + + # 需求标题 + title_label = QLabel(f"{self.requirement.req_id} {self.requirement.title}") + title_label.setStyleSheet(""" + font-weight: bold; + color: #60a5fa; + """) + title_layout.addWidget(title_label) + + title_layout.addStretch() + + # 置信度标签 + confidence_label = self._create_confidence_label() + title_layout.addWidget(confidence_label) + + # 优先级标签 + priority_label = self._create_priority_label() + title_layout.addWidget(priority_label) + + content_layout.addLayout(title_layout) + + # 需求描述 + desc_label = QLabel(self.requirement.description) + desc_label.setStyleSheet(""" + color: #94a3b8; + font-size: 12px; + """) + desc_label.setWordWrap(True) + content_layout.addWidget(desc_label) + + layout.addLayout(content_layout) + + # 设置整体样式 + self.setStyleSheet(""" + QWidget { + background: rgba(51, 65, 85, 0.3); + border: 1px solid rgba(59, 130, 246, 0.15); + border-radius: 6px; + } + """) + + def _create_confidence_label(self) -> QLabel: + """创建置信度标签""" + confidence = self.requirement.confidence + + if confidence >= 90: + color = "#10b981" + elif confidence >= 70: + color = "#f59e0b" + else: + color = "#ef4444" + + label = QLabel(f"{confidence}%") + label.setStyleSheet(f""" + background: {color}33; + color: {color}; + border: 1px solid {color}; + border-radius: 4px; + padding: 2px 6px; + font-size: 11px; + """) + + return label + + def _create_priority_label(self) -> QLabel: + """创建优先级标签""" + priority = self.requirement.priority + color = "#f59e0b" if priority == "高" else "#3b82f6" + + label = QLabel(f"{priority}优先级") + label.setStyleSheet(f""" + background: {color}33; + color: {color}; + border: 1px solid {color}; + border-radius: 4px; + padding: 2px 6px; + font-size: 11px; + """) + + return label diff --git a/windows/__init__.py b/windows/__init__.py new file mode 100644 index 0000000..616073f --- /dev/null +++ b/windows/__init__.py @@ -0,0 +1,6 @@ +""" +窗口模块 +""" +from .main_window import MainWindow + +__all__ = ['MainWindow'] diff --git a/windows/main_window.py b/windows/main_window.py new file mode 100644 index 0000000..842d248 --- /dev/null +++ b/windows/main_window.py @@ -0,0 +1,680 @@ +""" +主窗口 +""" +from PyQt5.QtWidgets import ( + QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, + QListWidget, QListWidgetItem, QTabWidget, QTextEdit, + QTreeWidget, QTreeWidgetItem, QPushButton, QLineEdit, + QAction, QMenu, QMessageBox, QFileDialog, QInputDialog, QLabel +) +from PyQt5.QtCore import Qt, QTimer, QSize +from PyQt5.QtGui import QFont + +from models import Project, Requirement, Module, Document +from widgets import PanelWidget, ProjectItemWidget, RequirementItemWidget, ModuleItemWidget +from dialogs import NewProjectDialog, CodeViewDialog, ModuleDetailDialog, PipelineDialog + + +class MainWindow(QMainWindow): + """主窗口类""" + + def __init__(self): + """初始化主窗口""" + super().__init__() + self.projects = [] + self.current_project = None + + self._setup_window() + self._setup_toolbar() + self._setup_ui() + self._setup_statusbar() + + # 加载示例数据 + self._load_sample_data() + + # 显示欢迎消息 + QTimer.singleShot(500, self._show_welcome) + + def _setup_window(self): + """设置窗口属性""" + self.setWindowTitle("智能低代码开发平台 v1.0") + self.setMinimumSize(1400, 900) + + def _setup_toolbar(self): + """设置工具栏""" + toolbar = self.addToolBar("主工具栏") + toolbar.setMovable(False) + toolbar.setIconSize(QSize(24, 24)) + + # 新建项目 + new_action = QAction("📁 新建项目", self) + new_action.setShortcut("Ctrl+N") + new_action.setToolTip("创建新项目 (Ctrl+N)") + new_action.triggered.connect(self._create_new_project) + toolbar.addAction(new_action) + + toolbar.addSeparator() + + # 保存 + save_action = QAction("💾 保存", self) + save_action.setShortcut("Ctrl+S") + save_action.setToolTip("保存项目 (Ctrl+S)") + save_action.triggered.connect(self._save_project) + toolbar.addAction(save_action) + + # 导出 + export_action = QAction("📤 导出", self) + export_action.setToolTip("导出项目") + export_action.triggered.connect(self._export_project) + toolbar.addAction(export_action) + + toolbar.addSeparator() + + # 运行流水线 + run_action = QAction("▶ 运行流水线", self) + run_action.setToolTip("运行CI/CD流水线") + run_action.triggered.connect(self._run_pipeline) + toolbar.addAction(run_action) + + toolbar.addSeparator() + + # 设置 + settings_action = QAction("⚙ 设置", self) + settings_action.setToolTip("系统设置") + settings_action.triggered.connect(self._show_settings) + toolbar.addAction(settings_action) + + # 帮助 + help_action = QAction("❓ 帮助", self) + help_action.setToolTip("帮助文档") + help_action.triggered.connect(self._show_help) + toolbar.addAction(help_action) + + def _setup_ui(self): + """设置UI""" + # 创建中心部件 + central = QWidget() + self.setCentralWidget(central) + + main_layout = QHBoxLayout(central) + main_layout.setContentsMargins(10, 10, 10, 10) + main_layout.setSpacing(10) + + # 左侧面板 - 项目列表 + self._create_left_panel(main_layout) + + # 中间面板 - 需求和功能 + self._create_center_panel(main_layout) + + # 右侧面板 - 文档和代码 + self._create_right_panel(main_layout) + + def _create_left_panel(self, parent_layout): + """创建左侧面板""" + left_panel = PanelWidget("📁 项目列表") + left_panel.setMaximumWidth(320) + + layout = QVBoxLayout() + + # 新建项目按钮 + new_btn = QPushButton("+ 新建项目") + new_btn.setMinimumHeight(40) + new_btn.clicked.connect(self._create_new_project) + layout.addWidget(new_btn) + + # 搜索框 + self.search_edit = QLineEdit() + self.search_edit.setPlaceholderText("🔍 搜索项目...") + self.search_edit.textChanged.connect(self._filter_projects) + layout.addWidget(self.search_edit) + + # 项目列表 + self.project_list = QListWidget() + self.project_list.itemClicked.connect(self._on_project_clicked) + self.project_list.setContextMenuPolicy(Qt.CustomContextMenu) + self.project_list.customContextMenuRequested.connect(self._show_project_context_menu) + layout.addWidget(self.project_list) + + left_panel.layout().addLayout(layout) + parent_layout.addWidget(left_panel, 2) + + def _create_center_panel(self, parent_layout): + """创建中间面板""" + center_widget = QWidget() + layout = QVBoxLayout(center_widget) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(10) + + # 需求面板 + req_panel = PanelWidget("📋 需求管理") + req_layout = QVBoxLayout() + + self.req_tabs = QTabWidget() + + # 原始需求标签页 + self.original_req_text = QTextEdit() + self.original_req_text.setPlaceholderText("原始需求内容将显示在这里...") + self.original_req_text.setReadOnly(True) + self.req_tabs.addTab(self.original_req_text, "原始需求") + + # 需求列表标签页 + self.req_list = QListWidget() + self.req_tabs.addTab(self.req_list, "需求列表") + + req_layout.addWidget(self.req_tabs) + req_panel.layout().addLayout(req_layout) + layout.addWidget(req_panel) + + # 功能模块面板 + func_panel = PanelWidget("⚙️ 功能模块") + func_layout = QVBoxLayout() + + self.module_list = QListWidget() + self.module_list.itemDoubleClicked.connect(self._show_module_detail) + func_layout.addWidget(self.module_list) + + func_panel.layout().addLayout(func_layout) + layout.addWidget(func_panel) + + parent_layout.addWidget(center_widget, 3) + + def _create_right_panel(self, parent_layout): + """创建右侧面板""" + right_widget = QWidget() + layout = QVBoxLayout(right_widget) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(10) + + # 文档面板 + doc_panel = PanelWidget("📚 项目文档") + doc_layout = QVBoxLayout() + + # 文档工具栏 + doc_toolbar = QHBoxLayout() + doc_toolbar.addStretch() + + download_all_btn = QPushButton("⬇ 全部下载") + download_all_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #10b981, stop:1 #059669); + } + """) + download_all_btn.clicked.connect(self._download_all_documents) + doc_toolbar.addWidget(download_all_btn) + + doc_layout.addLayout(doc_toolbar) + + self.doc_list = QListWidget() + self.doc_list.itemDoubleClicked.connect(self._open_document) + self.doc_list.setContextMenuPolicy(Qt.CustomContextMenu) + self.doc_list.customContextMenuRequested.connect(self._show_doc_context_menu) + doc_layout.addWidget(self.doc_list) + + doc_panel.layout().addLayout(doc_layout) + layout.addWidget(doc_panel) + + # 代码结构面板 + code_panel = PanelWidget("💻 代码结构") + code_layout = QVBoxLayout() + + # 代码工具栏 + code_toolbar = QHBoxLayout() + code_toolbar.addStretch() + + download_code_btn = QPushButton("⬇ 下载代码") + download_code_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #10b981, stop:1 #059669); + } + """) + download_code_btn.clicked.connect(self._download_all_code) + code_toolbar.addWidget(download_code_btn) + + code_layout.addLayout(code_toolbar) + + self.code_tree = QTreeWidget() + self.code_tree.setHeaderLabel("文件") + self.code_tree.itemDoubleClicked.connect(self._open_code_file) + self.code_tree.setContextMenuPolicy(Qt.CustomContextMenu) + self.code_tree.customContextMenuRequested.connect(self._show_code_context_menu) + code_layout.addWidget(self.code_tree) + + code_panel.layout().addLayout(code_layout) + layout.addWidget(code_panel) + + parent_layout.addWidget(right_widget, 2) + + def _setup_statusbar(self): + """设置状态栏""" + self.statusBar().showMessage("就绪") + + # 添加永久部件 + self.status_label = QLabel("无项目") + self.statusBar().addPermanentWidget(self.status_label) + + def _load_sample_data(self): + """加载示例数据""" + # 项目1 + p1 = Project("智能监控系统", "基于AI的实时监控平台", "进行中") + p1.original_requirement = """需要开发一个智能监控系统,包含以下功能: +1. 用户登录认证:支持用户名密码登录,集成多因素认证 +2. 实时数据监控:实时采集设备数据,可视化展示 +3. 数据导出:支持导出Excel、CSV格式 +4. 系统日志:记录所有操作日志""" + + p1.add_requirement(Requirement("REQ-001", "用户登录认证", "支持用户名密码登录,集成MFA", 95, "高")) + p1.add_requirement(Requirement("REQ-002", "实时数据监控", "实时采集设备数据并可视化", 92, "高")) + p1.add_requirement(Requirement("REQ-003", "数据导出功能", "支持导出Excel、CSV格式", 88, "中")) + p1.add_requirement(Requirement("REQ-004", "系统日志管理", "记录所有操作日志", 85, "中")) + + m1 = Module("用户认证模块", "实现登录、注册、权限管理", ["REQ-001"]) + m1.add_tech("Spring Boot") + m1.add_tech("Spring Security") + m1.add_tech("JWT") + m1.progress = 60 + p1.add_module(m1) + + m2 = Module("数据监控模块", "实时数据采集和可视化", ["REQ-002"]) + m2.add_tech("WebSocket") + m2.add_tech("ECharts") + m2.add_tech("Redis") + m2.progress = 40 + p1.add_module(m2) + + m3 = Module("数据管理模块", "数据查询、导出、备份", ["REQ-003"]) + m3.add_tech("MyBatis") + m3.add_tech("POI") + m3.add_tech("MySQL") + m3.progress = 30 + p1.add_module(m3) + + p1.add_document(Document("需求规格说明书.docx", "SRS", "2.3 MB")) + p1.add_document(Document("功能设计文档.docx", "功能设计", "1.8 MB")) + p1.add_document(Document("软件概要设计文档.docx", "概要设计", "3.1 MB")) + p1.add_document(Document("接口文档.pdf", "API", "1.2 MB")) + + # 项目2 + p2 = Project("数据分析平台", "大数据可视化分析工具", "已完成") + + # 项目3 + p3 = Project("物联网管理系统", "设备管理与数据采集", "进行中") + + self.projects = [p1, p2, p3] + self._refresh_project_list() + + def _refresh_project_list(self): + """刷新项目列表""" + self.project_list.clear() + + for project in self.projects: + item = QListWidgetItem() + item_widget = ProjectItemWidget(project) + item_widget.clicked.connect(self._load_project) + + item.setSizeHint(item_widget.sizeHint()) + item.setData(Qt.UserRole, project) + + self.project_list.addItem(item) + self.project_list.setItemWidget(item, item_widget) + + def _on_project_clicked(self, item): + """项目点击事件""" + project = item.data(Qt.UserRole) + if project: + self._load_project(project) + + def _load_project(self, project): + """加载项目""" + self.current_project = project + self.status_label.setText(f"当前项目: {project.name}") + self.statusBar().showMessage(f"已加载项目: {project.name}") + + # 加载原始需求 + self.original_req_text.setText(project.original_requirement) + + # 加载需求列表 + self.req_list.clear() + for req in project.requirements: + item = QListWidgetItem() + item_widget = RequirementItemWidget(req) + + item.setSizeHint(item_widget.sizeHint()) + self.req_list.addItem(item) + self.req_list.setItemWidget(item, item_widget) + + # 加载功能模块 + self.module_list.clear() + for module in project.modules: + item = QListWidgetItem() + item_widget = ModuleItemWidget(module) + + item.setSizeHint(item_widget.sizeHint()) + item.setData(Qt.UserRole, module) + self.module_list.addItem(item) + self.module_list.setItemWidget(item, item_widget) + + # 加载文档列表 + self.doc_list.clear() + for doc in project.documents: + item = QListWidgetItem(f"{doc.icon} {doc.name}") + item.setData(Qt.UserRole, doc) + self.doc_list.addItem(item) + + # 加载代码树 + self._load_code_tree(project) + + def _load_code_tree(self, project): + """加载代码树""" + self.code_tree.clear() + root = QTreeWidgetItem(self.code_tree, [f"📁 {project.name}"]) + + # src目录 + src = QTreeWidgetItem(root, ["📁 src"]) + QTreeWidgetItem(src, ["📄 Application.java"]) + + # modules目录 + modules = QTreeWidgetItem(src, ["📁 modules"]) + for module in project.modules: + module_name = module.name.replace("模块", "Module").replace(" ", "") + QTreeWidgetItem(modules, [f"☕ {module_name}.java"]) + + # utils目录 + utils = QTreeWidgetItem(src, ["📁 utils"]) + QTreeWidgetItem(utils, ["📄 HttpUtil.java"]) + QTreeWidgetItem(utils, ["📄 DateUtil.java"]) + QTreeWidgetItem(utils, ["📄 StringUtil.java"]) + + # 配置文件 + QTreeWidgetItem(root, ["📋 pom.xml"]) + QTreeWidgetItem(root, ["📋 application.yml"]) + QTreeWidgetItem(root, ["📝 README.md"]) + + self.code_tree.expandAll() + + def _create_new_project(self): + """创建新项目""" + dialog = NewProjectDialog(self) + if dialog.exec_() == dialog.Accepted: + project = dialog.get_project() + if project: + self.projects.insert(0, project) + self._refresh_project_list() + self._load_project(project) + QMessageBox.information( + self, + "成功", + f"项目 '{project.name}' 创建成功!" + ) + + def _filter_projects(self, text): + """过滤项目""" + for i in range(self.project_list.count()): + item = self.project_list.item(i) + project = item.data(Qt.UserRole) + if project: + visible = ( + text.lower() in project.name.lower() or + text.lower() in project.description.lower() + ) + item.setHidden(not visible) + + def _show_project_context_menu(self, pos): + """显示项目右键菜单""" + item = self.project_list.itemAt(pos) + if not item: + return + + menu = QMenu(self) + + open_action = menu.addAction("📂 打开项目") + open_action.triggered.connect(lambda: self._on_project_clicked(item)) + + menu.addSeparator() + + rename_action = menu.addAction("✏ 重命名") + rename_action.triggered.connect(lambda: self._rename_project(item)) + + export_action = menu.addAction("📤 导出项目") + export_action.triggered.connect(self._export_project) + + menu.addSeparator() + + delete_action = menu.addAction("🗑 删除项目") + delete_action.triggered.connect(lambda: self._delete_project(item)) + + menu.exec_(self.project_list.mapToGlobal(pos)) + + def _show_doc_context_menu(self, pos): + """显示文档右键菜单""" + item = self.doc_list.itemAt(pos) + if not item: + return + + menu = QMenu(self) + + open_action = menu.addAction("👁 预览") + open_action.triggered.connect(lambda: self._open_document(item)) + + download_action = menu.addAction("⬇ 下载") + download_action.triggered.connect(lambda: self._download_document(item)) + + menu.exec_(self.doc_list.mapToGlobal(pos)) + + def _show_code_context_menu(self, pos): + """显示代码右键菜单""" + item = self.code_tree.itemAt(pos) + if not item: + return + + menu = QMenu(self) + + open_action = menu.addAction("👁 查看代码") + open_action.triggered.connect(lambda: self._open_code_file(item, 0)) + + download_action = menu.addAction("⬇ 下载文件") + download_action.triggered.connect(lambda: self._download_code_file(item)) + + menu.exec_(self.code_tree.mapToGlobal(pos)) + + def _show_module_detail(self, item): + """显示模块详情""" + module = item.data(Qt.UserRole) + if module: + dialog = ModuleDetailDialog(module, self) + dialog.exec_() + + def _open_document(self, item): + """打开文档""" + doc = item.data(Qt.UserRole) + if doc: + QMessageBox.information( + self, + "文档预览", + f"正在打开文档: {doc.name}\n\n" + f"类型: {doc.doc_type}\n" + f"大小: {doc.size}" + ) + + def _download_document(self, item): + """下载文档""" + doc = item.data(Qt.UserRole) + if doc: + file_path, _ = QFileDialog.getSaveFileName( + self, + "保存文档", + doc.name + ) + if file_path: + QMessageBox.information( + self, + "下载", + f"文档已保存到:\n{file_path}" + ) + self.statusBar().showMessage(f"已下载: {doc.name}", 3000) + + def _download_all_documents(self): + """下载所有文档""" + if not self.current_project: + QMessageBox.warning(self, "提示", "请先选择一个项目") + return + + folder = QFileDialog.getExistingDirectory(self, "选择保存目录") + if folder: + QMessageBox.information( + self, + "下载", + f"所有文档已保存到:\n{folder}" + ) + self.statusBar().showMessage("文档批量下载完成", 3000) + + def _open_code_file(self, item, column): + """打开代码文件""" + file_name = item.text(0) + if "📄" in file_name or "☕" in file_name or "📋" in file_name or "📝" in file_name: + file_name = file_name.replace("📄 ", "").replace("☕ ", "").replace("📋 ", "").replace("📝 ", "") + dialog = CodeViewDialog(file_name, self) + dialog.exec_() + + def _download_code_file(self, item): + """下载代码文件""" + file_name = item.text(0).replace("📄 ", "").replace("📁 ", "").replace("☕ ", "").replace("📋 ", "").replace( + "📝 ", "") + file_path, _ = QFileDialog.getSaveFileName( + self, + "保存代码文件", + file_name + ) + if file_path: + QMessageBox.information( + self, + "下载", + f"文件已保存到:\n{file_path}" + ) + self.statusBar().showMessage(f"已下载: {file_name}", 3000) + + def _download_all_code(self): + """下载所有代码""" + if not self.current_project: + QMessageBox.warning(self, "提示", "请先选择一个项目") + return + + folder = QFileDialog.getExistingDirectory(self, "选择保存目录") + if folder: + QMessageBox.information( + self, + "下载", + f"项目代码已打包保存到:\n{folder}" + ) + self.statusBar().showMessage("代码下载完成", 3000) + + def _rename_project(self, item): + """重命名项目""" + project = item.data(Qt.UserRole) + if project: + new_name, ok = QInputDialog.getText( + self, + "重命名项目", + "新项目名称:", + text=project.name + ) + if ok and new_name: + project.name = new_name + self._refresh_project_list() + self.statusBar().showMessage(f"项目已重命名为: {new_name}", 3000) + + def _delete_project(self, item): + """删除项目""" + project = item.data(Qt.UserRole) + if project: + reply = QMessageBox.question( + self, + "确认删除", + f"确定要删除项目 '{project.name}' 吗?\n此操作不可恢复!", + QMessageBox.Yes | QMessageBox.No + ) + if reply == QMessageBox.Yes: + self.projects.remove(project) + self._refresh_project_list() + if self.current_project == project: + self.current_project = None + self.status_label.setText("无项目") + self.statusBar().showMessage(f"已删除项目: {project.name}", 3000) + + def _save_project(self): + """保存项目""" + if self.current_project: + QMessageBox.information( + self, + "保存", + f"项目 '{self.current_project.name}' 已保存" + ) + self.statusBar().showMessage("项目已保存", 3000) + else: + QMessageBox.warning(self, "提示", "没有打开的项目") + + def _export_project(self): + """导出项目""" + if not self.current_project: + QMessageBox.warning(self, "提示", "请先选择一个项目") + return + + file_path, _ = QFileDialog.getSaveFileName( + self, + "导出项目", + f"{self.current_project.name}.zip", + "ZIP文件 (*.zip)" + ) + if file_path: + QMessageBox.information( + self, + "导出", + f"项目已导出到:\n{file_path}" + ) + self.statusBar().showMessage("项目导出完成", 3000) + + def _run_pipeline(self): + """运行流水线""" + if not self.current_project: + QMessageBox.warning(self, "提示", "请先选择一个项目") + return + + dialog = PipelineDialog(self.current_project, self) + dialog.exec_() + + def _show_settings(self): + """显示设置""" + QMessageBox.information(self, "设置", "设置功能开发中...") + + def _show_help(self): + """显示帮助""" + help_text = """ +

智能低代码开发平台 v1.0

+

快捷键:

+
    +
  • Ctrl+N - 新建项目
  • +
  • Ctrl+S - 保存项目
  • +
+

功能说明:

+
    +
  • 支持基于AI的需求分析和功能生成
  • +
  • 自动生成项目文档和代码结构
  • +
  • 集成流水线进行编译、打包、部署
  • +
  • 支持多种项目类型和技术栈
  • +
+

使用提示:

+
    +
  • 双击模块查看详细信息
  • +
  • 右键点击项目/文档/代码可查看更多操作
  • +
  • 使用搜索框快速定位项目
  • +
+ """ + QMessageBox.about(self, "帮助", help_text) + + def _show_welcome(self): + """显示欢迎消息""" + self.statusBar().showMessage( + "欢迎使用智能低代码开发平台!按 Ctrl+N 创建新项目", + 5000 + )