129 lines
5.1 KiB
Python
129 lines
5.1 KiB
Python
from docx import Document
|
||
from docxtpl import DocxTemplate
|
||
from stuctor.constants import PREFIX
|
||
from docx.oxml.text.paragraph import CT_P
|
||
from docx.table import Table
|
||
from stuctor.item import TitleItem, TableItemList, Item
|
||
from nicegui import ui
|
||
from pathlib import Path
|
||
|
||
template_path = Path.cwd() / "templates"
|
||
|
||
class Operator:
|
||
"""
|
||
参数1: 传入被解析文档名称,不加.docx
|
||
参数2: 传入说明模版文档名称,不加.docx
|
||
参数3: 传入记录模版文档名称,不加.docx
|
||
属性1: item_list - 储存所有Item对象的列表
|
||
"""
|
||
# 标题过滤
|
||
TITLE_LIST = ['3', '30', '4', '40', '5', '50', '6', '60', '7', '70']
|
||
BASIC_CAPTER = '6.2'
|
||
|
||
def __init__(self, doc_name: str, tp_shuoming_name: str, tp_jilu_name: str, logger: ui.log) -> None:
|
||
# 记录器
|
||
self.logger = logger
|
||
# 被解析文档对象
|
||
self.doc = Document(doc_name)
|
||
# 说明模版文件
|
||
self.tp_shuom = DocxTemplate(template_path / (tp_shuoming_name+'.docx'))
|
||
# 记录模版文件
|
||
self.tp_jilu = DocxTemplate(template_path / (tp_jilu_name+'.docx'))
|
||
# 储存所有item对象的列表
|
||
self.item_list: list[Item] = []
|
||
# 储存大纲章节号排布
|
||
self.c3 = 0
|
||
self.c4 = 0
|
||
self.c5 = 0
|
||
self.c6 = 0
|
||
self.c7 = 0
|
||
self.last_title_item = None
|
||
|
||
def main_parse(self, parse_content_strategy: str = 'FPGA'):
|
||
"""默认是未解析的,调用该函数开始解析"""
|
||
# 解析开始-这里有点耦合了,其实该请TitleItem对象去处理的
|
||
for ele in self.doc._element.body.iter(): # type: ignore
|
||
if ele.tag.endswith('}p'):
|
||
for child in ele.iter():
|
||
if child.tag.endswith("pStyle"):
|
||
rank = child.get(f"{PREFIX}val")
|
||
title = self.__parse_ele_title(ele)
|
||
# 标题只有30,40,5,6
|
||
if rank in self.TITLE_LIST:
|
||
current_title_item = TitleItem(rank, title)
|
||
self.item_list.append(current_title_item)
|
||
# 解析当前章节号
|
||
self.__parse_current_capter(current_title_item)
|
||
elif ele.tag.endswith('}tbl'):
|
||
table = Table(ele, self.doc)
|
||
if table.cell(0, 0).text == "测试项名称":
|
||
self.item_list.append(TableItemList(table, self.last_title_item, self.logger, parse_content_strategy))
|
||
|
||
# 私有:解析标题文字
|
||
def __parse_ele_title(self, ele: CT_P):
|
||
t_ele = ele.findall(f".//{PREFIX}t") # type: ignore
|
||
title = ''
|
||
for i in range(len(t_ele)):
|
||
if not t_ele[i].text.isdigit():
|
||
title = title + t_ele[i].text
|
||
return title
|
||
|
||
# 私有:解析当前章节号-根据其rank
|
||
def __parse_current_capter(self, current_title_item: TitleItem):
|
||
rank = current_title_item.type
|
||
if rank == '30' or rank == '3':
|
||
self.c3 += 1
|
||
self.c4 = 0
|
||
self.c5 = 0
|
||
self.c6 = 0
|
||
self.c7 = 0
|
||
current_title_item.capter = ".".join([self.BASIC_CAPTER, str(self.c3)])
|
||
elif rank == '40' or rank == '4':
|
||
self.c4 += 1
|
||
self.c5 = 0
|
||
self.c6 = 0
|
||
self.c7 = 0
|
||
current_title_item.capter = '.'.join([self.BASIC_CAPTER, str(self.c3), str(self.c4)])
|
||
elif rank == '50' or rank == '5':
|
||
self.c5 += 1
|
||
self.c6 = 0
|
||
self.c7 = 0
|
||
current_title_item.capter = '.'.join([self.BASIC_CAPTER, str(self.c3), str(self.c4), str(self.c5)])
|
||
elif rank == '60' or rank == '6':
|
||
self.c6 += 1
|
||
self.c7 = 0
|
||
current_title_item.capter = '.'.join([self.BASIC_CAPTER, str(self.c3), str(self.c4), str(self.c6)])
|
||
elif rank == '70' or rank == '7':
|
||
self.c7 += 1
|
||
current_title_item.capter = '.'.join([self.BASIC_CAPTER, str(self.c3), str(self.c4), str(self.c6), str(self.c7)])
|
||
|
||
self.last_title_item = current_title_item
|
||
|
||
# 最后渲染
|
||
def render(self):
|
||
context = self.__create_context()
|
||
self.tp_shuom.render(context, autoescape = True)
|
||
self.tp_shuom.save("测试说明-输出.docx")
|
||
self.tp_jilu.render(context, autoescape = True)
|
||
self.tp_jilu.save("测试记录-输出.docx")
|
||
|
||
# 构造context
|
||
def __create_context(self):
|
||
data_list = []
|
||
for item in self.item_list:
|
||
if isinstance(item, TableItemList):
|
||
for it in item.table_item:
|
||
temp_item = {
|
||
'type': 'table',
|
||
'name': it.name,
|
||
'ident': it.ident,
|
||
'zhui': item.zhui,
|
||
'zong': it.zong,
|
||
'step': it.step,
|
||
'csh': it.csh
|
||
}
|
||
data_list.append(temp_item)
|
||
elif isinstance(item, TitleItem):
|
||
data_list.append({'type': item.type, 'title': item.title})
|
||
return {"datas": data_list}
|