修复:测试记录序号、测评报告统计、富文本渲染word字符问题

This commit is contained in:
2026-02-09 15:41:17 +08:00
parent 2f58bdc668
commit 74d3d22ffe
85 changed files with 1236 additions and 52 deletions

View File

@@ -19,7 +19,7 @@ from utils.util import get_str_dict, get_list_dict, create_problem_grade_str, cr
create_demand_summary, create_problem_type_str, create_problem_table, create_problem_type_table, \
get_str_abbr
# 根据轮次生成测评内容文档context
from apps.createDocument.extensions.content_result_tool import create_round_context
from apps.createDocument.extensions.content_result_tool import create_round_context, create_influence_context
from apps.createDocument.extensions.zhui import create_bg_round1_zhui
from apps.createDocument.extensions.solve_problem import create_one_problem_dit
from utils.path_utils import project_path
@@ -354,9 +354,11 @@ class GenerateControllerBG(ControllerBase):
# 每个轮次都需要生成一个测试内容和标题
project_path_str = project_path(id)
for round_str in round_str_list:
context = create_round_context(project_obj, round_str)
context, round_obj = create_round_context(project_obj, round_str)
template_path = Path.cwd() / 'media' / project_path_str / 'form_template' / 'bg' / '测试内容和结果_第二轮次.docx'
doc = DocxTemplate(template_path)
# ~~~额外添加:除第一轮次的影响域分析~~~
context['influence'] = create_influence_context(doc, round_obj, project_obj)
doc.render(context, autoescape=True)
try:
doc.save(
@@ -442,7 +444,7 @@ class GenerateControllerBG(ControllerBase):
design_dict['demands'] = '\a'.join(demand_list)
# 通过还是未通过
design_dict['pass'] = '通过'
design_dict['index'] = design_index
design_dict['index'] = design_index # noqa
data_list.append(design_dict)
design_index += 1

View File

@@ -10,7 +10,7 @@ from ninja.errors import HttpError
from ninja_extra import ControllerBase, api_controller, route
from django.db import transaction
from django.db.models import Q
from docxtpl import DocxTemplate, InlineImage, Subdoc
from docxtpl import DocxTemplate, InlineImage
from pathlib import Path
from utils.chen_response import ChenResponse
# 导入数据库ORM
@@ -82,12 +82,12 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
for tm_item in single_qs.testMethod:
if tm_item == dict_item_qs.key:
testmethod_str += dict_item_qs.title + " "
# 富文本解析
# ***Inspect-start检查设计需求的描述是否为空***
if single_qs.design.description == '':
design_info = single_qs.design.ident + '-' + single_qs.design.name
self.logger.write_warning_log('测试项', f'设计需求中的描述为空,请检查 -> {design_info}')
# ***Inspect-end***
# 富文本解析
html_parser = RichParser(single_qs.design.description)
desc_list = html_parser.get_final_list(doc)
# 查询关联design以及普通design
@@ -110,7 +110,8 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
"test_demand_content": content_list,
"testMethod": testmethod_str.strip(),
"adequacy": single_qs.adequacy.replace("\n", "\a"),
"testDesciption": single_qs.testDesciption.replace("\n", "\a"), # 测试项描述
# 测试项描述FPGA或'静态分析'、'文档审查'、'代码审查'
"testDesciption": single_qs.testDesciption.replace("\n", "\a"),
"testType": get_testType(single_qs.testType, 'testType'),
}
list_list[type_index].append(testdemand_dict)
@@ -470,11 +471,11 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
# 通用生成静态软件项、静态硬件项、动态软件项、动态硬件信息的context包含fontnote和table
@classmethod
def create_table_context(cls, table_data: list[list[str]], doc: DocxTemplate) -> Subdoc:
def create_table_context(cls, table_data: list[list[str]], doc: DocxTemplate):
"""注意:该函数会增加一列序号列"""
subdoc = doc.new_subdoc()
rows = len(table_data)
cols = len(table_data[0]) + 1 # 多渲染序号列
cols = len(table_data[0]) + 1 # 多渲染一个序号列
table = subdoc.add_table(rows=rows, cols=cols)
# 单元格处理
for row in range(rows):

View File

@@ -1,6 +1,6 @@
from pathlib import Path
from copy import deepcopy
from typing import Union, TypedDict, Optional
from typing import Union
from ninja_extra import api_controller, ControllerBase, route
from django.db import transaction
from django.shortcuts import get_object_or_404
@@ -20,6 +20,7 @@ from apps.createDocument.extensions.util import delete_dir_files
from apps.createDocument.extensions.parse_rich_text import RichParser
from apps.createDocument.extensions.documentTime import DocTime
from utils.util import get_str_abbr
from apps.createDocument.extensions.content_result_tool import create_influence_context
# 导入生成日志记录模块
from apps.createSeiTaiDocument.extensions.logger import GenerateLogger
# 导入排序
@@ -236,35 +237,9 @@ class GenerateControllerHSM(ControllerBase):
message=f'您第{chinese_round_name[int(hround.key)]}轮次中缺少源代码版本信息,请添加')
last_dm_version = last_round_so_dut.version
now_dm_version = so_dut.version
# 这里插入影响域分析部分
## 先查找是否有影响域分析填写
area_qs = InfluenceArea.objects.filter(round=hround)
## 如果存在则查询items
item_render_list = []
if area_qs.exists():
area_obj = area_qs.first()
items_qs = area_obj.influence_items.all()
if items_qs.exists():
index = 1
for item in items_qs:
# 1.处理关联case - 找第一轮cases
case_str_list = []
for case in project_obj.pcField.filter(key__in=item.effect_cases):
case_ident_index = str(int(case.key.split("-")[-1]) + 1).zfill(3)
case_str_list.append("_".join(["YL", get_str_abbr(case.test.testType, "testType"), case.ident, case_ident_index]))
# 2.处理富文本框
parser = RichParser(item.change_des)
item_dict = {
"change_type": item.change_type,
"change_influ": item.change_influ,
"case_str_list": case_str_list,
"change_des": parser.get_final_list(doc, img_size=40, height=30), # 富文本未处理
"index": str(index),
}
index = index + 1
item_render_list.append(item_dict)
# 将影响域分析加入context
context_round['influence'] = item_render_list # noqa
# 这里插入影响域分析部分并加入context
context_round['influence'] = create_influence_context(doc, hround, project_obj) # noqa
context_round['influence'] = None
# 如果存在这个轮次的需求文档,则查询上个版本
last_xq_version = ""
if xq_dut:

View File

@@ -1,7 +1,9 @@
from apps.project.models import Project
from apps.project.models import Project, Round, InfluenceArea
from docxtpl import DocxTemplate
from utils.util import *
from utils.chen_response import ChenResponse
from django.db.models import Q
from apps.createDocument.extensions.parse_rich_text import RichParser
def create_round_context(project_obj: Project, round_id: str):
"""根据轮次,生成测评报告中的测评结果"""
@@ -77,4 +79,37 @@ def create_round_context(project_obj: Project, round_id: str):
'r2_dynamic_str': r2_dynamic_str,
'round_id': round_chinese[round_id],
}
return context
return context, round_obj
# ~~~影响域分析内容返回influence的render_list~~~
def create_influence_context(doc: DocxTemplate, round_obj: Round, project_obj: Project) -> None | list:
area_qs = InfluenceArea.objects.filter(round=round_obj)
item_render_list = []
## 如果存在则查询items
if area_qs.exists():
area_obj = area_qs.first()
items_qs = area_obj.influence_items.all()
if items_qs.exists():
index = 1
for item in items_qs:
# 1.处理关联case - 找第一轮cases
case_str_list = []
for case in project_obj.pcField.filter(key__in=item.effect_cases):
case_ident_index = str(int(case.key.split("-")[-1]) + 1).zfill(3)
case_str_list.append("_".join(["YL", get_str_abbr(case.test.testType, "testType"), case.ident, case_ident_index]))
# 2.处理富文本框
parser = RichParser(item.change_des)
item_dict = {
"change_type": item.change_type,
"change_influ": item.change_influ,
"case_str_list": case_str_list,
"change_des": parser.get_final_list(doc, img_size=40, height=30), # 富文本未处理
"index": str(index),
}
index = index + 1
item_render_list.append(item_dict)
if len(item_render_list) > 0:
return item_render_list
else:
return None

View File

@@ -22,6 +22,8 @@ class RichParser:
# 最终的解析后的列表
self.data_list = []
self.line_parse()
# 匹配“表1-3”或“表1”等字符的正则
self.biao_pattern = re.compile(r"\d+(?:-\d+)?")
# 1.函数将self.bs.contents去掉\n获取每行数据
def remove_n_in_contents(self):
@@ -127,6 +129,13 @@ class RichParser:
for oneline in self.data_list:
if isinstance(oneline, list) or oneline.startswith("data:image/png;base64"):
continue
else:
final_list.append(oneline)
cleaned_line = oneline
cleaned_line = re.sub(r'\s+', '', cleaned_line)
cleaned_line = cleaned_line.replace(')', '')
cleaned_line = cleaned_line.strip()
# 去掉以“表3”的行
if self.biao_pattern.search(cleaned_line):
continue
if cleaned_line:
final_list.append(cleaned_line)
return final_list

View File

@@ -95,3 +95,4 @@ def delete_dir_files(path: Path) -> Any:
for file in path.iterdir():
if file.is_file():
file.unlink()