Files

129 lines
5.1 KiB
Python
Raw Permalink Normal View History

2026-01-28 17:01:19 +08:00
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)
# 标题只有304056
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}