소스 검색

add: 报告生成-图片

yq 5 달 전
부모
커밋
415c6f9cdd
5개의 변경된 파일78개의 추가작업 그리고 27개의 파일을 삭제
  1. 1 1
      config/model_monitor_config_template.json
  2. 1 1
      data/loader/data_loader_excel.py
  3. 2 2
      enums/placeholder_prefix_enum.py
  4. 1 1
      metrics/metric_by_sql_general.py
  5. 73 22
      monitor/report_generate.py

+ 1 - 1
config/model_monitor_config_template.json

@@ -9,7 +9,7 @@
     {
       "metric_code": "auc",
       "metric_func": "MetricBySqlGeneral",
-      "sql": "select * from test.t1 where date>{{date-1}}"
+      "sql": "select * from test.t1 where date>'2024-11-07'"
     }
   ]
 }

+ 1 - 1
data/loader/data_loader_excel.py

@@ -23,5 +23,5 @@ class DataLoaderExcel(DataLoaderBase):
         pass
 
     def get_data(self, file_path: str, sheet_name: str = 0) -> pd.DataFrame:
-        df = pd.read_excel(file_path, sheet_name=sheet_name)
+        df = pd.read_excel(file_path, sheet_name=sheet_name, index_col=False)
         return df

+ 2 - 2
enums/placeholder_prefix_enum.py

@@ -11,5 +11,5 @@ from enum import Enum
 class PlaceholderPrefixEnum(Enum):
 
     VALUE = ""
-    TABLE = "table"
-    IMAGE = "image"
+    TABLE = "table_"
+    IMAGE = "image_"

+ 1 - 1
metrics/metric_by_sql_general.py

@@ -30,4 +30,4 @@ class MetricBySqlGeneral(MetricBase):
         return data
 
     def calculate(self, *args, **kwargs) -> MetricFucEntity:
-        return MetricFucEntity(table=self._load_data(*args, **kwargs))
+        return MetricFucEntity(table=self._load_data(*args, **kwargs), value='0', image_path='./cache/t1.png')

+ 73 - 22
monitor/report_generate.py

@@ -9,6 +9,9 @@ from typing import Dict
 
 from docx import Document
 from docx.enum.text import WD_ALIGN_PARAGRAPH
+from docx.oxml import OxmlElement
+from docx.oxml.ns import qn
+from docx.shared import Inches
 
 from commom import GeneralException, f_get_datetime
 from entitys import MetricFucEntity
@@ -17,16 +20,59 @@ from enums import ResultCodesEnum, PlaceholderPrefixEnum
 
 class Report():
 
+    # 设置 table 的边框,用法与 cell 类似
+    @staticmethod
+    def _set_table_boarder(table, **kwargs):
+        """
+        Set table`s border
+        Usage:
+        set_table_border(
+            cell,
+            top={"sz": 12, "val": "single", "color": "#FF0000"},
+            bottom={"sz": 12, "color": "#00FF00", "val": "single"},
+            left={"sz": 24, "val": "dashed"},
+            right={"sz": 12, "val": "dashed"},
+        )
+        """
+        borders = OxmlElement('w:tblBorders')
+        for tag in ('bottom', 'top', 'left', 'right', 'insideV', 'insideH'):
+            edge_data = kwargs.get(tag)
+            if edge_data:
+                any_border = OxmlElement(f'w:{tag}')
+                for key in ["sz", "val", "color", "space", "shadow"]:
+                    if key in edge_data:
+                        any_border.set(qn(f'w:{key}'), str(edge_data[key]))
+                borders.append(any_border)
+                table._tbl.tblPr.append(borders)
+
+    # 将table 的所有单元格四个边设置为 0.5 镑, 黑色, 实线
+    @staticmethod
+    def _set_table_singleBoard(table):
+        return Report._set_table_boarder(
+            table,
+            top={"sz": 4, "val": "single", "color": "#000000"},
+            bottom={"sz": 4, "val": "single", "color": "#000000"},
+            left={"sz": 4, "val": "single", "color": "#000000"},
+            right={"sz": 4, "val": "single", "color": "#000000"},
+            insideV={"sz": 4, "val": "single", "color": "#000000"},
+            insideH={"sz": 4, "val": "single", "color": "#000000"}
+        )
+
+    @staticmethod
+    def _get_placeholder(placeholder_prefix_enum: PlaceholderPrefixEnum, metric_code: str):
+        return "{{" + f"{placeholder_prefix_enum.value}{metric_code}" + "}}"
+
     @staticmethod
     def _fill_value_placeholder(doc: Document, metric_value_dict: Dict[str, MetricFucEntity]):
         # 替换指标
         for paragraph in doc.paragraphs:
             text = paragraph.text
             for metric_code, metric_fuc_entity in metric_value_dict.items():
-                placeholder = f"{PlaceholderPrefixEnum.VALUE.value}_{metric_code}"
+                placeholder = Report._get_placeholder(PlaceholderPrefixEnum.VALUE, metric_code)
                 metric_value = metric_fuc_entity.value
-                if metric_value:
-                    text = text.replace(placeholder, metric_value)
+                if metric_value is None:
+                    continue
+                text = text.replace(placeholder, metric_value)
             # 段落中多个runs时执行,最后一个run改成替换好的文本,其他run置空
             if len(paragraph.runs[:-1]) > 0:
                 for run in paragraph.runs[:-1]:
@@ -38,13 +84,13 @@ class Report():
         # 替换表格
         for paragraph in doc.paragraphs:
             for metric_code, metric_fuc_entity in metric_value_dict.items():
-                placeholder = f"{PlaceholderPrefixEnum.TABLE.value}_{metric_code}"
+                placeholder = Report._get_placeholder(PlaceholderPrefixEnum.TABLE, metric_code)
                 metric_table = metric_fuc_entity.table
-                if metric_table.empty:
+                if metric_table is None:
                     continue
-                # 清除占位符
                 if not placeholder in paragraph.text:
                     continue
+                # 清除占位符
                 for run in paragraph.runs:
                     run.text = run.text.replace(placeholder, "")
                 table = doc.add_table(rows=metric_table.shape[0] + 1, cols=metric_table.shape[1])
@@ -63,22 +109,27 @@ class Report():
                         cell = table.cell(row_idx + 1, column_idx)
                         cell.text = str(value)
                         cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
+                Report._set_table_singleBoard(table)
 
-    # @staticmethod
-    # def _fill_image_placeholder(doc: Document, metric_value_dict: Dict[str, MetricFucEntity]):
-    #     # 替换图片
-    #     for paragraph in doc.paragraphs:
-    #         text = paragraph.text
-    #         for metric_code, metric_fuc_entity in metric_value_dict.items():
-    #             placeholder = f"{PlaceholderPrefixEnum.IMAGE.value}_{metric_code}"
-    #             metric_value = metric_fuc_entity.value
-    #             if metric_value:
-    #                 text = text.replace(placeholder, metric_value)
-    #         # 段落中多个runs时执行,最后一个run改成替换好的文本,其他run置空
-    #         if len(paragraph.runs[:-1]) > 0:
-    #             for run in paragraph.runs[:-1]:
-    #                 run.text = ''
-    #             paragraph.runs[-1].text = text
+    @staticmethod
+    def _fill_image_placeholder(doc: Document, metric_value_dict: Dict[str, MetricFucEntity]):
+        # 替换图片
+        for paragraph in doc.paragraphs:
+            for metric_code, metric_fuc_entity in metric_value_dict.items():
+                placeholder = Report._get_placeholder(PlaceholderPrefixEnum.IMAGE, metric_code)
+                image_path = metric_fuc_entity.image_path
+                if image_path is None:
+                    continue
+                if not placeholder in paragraph.text:
+                    continue
+                if not os.path.exists(image_path):
+                    raise GeneralException(ResultCodesEnum.NOT_FOUND, message=f"文件【{image_path}】不存在")
+                # 清除占位符
+                for run in paragraph.runs:
+                    if placeholder not in run.text:
+                        continue
+                    run.text = run.text.replace(placeholder, "")
+                    run.add_picture(image_path, width=Inches(5))
 
     @staticmethod
     def generate_report(metric_value_dict: Dict[str, MetricFucEntity], template_path: str):
@@ -89,7 +140,7 @@ class Report():
 
         Report._fill_value_placeholder(doc, metric_value_dict)
         Report._fill_table_placeholder(doc, metric_value_dict)
-        # Report._fill_image_placeholder(doc, metric_value_dict)
+        Report._fill_image_placeholder(doc, metric_value_dict)
         new_path = template_path.replace(".docx", f"{f_get_datetime()}.docx")
         doc.save(f"./{new_path}")