adjustments.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. """
  2. 手动调整功能
  3. """
  4. import streamlit as st
  5. from .state_manager import save_state_for_undo
  6. from .drawing import clear_table_image_cache
  7. def create_adjustment_section(structure):
  8. """
  9. 创建手动调整区域
  10. Args:
  11. structure: 表格结构字典
  12. Returns:
  13. 是否进行了调整(用于判断是否需要重新渲染)
  14. """
  15. st.divider()
  16. st.header("🛠️ 手动调整")
  17. adjusted = False
  18. # 横线调整
  19. with st.expander("📏 调整横线位置", expanded=False):
  20. horizontal_lines = structure.get('horizontal_lines', [])
  21. if not horizontal_lines:
  22. st.warning("⚠️ 没有检测到横线")
  23. else:
  24. st.info(f"当前有 {len(horizontal_lines)} 条横线")
  25. # 选择要调整的横线
  26. line_index = st.selectbox(
  27. "选择横线",
  28. range(len(horizontal_lines)),
  29. format_func=lambda i: f"R{i+1} (Y={horizontal_lines[i]})"
  30. )
  31. # 显示当前Y坐标
  32. current_y = horizontal_lines[line_index]
  33. st.text(f"当前Y坐标: {current_y}")
  34. # 输入新的Y坐标
  35. col1, col2 = st.columns([3, 1])
  36. with col1:
  37. new_y = st.number_input(
  38. "新的Y坐标",
  39. min_value=0,
  40. value=current_y,
  41. step=1,
  42. key=f"h_line_{line_index}"
  43. )
  44. with col2:
  45. if st.button("✅ 应用", key=f"apply_h_{line_index}"):
  46. if new_y != current_y:
  47. # 保存状态
  48. save_state_for_undo(structure)
  49. # 更新横线
  50. structure['horizontal_lines'][line_index] = new_y
  51. # 标记为已修改
  52. structure.setdefault('modified_h_lines', set()).add(line_index)
  53. # 重新计算行区间
  54. _update_row_intervals(structure)
  55. clear_table_image_cache()
  56. adjusted = True
  57. st.success(f"✅ 已更新 R{line_index+1} 到 Y={new_y}")
  58. st.rerun()
  59. # 竖线调整
  60. with st.expander("📏 调整竖线位置", expanded=False):
  61. vertical_lines = structure.get('vertical_lines', [])
  62. if not vertical_lines:
  63. st.warning("⚠️ 没有检测到竖线")
  64. else:
  65. st.info(f"当前有 {len(vertical_lines)} 条竖线")
  66. # 选择要调整的竖线
  67. line_index = st.selectbox(
  68. "选择竖线",
  69. range(len(vertical_lines)),
  70. format_func=lambda i: f"C{i+1} (X={vertical_lines[i]})"
  71. )
  72. # 显示当前X坐标
  73. current_x = vertical_lines[line_index]
  74. st.text(f"当前X坐标: {current_x}")
  75. # 输入新的X坐标
  76. col1, col2 = st.columns([3, 1])
  77. with col1:
  78. new_x = st.number_input(
  79. "新的X坐标",
  80. min_value=0,
  81. value=current_x,
  82. step=1,
  83. key=f"v_line_{line_index}"
  84. )
  85. with col2:
  86. if st.button("✅ 应用", key=f"apply_v_{line_index}"):
  87. if new_x != current_x:
  88. # 保存状态
  89. save_state_for_undo(structure)
  90. # 更新竖线
  91. structure['vertical_lines'][line_index] = new_x
  92. # 标记为已修改
  93. structure.setdefault('modified_v_lines', set()).add(line_index)
  94. # 重新计算列区间
  95. _update_column_intervals(structure)
  96. clear_table_image_cache()
  97. adjusted = True
  98. st.success(f"✅ 已更新 C{line_index+1} 到 X={new_x}")
  99. st.rerun()
  100. # 添加横线
  101. with st.expander("➕ 添加横线", expanded=False):
  102. horizontal_lines = structure.get('horizontal_lines', [])
  103. col1, col2 = st.columns([3, 1])
  104. with col1:
  105. new_h_y = st.number_input(
  106. "新横线的Y坐标",
  107. min_value=0,
  108. value=horizontal_lines[-1] + 50 if horizontal_lines else 100,
  109. step=1,
  110. key="new_h_line"
  111. )
  112. with col2:
  113. if st.button("➕ 添加", key="add_h_line"):
  114. # 保存状态
  115. save_state_for_undo(structure)
  116. # 插入新横线(保持排序)
  117. horizontal_lines.append(new_h_y)
  118. horizontal_lines.sort()
  119. # 找到新线的索引
  120. new_index = horizontal_lines.index(new_h_y)
  121. # 标记为已修改
  122. structure.setdefault('modified_h_lines', set()).add(new_index)
  123. # 重新计算行区间
  124. _update_row_intervals(structure)
  125. clear_table_image_cache()
  126. adjusted = True
  127. st.success(f"✅ 已添加横线 Y={new_h_y}")
  128. st.rerun()
  129. # 删除横线
  130. with st.expander("🗑️ 删除横线", expanded=False):
  131. horizontal_lines = structure.get('horizontal_lines', [])
  132. if len(horizontal_lines) <= 2:
  133. st.warning("⚠️ 至少需要保留2条横线(表格顶部和底部)")
  134. else:
  135. # 多选要删除的横线
  136. to_delete = st.multiselect(
  137. "选择要删除的横线",
  138. range(len(horizontal_lines)),
  139. format_func=lambda i: f"R{i+1} (Y={horizontal_lines[i]})",
  140. key="delete_h_lines"
  141. )
  142. if to_delete and st.button("🗑️ 删除选中", key="confirm_delete_h"):
  143. # 保存状态
  144. save_state_for_undo(structure)
  145. # 删除选中的横线(从后往前删)
  146. for idx in sorted(to_delete, reverse=True):
  147. del horizontal_lines[idx]
  148. # 重新计算修改标记
  149. structure['modified_h_lines'] = set()
  150. # 重新计算行区间
  151. _update_row_intervals(structure)
  152. clear_table_image_cache()
  153. adjusted = True
  154. st.success(f"✅ 已删除 {len(to_delete)} 条横线")
  155. st.rerun()
  156. # 添加竖线
  157. with st.expander("➕ 添加竖线", expanded=False):
  158. vertical_lines = structure.get('vertical_lines', [])
  159. col1, col2 = st.columns([3, 1])
  160. with col1:
  161. new_v_x = st.number_input(
  162. "新竖线的X坐标",
  163. min_value=0,
  164. value=vertical_lines[-1] + 100 if vertical_lines else 100,
  165. step=1,
  166. key="new_v_line"
  167. )
  168. with col2:
  169. if st.button("➕ 添加", key="add_v_line"):
  170. # 保存状态
  171. save_state_for_undo(structure)
  172. # 插入新竖线(保持排序)
  173. vertical_lines.append(new_v_x)
  174. vertical_lines.sort()
  175. # 找到新线的索引
  176. new_index = vertical_lines.index(new_v_x)
  177. # 标记为已修改
  178. structure.setdefault('modified_v_lines', set()).add(new_index)
  179. # 重新计算列区间
  180. _update_column_intervals(structure)
  181. clear_table_image_cache()
  182. adjusted = True
  183. st.success(f"✅ 已添加竖线 X={new_v_x}")
  184. st.rerun()
  185. # 删除竖线
  186. with st.expander("🗑️ 删除竖线", expanded=False):
  187. vertical_lines = structure.get('vertical_lines', [])
  188. if len(vertical_lines) <= 2:
  189. st.warning("⚠️ 至少需要保留2条竖线(表格左侧和右侧)")
  190. else:
  191. # 多选要删除的竖线
  192. to_delete = st.multiselect(
  193. "选择要删除的竖线",
  194. range(len(vertical_lines)),
  195. format_func=lambda i: f"C{i+1} (X={vertical_lines[i]})",
  196. key="delete_v_lines"
  197. )
  198. if to_delete and st.button("🗑️ 删除选中", key="confirm_delete_v"):
  199. # 保存状态
  200. save_state_for_undo(structure)
  201. # 删除选中的竖线(从后往前删)
  202. for idx in sorted(to_delete, reverse=True):
  203. del vertical_lines[idx]
  204. # 重新计算修改标记
  205. structure['modified_v_lines'] = set()
  206. # 重新计算列区间
  207. _update_column_intervals(structure)
  208. clear_table_image_cache()
  209. adjusted = True
  210. st.success(f"✅ 已删除 {len(to_delete)} 条竖线")
  211. st.rerun()
  212. return adjusted
  213. def _update_row_intervals(structure):
  214. """根据横线坐标更新行区间"""
  215. horizontal_lines = structure.get('horizontal_lines', [])
  216. rows = []
  217. for i in range(len(horizontal_lines) - 1):
  218. rows.append({
  219. 'y_start': horizontal_lines[i],
  220. 'y_end': horizontal_lines[i + 1],
  221. 'bboxes': []
  222. })
  223. structure['rows'] = rows
  224. # 更新表格边界框
  225. if 'table_bbox' in structure:
  226. vertical_lines = structure.get('vertical_lines', [])
  227. structure['table_bbox'] = [
  228. vertical_lines[0] if vertical_lines else 0,
  229. horizontal_lines[0],
  230. vertical_lines[-1] if vertical_lines else 0,
  231. horizontal_lines[-1]
  232. ]
  233. def _update_column_intervals(structure):
  234. """根据竖线坐标更新列区间"""
  235. vertical_lines = structure.get('vertical_lines', [])
  236. columns = []
  237. for i in range(len(vertical_lines) - 1):
  238. columns.append({
  239. 'x_start': vertical_lines[i],
  240. 'x_end': vertical_lines[i + 1]
  241. })
  242. structure['columns'] = columns
  243. # 更新列宽
  244. col_widths = [col['x_end'] - col['x_start'] for col in columns]
  245. structure['col_widths'] = col_widths
  246. # 更新表格边界框
  247. if 'table_bbox' in structure:
  248. horizontal_lines = structure.get('horizontal_lines', [])
  249. structure['table_bbox'] = [
  250. vertical_lines[0],
  251. horizontal_lines[0] if horizontal_lines else 0,
  252. vertical_lines[-1],
  253. horizontal_lines[-1] if horizontal_lines else 0
  254. ]