Преглед изворни кода

feat(export): 增强图片块渲染支持样式映射和对齐方式

- 为 _render_image_block 函数添加 style_map 参数,支持 Word 样式映射
- 实现图片段落的 Word 样式应用,包括样式ID解析和样式名称兼容
- 完善对齐方式处理,显式支持左对齐、居中和右对齐三种模式
- 添加样式应用的错误处理和降级逻辑,确保样式不可用时默认使用 Normal 样式
- 在调用 _render_image_block 时传入 style_map 参数,保持与其他渲染函数的一致性
- 提高图片块渲染的样式一致性和用户体验
chensiyu пре 1 месец
родитељ
комит
67ef39500e
1 измењених фајлова са 33 додато и 4 уклоњено
  1. 33 4
      app/services/export_service.py

+ 33 - 4
app/services/export_service.py

@@ -464,7 +464,7 @@ def blocks_to_docx_bytes(blocks: list[dict], style_map: dict, style_data: dict)
464
         elif block_type == 'table':
464
         elif block_type == 'table':
465
             _render_table_block(doc, block, style_map)
465
             _render_table_block(doc, block, style_map)
466
         elif block_type == 'image':
466
         elif block_type == 'image':
467
-            _render_image_block(doc, block)
467
+            _render_image_block(doc, block, style_map)
468
     
468
     
469
     # 先保存到临时缓冲区
469
     # 先保存到临时缓冲区
470
     buf = io.BytesIO()
470
     buf = io.BytesIO()
@@ -1087,10 +1087,11 @@ def _render_table_block(doc: Document, block: dict, style_map: dict):
1087
                 _apply_run_style(run, cell_style)
1087
                 _apply_run_style(run, cell_style)
1088
 
1088
 
1089
 
1089
 
1090
-def _render_image_block(doc: Document, block: dict):
1091
-    """渲染图片块(支持 Base64 Data URL)"""
1090
+def _render_image_block(doc: Document, block: dict, style_map: dict = None):
1091
+    """渲染图片块(支持 Base64 Data URL 和 Word 样式)"""
1092
     content = block['content']
1092
     content = block['content']
1093
     style = block.get('style', {})
1093
     style = block.get('style', {})
1094
+    word_style = block.get('word_style', 'Normal')
1094
     
1095
     
1095
     # 只处理 Data URL
1096
     # 只处理 Data URL
1096
     if not isinstance(content, str) or not content.startswith('data:'):
1097
     if not isinstance(content, str) or not content.startswith('data:'):
@@ -1104,14 +1105,42 @@ def _render_image_block(doc: Document, block: dict):
1104
         header, b64_data = content.split(',', 1)
1105
         header, b64_data = content.split(',', 1)
1105
         image_bytes = base64.b64decode(b64_data)
1106
         image_bytes = base64.b64decode(b64_data)
1106
         
1107
         
1107
-        # 创建段落并设置对齐
1108
+        # 创建段落并应用 Word 样式
1108
         paragraph = doc.add_paragraph()
1109
         paragraph = doc.add_paragraph()
1109
         
1110
         
1111
+        # 应用 Word 样式(如"图表标题")
1112
+        if style_map:
1113
+            style_id = _resolve_style_id(style_map, word_style, 'Normal')
1114
+            if style_id:
1115
+                try:
1116
+                    paragraph.style = doc.styles[style_id]
1117
+                except KeyError:
1118
+                    # 如果找不到样式ID,尝试使用样式名称
1119
+                    try:
1120
+                        paragraph.style = word_style
1121
+                    except KeyError:
1122
+                        paragraph.style = 'Normal'
1123
+            else:
1124
+                # 如果没有找到映射,尝试直接使用 word_style
1125
+                try:
1126
+                    paragraph.style = word_style
1127
+                except KeyError:
1128
+                    paragraph.style = 'Normal'
1129
+        else:
1130
+            # 没有 style_map,尝试直接使用 word_style
1131
+            try:
1132
+                paragraph.style = word_style
1133
+            except KeyError:
1134
+                paragraph.style = 'Normal'
1135
+        
1136
+        # 设置对齐方式(可能覆盖样式中的对齐)
1110
         align = style.get('align', 'left')
1137
         align = style.get('align', 'left')
1111
         if align == 'center':
1138
         if align == 'center':
1112
             paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
1139
             paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
1113
         elif align == 'right':
1140
         elif align == 'right':
1114
             paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
1141
             paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
1142
+        elif align == 'left':
1143
+            paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT
1115
         
1144
         
1116
         # 插入图片
1145
         # 插入图片
1117
         run = paragraph.add_run()
1146
         run = paragraph.add_run()