tab3.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #!/usr/bin/env python3
  2. """
  3. Tab3内容生成器 - 整体结构理解
  4. 包含:整体解构(节点基础信息、整体实质×形式、纵向逻辑流)、段落解构
  5. """
  6. import html as html_module
  7. from typing import Dict, Any, List
  8. def render_overall_deconstruction_card(overall: Dict[str, Any]) -> str:
  9. """渲染整体解构卡片"""
  10. card_id = "overall-deconstruction"
  11. html = f'<div class="point-card overall-card" data-card-id="{card_id}">\n'
  12. html += f'<div class="point-card-header" onclick="toggleCardDetails(\'{card_id}\')">\n'
  13. html += '<span class="point-text">整体解构</span>\n'
  14. html += '<span class="toggle-icon">▼</span>\n'
  15. html += '</div>\n'
  16. html += f'<div class="point-card-details" id="{card_id}-details">\n'
  17. # 节点基础信息
  18. basic_info = overall.get("节点基础信息", "")
  19. if basic_info:
  20. html += '<div class="detail-section">\n'
  21. html += '<strong>节点基础信息:</strong>\n'
  22. html += f'<div class="detail-text">{html_module.escape(basic_info)}</div>\n'
  23. html += '</div>\n'
  24. # 整体实质×形式
  25. substance_form = overall.get("整体实质×形式", {})
  26. if substance_form:
  27. html += '<div class="detail-section">\n'
  28. html += '<strong>整体实质×形式:</strong>\n'
  29. # 处理可能是字符串或字典的情况
  30. if isinstance(substance_form, dict):
  31. if substance_form.get("抽象概念"):
  32. html += f'<div class="form-item"><strong>抽象概念:</strong>{html_module.escape(substance_form["抽象概念"])}</div>\n'
  33. if substance_form.get("画面形式"):
  34. html += f'<div class="form-item"><strong>画面形式:</strong>{html_module.escape(substance_form["画面形式"])}</div>\n'
  35. if substance_form.get("文案形式"):
  36. html += f'<div class="form-item"><strong>文案形式:</strong>{html_module.escape(substance_form["文案形式"])}</div>\n'
  37. if substance_form.get("声音形式"):
  38. html += f'<div class="form-item"><strong>声音形式:</strong>{html_module.escape(substance_form["声音形式"])}</div>\n'
  39. elif isinstance(substance_form, str):
  40. html += f'<div class="form-item">{html_module.escape(substance_form)}</div>\n'
  41. html += '</div>\n'
  42. # 纵向逻辑流
  43. logic_flow = overall.get("纵向逻辑流", [])
  44. if logic_flow:
  45. html += '<div class="detail-section">\n'
  46. html += '<strong>纵向逻辑流:</strong>\n'
  47. html += '<div class="logic-flow">\n'
  48. for stage in logic_flow:
  49. stage_num = stage.get("阶段编号", "")
  50. stage_name = stage.get("阶段逻辑名称", "")
  51. stage_desc = stage.get("阶段逻辑描述", "")
  52. html += '<div class="logic-stage">\n'
  53. if stage_num:
  54. html += f'<div class="stage-number">阶段 {stage_num}</div>\n'
  55. if stage_name:
  56. html += f'<div class="stage-name">{html_module.escape(stage_name)}</div>\n'
  57. if stage_desc:
  58. html += f'<div class="stage-desc">{html_module.escape(stage_desc)}</div>\n'
  59. html += '</div>\n'
  60. html += '</div>\n'
  61. html += '</div>\n'
  62. html += '</div>\n'
  63. html += '</div>\n'
  64. return html
  65. def render_paragraph_card(paragraph: Dict[str, Any], idx: int) -> str:
  66. """渲染段落解构卡片"""
  67. para_num = paragraph.get("段落序号", idx)
  68. time_range = paragraph.get("时间范围", "")
  69. units = paragraph.get("包含单元", [])
  70. full_text = paragraph.get("段落完整文案", "")
  71. card_id = f'paragraph-{para_num}'
  72. html = f'<div class="point-card paragraph-card" data-card-id="{card_id}">\n'
  73. html += f'<div class="point-card-header" onclick="toggleCardDetails(\'{card_id}\')">\n'
  74. html += f'<span class="point-number">段落 #{para_num}</span>\n'
  75. if time_range:
  76. html += f'<span class="point-time">{html_module.escape(time_range)}</span>\n'
  77. if units:
  78. units_str = ", ".join([str(u) for u in units])
  79. html += f'<span class="point-units">包含单元: {units_str}</span>\n'
  80. html += '<span class="toggle-icon">▼</span>\n'
  81. html += '</div>\n'
  82. html += f'<div class="point-card-details" id="{card_id}-details">\n'
  83. # 段落完整文案
  84. if full_text:
  85. html += '<div class="detail-section">\n'
  86. html += '<strong>段落完整文案:</strong>\n'
  87. html += f'<div class="detail-text">{html_module.escape(full_text)}</div>\n'
  88. html += '</div>\n'
  89. # 具体元素实质和形式
  90. concrete_elements = paragraph.get("具体元素实质和形式", [])
  91. if concrete_elements:
  92. html += '<div class="detail-section">\n'
  93. html += '<strong>具体元素实质和形式:</strong>\n'
  94. for elem in concrete_elements:
  95. elem_name = elem.get("具体元素名称", "")
  96. html += '<div class="sub-section">\n'
  97. if elem_name:
  98. html += f'<div class="element-name"><strong>{html_module.escape(elem_name)}</strong></div>\n'
  99. if elem.get("对应形式-文案"):
  100. html += f'<div class="form-item"><strong>对应形式-文案:</strong>{html_module.escape(elem["对应形式-文案"])}</div>\n'
  101. if elem.get("对应形式-画面"):
  102. html += f'<div class="form-item"><strong>对应形式-画面:</strong>{html_module.escape(elem["对应形式-画面"])}</div>\n'
  103. if elem.get("对应形式-声音"):
  104. html += f'<div class="form-item"><strong>对应形式-声音:</strong>{html_module.escape(elem["对应形式-声音"])}</div>\n'
  105. html += '</div>\n'
  106. html += '</div>\n'
  107. # 具象概念实质和形式
  108. concrete_concepts = paragraph.get("具象概念实质和形式", [])
  109. if concrete_concepts:
  110. html += '<div class="detail-section">\n'
  111. html += '<strong>具象概念实质和形式:</strong>\n'
  112. for concept in concrete_concepts:
  113. concept_name = concept.get("具象概念名称", "")
  114. html += '<div class="sub-section">\n'
  115. if concept_name:
  116. html += f'<div class="element-name"><strong>{html_module.escape(concept_name)}</strong></div>\n'
  117. if concept.get("对应形式-文案"):
  118. html += f'<div class="form-item"><strong>对应形式-文案:</strong>{html_module.escape(concept["对应形式-文案"])}</div>\n'
  119. if concept.get("对应形式-画面"):
  120. html += f'<div class="form-item"><strong>对应形式-画面:</strong>{html_module.escape(concept["对应形式-画面"])}</div>\n'
  121. if concept.get("对应形式-声音"):
  122. html += f'<div class="form-item"><strong>对应形式-声音:</strong>{html_module.escape(concept["对应形式-声音"])}</div>\n'
  123. html += '</div>\n'
  124. html += '</div>\n'
  125. # 抽象概念实质和形式
  126. abstract_concepts = paragraph.get("抽象概念实质和形式", [])
  127. if abstract_concepts:
  128. html += '<div class="detail-section">\n'
  129. html += '<strong>抽象概念实质和形式:</strong>\n'
  130. for concept in abstract_concepts:
  131. concept_name = concept.get("抽象概念名称", "")
  132. html += '<div class="sub-section">\n'
  133. if concept_name:
  134. html += f'<div class="element-name"><strong>{html_module.escape(concept_name)}</strong></div>\n'
  135. if concept.get("对应形式-文案"):
  136. html += f'<div class="form-item"><strong>对应形式-文案:</strong>{html_module.escape(concept["对应形式-文案"])}</div>\n'
  137. if concept.get("对应形式-画面"):
  138. html += f'<div class="form-item"><strong>对应形式-画面:</strong>{html_module.escape(concept["对应形式-画面"])}</div>\n'
  139. if concept.get("对应形式-声音"):
  140. html += f'<div class="form-item"><strong>对应形式-声音:</strong>{html_module.escape(concept["对应形式-声音"])}</div>\n'
  141. html += '</div>\n'
  142. html += '</div>\n'
  143. html += '</div>\n'
  144. html += '</div>\n'
  145. return html
  146. def generate_tab3_content(data: Dict[str, Any]) -> str:
  147. """生成Tab3内容:整体结构理解"""
  148. html = '<div class="tab-content" id="tab3" style="display: none;">\n'
  149. html += '<div class="section">\n'
  150. html += '<h3>整体结构理解</h3>\n'
  151. structure_understanding = data.get("整体结构理解", {})
  152. if not structure_understanding:
  153. html += '<p>暂无数据</p>\n'
  154. else:
  155. # 整体解构
  156. overall = structure_understanding.get("整体解构", {})
  157. if overall:
  158. html += render_overall_deconstruction_card(overall)
  159. # 段落解构
  160. paragraph_list = structure_understanding.get("段落解构", [])
  161. if paragraph_list:
  162. html += '<div class="section-divider"></div>\n'
  163. html += f'<div class="section-info">共 {len(paragraph_list)} 个段落</div>\n'
  164. for idx, paragraph in enumerate(paragraph_list, start=1):
  165. html += render_paragraph_card(paragraph, idx)
  166. html += '</div>\n'
  167. html += '</div>\n'
  168. return html