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}
|