123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- 软著项目诊断和自动修复工具
- 功能:全面诊断项目状态,自动修复常见问题,提供用户友好的操作指导
- 修复功能:
- 1. 自动检测和修复常见配置问题
- 2. 恢复缺失的文件和目录
- 3. 修复权限和编码问题
- 4. 提供智能操作建议
- 5. 一键式问题解决方案
- """
- import os
- import sys
- import json
- import shutil
- import subprocess
- from pathlib import Path
- from datetime import datetime
- from typing import Dict, List, Optional, Tuple
- # 颜色输出类
- class Colors:
- RED = '\033[0;31m'
- GREEN = '\033[0;32m'
- YELLOW = '\033[1;33m'
- BLUE = '\033[0;34m'
- PURPLE = '\033[0;35m'
- CYAN = '\033[0;36m'
- BOLD = '\033[1m'
- NC = '\033[0m' # No Color
- def print_success(message: str):
- print(f"{Colors.GREEN}✓ {message}{Colors.NC}")
- def print_info(message: str):
- print(f"{Colors.BLUE}ℹ {message}{Colors.NC}")
- def print_warning(message: str):
- print(f"{Colors.YELLOW}⚠ {message}{Colors.NC}")
- def print_error(message: str):
- print(f"{Colors.RED}✗ {message}{Colors.NC}")
- def print_header(message: str):
- print(f"{Colors.PURPLE}{Colors.BOLD}{'=' * 80}{Colors.NC}")
- print(f"{Colors.PURPLE}{Colors.BOLD}{message.center(80)}{Colors.NC}")
- print(f"{Colors.PURPLE}{Colors.BOLD}{'=' * 80}{Colors.NC}")
- def print_fix(message: str):
- print(f"{Colors.CYAN}🔧 {message}{Colors.NC}")
- class ProjectDoctor:
- """项目诊断和修复工具"""
-
- def __init__(self):
- self.project_root = Path.cwd()
- self.original_template_dir = None
- self.issues_found = []
- self.fixes_applied = []
- self.recommendations = []
-
- # 查找原始模板目录
- possible_template_dirs = [
- Path.home() / "AI-Copyright-Application-Generator",
- Path("/usr/local/AI-Copyright-Application-Generator"),
- Path("../AI-Copyright-Application-Generator"),
- Path("../../AI-Copyright-Application-Generator")
- ]
-
- for template_dir in possible_template_dirs:
- if template_dir.exists() and (template_dir / "scripts").exists():
- self.original_template_dir = template_dir
- break
-
- def add_issue(self, severity: str, description: str):
- """添加发现的问题"""
- self.issues_found.append({'severity': severity, 'description': description})
-
- def add_fix(self, description: str):
- """添加应用的修复"""
- self.fixes_applied.append(description)
-
- def add_recommendation(self, description: str):
- """添加建议"""
- self.recommendations.append(description)
-
- def check_project_structure(self) -> bool:
- """检查项目目录结构"""
- print_info("检查项目目录结构...")
-
- required_dirs = [
- "specs_docs/ui_design_specs",
- "specs_docs/tech_stack_specs",
- "system_prompts",
- "requires_docs",
- "process_docs",
- "output_docs",
- "output_sourcecode/front",
- "output_sourcecode/backend",
- "output_sourcecode/db",
- "scripts/generators",
- "scripts/validators"
- ]
-
- missing_dirs = []
- for directory in required_dirs:
- dir_path = self.project_root / directory
- if not dir_path.exists():
- missing_dirs.append(directory)
- self.add_issue("error", f"缺失关键目录: {directory}")
-
- if missing_dirs:
- return self.fix_missing_directories(missing_dirs)
- else:
- print_success("目录结构完整")
- return True
-
- def fix_missing_directories(self, missing_dirs: List[str]) -> bool:
- """修复缺失的目录"""
- print_fix("正在修复缺失的目录...")
-
- try:
- for directory in missing_dirs:
- dir_path = self.project_root / directory
- dir_path.mkdir(parents=True, exist_ok=True)
- print_success(f"创建目录: {directory}")
- self.add_fix(f"创建缺失目录: {directory}")
- return True
- except Exception as e:
- print_error(f"目录修复失败: {e}")
- return False
-
- def check_config_file(self) -> bool:
- """检查配置文件"""
- print_info("检查配置文件...")
-
- config_file = self.project_root / "ai-copyright-config.json"
-
- if not config_file.exists():
- self.add_issue("error", "配置文件不存在")
- return self.fix_missing_config()
-
- try:
- with open(config_file, 'r', encoding='utf-8') as f:
- config = json.load(f)
-
- # 检查必需的配置项
- required_keys = ['title', 'ui_design_style', 'generation_mode', 'ui_design_spec']
- missing_keys = [key for key in required_keys if key not in config]
-
- if missing_keys:
- self.add_issue("warning", f"配置文件缺少必要字段: {', '.join(missing_keys)}")
- return self.fix_config_keys(config, missing_keys)
-
- print_success("配置文件正常")
- return True
-
- except json.JSONDecodeError:
- self.add_issue("error", "配置文件JSON格式错误")
- return self.fix_config_format()
- except Exception as e:
- self.add_issue("error", f"配置文件读取失败: {e}")
- return False
-
- def fix_missing_config(self) -> bool:
- """修复缺失的配置文件"""
- print_fix("正在生成默认配置文件...")
-
- default_config = {
- "_comment_init": "=== 项目初始化配置(用户设置) ===",
- "front": "JavaScript",
- "backend": "Java",
- "title": "软件系统",
- "short_title": "软件系统",
- "requirements_description": "requires_docs/需求文档.md",
- "dev_tech_stack": "specs_docs/tech_stack_specs/技术栈说明文档_默认.md",
- "ui_design_spec": "specs_docs/ui_design_specs/01-UI设计规范_默认_Corporate.md",
- "ui_design_style": "corporate",
-
- "_comment_generation": "=== 生成配置(可调整) ===",
- "page_count_fast": 5,
- "page_count_full": 10,
- "api_count_min": 8,
- "api_count_max": 35,
- "generation_mode": "fast",
-
- "_comment_usage": "=== 使用说明 ===",
- "_usage_note_1": "请修改 title 和 short_title 为您的实际项目名称",
- "_usage_note_2": "可根据实际情况调整技术栈和UI设计风格",
- "_usage_note_3": "详细说明请参考项目文档",
-
- "_comment_fixed": "=== 固定配置(请勿修改) ===",
- "system_prompt_dir": "system_prompts",
- "ui_design_spec_default": "specs_docs/ui_design_specs/01-UI设计规范_默认_Corporate.md"
- }
-
- try:
- config_file = self.project_root / "ai-copyright-config.json"
- with open(config_file, 'w', encoding='utf-8') as f:
- json.dump(default_config, f, ensure_ascii=False, indent=2)
-
- print_success("已生成默认配置文件")
- self.add_fix("生成默认配置文件")
- self.add_recommendation("请修改配置文件中的项目名称和技术栈信息")
- return True
-
- except Exception as e:
- print_error(f"配置文件生成失败: {e}")
- return False
-
- def fix_config_keys(self, config: dict, missing_keys: List[str]) -> bool:
- """修复配置文件缺失的键"""
- print_fix("正在补充配置文件缺失字段...")
-
- defaults = {
- 'title': '软件系统',
- 'ui_design_style': 'corporate',
- 'generation_mode': 'fast',
- 'ui_design_spec': 'specs_docs/ui_design_specs/01-UI设计规范_默认_Corporate.md'
- }
-
- for key in missing_keys:
- if key in defaults:
- config[key] = defaults[key]
- print_success(f"添加配置项: {key} = {defaults[key]}")
-
- try:
- config_file = self.project_root / "ai-copyright-config.json"
- with open(config_file, 'w', encoding='utf-8') as f:
- json.dump(config, f, ensure_ascii=False, indent=2)
-
- self.add_fix(f"补充配置文件字段: {', '.join(missing_keys)}")
- return True
-
- except Exception as e:
- print_error(f"配置文件更新失败: {e}")
- return False
-
- def check_scripts(self) -> bool:
- """检查脚本文件"""
- print_info("检查脚本文件...")
-
- script_dirs = ["scripts/generators", "scripts/validators"]
- missing_scripts = []
-
- for script_dir in script_dirs:
- dir_path = self.project_root / script_dir
- if not dir_path.exists():
- missing_scripts.append(script_dir)
- continue
-
- # 检查是否有脚本文件
- script_files = list(dir_path.glob("*.py")) + list(dir_path.glob("*.sh"))
- if not script_files:
- missing_scripts.append(f"{script_dir} (空目录)")
-
- if missing_scripts:
- self.add_issue("error", f"缺失脚本: {', '.join(missing_scripts)}")
- return self.fix_missing_scripts()
- else:
- print_success("脚本文件完整")
- return True
-
- def fix_missing_scripts(self) -> bool:
- """修复缺失的脚本"""
- if not self.original_template_dir:
- print_error("未找到原始模板目录,无法自动修复脚本")
- self.add_recommendation("请手动从原始项目复制 scripts/ 目录")
- return False
-
- print_fix("正在从模板恢复脚本文件...")
-
- try:
- source_scripts = self.original_template_dir / "scripts"
- target_scripts = self.project_root / "scripts"
-
- if source_scripts.exists():
- # 确保目标目录存在
- target_scripts.mkdir(exist_ok=True)
-
- # 复制generators目录
- source_gen = source_scripts / "generators"
- target_gen = target_scripts / "generators"
- if source_gen.exists():
- target_gen.mkdir(exist_ok=True)
- for script_file in source_gen.iterdir():
- if script_file.is_file():
- shutil.copy2(script_file, target_gen / script_file.name)
- print_success("恢复 generators 脚本")
-
- # 复制validators目录
- source_val = source_scripts / "validators"
- target_val = target_scripts / "validators"
- if source_val.exists():
- target_val.mkdir(exist_ok=True)
- for script_file in source_val.iterdir():
- if script_file.is_file():
- shutil.copy2(script_file, target_val / script_file.name)
- print_success("恢复 validators 脚本")
-
- # 设置执行权限
- self.fix_script_permissions()
-
- self.add_fix("从模板恢复脚本文件")
- return True
- else:
- print_error("模板目录中未找到scripts文件夹")
- return False
-
- except Exception as e:
- print_error(f"脚本恢复失败: {e}")
- return False
-
- def fix_script_permissions(self) -> bool:
- """修复脚本权限"""
- print_fix("设置脚本执行权限...")
-
- script_dirs = ["scripts/generators", "scripts/validators"]
-
- try:
- for script_dir in script_dirs:
- dir_path = self.project_root / script_dir
- if dir_path.exists():
- for script_file in dir_path.iterdir():
- if script_file.is_file() and script_file.suffix in ['.py', '.sh']:
- script_file.chmod(0o755)
-
- print_success("脚本权限设置完成")
- self.add_fix("设置脚本执行权限")
- return True
-
- except Exception as e:
- print_error(f"权限设置失败: {e}")
- return False
-
- def check_system_prompts(self) -> bool:
- """检查系统提示词"""
- print_info("检查系统提示词...")
-
- prompt_dir = self.project_root / "system_prompts"
- if not prompt_dir.exists():
- self.add_issue("error", "系统提示词目录不存在")
- return False
-
- expected_prompts = [
- "01-软著框架系统提示词.md",
- "02-页面规划系统提示词.md",
- "03-界面设计系统提示词.md",
- "04-网页代码生成系统提示词.md",
- "05-数据库代码生成系统提示词.md",
- "06-后端代码生成系统提示词.md",
- "07-用户手册系统提示词.md",
- "08-软件著作权登记信息表系统提示词.md"
- ]
-
- missing_prompts = []
- for prompt_file in expected_prompts:
- if not (prompt_dir / prompt_file).exists():
- missing_prompts.append(prompt_file)
-
- if missing_prompts:
- self.add_issue("error", f"缺失系统提示词: {len(missing_prompts)}/{len(expected_prompts)}")
- return self.fix_missing_prompts(missing_prompts)
- else:
- print_success("系统提示词完整")
- return True
-
- def fix_missing_prompts(self, missing_prompts: List[str]) -> bool:
- """修复缺失的系统提示词"""
- if not self.original_template_dir:
- print_error("未找到原始模板目录,无法自动修复提示词")
- self.add_recommendation("请手动从原始项目复制 system_prompts/ 目录")
- return False
-
- print_fix("正在从模板恢复系统提示词...")
-
- try:
- source_prompts = self.original_template_dir / "system_prompts"
- target_prompts = self.project_root / "system_prompts"
-
- if source_prompts.exists():
- target_prompts.mkdir(exist_ok=True)
-
- for prompt_file in missing_prompts:
- source_file = source_prompts / prompt_file
- target_file = target_prompts / prompt_file
-
- if source_file.exists():
- shutil.copy2(source_file, target_file)
- print_success(f"恢复: {prompt_file}")
-
- self.add_fix(f"恢复 {len(missing_prompts)} 个系统提示词文件")
- return True
- else:
- print_error("模板目录中未找到system_prompts文件夹")
- return False
-
- except Exception as e:
- print_error(f"系统提示词恢复失败: {e}")
- return False
-
- def check_requirements_doc(self) -> bool:
- """检查需求文档"""
- print_info("检查需求文档...")
-
- req_file = self.project_root / "requires_docs" / "需求文档.md"
-
- if not req_file.exists():
- self.add_issue("warning", "需求文档不存在")
- return self.fix_missing_requirements()
-
- try:
- with open(req_file, 'r', encoding='utf-8') as f:
- content = f.read()
-
- if len(content.strip()) < 100:
- self.add_issue("warning", "需求文档内容过少")
- self.add_recommendation("建议详细填写需求文档以获得更好的生成效果")
- else:
- print_success("需求文档存在且有内容")
-
- return True
-
- except Exception as e:
- self.add_issue("error", f"需求文档读取失败: {e}")
- return False
-
- def fix_missing_requirements(self) -> bool:
- """修复缺失的需求文档"""
- print_fix("正在创建需求文档模板...")
-
- template_content = f"""# 软件系统需求文档
- ## 项目背景
- 请在此描述项目的背景、目标和价值。
- ## 功能需求
- ### 核心功能
- 1. 用户管理功能
- - 用户注册、登录、注销
- - 用户信息管理和权限控制
- - 密码修改和找回
- 2. 数据管理功能
- - 数据录入、查询、修改、删除
- - 数据导入和导出
- - 数据统计和报表
- 3. 系统管理功能
- - 系统配置和参数设置
- - 日志管理和监控
- - 备份和恢复
- ### 非功能需求
- - 性能要求:系统响应时间不超过3秒
- - 安全要求:数据加密存储,支持HTTPS访问
- - 可用性要求:系统可用性达到99%以上
- - 兼容性要求:支持主流浏览器
- ## 技术要求
- - 前端技术:JavaScript, HTML5, CSS3
- - 后端技术:Java Spring Boot
- - 数据库:MySQL
- - 部署环境:Linux服务器
- ## 用户角色
- - 系统管理员:具有所有权限,负责系统维护
- - 普通用户:具有基本操作权限
- - 访客用户:只能查看公开信息
- ## 业务流程
- 1. 用户登录系统
- 2. 选择相应功能模块
- 3. 执行具体操作
- 4. 系统返回操作结果
- 5. 记录操作日志
- ---
- *请根据实际项目需求完善此文档内容*
- """
-
- try:
- req_file = self.project_root / "requires_docs" / "需求文档.md"
- req_file.parent.mkdir(exist_ok=True)
-
- with open(req_file, 'w', encoding='utf-8') as f:
- f.write(template_content)
-
- print_success("已创建需求文档模板")
- self.add_fix("创建需求文档模板")
- self.add_recommendation("请详细填写需求文档内容")
- return True
-
- except Exception as e:
- print_error(f"需求文档创建失败: {e}")
- return False
-
- def generate_diagnostic_report(self) -> str:
- """生成诊断报告"""
- current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-
- report = f"""
- {'-' * 80}
- 软著项目诊断报告
- {'-' * 80}
- 诊断时间: {current_time}
- 项目路径: {self.project_root}
- {'-' * 80}
- 问题诊断结果
- {'-' * 80}
- 发现问题总数: {len(self.issues_found)}
- """
-
- # 按严重程度分组问题
- errors = [issue for issue in self.issues_found if issue['severity'] == 'error']
- warnings = [issue for issue in self.issues_found if issue['severity'] == 'warning']
-
- if errors:
- report += "🔴 严重问题:\n"
- for i, issue in enumerate(errors, 1):
- report += f" {i}. {issue['description']}\n"
- report += "\n"
-
- if warnings:
- report += "🟡 警告问题:\n"
- for i, issue in enumerate(warnings, 1):
- report += f" {i}. {issue['description']}\n"
- report += "\n"
-
- if not self.issues_found:
- report += "✅ 未发现问题,项目状态良好\n\n"
-
- # 修复结果
- if self.fixes_applied:
- report += f"{'-' * 80}\n自动修复结果\n{'-' * 80}\n\n"
- report += f"成功修复: {len(self.fixes_applied)} 个问题\n\n"
- for i, fix in enumerate(self.fixes_applied, 1):
- report += f" {i}. {fix}\n"
- report += "\n"
-
- # 建议
- if self.recommendations:
- report += f"{'-' * 80}\n改进建议\n{'-' * 80}\n\n"
- for i, rec in enumerate(self.recommendations, 1):
- report += f" {i}. {rec}\n"
- report += "\n"
-
- # 下一步操作
- report += f"{'-' * 80}\n下一步操作建议\n{'-' * 80}\n\n"
-
- remaining_errors = len([issue for issue in self.issues_found if issue['severity'] == 'error']) - len([fix for fix in self.fixes_applied if '严重' in fix or '关键' in fix])
-
- if remaining_errors > 0:
- report += "🔴 仍有严重问题未解决:\n"
- report += " 1. 手动检查并修复剩余的严重问题\n"
- report += " 2. 重新运行诊断工具验证修复效果\n"
- report += " 3. 联系技术支持获取帮助\n"
- else:
- report += "✅ 项目已就绪,可以开始软著申请材料生成:\n"
- report += " 1. 详细填写 requires_docs/需求文档.md\n"
- report += " 2. 运行质量检查: python3 scripts/validators/validate_requirements.py\n"
- report += " 3. 开始按照工作流程生成申请材料\n"
- report += " 4. 定期运行质量监控: python3 scripts/validators/quality_monitor.py\n"
-
- report += f"\n{'-' * 80}\n诊断完成时间: {current_time}\n{'-' * 80}\n"
-
- return report
-
- def run_full_diagnosis(self) -> Dict[str, any]:
- """执行完整诊断"""
- print_header("软著项目健康诊断")
-
- print_info(f"项目路径: {self.project_root}")
- if self.original_template_dir:
- print_info(f"模板路径: {self.original_template_dir}")
- print()
-
- # 执行各项检查
- checks = [
- ("项目目录结构", self.check_project_structure),
- ("配置文件", self.check_config_file),
- ("脚本文件", self.check_scripts),
- ("系统提示词", self.check_system_prompts),
- ("需求文档", self.check_requirements_doc)
- ]
-
- check_results = {}
-
- for check_name, check_func in checks:
- print(f"\n{'-' * 40}")
- result = check_func()
- check_results[check_name] = result
- if result:
- print_success(f"{check_name}: 检查通过")
- else:
- print_error(f"{check_name}: 检查失败")
-
- print(f"\n{'-' * 40}")
-
- # 统计结果
- total_checks = len(checks)
- passed_checks = sum(check_results.values())
-
- print_header("诊断结果概览")
- print_info(f"检查项目: {passed_checks}/{total_checks} 通过")
- print_info(f"发现问题: {len(self.issues_found)} 个")
- print_info(f"自动修复: {len(self.fixes_applied)} 个")
-
- if passed_checks == total_checks and not self.issues_found:
- print_success("🎉 项目状态优秀,可以开始生成软著申请材料!")
- elif passed_checks >= total_checks * 0.8:
- print_warning("⚠️ 项目状态良好,有少量问题已自动修复")
- else:
- print_error("❌ 项目存在较多问题,请根据报告进行修复")
-
- return {
- 'total_checks': total_checks,
- 'passed_checks': passed_checks,
- 'issues_found': len(self.issues_found),
- 'fixes_applied': len(self.fixes_applied),
- 'check_results': check_results,
- 'health_score': (passed_checks / total_checks) * 100
- }
- def main():
- """主函数"""
- if len(sys.argv) > 1 and sys.argv[1] in ['-h', '--help']:
- print("软著项目诊断和自动修复工具")
- print("\n用法:")
- print(" python3 project_doctor.py")
- print("\n功能:")
- print(" - 全面诊断项目状态")
- print(" - 自动修复常见问题")
- print(" - 恢复缺失的文件和配置")
- print(" - 生成详细的诊断报告")
- print("\n检查项目:")
- print(" - 项目目录结构")
- print(" - 配置文件完整性")
- print(" - 脚本文件和权限")
- print(" - 系统提示词文件")
- print(" - 需求文档状态")
- print("\n输出:")
- print(" - 终端显示诊断过程和结果")
- print(" - 生成详细的诊断报告文件")
- return
-
- # 执行诊断
- doctor = ProjectDoctor()
- result = doctor.run_full_diagnosis()
-
- # 生成并保存报告
- print()
- print_info("生成详细诊断报告...")
-
- report = doctor.generate_diagnostic_report()
-
- # 保存报告
- report_file = Path("项目诊断报告.txt")
- try:
- with open(report_file, 'w', encoding='utf-8') as f:
- f.write(report)
- print_success(f"诊断报告已保存: {report_file}")
- except Exception as e:
- print_error(f"保存报告失败: {e}")
-
- # 显示关键建议
- if doctor.recommendations:
- print()
- print_header("重要建议")
- for i, rec in enumerate(doctor.recommendations[:3], 1): # 显示前3条
- print_info(f"{i}. {rec}")
-
- # 返回状态码
- health_score = result['health_score']
- if health_score >= 90:
- sys.exit(0) # 优秀
- elif health_score >= 70:
- sys.exit(1) # 良好但有改进空间
- else:
- sys.exit(2) # 需要重要改进
- if __name__ == "__main__":
- main()
|