save_controls.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. """
  2. 保存功能控件
  3. """
  4. import streamlit as st
  5. import io
  6. from pathlib import Path
  7. from typing import Dict
  8. from .config_loader import save_structure_to_config
  9. from .drawing import draw_clean_table_lines
  10. def create_save_section(work_mode: str, structure: Dict, image, line_width: int, output_config: Dict):
  11. """
  12. 保存设置(目录/命名来自配置)
  13. Args:
  14. work_mode: 工作模式
  15. structure: 表格结构
  16. image: 图片对象
  17. line_width: 线条宽度
  18. output_config: 输出配置
  19. """
  20. st.divider()
  21. defaults = output_config.get("defaults", {})
  22. line_colors = output_config.get("line_colors") or [
  23. {"name": "黑色", "rgb": [0, 0, 0]},
  24. {"name": "蓝色", "rgb": [0, 0, 255]},
  25. {"name": "红色", "rgb": [255, 0, 0]},
  26. ]
  27. save_col1, save_col2, save_col3 = st.columns(3)
  28. with save_col1:
  29. save_structure = st.checkbox(
  30. "保存表格结构配置",
  31. value=bool(defaults.get("save_structure", True)),
  32. )
  33. with save_col2:
  34. save_image = st.checkbox(
  35. "保存表格线图片",
  36. value=bool(defaults.get("save_image", True)),
  37. )
  38. color_names = [c["name"] for c in line_colors]
  39. default_color = defaults.get("line_color", color_names[0])
  40. default_index = (
  41. color_names.index(default_color)
  42. if default_color in color_names
  43. else 0
  44. )
  45. with save_col3:
  46. line_color_option = st.selectbox(
  47. "保存时线条颜色",
  48. color_names,
  49. label_visibility="collapsed",
  50. index=default_index,
  51. )
  52. if st.button("💾 保存", type="primary"):
  53. output_dir = Path(output_config.get("directory", "output/table_structures"))
  54. output_dir.mkdir(parents=True, exist_ok=True)
  55. structure_suffix = output_config.get("structure_suffix", "_structure.json")
  56. image_suffix = output_config.get("image_suffix", "_with_lines.png")
  57. # 确定文件名
  58. base_name = _determine_base_name(work_mode)
  59. saved_files = []
  60. if save_structure:
  61. _save_structure_file(
  62. structure,
  63. output_dir,
  64. base_name,
  65. structure_suffix,
  66. saved_files
  67. )
  68. if save_image:
  69. _save_image_file(
  70. image,
  71. structure,
  72. line_width,
  73. line_color_option,
  74. line_colors,
  75. output_dir,
  76. base_name,
  77. image_suffix,
  78. saved_files
  79. )
  80. if saved_files:
  81. st.success(f"✅ 已保存 {len(saved_files)} 个文件:")
  82. for file_type, file_path in saved_files:
  83. st.info(f" • {file_type}: {file_path}")
  84. def _determine_base_name(work_mode: str) -> str:
  85. """确定保存文件的基础名称"""
  86. if work_mode == "🆕 新建标注" or work_mode == "new":
  87. if st.session_state.loaded_json_name:
  88. return Path(st.session_state.loaded_json_name).stem
  89. else:
  90. return "table_structure"
  91. else:
  92. if st.session_state.loaded_config_name:
  93. base_name = Path(st.session_state.loaded_config_name).stem
  94. if base_name.endswith('_structure'):
  95. base_name = base_name[:-10]
  96. return base_name
  97. elif st.session_state.loaded_image_name:
  98. return Path(st.session_state.loaded_image_name).stem
  99. else:
  100. return "table_structure"
  101. def _save_structure_file(structure, output_dir, base_name, suffix, saved_files):
  102. """保存结构配置文件"""
  103. structure_filename = f"{base_name}{suffix}"
  104. structure_path = output_dir / structure_filename
  105. save_structure_to_config(structure, structure_path)
  106. saved_files.append(("配置文件", structure_path))
  107. with open(structure_path, 'r') as f:
  108. st.download_button(
  109. "📥 下载配置文件",
  110. f.read(),
  111. file_name=f"{base_name}_structure.json",
  112. mime="application/json"
  113. )
  114. def _save_image_file(image, structure, line_width, color_option, line_colors,
  115. output_dir, base_name, suffix, saved_files):
  116. """保存表格线图片"""
  117. if image is None:
  118. st.warning("⚠️ 无法保存图片:未加载图片文件")
  119. return
  120. selected_color_rgb = next(
  121. (tuple(c["rgb"]) for c in line_colors if c["name"] == color_option),
  122. (0, 0, 0),
  123. )
  124. clean_img = draw_clean_table_lines(
  125. image,
  126. structure,
  127. line_width=line_width,
  128. line_color=selected_color_rgb,
  129. )
  130. image_filename = f"{base_name}{suffix}"
  131. output_image_path = output_dir / image_filename
  132. clean_img.save(output_image_path)
  133. saved_files.append(("表格线图片", output_image_path))
  134. buf = io.BytesIO()
  135. clean_img.save(buf, format='PNG')
  136. buf.seek(0)
  137. st.download_button(
  138. "📥 下载表格线图片",
  139. buf,
  140. file_name=f"{base_name}_with_lines.png",
  141. mime="image/png"
  142. )