merge_frontend_simple.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. 前端页面源代码软著申请专用拼接脚本 (Python版本)
  5. 功能:将所有前端HTML文件完整拼接成单一文档,专用于软件著作权申请材料
  6. 与现有generate_frontend_sourcecode.py的差异:
  7. - 现有脚本:分批生成,适用于AI对话(避免token超限)
  8. - 本脚本: 单文件生成,适用于软著申请(便于提交)
  9. 优点:
  10. - 生成单一完整文档,符合软著申请要求
  11. - 保持源代码完整性,无压缩或分批
  12. - 零token消耗,纯本地文本处理
  13. - 直接可用于软著申请提交
  14. - 跨平台兼容(Windows/Linux/macOS)
  15. """
  16. import sys
  17. import json
  18. from pathlib import Path
  19. from datetime import datetime
  20. from typing import List, Optional
  21. # 颜色输出类
  22. class Colors:
  23. RED = '\033[0;31m'
  24. GREEN = '\033[0;32m'
  25. YELLOW = '\033[1;33m'
  26. BLUE = '\033[0;34m'
  27. NC = '\033[0m' # No Color
  28. def print_success(message: str):
  29. print(f"{Colors.GREEN}✓ {message}{Colors.NC}")
  30. def print_info(message: str):
  31. print(f"{Colors.BLUE}ℹ {message}{Colors.NC}")
  32. def print_warning(message: str):
  33. print(f"{Colors.YELLOW}⚠ {message}{Colors.NC}")
  34. def print_error(message: str):
  35. print(f"{Colors.RED}✗ {message}{Colors.NC}")
  36. def get_project_config() -> Optional[dict]:
  37. """读取项目配置文件"""
  38. config_file = Path("ai-copyright-config.json")
  39. if not config_file.exists():
  40. print_error("配置文件不存在: ai-copyright-config.json")
  41. return None
  42. try:
  43. with open(config_file, 'r', encoding='utf-8') as f:
  44. return json.load(f)
  45. except json.JSONDecodeError as e:
  46. print_error(f"配置文件JSON格式错误: {e}")
  47. return None
  48. except Exception as e:
  49. print_error(f"读取配置文件失败: {e}")
  50. return None
  51. def collect_html_files(front_dir: Path) -> List[Path]:
  52. """收集所有HTML文件并排序"""
  53. if not front_dir.exists():
  54. return []
  55. html_files = []
  56. for file_path in front_dir.iterdir():
  57. if file_path.is_file() and file_path.suffix.lower() == '.html':
  58. html_files.append(file_path)
  59. # 按文件名排序,确保一致的输出顺序
  60. html_files.sort(key=lambda x: x.name.lower())
  61. return html_files
  62. def read_html_file(file_path: Path) -> str:
  63. """安全读取HTML文件内容"""
  64. try:
  65. with open(file_path, 'r', encoding='utf-8') as f:
  66. return f.read()
  67. except UnicodeDecodeError:
  68. # 尝试其他编码
  69. try:
  70. with open(file_path, 'r', encoding='gb2312') as f:
  71. return f.read()
  72. except:
  73. try:
  74. with open(file_path, 'r', encoding='latin-1') as f:
  75. return f.read()
  76. except Exception as e:
  77. print_warning(f"无法读取文件 {file_path.name}: {e}")
  78. return f"<!-- 文件读取失败: {file_path.name} -->"
  79. def generate_header(config: dict, file_count: int) -> str:
  80. """生成文档头部信息"""
  81. current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  82. header = f"""
  83. {'-' * 80}
  84. 软件著作权申请材料 - 前端源代码文档
  85. {'-' * 80}
  86. 软件名称: {config.get('title', '未设置')}
  87. 软件简称: {config.get('short_title', config.get('title', '未设置'))}
  88. 前端技术: {config.get('front', '未设置')}
  89. UI设计风格: {config.get('ui_design_style', '未设置')}
  90. 生成模式: {config.get('generation_mode', '未设置')}
  91. 文档生成信息:
  92. - 生成时间: {current_time}
  93. - 页面文件数量: {file_count}
  94. - 文档类型: 前端页面完整源代码
  95. - 编码格式: UTF-8
  96. {'-' * 80}
  97. """
  98. return header
  99. def generate_footer() -> str:
  100. """生成文档尾部信息"""
  101. footer = f"""
  102. {'-' * 80}
  103. 文档结束
  104. 生成工具: AI驱动的软件著作权申请材料生成系统 (Python版本)
  105. 生成时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
  106. {'-' * 80}
  107. """
  108. return footer
  109. def merge_frontend_files():
  110. """主要的前端文件合并逻辑"""
  111. print_info("🔄 开始拼接前端页面源代码...")
  112. # 1. 确定项目根目录
  113. script_dir = Path(__file__).parent.parent.parent
  114. front_dir = script_dir / "output_sourcecode" / "front"
  115. output_dir = script_dir / "output_docs"
  116. output_file = output_dir / "前端源代码.txt"
  117. print_info(f"项目根目录: {script_dir}")
  118. print_info(f"前端目录: {front_dir}")
  119. print_info(f"输出文件: {output_file}")
  120. # 2. 检查前端目录
  121. if not front_dir.exists():
  122. print_error(f"前端目录不存在: {front_dir}")
  123. print_info("💡 请先生成前端源代码文件")
  124. return False
  125. # 3. 确保输出目录存在
  126. output_dir.mkdir(parents=True, exist_ok=True)
  127. # 4. 读取项目配置
  128. config = get_project_config()
  129. if not config:
  130. print_warning("无法读取项目配置,使用默认配置")
  131. config = {
  132. 'title': '软件系统',
  133. 'short_title': '软件系统',
  134. 'front': 'JavaScript',
  135. 'ui_design_style': 'corporate',
  136. 'generation_mode': 'fast'
  137. }
  138. # 5. 收集HTML文件
  139. html_files = collect_html_files(front_dir)
  140. if not html_files:
  141. print_error(f"在 {front_dir} 中未发现HTML文件")
  142. print_info("💡 请先生成前端页面代码")
  143. return False
  144. print_success(f"发现 {len(html_files)} 个HTML文件")
  145. # 6. 开始合并文件
  146. try:
  147. with open(output_file, 'w', encoding='utf-8') as output:
  148. # 写入文档头部
  149. output.write(generate_header(config, len(html_files)))
  150. # 逐个处理HTML文件
  151. for i, html_file in enumerate(html_files, 1):
  152. print_info(f"处理文件 {i}/{len(html_files)}: {html_file.name}")
  153. # 添加文件分隔标识
  154. separator = f"""
  155. {'=' * 80}
  156. 文件 {i}: {html_file.name}
  157. 文件路径: output_sourcecode/front/{html_file.name}
  158. 文件大小: {html_file.stat().st_size} 字节
  159. {'=' * 80}
  160. """
  161. output.write(separator)
  162. # 读取并写入文件内容
  163. content = read_html_file(html_file)
  164. output.write(content)
  165. # 添加文件结束标识
  166. output.write(f"\n\n{'=' * 80}\n文件 {i} 结束: {html_file.name}\n{'=' * 80}\n\n")
  167. # 写入文档尾部
  168. output.write(generate_footer())
  169. # 7. 输出统计信息
  170. file_size = output_file.stat().st_size
  171. file_size_mb = file_size / (1024 * 1024)
  172. print_success("✅ 前端源代码拼接完成")
  173. print_info(f"📄 输出文件: {output_file}")
  174. print_info(f"📊 文件统计:")
  175. print_info(f" - HTML文件数量: {len(html_files)}")
  176. print_info(f" - 总文件大小: {file_size:,} 字节 ({file_size_mb:.2f} MB)")
  177. print_info(f" - 平均文件大小: {file_size // len(html_files):,} 字节")
  178. # 8. 生成详细报告
  179. with open(output_dir / "前端拼接报告.txt", 'w', encoding='utf-8') as report:
  180. report.write(f"前端源代码拼接报告\n")
  181. report.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
  182. report.write(f"文件列表:\n")
  183. for i, html_file in enumerate(html_files, 1):
  184. file_size = html_file.stat().st_size
  185. report.write(f"{i:2d}. {html_file.name} ({file_size:,} 字节)\n")
  186. report.write(f"\n总计: {len(html_files)} 个文件,{sum(f.stat().st_size for f in html_files):,} 字节\n")
  187. print_success("📋 生成详细报告: 前端拼接报告.txt")
  188. return True
  189. except Exception as e:
  190. print_error(f"文件合并过程中发生错误: {e}")
  191. return False
  192. def main():
  193. """主函数"""
  194. if len(sys.argv) > 1 and sys.argv[1] in ['-h', '--help']:
  195. print("前端页面源代码拼接脚本 (Python版本)")
  196. print("\n用法:")
  197. print(" python3 merge_frontend_simple.py")
  198. print("\n说明:")
  199. print(" 将 output_sourcecode/front/ 目录下的所有HTML文件")
  200. print(" 拼接成单一的源代码文档用于软著申请")
  201. print("\n输出:")
  202. print(" output_docs/前端源代码.txt")
  203. print(" output_docs/前端拼接报告.txt")
  204. return
  205. success = merge_frontend_files()
  206. sys.exit(0 if success else 1)
  207. if __name__ == "__main__":
  208. main()