from hashlib import sha1 from reportlab.lib.colors import HexColor from reportlab.lib.units import cm, inch from reportlab.platypus import Paragraph, Image, PageBreak, Frame, Table from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate from reportlab.platypus.tableofcontents import TableOfContents from reportlab.pdfgen import canvas from Report.scripts.PdfStyle import cover_space, cover_company_style, cover_report_style, cover_time_style, \ chapter_style, \ section_style, adjust_line_width, para_style_single, para_style_bold, table_name, table_unit, table_mark, \ adjust_table_widths, adjust_table_style, Seashell4, toc_style_1, table_content_style, toc_style_2, darkGolden, \ adjust_table_data, para_bold_style, para_style_esg, para_style_special from Report.scripts.path_tool import gen_pdf_path, get_pic_path from common.scripts import read_json_file class HeaderAndFooterCanvas(canvas.Canvas): def __init__(self, *args, **kwargs): self.offeset = 3 canvas.Canvas.__init__(self, *args, **kwargs) self._saved_page_states = [] def showPage(self): self._saved_page_states.append(dict(self.__dict__)) self._startPage() def draw_header_and_footer(self, page_count): self.setFont("Helvetica", 7) if self._pageNumber > self.offeset: self.setFont('pingbold', 8) self.setFillColor(HexColor(Seashell4)) self.drawString(74, 805, "远东资信评估有限公司") self.drawString(74, 40, "%d / %d" % (self._pageNumber - self.offeset, page_count - self.offeset)) self.setStrokeColor(darkGolden) self.setLineWidth(2.5) self.line(74, 820, 6.8 * inch, 820) self.setLineWidth(1) self.line(74, 50, 6.8 * inch, 50) def save(self): num_pages = len(self._saved_page_states) for state in self._saved_page_states: self.__dict__.update(state) self.draw_header_and_footer(num_pages) canvas.Canvas.showPage(self) canvas.Canvas.save(self) class EsgHeaderAndFooterCanvas(canvas.Canvas): def __init__(self, *args, **kwargs): self.offeset = 2 canvas.Canvas.__init__(self, *args, **kwargs) self._saved_page_states = [] def showPage(self): self._saved_page_states.append(dict(self.__dict__)) self._startPage() def draw_header_and_footer(self, page_count): self.setFont("Helvetica", 7) if self._pageNumber > self.offeset: self.setFont('pingbold', 8) self.setFillColor(HexColor(Seashell4)) self.drawString(74, 805, "远东资信评估有限公司") self.drawString(74, 40, "%d / %d" % (self._pageNumber - self.offeset, page_count - self.offeset)) self.setStrokeColor(darkGolden) self.setLineWidth(2.5) self.line(74, 820, 6.8 * inch, 820) self.setLineWidth(1) self.line(74, 50, 6.8 * inch, 50) def save(self): num_pages = len(self._saved_page_states) for state in self._saved_page_states: self.__dict__.update(state) self.draw_header_and_footer(num_pages) canvas.Canvas.showPage(self) canvas.Canvas.save(self) class MyDocTemplate(BaseDocTemplate): def __init__(self, filename, **kw): self.allowSplitting = 1 BaseDocTemplate.__init__(self, filename, **kw) template = PageTemplate('normal', [Frame(2.5 * cm, 2.5 * cm, 15 * cm, 25 * cm, id='F1')]) self.addPageTemplates(template) self.offeset = kw['offeset'] def afterFlowable(self, flowable): if flowable.__class__.__name__ == 'Paragraph': text = flowable.getPlainText() style = flowable.style.name if style == 'chapter_style': level = 1 elif style == 'section_style': level = 2 else: return e = (level, text, self.page - self.offeset) self.notify('TOCEntry', e) class ReportGenerator: def __init__(self, **kwargs): # 文本数据 self.text_model = kwargs['text_model'] if '报告类型' in self.text_model: # 调用模板,在临时报告文件夹中创建指定名称的PDF文档 self.doc = MyDocTemplate(gen_pdf_path(name=kwargs['name']), offeset=2) else: self.doc = MyDocTemplate(gen_pdf_path(name=kwargs['name']), offeset=3) # 内容框 self.story = list() # 生成报告 def gen_report(self): if '报告类型' in self.text_model: offeset = 2 self.gen_esg_cover() self.gen_menu() self.gen_esg_part() self.doc.multiBuild(self.story, canvasmaker=EsgHeaderAndFooterCanvas) else: offeset = 3 self.gen_cover() self.gen_menu() self.gen_main_part() self.doc.multiBuild(self.story, canvasmaker=HeaderAndFooterCanvas) # 设置章节、小节标题 def set_head(self, text, sty): bn = sha1("Vintage".encode('utf-8')).hexdigest() h = Paragraph(text + '' % bn, sty) h._bookmarkName = bn self.story.append(h) # 目录 def gen_menu(self): toc = TableOfContents() toc.levelStyles = [toc_style_1, toc_style_2] self.story.append(Paragraph('目录', table_content_style)) self.story.append(toc) self.story.append(PageBreak()) # 封面 def gen_cover(self): data = self.text_model # self.story.append(PageBreak()) self.story.append(Paragraph('.', cover_space)) self.story.append(Paragraph(data['企业名称'], cover_company_style)) self.story.append(Paragraph('综合信用等级评价报告', cover_report_style)) self.story.append(Image(get_pic_path(pic_name='ydzx.png'), width=202, height=37)) self.story.append(Paragraph(data['生成日期'], cover_time_style)) self.story.append(PageBreak()) # esg封面 def gen_esg_cover(self): data = self.text_model self.story.append(Paragraph('.', cover_space)) self.story.append(Paragraph(data['企业名称'], cover_company_style)) self.story.append(Paragraph('ESG评价报告', cover_report_style)) self.story.append(Image(get_pic_path(pic_name='ydzx.png'), width=202, height=37)) self.story.append(Paragraph(data['生成日期'], cover_time_style)) self.story.append(PageBreak()) # 正文 def gen_main_part(self): data = self.text_model['报告内容'] for chapter in data: self.set_head(chapter['章节'], chapter_style) for section in chapter['章节内容']: self.set_head(section['小节'], section_style) for part in section['小节内容']: # 段落 if list(part.keys())[0] == '段落': self.story.append(Paragraph(adjust_line_width(part['段落'], 8), para_style_single)) # self.story.append(Paragraph(part['段落'], para_style_single)) # 节点 elif list(part.keys())[0] == '节点': self.story.append(Paragraph(part['节点'], para_style_bold)) # 表名 elif list(part.keys())[0] == '表名': self.story.append(Paragraph(part['表名'], table_name)) # 单位 elif list(part.keys())[0] == '单位': self.story.append(Paragraph(part['单位'], table_unit)) # 注释 elif list(part.keys())[0] == '注释': self.story.append(Paragraph(part['注释'], table_mark)) # 表格 elif list(part.keys())[0] == '表格': style = adjust_table_style(part['表格']) td = adjust_table_data(part['表格']) self.story.append(Table(td, style=style)) # esg正文 def gen_esg_part(self): data = self.text_model['报告内容'] for chapter in data: self.set_head(chapter['章节'], chapter_style) for section in chapter['章节内容']: # 段落 if list(section.keys())[0] == '段落': factor_01 = True if '绿色业务收入占比(%)' in section['段落'] else False factor_02 = True if '公司在近三年因环境问题受到监管处罚' in section['段落'] else False factor_03 = True if '这影响了公司的社会得分' in section['段落'] else False factor_04 = True if '公司在近三年有过扶贫、捐赠行为' in section['段落'] else False factor_05 = True if '经查,公司存在1项或多项的法律诉讼' in section['段落'] else False factor_06 = True if '这影响了公司在治理方面的得分' in section['段落'] else False if factor_01 or factor_02 or factor_03 or factor_04 or factor_05 or factor_06: self.story.append(Paragraph(adjust_line_width(section['段落'], 8), para_style_special)) else: self.story.append(Paragraph(adjust_line_width(section['段落'], 8), para_style_single)) if __name__ == '__main__': text_data = read_json_file('/Report/static/ReportTemplates/ESG报告.json') m = ReportGenerator(name=text_data['企业名称'], text_model=text_data) m.gen_report()