diff --git a/apps/createDocument/controllers/__pycache__/dg.cpython-313.pyc b/apps/createDocument/controllers/__pycache__/dg.cpython-313.pyc index 930acb2..655e84f 100644 Binary files a/apps/createDocument/controllers/__pycache__/dg.cpython-313.pyc and b/apps/createDocument/controllers/__pycache__/dg.cpython-313.pyc differ diff --git a/apps/createDocument/controllers/__pycache__/hsm.cpython-313.pyc b/apps/createDocument/controllers/__pycache__/hsm.cpython-313.pyc index c95a0ad..ec5f267 100644 Binary files a/apps/createDocument/controllers/__pycache__/hsm.cpython-313.pyc and b/apps/createDocument/controllers/__pycache__/hsm.cpython-313.pyc differ diff --git a/apps/createDocument/controllers/dg.py b/apps/createDocument/controllers/dg.py index 15c1643..45b63b1 100644 --- a/apps/createDocument/controllers/dg.py +++ b/apps/createDocument/controllers/dg.py @@ -15,7 +15,7 @@ from pathlib import Path from utils.chen_response import ChenResponse # 导入数据库ORM from apps.project.models import Project, Contact, Abbreviation, ProjectSoftSummary, StuctSortData, StaticSoftItem, StaticSoftHardware, \ - DynamicSoftTable, DynamicHardwareTable + DynamicSoftTable, DynamicHardwareTable, ProjectDynamicDescription, EvaluateData, EnvAnalysis from apps.dict.models import Dict # 导入工具函数 from utils.util import get_str_dict, get_list_dict, get_testType, get_ident, get_str_abbr @@ -290,67 +290,80 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin): except PermissionError as e: return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e)) + # 生成dataSchemas的context - 服务于 1、测评对象 2、动态环境描述 + @classmethod + def create_data_schema_list_context(cls, data_qs, doc: DocxTemplate): + if data_qs.exists(): + data_list = [] + for data_obj in data_qs.all(): + item_context: dict[str, Any] = {"fontnote": data_obj.fontnote, 'type': data_obj.type} + # 根据数据类型处理content字段 + if data_obj.type == 'text': + item_context['content'] = data_obj.content + elif data_obj.type == 'table': + # 使用subdoc + subdoc = doc.new_subdoc() + rows = len(data_obj.content) + cols = len(data_obj.content[0]) + table = subdoc.add_table(rows=rows, cols=cols) + # 单元格处理 + for row in range(rows): + for col in range(cols): + cell = table.cell(row, col) + cell.text = data_obj.content[row][col] + # 第一行设置居中 + if row == 0: + # 黑体设置 + cell.text = "" + pa = cell.paragraphs[0] + run = pa.add_run(str(data_obj.content[row][col])) + run.font.name = '黑体' + run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体') + run.font.bold = False + pa.alignment = WD_ALIGN_PARAGRAPH.CENTER + # 垂直居中 + cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER + # 表格居中 + table.alignment = WD_ALIGN_PARAGRAPH.CENTER + # 设置边框 + set_table_border_by_cell_position(table) + item_context['content'] = subdoc + elif data_obj.type == 'image': + base64_bytes = base64.b64decode(data_obj.content.replace("data:image/png;base64,", "")) + item_context['content'] = InlineImage(doc, io.BytesIO(base64_bytes), width=Mm(120)) + data_list.append(item_context) + context = { + "datas": data_list, + } + return context + return None + + # 统将需要多个DataSchemas的一对一项目字段生成响应 + @classmethod + def uniform_res_from_mul_data_schemas(cls, id: int, filename: str, r_filename: str, model) -> ChenResponse | None: + project_obj = get_object_or_404(Project, id=id) + input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / filename + doc = DocxTemplate(input_path) + qs = model.objects.filter(project=project_obj) + if qs.exists(): + data_qs = qs.first().data_schemas + context = cls.create_data_schema_list_context(data_qs, doc) + doc.render(context) + try: + doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / r_filename) + return ChenResponse(status=200, code=200, message="文档生成成功!") + except PermissionError as e: + return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e)) + return None + # 生成测评对象 - 包括大纲、说明、回归说明和报告 @route.get('/create/softComposition', url_name='create-softComposition') @transaction.atomic def create_softComposition(self, id: int): # 首先判断是否包含 - 项目信息-软件概述 - project_obj = get_object_or_404(Project, id=id) - input_path_2 = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '测评对象_2.docx' - doc = DocxTemplate(input_path_2) - soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj) - if soft_summary_qs.exists(): - data_qs = soft_summary_qs.first().data_schemas - if data_qs.exists(): - # 如果存在则渲染此处 - data_list = [] - for data_obj in data_qs.all(): - item_context: dict[str, Any] = {"fontnote": data_obj.fontnote, 'type': data_obj.type} - # 根据数据类型处理content字段 - if data_obj.type == 'text': - item_context['content'] = data_obj.content - elif data_obj.type == 'table': - # 使用subdoc - subdoc = doc.new_subdoc() - rows = len(data_obj.content) - cols = len(data_obj.content[0]) - table = subdoc.add_table(rows=rows, cols=cols) - # 单元格处理 - for row in range(rows): - for col in range(cols): - cell = table.cell(row, col) - cell.text = data_obj.content[row][col] - # 第一行设置居中 - if row == 0: - # 黑体设置 - cell.text = "" - pa = cell.paragraphs[0] - run = pa.add_run(str(data_obj.content[row][col])) - run.font.name = '黑体' - run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体') - run.font.bold = False - pa.alignment = WD_ALIGN_PARAGRAPH.CENTER - # 垂直居中 - cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER - # 表格居中 - table.alignment = WD_ALIGN_PARAGRAPH.CENTER - # 设置边框 - set_table_border_by_cell_position(table) - item_context['content'] = subdoc - elif data_obj.type == 'image': - base64_bytes = base64.b64decode(data_obj.content.replace("data:image/png;base64,", "")) - item_context['content'] = InlineImage(doc, io.BytesIO(base64_bytes), width=Mm(120)) - data_list.append(item_context) - context = { - "datas": data_list, - } - doc.render(context) - try: - doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / '测评对象.docx') - return ChenResponse(status=200, code=200, message="文档生成成功!") - except PermissionError as e: - return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e)) - + res = self.uniform_res_from_mul_data_schemas(id, '测评对象_2.docx', '测评对象.docx', ProjectSoftSummary) + if res is not None: + return res # 原来文档片段或者初始内容 input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '测评对象.docx' doc = DocxTemplate(input_path) @@ -480,6 +493,8 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin): # 处理非第一列 else: cell.text = table_data[row][col - 1] + # 垂直居中 + cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER # 单独处理第一行 for col in range(cols): cell = table.cell(0, col) @@ -559,9 +574,14 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin): } return create_dg_docx("静态硬件和固件项.docx", context, id) - # 动态测评环境说明 + # 动态测评环境说明 - 多dataSchemas格式 @route.get('/create/dynamic_env', url_name='create-dynamic_env') def create_dynamic_env(self, id: int): + res = self.uniform_res_from_mul_data_schemas(id, '动态测试环境说明_2.docx', + '动态测试环境说明.docx', ProjectDynamicDescription) + if res is not None: + return res + # 老内容 project_obj: Project = get_object_or_404(Project, id=id) input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '动态测试环境说明.docx' doc = DocxTemplate(input_path) @@ -616,6 +636,11 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin): # 测试数据 @route.get('/create/test_data', url_name='create-test_data') def create_test_data(self, id: int): + res = self.uniform_static_dynamic_response(id, '测评数据_2.docx', + '测评数据.docx', EvaluateData) + if res is not None: + return res + # 老内容 input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '测评数据.docx' doc = DocxTemplate(input_path) replace, frag, rich_text_list = self._generate_frag(id, doc, '测评数据') @@ -628,6 +653,27 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin): # 环境差异性分析 @route.get('/create/env_diff', url_name='create-env_diff') def create_env_diff(self, id: int): + project_obj: Project = get_object_or_404(Project, id=id) + input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '环境差异性分析_2.docx' + doc = DocxTemplate(input_path) + qs = EnvAnalysis.objects.filter(project=project_obj) + if qs.exists(): + obj = qs.first() + table_data = obj.table + subdoc = self.create_table_context(table_data, doc) + context = { + "description": obj.description, + "table": subdoc, + "fontnote": obj.fontnote, + } + doc.render(context, autoescape=True) + try: + doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / '环境差异性分析.docx') + return ChenResponse(status=200, code=200, message="文档生成成功!") + except PermissionError as e: + return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e)) + + # 老内容 input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '环境差异性分析.docx' doc = DocxTemplate(input_path) replace, frag, rich_text_list = self._generate_frag(id, doc, '环境差异性分析') diff --git a/apps/createDocument/controllers/hsm.py b/apps/createDocument/controllers/hsm.py index a0efc7a..66296c0 100644 --- a/apps/createDocument/controllers/hsm.py +++ b/apps/createDocument/controllers/hsm.py @@ -8,7 +8,7 @@ from django.db.models import QuerySet, Q from docxtpl import DocxTemplate from docx import Document # 导入模型 -from apps.project.models import Project, Round, Dut +from apps.project.models import Project, Round, Dut, InfluenceArea from apps.dict.models import Dict # 导入项目工具 from utils.util import get_list_dict, get_str_dict, get_ident, get_case_ident, get_testType @@ -19,6 +19,7 @@ from utils.path_utils import project_path 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.createSeiTaiDocument.extensions.logger import GenerateLogger # 导入排序 @@ -235,6 +236,30 @@ 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 + if area_qs.exists(): + area_obj = area_qs.first() + items_qs = area_obj.influence_items.all() + if items_qs.exists(): + # 遍历items + item_render_list = [] + 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])) + item_dict = { + "change_type": item.change_type, + "change_influ": item.change_influ, + "case_str_list": case_str_list, + "change_des": item.change_des, # 富文本未处理 + } + item_render_list.append(item_dict) + # 如果存在这个轮次的需求文档,则查询上个版本 last_xq_version = "" if xq_dut: diff --git a/apps/project/__pycache__/models.cpython-313.pyc b/apps/project/__pycache__/models.cpython-313.pyc index a690e41..75dc498 100644 Binary files a/apps/project/__pycache__/models.cpython-313.pyc and b/apps/project/__pycache__/models.cpython-313.pyc differ diff --git a/apps/project/controllers/__pycache__/case.cpython-313.pyc b/apps/project/controllers/__pycache__/case.cpython-313.pyc index 9b00671..d3dc8c5 100644 Binary files a/apps/project/controllers/__pycache__/case.cpython-313.pyc and b/apps/project/controllers/__pycache__/case.cpython-313.pyc differ diff --git a/apps/project/controllers/__pycache__/project.cpython-313.pyc b/apps/project/controllers/__pycache__/project.cpython-313.pyc index a2921c2..44a6da6 100644 Binary files a/apps/project/controllers/__pycache__/project.cpython-313.pyc and b/apps/project/controllers/__pycache__/project.cpython-313.pyc differ diff --git a/apps/project/controllers/__pycache__/round.cpython-313.pyc b/apps/project/controllers/__pycache__/round.cpython-313.pyc index 24b97de..f2dfc6e 100644 Binary files a/apps/project/controllers/__pycache__/round.cpython-313.pyc and b/apps/project/controllers/__pycache__/round.cpython-313.pyc differ diff --git a/apps/project/controllers/case.py b/apps/project/controllers/case.py index 4114765..580c5e5 100644 --- a/apps/project/controllers/case.py +++ b/apps/project/controllers/case.py @@ -396,3 +396,21 @@ class CaseController(ControllerBase): Case.objects.bulk_update(updated_cases, ['exe_time']) return ChenResponse(status=200, code=200, data=len(updated_cases), message=f"成功更新{len(updated_cases)}个用例执行时间") + + # 给级联选择器数据 -> 上一轮次所有用例 + @route.get("/case/getRelatedCase", url_name='case-related-case') + def get_cases_related_case(self, id: int, round_key: str): + project_obj = get_object_or_404(Project, id=id) + previous_round_obj = project_obj.pField.filter(key=int(round_key) - 1).first() + # dut -> design + data_list = [] + for dut in previous_round_obj.rdField.all(): + dut_dict = {'label': dut.name, 'value': dut.id, 'children': []} + for design in dut.rsField.all(): + design_dict = {'label': design.name, 'value': design.id, 'key': design.key, 'children': []} + for case in design.dcField.all(): + case_dict = {'label': case.name, 'value': case.id, 'key': case.key} + design_dict['children'].append(case_dict) + dut_dict['children'].append(design_dict) + data_list.append(dut_dict) + return ChenResponse(message='获取成功', data=data_list) \ No newline at end of file diff --git a/apps/project/controllers/project.py b/apps/project/controllers/project.py index 40f9f92..f393181 100644 --- a/apps/project/controllers/project.py +++ b/apps/project/controllers/project.py @@ -15,9 +15,9 @@ from ninja import Query from utils.chen_response import ChenResponse from utils.chen_crud import create, multi_delete_project from apps.project.models import Project, Round, ProjectSoftSummary, StuctSortData, StaticSoftItem, StaticSoftHardware, DynamicSoftTable, \ - DynamicHardwareTable + DynamicHardwareTable, ProjectDynamicDescription, EvaluateData, EnvAnalysis from apps.project.schemas.project import ProjectRetrieveSchema, ProjectFilterSchema, ProjectCreateInput, \ - DeleteSchema, SoftSummarySchema, DataSchema, StaticDynamicData + DeleteSchema, SoftSummarySchema, DataSchema, StaticDynamicData, EnvAnalysisSchema from utils.util import get_str_dict # 时间处理模块 from apps.project.tool.timeList import time_return_to @@ -99,6 +99,7 @@ class ProjectController(ControllerBase): except FileNotFoundError: return ChenResponse(code=500, status=500, message='文件不存在,请检查') return ChenResponse(code=200, status=200, message="添加项目成功,并添加第一轮测试") + return ChenResponse(code=400, status=400, message="未添加任何项目") @route.put("/update/{project_id}") @transaction.atomic @@ -139,7 +140,7 @@ class ProjectController(ControllerBase): project_media_path = media_path / ident try: rmtree(project_media_path) - except FileNotFoundError as e: + except FileNotFoundError: return ChenResponse(status=400, code=400, message='项目模版目录可能不存在,可能之前已删除') return ChenResponse(message="删除成功!") @@ -270,48 +271,59 @@ class ProjectController(ControllerBase): time = time_return_to(id) return time - # 项目级信息前端告警数据获取 + # [变] 项目级信息前端告警数据获取 @route.get("/project_info_status/") @transaction.atomic def project_info_status(self, id: int): - # 全部状态 - all_status = { - "soft_summary": False, - "interface_image": False, - "static_soft_item": False, - "static_soft_hardware": False, - "dynamic_soft_item": False, - "dynamic_soft_hardware": False, - } - # 1.查看软件概述是否填写 project_obj = self.get_project_by_id(id) - soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj) - if soft_summary_qs.exists(): - # 存在还要判断是否有子项 - if soft_summary_qs.first().data_schemas.exists(): - all_status['soft_summary'] = True - # 2.查看接口图是否填写 - image_qs = StuctSortData.objects.filter(project=project_obj) - if image_qs.exists(): - all_status['interface_image'] = True - # 3.查看静态软件项是否填写 - static_item_qs = StaticSoftItem.objects.filter(project=project_obj) - if static_item_qs.exists(): - all_status['static_soft_item'] = True - # 4.静态硬件项 - static_hardware_qs = StaticSoftHardware.objects.filter(project=project_obj) - if static_hardware_qs.exists(): - all_status['static_soft_hardware'] = True - # 5.动态软件项 - dynamic_soft_item_qs = DynamicSoftTable.objects.filter(project=project_obj) - if dynamic_soft_item_qs.exists(): - all_status['dynamic_soft_item'] = True - # 5.动态软件项 - dynamic_hardware_qs = DynamicHardwareTable.objects.filter(project=project_obj) - if dynamic_hardware_qs.exists(): - all_status['dynamic_soft_hardware'] = True + + # 统一配置每个状态的检查逻辑 + status_configs = { + "soft_summary": { + "model": ProjectSoftSummary, + "check": lambda qs: qs.exists() and qs.first().data_schemas.exists() + }, + "interface_image": { + "model": StuctSortData, + "check": lambda qs: qs.exists() + }, + "static_soft_item": { + "model": StaticSoftItem, + "check": lambda qs: qs.exists() + }, + "static_soft_hardware": { + "model": StaticSoftHardware, + "check": lambda qs: qs.exists() + }, + "dynamic_soft_item": { + "model": DynamicSoftTable, + "check": lambda qs: qs.exists() + }, + "dynamic_soft_hardware": { + "model": DynamicHardwareTable, + "check": lambda qs: qs.exists() + }, + "dynamic_des": { + "model": ProjectDynamicDescription, + "check": lambda qs: qs.exists() and qs.first().data_schemas.exists() + }, + "evaluate_data": { + "model": EvaluateData, + "check": lambda qs: qs.exists() + }, + "env_analysis": { + "model": EnvAnalysis, + "check": lambda qs: qs.exists() + } + } + + all_status = {} + for status_key, config in status_configs.items(): + qs = config["model"].objects.filter(project=project_obj) + all_status[status_key] = config["check"](qs) return ChenResponse(status=200, code=20000, data=all_status, message='查询成功') + # [变] 封装结构化数据新增-修改(针对project - OneToOne - DataSchemas形式) @classmethod def bulk_create_data_schemas(cls, parent_obj, datas: list[DataSchema]): """ @@ -321,11 +333,13 @@ class ProjectController(ControllerBase): datas (list[DataSchema]): 数据模式对象列表 """ # 动态确定所属父model - field_name = None + field_name = None # type:ignore if isinstance(parent_obj, ProjectSoftSummary): field_name = 'soft_summary' elif isinstance(parent_obj, Project): field_name = 'project' + elif isinstance(parent_obj, ProjectDynamicDescription): + field_name = 'dynamic_description' else: raise HttpError(400, "添加的数据未在系统内,请联系管理员") @@ -340,39 +354,66 @@ class ProjectController(ControllerBase): data_list.append(new_data) StuctSortData.objects.bulk_create(data_list) + # 封装只有model不同 -修改和新增dataSchemas(针对project - OneToOne - DataSchemas形式) + @classmethod + def create_or_modify_data_schemas(cls, id: int, model, data): + project_obj = get_object_or_404(Project, pk=id) + qs = model.objects.filter(project=project_obj) + if qs.exists(): + obj = qs.first() + # 如果存在则修改:先删除再创建 + obj.data_schemas.all().delete() + cls.bulk_create_data_schemas(obj, data) + else: + parent_obj = model.objects.create(project=project_obj) + cls.bulk_create_data_schemas(parent_obj, data) + # ~~~软件概述-新增和修改~~~ @route.post('/soft_summary/') @transaction.atomic def soft_summary(self, payload: SoftSummarySchema): - project_obj = self.get_project_by_id(payload.id) - # 安全获取-软件概述 - soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj) - if soft_summary_qs.exists(): - soft_summary = soft_summary_qs.first() - # 如果存在则修改:先删除然后创建 - soft_summary.data_schemas.all().delete() - self.bulk_create_data_schemas(soft_summary, payload.data) - else: - # 不存在软件概述则创建 - soft_summary_obj = ProjectSoftSummary.objects.create(project=project_obj) - self.bulk_create_data_schemas(soft_summary_obj, payload.data) + self.create_or_modify_data_schemas(payload.id, ProjectSoftSummary, payload.data) + + # ~~~动态环境描述-新增和修改~~~ + @route.post('/dynamic_description/') + @transaction.atomic + def dynamic_description(self, payload: SoftSummarySchema): + self.create_or_modify_data_schemas(payload.id, ProjectDynamicDescription, payload.data) + + @classmethod + def get_res_from_info(cls, project_obj: Project, model) -> list[dict] | None: + """model: 当前一对一模型,直接获取结构化数据信息数组返回""" + qs = model.objects.filter(project=project_obj) + if qs.exists(): + obj = qs.first() + ds_qs = obj.data_schemas.all() + data_list = [{ + "type": item.type, + "content": item.content, + "fontnote": item.fontnote, + } for item in ds_qs] + return data_list + return None # ~~~软件概述-获取到前端展示~~~ @route.get("/get_soft_summary/", response=list[DataSchema]) @transaction.atomic def get_soft_summary(self, id: int): project_obj = self.get_project_by_id(id) - soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj) - if soft_summary_qs.exists(): - # 如果存在则返回数据 - soft_summary = soft_summary_qs.first() - dataSchem_qs = soft_summary.data_schemas.all() - return ChenResponse(status=200, code=25001, data=[{ - "type": item.type, - "content": item.content, - "fontnote": item.fontnote, - } for item in dataSchem_qs]) - return ChenResponse(status=200, code=25002, data=[]) + data_list = self.get_res_from_info(project_obj, ProjectSoftSummary) + if data_list: + return ChenResponse(status=200, code=20000, data=data_list) + return ChenResponse(status=200, code=20000, data=[]) + + # ~~~动态环境描述 - 获取展示~~~ + @route.get("/dynamic_des/", response=list[DataSchema]) + @transaction.atomic + def get_dynamic_des(self, id: int): + project_obj = self.get_project_by_id(id) + data_list = self.get_res_from_info(project_obj, ProjectDynamicDescription) + if data_list: + return ChenResponse(status=200, code=20000, data=data_list) + return ChenResponse(status=200, code=20000, data=[]) # ~~~接口图新增或修改~~~ @route.post("/interface_image/") @@ -400,13 +441,15 @@ class ProjectController(ControllerBase): }) return ChenResponse(status=200, code=25002, data=None) + # 动态返回是哪个模型 @classmethod def get_model_from_category(cls, category: str): mapDict = { '静态软件项': StaticSoftItem, '静态硬件项': StaticSoftHardware, '动态软件项': DynamicSoftTable, - '动态硬件项': DynamicHardwareTable + '动态硬件项': DynamicHardwareTable, + '测评数据': EvaluateData } return mapDict[category] @@ -424,7 +467,6 @@ class ProjectController(ControllerBase): @route.post("/post_static_dynamic_item/") @transaction.atomic def post_static_dynamic_item(self, data: StaticDynamicData): - print(data) project_obj = self.get_project_by_id(data.id) model = self.get_model_from_category(data.category) item_qs = model.objects.filter(project=project_obj) @@ -432,3 +474,24 @@ class ProjectController(ControllerBase): # 如果存在则修改 item_qs.delete() model.objects.create(project=project_obj, table=data.table, fontnote=data.fontnote) + + # ~~~环境差异性分析 - 获取~~~ + @route.get("/get_env_analysis/") + @transaction.atomic + def get_env_analysis(self, id: int): + project_obj = self.get_project_by_id(id) + qs = EnvAnalysis.objects.filter(project=project_obj) + if qs.exists(): + obj = qs.first() + return ChenResponse(status=200, code=25001, data={"table": obj.table, "fontnote": obj.fontnote, "description": obj.description}) + return ChenResponse(status=200, code=25002, data=None) + + # ~~~环境差异性分析 - 新增和修改~~~ + @route.post("/post_env_analysis/") + @transaction.atomic + def post_env_analysis(self, data: EnvAnalysisSchema): + project_obj = self.get_project_by_id(data.id) + qs = EnvAnalysis.objects.filter(project=project_obj) + if qs.exists(): + qs.delete() + EnvAnalysis.objects.create(project=project_obj, table=data.table, fontnote=data.fontnote, description=data.description) diff --git a/apps/project/controllers/round.py b/apps/project/controllers/round.py index 46a9e1d..b889b24 100644 --- a/apps/project/controllers/round.py +++ b/apps/project/controllers/round.py @@ -2,9 +2,9 @@ from ninja_extra import api_controller, ControllerBase, route from ninja_jwt.authentication import JWTAuth from ninja_extra.permissions import IsAuthenticated from django.db import transaction -from apps.project.models import Round +from apps.project.models import Round, InfluenceArea, InfluenceItem from apps.project.schemas.round import TreeReturnRound, RoundInfoOutSchema, EditSchemaIn, DeleteSchema, \ - CreateRoundOutSchema, CreateRoundInputSchema + CreateRoundOutSchema, CreateRoundInputSchema, InfluenceItemOutSchema, InfluenceInputSchema from typing import List from utils.chen_response import ChenResponse from apps.project.tools.delete_change_key import round_delete_sub_node_key @@ -81,3 +81,63 @@ class RoundController(ControllerBase): return ChenResponse(code=400, status=400, message='标识和其他重复') Round.objects.create(**asert_dict) return ChenResponse(message="新增轮次成功") + + # ~~~影响域分析 - 获取数据和状态~~~ + @route.get("/round/get_influence", response=List[InfluenceItemOutSchema], url_name="round-get-influence-items") + @transaction.atomic + def get_influence(self, id: int, round_key: str): + round_qs = Round.objects.filter(project__id=id, key=round_key) + round_obj = round_qs.first() + influence_qs = InfluenceArea.objects.filter(round=round_obj) + if influence_qs.exists(): + influence = influence_qs.first() + items_qs = influence.influence_items.all() + if items_qs.exists(): + return items_qs + return ChenResponse(status=200, code=25002, data=[]) + + # ~~~影响域分析是否有值~~~ + @route.get("/round/get_status_influence", url_name="round-get-status-influence") + @transaction.atomic + def get_status_influence(self, id: int, round_key: str): + round_qs = Round.objects.filter(project__id=id, key=round_key) + round_obj = round_qs.first() + influence_qs = InfluenceArea.objects.filter(round=round_obj) + if influence_qs.exists(): + influence = influence_qs.first() + items_qs = influence.influence_items.all() + if items_qs.exists(): + return ChenResponse(status=200, code=25005, data=True) + return ChenResponse(status=200, code=25006, data=False) + + # ~~~影响域分析 - 修改或新增~~~ + @route.post("/round/create_influence", url_name="round-influence-create") + @transaction.atomic + def post_influence(self, data: InfluenceInputSchema): + print(data) + round_obj = Round.objects.filter(project_id=data.id, key=data.round_key).first() + influence_area_qs = InfluenceArea.objects.filter(round=round_obj) + if influence_area_qs.exists(): + influence_area_obj = influence_area_qs.first() + influence_area_obj.influence_items.all().delete() + # 先删除再创建 + data_list = [] + for item in data.item_list: + new_item = InfluenceItem(influence=influence_area_obj, + change_type=item.change_type, + change_influ=item.change_influ, + change_des=item.change_des, + effect_cases=item.effect_cases) + data_list.append(new_item) + InfluenceItem.objects.bulk_create(data_list) + else: + parent_obj = InfluenceArea.objects.create(round=round_obj) + data_list = [] + for item in data.item_list: + new_item = InfluenceItem(influence=parent_obj, + change_type=item.change_type, + change_influ=item.change_influ, + change_des=item.change_des, + effect_cases=item.effect_cases) + data_list.append(new_item) + InfluenceItem.objects.bulk_create(data_list) diff --git a/apps/project/migrations/0025_evaluatedata.py b/apps/project/migrations/0025_evaluatedata.py new file mode 100644 index 0000000..6d50b72 --- /dev/null +++ b/apps/project/migrations/0025_evaluatedata.py @@ -0,0 +1,28 @@ +# Generated by Django 6.0.2 on 2026-02-06 10:56 + +import apps.project.models +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('project', '0024_projectdynamicdescription_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='EvaluateData', + fields=[ + ('project', models.OneToOneField(db_constraint=False, help_text='关联项目', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='evaluate_data', serialize=False, to='project.project', verbose_name='关联项目')), + ('table', models.JSONField(default=apps.project.models.default_json_value, help_text='储存表格二维数组', verbose_name='储存表格二维数组')), + ('fontnote', models.CharField(default='', help_text='数据的题注说明', max_length=256, null=True, verbose_name='题注')), + ], + options={ + 'verbose_name': '测评数据', + 'verbose_name_plural': '测评数据', + 'db_table': 'project_evaluate_data', + }, + ), + ] diff --git a/apps/project/migrations/0026_envanalysis.py b/apps/project/migrations/0026_envanalysis.py new file mode 100644 index 0000000..0f4c2dc --- /dev/null +++ b/apps/project/migrations/0026_envanalysis.py @@ -0,0 +1,29 @@ +# Generated by Django 6.0.2 on 2026-02-06 13:56 + +import apps.project.models +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('project', '0025_evaluatedata'), + ] + + operations = [ + migrations.CreateModel( + name='EnvAnalysis', + fields=[ + ('project', models.OneToOneField(db_constraint=False, help_text='关联项目', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='env_analysis', serialize=False, to='project.project', verbose_name='关联项目')), + ('table', models.JSONField(default=apps.project.models.default_json_value, help_text='储存表格二维数组', verbose_name='储存表格二维数组')), + ('fontnote', models.CharField(default='', help_text='数据的题注说明', max_length=256, null=True, verbose_name='题注')), + ('description', models.CharField(default='', max_length=1024, null=True, verbose_name='差异性分析文字')), + ], + options={ + 'verbose_name': '环境差异性分析表', + 'verbose_name_plural': '环境差异性分析表', + 'db_table': 'project_env_analysis', + }, + ), + ] diff --git a/apps/project/migrations/0027_influencearea_influenceitem.py b/apps/project/migrations/0027_influencearea_influenceitem.py new file mode 100644 index 0000000..28018ed --- /dev/null +++ b/apps/project/migrations/0027_influencearea_influenceitem.py @@ -0,0 +1,46 @@ +# Generated by Django 6.0.2 on 2026-02-06 16:05 + +import apps.project.models +import django.db.models.deletion +import tinymce.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('project', '0026_envanalysis'), + ] + + operations = [ + migrations.CreateModel( + name='InfluenceArea', + fields=[ + ('project', models.OneToOneField(db_constraint=False, help_text='关联项目', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='influence', serialize=False, to='project.round', verbose_name='关联项目')), + ], + options={ + 'verbose_name': '影响域分析', + 'verbose_name_plural': '影响域分析', + 'db_table': 'round_influence_area', + }, + ), + migrations.CreateModel( + name='InfluenceItem', + fields=[ + ('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')), + ('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')), + ('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')), + ('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')), + ('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')), + ('change_type', models.CharField(default='', help_text='更改类型', max_length=256, null=True, verbose_name='更改类型')), + ('change_des', tinymce.models.HTMLField(blank=True, null=True, verbose_name='更改内容描述')), + ('effect_cases', models.JSONField(default=apps.project.models.create_list, verbose_name='影响的用例key数组')), + ('influence', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='influence_items', to='project.influencearea', verbose_name='所属影响域分析')), + ], + options={ + 'verbose_name': '影响域分析 - 行数据', + 'verbose_name_plural': '影响域分析 - 行数据', + 'db_table': 'influence_item', + }, + ), + ] diff --git a/apps/project/migrations/0028_rename_project_influencearea_round.py b/apps/project/migrations/0028_rename_project_influencearea_round.py new file mode 100644 index 0000000..a94a8db --- /dev/null +++ b/apps/project/migrations/0028_rename_project_influencearea_round.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0.2 on 2026-02-07 13:45 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('project', '0027_influencearea_influenceitem'), + ] + + operations = [ + migrations.RenameField( + model_name='influencearea', + old_name='project', + new_name='round', + ), + ] diff --git a/apps/project/migrations/0029_influenceitem_change_influ.py b/apps/project/migrations/0029_influenceitem_change_influ.py new file mode 100644 index 0000000..b9744db --- /dev/null +++ b/apps/project/migrations/0029_influenceitem_change_influ.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0.2 on 2026-02-07 16:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('project', '0028_rename_project_influencearea_round'), + ] + + operations = [ + migrations.AddField( + model_name='influenceitem', + name='change_influ', + field=models.TextField(default='', help_text='影响域分析', max_length=2048, null=True, verbose_name='影响域分析'), + ), + ] diff --git a/apps/project/migrations/__pycache__/0025_evaluatedata.cpython-313.pyc b/apps/project/migrations/__pycache__/0025_evaluatedata.cpython-313.pyc new file mode 100644 index 0000000..c982c0f Binary files /dev/null and b/apps/project/migrations/__pycache__/0025_evaluatedata.cpython-313.pyc differ diff --git a/apps/project/migrations/__pycache__/0026_envanalysis.cpython-313.pyc b/apps/project/migrations/__pycache__/0026_envanalysis.cpython-313.pyc new file mode 100644 index 0000000..061da63 Binary files /dev/null and b/apps/project/migrations/__pycache__/0026_envanalysis.cpython-313.pyc differ diff --git a/apps/project/migrations/__pycache__/0027_influencearea_influenceitem.cpython-313.pyc b/apps/project/migrations/__pycache__/0027_influencearea_influenceitem.cpython-313.pyc new file mode 100644 index 0000000..9928bb4 Binary files /dev/null and b/apps/project/migrations/__pycache__/0027_influencearea_influenceitem.cpython-313.pyc differ diff --git a/apps/project/migrations/__pycache__/0028_rename_project_influencearea_round.cpython-313.pyc b/apps/project/migrations/__pycache__/0028_rename_project_influencearea_round.cpython-313.pyc new file mode 100644 index 0000000..784eb32 Binary files /dev/null and b/apps/project/migrations/__pycache__/0028_rename_project_influencearea_round.cpython-313.pyc differ diff --git a/apps/project/migrations/__pycache__/0029_influenceitem_change_influ.cpython-313.pyc b/apps/project/migrations/__pycache__/0029_influenceitem_change_influ.cpython-313.pyc new file mode 100644 index 0000000..9debd5a Binary files /dev/null and b/apps/project/migrations/__pycache__/0029_influenceitem_change_influ.cpython-313.pyc differ diff --git a/apps/project/models.py b/apps/project/models.py index 95b5e02..86f034a 100644 --- a/apps/project/models.py +++ b/apps/project/models.py @@ -542,7 +542,6 @@ class DynamicSoftTable(models.Model): class DynamicHardwareTable(models.Model): project = models.OneToOneField(to="Project", primary_key=True, db_constraint=False, related_name="dynamic_hardware", on_delete=models.CASCADE, verbose_name="关联项目", help_text="关联项目") - table = models.JSONField(verbose_name="储存表格二维数组", help_text="储存表格二维数组", default=default_json_value) fontnote = models.CharField(max_length=256, null=True, default="", verbose_name="题注", help_text="数据的题注说明") @@ -551,6 +550,32 @@ class DynamicHardwareTable(models.Model): verbose_name = "动态硬件项表" verbose_name_plural = verbose_name +# 一对一项目model:动态环境 - 测评数据 +class EvaluateData(models.Model): + project = models.OneToOneField(to="Project", primary_key=True, db_constraint=False, related_name="evaluate_data", on_delete=models.CASCADE, + verbose_name="关联项目", help_text="关联项目") + table = models.JSONField(verbose_name="储存表格二维数组", help_text="储存表格二维数组", default=default_json_value) + fontnote = models.CharField(max_length=256, null=True, default="", verbose_name="题注", help_text="数据的题注说明") + + class Meta: + db_table = 'project_evaluate_data' + verbose_name = "测评数据" + verbose_name_plural = verbose_name + +# 一对一项目model:环境差异性分析 +class EnvAnalysis(models.Model): + project = models.OneToOneField(to="Project", primary_key=True, db_constraint=False, + related_name="env_analysis", on_delete=models.CASCADE, + verbose_name="关联项目", help_text="关联项目") + table = models.JSONField(verbose_name="储存表格二维数组", help_text="储存表格二维数组", default=default_json_value) + fontnote = models.CharField(max_length=256, null=True, default="", verbose_name="题注", help_text="数据的题注说明") + description = models.CharField(max_length=1024, null=True, default="", verbose_name="差异性分析文字") + + class Meta: + db_table = 'project_env_analysis' + verbose_name = "环境差异性分析表" + verbose_name_plural = verbose_name + # 结构化排序数据 class StuctSortData(CoreModel): """ @@ -582,11 +607,7 @@ class StuctSortData(CoreModel): help_text="数据的题注说明" ) # 内容字段 - 存储字符串、列表、字典 - content = models.JSONField( - verbose_name="内容", - help_text="存储文本内容或二维表格数据或图片数据", - default=default_json_value - ) + content = models.JSONField(verbose_name="内容", help_text="存储文本内容或二维表格数据或图片数据", default=default_json_value) class Meta: db_table = 'data_schemas' @@ -595,3 +616,28 @@ class StuctSortData(CoreModel): def __str__(self): return f"结构排序化数据:({self.pk})" + +# 影响域分析 - 隶属:轮次(不能是第一轮次) +class InfluenceArea(models.Model): + round = models.OneToOneField(to="Round", primary_key=True, db_constraint=False, + related_name="influence", on_delete=models.CASCADE, + verbose_name="关联项目", help_text="关联项目") + + class Meta: + db_table = 'round_influence_area' + verbose_name = "影响域分析" + verbose_name_plural = verbose_name + +class InfluenceItem(CoreModel): + # 外键:影响域分析 + influence = models.ForeignKey(InfluenceArea, db_constraint=False, related_name="influence_items", verbose_name="所属影响域分析", + on_delete=models.CASCADE, null=True, blank=True) + change_type = models.CharField(max_length=256, null=True, default="", verbose_name="更改类型", help_text="更改类型") + change_influ = models.TextField(max_length=2048, null=True, default="", verbose_name="影响域分析", help_text="影响域分析") + change_des = HTMLField(blank=True, null=True, verbose_name="更改内容描述") + effect_cases = models.JSONField(default=create_list, verbose_name="影响的用例key数组") + + class Meta: + db_table = 'influence_item' + verbose_name = "影响域分析 - 行数据" + verbose_name_plural = verbose_name diff --git a/apps/project/schemas/__pycache__/project.cpython-313.pyc b/apps/project/schemas/__pycache__/project.cpython-313.pyc index da415e7..82ce6a7 100644 Binary files a/apps/project/schemas/__pycache__/project.cpython-313.pyc and b/apps/project/schemas/__pycache__/project.cpython-313.pyc differ diff --git a/apps/project/schemas/__pycache__/round.cpython-313.pyc b/apps/project/schemas/__pycache__/round.cpython-313.pyc index c7e50b7..d14f7b0 100644 Binary files a/apps/project/schemas/__pycache__/round.cpython-313.pyc and b/apps/project/schemas/__pycache__/round.cpython-313.pyc differ diff --git a/apps/project/schemas/project.py b/apps/project/schemas/project.py index 92cba51..cc559ce 100644 --- a/apps/project/schemas/project.py +++ b/apps/project/schemas/project.py @@ -62,3 +62,10 @@ class StaticDynamicData(Schema): category: str table: list[list[str]] fontnote: Optional[str] = "" + +# ~~~环境差异性分析~~~ +class EnvAnalysisSchema(Schema): + id: int + table: list[list[str]] + fontnote: Optional[str] = "" + description: Optional[str] = "" \ No newline at end of file diff --git a/apps/project/schemas/round.py b/apps/project/schemas/round.py index de6437e..c198e3d 100644 --- a/apps/project/schemas/round.py +++ b/apps/project/schemas/round.py @@ -1,7 +1,7 @@ from typing import Optional from ninja import Schema, ModelSchema from pydantic import Field -from apps.project.models import Round +from apps.project.models import Round, InfluenceItem # 输出树状信息的schema class TreeReturnRound(Schema): @@ -55,3 +55,21 @@ class CreateRoundInputSchema(ModelSchema): fields_optional = ['best_condition_tem', 'best_condition_voltage', 'low_condition_tem', 'low_condition_voltage', 'typical_condition_tem', 'typical_condition_voltage' 'grade'] + +# influence_item return +class InfluenceItemOutSchema(ModelSchema): + class Meta: + model = InfluenceItem + fields = ['id', 'change_type', 'change_des', 'effect_cases', 'change_influ'] + +# influence input +class OneItemInputSchema(Schema): + change_type: str + change_des: Optional[str] = "" + effect_cases: Optional[list[str]] = [] + change_influ: Optional[str] = "" + +class InfluenceInputSchema(Schema): + id: int + round_key: str + item_list: list[OneItemInputSchema] diff --git a/conf/base_document/form_template/dg/动态测试环境说明_2.docx b/conf/base_document/form_template/dg/动态测试环境说明_2.docx new file mode 100644 index 0000000..9d78527 Binary files /dev/null and b/conf/base_document/form_template/dg/动态测试环境说明_2.docx differ diff --git a/conf/base_document/form_template/dg/测评数据_2.docx b/conf/base_document/form_template/dg/测评数据_2.docx new file mode 100644 index 0000000..764a481 Binary files /dev/null and b/conf/base_document/form_template/dg/测评数据_2.docx differ diff --git a/conf/base_document/form_template/dg/环境差异性分析_2.docx b/conf/base_document/form_template/dg/环境差异性分析_2.docx new file mode 100644 index 0000000..de82395 Binary files /dev/null and b/conf/base_document/form_template/dg/环境差异性分析_2.docx differ diff --git a/conf/base_document/form_template/hsm/~$软件更改部分.docx b/conf/base_document/form_template/hsm/~$软件更改部分.docx new file mode 100644 index 0000000..4adf549 Binary files /dev/null and b/conf/base_document/form_template/hsm/~$软件更改部分.docx differ diff --git a/conf/base_document/form_template/hsm/软件更改部分.docx b/conf/base_document/form_template/hsm/软件更改部分.docx index dad9c64..2c5c366 100644 Binary files a/conf/base_document/form_template/hsm/软件更改部分.docx and b/conf/base_document/form_template/hsm/软件更改部分.docx differ diff --git a/logs/root_log b/logs/root_log index 2555b09..a7d5d70 100644 --- a/logs/root_log +++ b/logs/root_log @@ -292,3 +292,307 @@ FileNotFoundError: [Errno 2] No such file or directory: 'E:\\pycharmProjects\\cd [WARNING][2026-02-05 18:19:31,559][log.py:249]Unprocessable Content: /api/testmanage/project/soft_summary/ [WARNING][2026-02-05 18:20:01,886][operation.py:131]"POST - ProjectController[soft_summary] /api/testmanage/project/soft_summary/" ([{'type': 'missing', 'loc': ('body', 'payload', 'id'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'payload', 'data'), 'msg': 'Field required'}],) [WARNING][2026-02-05 18:20:01,896][log.py:249]Unprocessable Content: /api/testmanage/project/soft_summary/ +[WARNING][2026-02-06 09:19:08,011][log.py:249]Unauthorized: /api/system/getInfo +[WARNING][2026-02-06 09:19:08,068][log.py:249]Unauthorized: /api/system/logout +[WARNING][2026-02-06 09:19:17,445][backend.py:91]Caught LDAPError looking up user: SERVER_DOWN({'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []}) +[WARNING][2026-02-06 09:32:51,032][log.py:249]Not Found: /api/testmanage/project/dynamic_des/ +[WARNING][2026-02-06 09:32:57,510][log.py:249]Not Found: /api/testmanage/project/dynamic_des/ +[WARNING][2026-02-06 09:33:05,303][log.py:249]Method Not Allowed: /api/testmanage/project/dynamic_des/ +[WARNING][2026-02-06 10:01:55,025][operation.py:131]"POST - ProjectController[dynamic_description] /api/testmanage/project/dynamic_description/" (400, '添加的数据未在系统内,请联系管理员') +[WARNING][2026-02-06 10:01:55,034][log.py:249]Bad Request: /api/testmanage/project/dynamic_description/ +[WARNING][2026-02-06 10:02:03,145][operation.py:131]"POST - ProjectController[dynamic_description] /api/testmanage/project/dynamic_description/" (400, '添加的数据未在系统内,请联系管理员') +[WARNING][2026-02-06 10:02:03,155][log.py:249]Bad Request: /api/testmanage/project/dynamic_description/ +[WARNING][2026-02-06 10:02:43,130][operation.py:131]"POST - ProjectController[dynamic_description] /api/testmanage/project/dynamic_description/" (400, '添加的数据未在系统内,请联系管理员') +[WARNING][2026-02-06 10:02:43,141][log.py:249]Bad Request: /api/testmanage/project/dynamic_description/ +[WARNING][2026-02-06 10:39:53,890][operation.py:131]"GET - GenerateControllerDG[create_dynamic_env] /api/generate/create/dynamic_env" ("expected token 'end of statement block', got 'table'",) +[ERROR][2026-02-06 10:39:53,891][errors.py:131]expected token 'end of statement block', got 'table' +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 578, in create_dynamic_env + res = self.uniform_res_from_mul_data_schemas(id, '动态测试环境说明_2.docx', + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + '动态测试环境说明.docx', ProjectDynamicDescription) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 351, in uniform_res_from_mul_data_schemas + doc.render(context) + ~~~~~~~~~~^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 489, in render + xml_src = self.build_xml(context, jinja_env) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 436, in build_xml + xml = self.render_xml_part(xml, self.docx._part, context, jinja_env) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 322, in render_xml_part + raise exc + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 312, in render_xml_part + template = Template(src_xml) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1214, in __new__ + return env.from_string(source, template_class=cls) + ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1111, in from_string + return cls.from_code(self, self.compile(source), gs, None) + ~~~~~~~~~~~~^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 771, in compile + self.handle_exception(source=source_hint) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 942, in handle_exception + raise rewrite_traceback_stack(source=source) + File "", line 4, in template +jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block', got 'table' +[ERROR][2026-02-06 10:39:53,923][log.py:249]Internal Server Error: /api/generate/create/dynamic_env +[WARNING][2026-02-06 10:40:33,124][operation.py:131]"GET - GenerateControllerDG[create_dynamic_env] /api/generate/create/dynamic_env" ('unexpected char "\'" at 5156',) +[ERROR][2026-02-06 10:40:33,127][errors.py:131]unexpected char "'" at 5156 +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 578, in create_dynamic_env + res = self.uniform_res_from_mul_data_schemas(id, '动态测试环境说明_2.docx', + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + '动态测试环境说明.docx', ProjectDynamicDescription) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 351, in uniform_res_from_mul_data_schemas + doc.render(context) + ~~~~~~~~~~^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 489, in render + xml_src = self.build_xml(context, jinja_env) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 436, in build_xml + xml = self.render_xml_part(xml, self.docx._part, context, jinja_env) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 322, in render_xml_part + raise exc + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 312, in render_xml_part + template = Template(src_xml) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1214, in __new__ + return env.from_string(source, template_class=cls) + ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1111, in from_string + return cls.from_code(self, self.compile(source), gs, None) + ~~~~~~~~~~~~^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 771, in compile + self.handle_exception(source=source_hint) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 942, in handle_exception + raise rewrite_traceback_stack(source=source) + File "", line 4, in template +jinja2.exceptions.TemplateSyntaxError: unexpected char "'" at 5156 +[ERROR][2026-02-06 10:40:33,143][log.py:249]Internal Server Error: /api/generate/create/dynamic_env +[WARNING][2026-02-06 10:52:55,927][operation.py:131]"GET - ProjectController[get_static_dynamic_items] /api/testmanage/project/get_static_dynamic_items/" ('测评数据',) +[ERROR][2026-02-06 10:52:55,927][errors.py:131]'测评数据' +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 454, in get_static_dynamic_items + item_qs = self.get_model_from_category(category).objects.filter(project=project_obj) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 448, in get_model_from_category + return mapDict[category] + ~~~~~~~^^^^^^^^^^ +KeyError: '测评数据' +[ERROR][2026-02-06 10:52:55,929][log.py:249]Internal Server Error: /api/testmanage/project/get_static_dynamic_items/ +[WARNING][2026-02-06 13:56:16,158][operation.py:131]"GET - ProjectController[get_env_analysis] /api/testmanage/project/get_env_analysis/" (1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist") +[ERROR][2026-02-06 13:56:16,158][errors.py:131](1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist") +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute + return self.cursor.execute(sql, params) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\mysql\base.py", line 78, in execute + return self.cursor.execute(query, args) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 179, in execute + res = self._query(mogrified_query) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 330, in _query + db.query(q) + ~~~~~~~~^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\connections.py", line 280, in query + _mysql.connection.query(self, query) + ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ +MySQLdb.ProgrammingError: (1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist") + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "D:\programs\uv\python\cpython-3.13.11-windows-x86_64-none\Lib\contextlib.py", line 85, in inner + return func(*args, **kwds) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 485, in get_env_analysis + if qs.exists(): + ~~~~~~~~~^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\query.py", line 1337, in exists + return self.query.has_results(using=self.db) + ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\query.py", line 686, in has_results + return compiler.has_results() + ~~~~~~~~~~~~~~~~~~~~^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\compiler.py", line 1592, in has_results + return bool(self.execute_sql(SINGLE)) + ~~~~~~~~~~~~~~~~^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\compiler.py", line 1624, in execute_sql + cursor.execute(sql, params) + ~~~~~~~~~~~~~~^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 122, in execute + return super().execute(sql, params) + ~~~~~~~~~~~~~~~^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 79, in execute + return self._execute_with_wrappers( + ~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + sql, params, many=False, executor=self._execute + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 92, in _execute_with_wrappers + return executor(sql, params, many, context) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 100, in _execute + with self.db.wrap_database_errors: + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\utils.py", line 94, in __exit__ + raise dj_exc_value.with_traceback(traceback) from exc_value + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute + return self.cursor.execute(sql, params) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\mysql\base.py", line 78, in execute + return self.cursor.execute(query, args) + ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 179, in execute + res = self._query(mogrified_query) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 330, in _query + db.query(q) + ~~~~~~~~^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\connections.py", line 280, in query + _mysql.connection.query(self, query) + ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ +django.db.utils.ProgrammingError: (1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist") +[ERROR][2026-02-06 13:56:16,179][log.py:249]Internal Server Error: /api/testmanage/project/get_env_analysis/ +[WARNING][2026-02-06 14:05:16,384][operation.py:131]"GET - ProjectController[get_env_analysis] /api/testmanage/project/get_env_analysis/" ([{'type': 'missing', 'loc': ('query', 'id'), 'msg': 'Field required'}],) +[WARNING][2026-02-06 14:05:16,392][log.py:249]Unprocessable Content: /api/testmanage/project/get_env_analysis/ +[WARNING][2026-02-06 14:05:45,945][operation.py:131]"GET - ProjectController[get_env_analysis] /api/testmanage/project/get_env_analysis/" ([{'type': 'missing', 'loc': ('query', 'id'), 'msg': 'Field required'}],) +[WARNING][2026-02-06 14:05:45,955][log.py:249]Unprocessable Content: /api/testmanage/project/get_env_analysis/ +[WARNING][2026-02-06 14:07:06,442][log.py:249]Method Not Allowed: /api/testmanage/project/post_env_analysis/ +[WARNING][2026-02-06 17:54:26,693][log.py:249]Not Found: /api/project/case/getRelatedCase/ +[WARNING][2026-02-06 17:55:19,893][log.py:249]Not Found: /api/project/case/getRelatedCase/ +[WARNING][2026-02-06 17:55:54,935][log.py:249]Not Found: /api/project/case/getRelatedCase/ +[WARNING][2026-02-06 17:55:57,677][log.py:249]Not Found: /api/project/case/getRelatedCase/ +[WARNING][2026-02-06 17:56:36,885][log.py:249]Not Found: /api/project/case/getRelatedCase/ +[WARNING][2026-02-06 17:56:39,905][log.py:249]Not Found: /api/project/case/getRelatedCase/ +[WARNING][2026-02-07 12:50:41,012][log.py:249]Unauthorized: /api/system/getInfo +[WARNING][2026-02-07 12:50:41,075][log.py:249]Unauthorized: /api/system/logout +[WARNING][2026-02-07 12:50:44,998][backend.py:91]Caught LDAPError looking up user: SERVER_DOWN({'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []}) +[WARNING][2026-02-07 13:37:04,069][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ("'QuerySet' object has no attribute 'influence'",) +[ERROR][2026-02-07 13:37:04,069][errors.py:131]'QuerySet' object has no attribute 'influence' +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence + influence_qs = round_qs.influence.all() + ^^^^^^^^^^^^^^^^^^ +AttributeError: 'QuerySet' object has no attribute 'influence' +[ERROR][2026-02-07 13:37:04,071][log.py:249]Internal Server Error: /api/project/round/get_influence +[WARNING][2026-02-07 13:37:39,505][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ('Round has no influence.',) +[ERROR][2026-02-07 13:37:39,505][errors.py:131]Round has no influence. +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence + influence_qs = round_qs.first().influence.all() + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 520, in __get__ + raise self.RelatedObjectDoesNotExist( + ...<2 lines>... + ) +apps.project.models.Round.influence.RelatedObjectDoesNotExist: Round has no influence. +[ERROR][2026-02-07 13:37:39,508][log.py:249]Internal Server Error: /api/project/round/get_influence +[WARNING][2026-02-07 13:38:15,267][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ('Round has no influence.',) +[ERROR][2026-02-07 13:38:15,267][errors.py:131]Round has no influence. +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence + influence_qs = round_qs.first().influence.all() + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 520, in __get__ + raise self.RelatedObjectDoesNotExist( + ...<2 lines>... + ) +apps.project.models.Round.influence.RelatedObjectDoesNotExist: Round has no influence. +[ERROR][2026-02-07 13:38:15,269][log.py:249]Internal Server Error: /api/project/round/get_influence +[WARNING][2026-02-07 13:39:10,565][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ('Round has no influence.',) +[ERROR][2026-02-07 13:39:10,565][errors.py:131]Round has no influence. +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence + influence_qs = round_qs.first().influence.all() + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 520, in __get__ + raise self.RelatedObjectDoesNotExist( + ...<2 lines>... + ) +apps.project.models.Round.influence.RelatedObjectDoesNotExist: Round has no influence. +[ERROR][2026-02-07 13:39:10,568][log.py:249]Internal Server Error: /api/project/round/get_influence +[WARNING][2026-02-07 14:25:27,963][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'missing', 'loc': ('body', 'data', 'id'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'round_key'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'item_list'), 'msg': 'Field required'}],) +[WARNING][2026-02-07 14:25:27,972][log.py:249]Unprocessable Content: /api/project/round/create_influence +[WARNING][2026-02-07 14:25:49,141][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'missing', 'loc': ('body', 'data', 'id'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'round_key'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'item_list'), 'msg': 'Field required'}],) +[WARNING][2026-02-07 14:25:49,154][log.py:249]Unprocessable Content: /api/project/round/create_influence +[WARNING][2026-02-07 15:01:21,250][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ('Cannot assign "]>": "InfluenceItem.influence" must be a "InfluenceArea" instance.',) +[ERROR][2026-02-07 15:01:21,250][errors.py:131]Cannot assign "]>": "InfluenceItem.influence" must be a "InfluenceArea" instance. +Traceback (most recent call last): + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run + result = self.view_func(request, **ctx.kwargs["view_func_kwargs"]) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view + result = self.route.view_func( + ctx.controller_instance, *args, **ctx.view_func_kwargs + ) + File "D:\programs\uv\python\cpython-3.13.11-windows-x86_64-none\Lib\contextlib.py", line 85, in inner + return func(*args, **kwds) + File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 110, in post_influence + new_item = InfluenceItem(influence=influence_area_qs, + change_type=item.change_type, + change_des=item.change_des, + effect_cases=item.effect_cases) + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 566, in __init__ + _setattr(self, field.name, rel_obj) + ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 287, in __set__ + raise ValueError( + ...<7 lines>... + ) +ValueError: Cannot assign "]>": "InfluenceItem.influence" must be a "InfluenceArea" instance. +[ERROR][2026-02-07 15:01:21,258][log.py:249]Internal Server Error: /api/project/round/create_influence +[WARNING][2026-02-07 15:19:38,249][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}],) +[WARNING][2026-02-07 15:19:38,257][log.py:249]Unprocessable Content: /api/project/round/create_influence +[WARNING][2026-02-07 15:19:43,626][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}],) +[WARNING][2026-02-07 15:19:43,635][log.py:249]Unprocessable Content: /api/project/round/create_influence +[WARNING][2026-02-07 15:20:44,492][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}],) +[WARNING][2026-02-07 15:20:44,503][log.py:249]Unprocessable Content: /api/project/round/create_influence +[WARNING][2026-02-07 15:21:39,506][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 2), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 3), 'msg': 'Input should be a valid string'}],) +[WARNING][2026-02-07 15:21:39,515][log.py:249]Unprocessable Content: /api/project/round/create_influence diff --git a/media/R25999/final_seitai/测评大纲.docx b/media/R25999/final_seitai/测评大纲.docx index a2cd2d3..b54b955 100644 Binary files a/media/R25999/final_seitai/测评大纲.docx and b/media/R25999/final_seitai/测评大纲.docx differ diff --git a/media/R25999/final_seitai/第二轮回归测试说明.docx b/media/R25999/final_seitai/第二轮回归测试说明.docx index d4c1b26..4499e53 100644 Binary files a/media/R25999/final_seitai/第二轮回归测试说明.docx and b/media/R25999/final_seitai/第二轮回归测试说明.docx differ diff --git a/media/R25999/form_template/dg/动态测试环境说明_2.docx b/media/R25999/form_template/dg/动态测试环境说明_2.docx new file mode 100644 index 0000000..9d78527 Binary files /dev/null and b/media/R25999/form_template/dg/动态测试环境说明_2.docx differ diff --git a/media/R25999/form_template/dg/测评数据_2.docx b/media/R25999/form_template/dg/测评数据_2.docx new file mode 100644 index 0000000..764a481 Binary files /dev/null and b/media/R25999/form_template/dg/测评数据_2.docx differ diff --git a/media/R25999/form_template/dg/环境差异性分析_2.docx b/media/R25999/form_template/dg/环境差异性分析_2.docx new file mode 100644 index 0000000..de82395 Binary files /dev/null and b/media/R25999/form_template/dg/环境差异性分析_2.docx differ diff --git a/media/R25999/form_template/hsm/temporary/第二轮用例追踪_temp.docx b/media/R25999/form_template/hsm/temporary/第二轮用例追踪_temp.docx index 02261c9..4ec4149 100644 Binary files a/media/R25999/form_template/hsm/temporary/第二轮用例追踪_temp.docx and b/media/R25999/form_template/hsm/temporary/第二轮用例追踪_temp.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮回归测试用例概述.docx b/media/R25999/output_dir/hsm/第二轮回归测试用例概述.docx index f17c5c9..ef6edca 100644 Binary files a/media/R25999/output_dir/hsm/第二轮回归测试用例概述.docx and b/media/R25999/output_dir/hsm/第二轮回归测试用例概述.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮回归测试需求.docx b/media/R25999/output_dir/hsm/第二轮回归测试需求.docx index c7a6216..afe58be 100644 Binary files a/media/R25999/output_dir/hsm/第二轮回归测试需求.docx and b/media/R25999/output_dir/hsm/第二轮回归测试需求.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮技术依据文件.docx b/media/R25999/output_dir/hsm/第二轮技术依据文件.docx index 08d74cd..d2bd12b 100644 Binary files a/media/R25999/output_dir/hsm/第二轮技术依据文件.docx and b/media/R25999/output_dir/hsm/第二轮技术依据文件.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮文档概述.docx b/media/R25999/output_dir/hsm/第二轮文档概述.docx index 8247146..11bab1b 100644 Binary files a/media/R25999/output_dir/hsm/第二轮文档概述.docx and b/media/R25999/output_dir/hsm/第二轮文档概述.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮测试用例.docx b/media/R25999/output_dir/hsm/第二轮测试用例.docx index 570baa4..1c11a3d 100644 Binary files a/media/R25999/output_dir/hsm/第二轮测试用例.docx and b/media/R25999/output_dir/hsm/第二轮测试用例.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮用例追踪.docx b/media/R25999/output_dir/hsm/第二轮用例追踪.docx index 298bb09..f95de00 100644 Binary files a/media/R25999/output_dir/hsm/第二轮用例追踪.docx and b/media/R25999/output_dir/hsm/第二轮用例追踪.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮被测软件基本信息.docx b/media/R25999/output_dir/hsm/第二轮被测软件基本信息.docx index 64b0b20..369530d 100644 Binary files a/media/R25999/output_dir/hsm/第二轮被测软件基本信息.docx and b/media/R25999/output_dir/hsm/第二轮被测软件基本信息.docx differ diff --git a/media/R25999/output_dir/hsm/第二轮软件更改部分.docx b/media/R25999/output_dir/hsm/第二轮软件更改部分.docx index 5c6f12e..69eddca 100644 Binary files a/media/R25999/output_dir/hsm/第二轮软件更改部分.docx and b/media/R25999/output_dir/hsm/第二轮软件更改部分.docx differ diff --git a/media/R25999/output_dir/主要功能和性能指标.docx b/media/R25999/output_dir/主要功能和性能指标.docx index 5999f6e..0ff65bd 100644 Binary files a/media/R25999/output_dir/主要功能和性能指标.docx and b/media/R25999/output_dir/主要功能和性能指标.docx differ diff --git a/media/R25999/output_dir/代码质量度量分析表.docx b/media/R25999/output_dir/代码质量度量分析表.docx index dc2d6bd..0756aed 100644 Binary files a/media/R25999/output_dir/代码质量度量分析表.docx and b/media/R25999/output_dir/代码质量度量分析表.docx differ diff --git a/media/R25999/output_dir/动态测试环境说明.docx b/media/R25999/output_dir/动态测试环境说明.docx index df7c453..033f6a8 100644 Binary files a/media/R25999/output_dir/动态测试环境说明.docx and b/media/R25999/output_dir/动态测试环境说明.docx differ diff --git a/media/R25999/output_dir/动态硬件和固件项.docx b/media/R25999/output_dir/动态硬件和固件项.docx index 9483809..37afb11 100644 Binary files a/media/R25999/output_dir/动态硬件和固件项.docx and b/media/R25999/output_dir/动态硬件和固件项.docx differ diff --git a/media/R25999/output_dir/动态软件项.docx b/media/R25999/output_dir/动态软件项.docx index 66afa77..c5840bb 100644 Binary files a/media/R25999/output_dir/动态软件项.docx and b/media/R25999/output_dir/动态软件项.docx differ diff --git a/media/R25999/output_dir/反向需求规格追踪表.docx b/media/R25999/output_dir/反向需求规格追踪表.docx index 2dbf816..44c391e 100644 Binary files a/media/R25999/output_dir/反向需求规格追踪表.docx and b/media/R25999/output_dir/反向需求规格追踪表.docx differ diff --git a/media/R25999/output_dir/技术依据文件.docx b/media/R25999/output_dir/技术依据文件.docx index b6a3760..9f98879 100644 Binary files a/media/R25999/output_dir/技术依据文件.docx and b/media/R25999/output_dir/技术依据文件.docx differ diff --git a/media/R25999/output_dir/标准依据文件.docx b/media/R25999/output_dir/标准依据文件.docx index acf990f..5a717b3 100644 Binary files a/media/R25999/output_dir/标准依据文件.docx and b/media/R25999/output_dir/标准依据文件.docx differ diff --git a/media/R25999/output_dir/测评对象.docx b/media/R25999/output_dir/测评对象.docx index ca076d1..8c86a22 100644 Binary files a/media/R25999/output_dir/测评对象.docx and b/media/R25999/output_dir/测评对象.docx differ diff --git a/media/R25999/output_dir/测评数据.docx b/media/R25999/output_dir/测评数据.docx index f5beac8..3135552 100644 Binary files a/media/R25999/output_dir/测评数据.docx and b/media/R25999/output_dir/测评数据.docx differ diff --git a/media/R25999/output_dir/测评时间和地点.docx b/media/R25999/output_dir/测评时间和地点.docx index 8cfe5d3..235a626 100644 Binary files a/media/R25999/output_dir/测评时间和地点.docx and b/media/R25999/output_dir/测评时间和地点.docx differ diff --git a/media/R25999/output_dir/测评条件保障.docx b/media/R25999/output_dir/测评条件保障.docx index e50f040..17a29e1 100644 Binary files a/media/R25999/output_dir/测评条件保障.docx and b/media/R25999/output_dir/测评条件保障.docx differ diff --git a/media/R25999/output_dir/测评组织及任务分工.docx b/media/R25999/output_dir/测评组织及任务分工.docx index 438448b..78ebc4a 100644 Binary files a/media/R25999/output_dir/测评组织及任务分工.docx and b/media/R25999/output_dir/测评组织及任务分工.docx differ diff --git a/media/R25999/output_dir/测试内容充分性及测试方法有效性分析.docx b/media/R25999/output_dir/测试内容充分性及测试方法有效性分析.docx index c3554c8..39ab329 100644 Binary files a/media/R25999/output_dir/测试内容充分性及测试方法有效性分析.docx and b/media/R25999/output_dir/测试内容充分性及测试方法有效性分析.docx differ diff --git a/media/R25999/output_dir/测试策略.docx b/media/R25999/output_dir/测试策略.docx index 9091b80..c2a510f 100644 Binary files a/media/R25999/output_dir/测试策略.docx and b/media/R25999/output_dir/测试策略.docx differ diff --git a/media/R25999/output_dir/测试级别和测试类型.docx b/media/R25999/output_dir/测试级别和测试类型.docx index 6abf7b7..1df2ed1 100644 Binary files a/media/R25999/output_dir/测试级别和测试类型.docx and b/media/R25999/output_dir/测试级别和测试类型.docx differ diff --git a/media/R25999/output_dir/测试项及方法.docx b/media/R25999/output_dir/测试项及方法.docx index a9b6a25..9b31700 100644 Binary files a/media/R25999/output_dir/测试项及方法.docx and b/media/R25999/output_dir/测试项及方法.docx differ diff --git a/media/R25999/output_dir/环境差异性分析.docx b/media/R25999/output_dir/环境差异性分析.docx index 16e3a21..31e2234 100644 Binary files a/media/R25999/output_dir/环境差异性分析.docx and b/media/R25999/output_dir/环境差异性分析.docx differ diff --git a/media/R25999/output_dir/研制总要求追踪表.docx b/media/R25999/output_dir/研制总要求追踪表.docx index 37268b8..5440b74 100644 Binary files a/media/R25999/output_dir/研制总要求追踪表.docx and b/media/R25999/output_dir/研制总要求追踪表.docx differ diff --git a/media/R25999/output_dir/缩略语.docx b/media/R25999/output_dir/缩略语.docx index 0a24fcf..a8df3a3 100644 Binary files a/media/R25999/output_dir/缩略语.docx and b/media/R25999/output_dir/缩略语.docx differ diff --git a/media/R25999/output_dir/联系人和方式.docx b/media/R25999/output_dir/联系人和方式.docx index 9ce06a1..1e4da26 100644 Binary files a/media/R25999/output_dir/联系人和方式.docx and b/media/R25999/output_dir/联系人和方式.docx differ diff --git a/media/R25999/output_dir/被测软件基本信息.docx b/media/R25999/output_dir/被测软件基本信息.docx index 251367d..2ccff72 100644 Binary files a/media/R25999/output_dir/被测软件基本信息.docx and b/media/R25999/output_dir/被测软件基本信息.docx differ diff --git a/media/R25999/output_dir/被测软件接口.docx b/media/R25999/output_dir/被测软件接口.docx index f7f9253..fccc8b2 100644 Binary files a/media/R25999/output_dir/被测软件接口.docx and b/media/R25999/output_dir/被测软件接口.docx differ diff --git a/media/R25999/output_dir/需求规格说明追踪表.docx b/media/R25999/output_dir/需求规格说明追踪表.docx index 79b6c54..a3fae55 100644 Binary files a/media/R25999/output_dir/需求规格说明追踪表.docx and b/media/R25999/output_dir/需求规格说明追踪表.docx differ diff --git a/media/R25999/output_dir/静态测试环境说明.docx b/media/R25999/output_dir/静态测试环境说明.docx index b18cf58..ffbfa3d 100644 Binary files a/media/R25999/output_dir/静态测试环境说明.docx and b/media/R25999/output_dir/静态测试环境说明.docx differ diff --git a/media/R25999/output_dir/静态硬件和固件项.docx b/media/R25999/output_dir/静态硬件和固件项.docx index 5a5ddda..9d5c53d 100644 Binary files a/media/R25999/output_dir/静态硬件和固件项.docx and b/media/R25999/output_dir/静态硬件和固件项.docx differ diff --git a/media/R25999/output_dir/静态软件项.docx b/media/R25999/output_dir/静态软件项.docx index a9eadc0..d44c5fe 100644 Binary files a/media/R25999/output_dir/静态软件项.docx and b/media/R25999/output_dir/静态软件项.docx differ diff --git a/media/R25999/output_dir/顶层技术文件.docx b/media/R25999/output_dir/顶层技术文件.docx index ccef0c2..2e53777 100644 Binary files a/media/R25999/output_dir/顶层技术文件.docx and b/media/R25999/output_dir/顶层技术文件.docx differ diff --git a/media/R25999/temp/测评大纲.docx b/media/R25999/temp/测评大纲.docx index d547573..332d115 100644 Binary files a/media/R25999/temp/测评大纲.docx and b/media/R25999/temp/测评大纲.docx differ diff --git a/media/R25999/temp/第二轮回归测试说明.docx b/media/R25999/temp/第二轮回归测试说明.docx index eb3f1aa..13a1576 100644 Binary files a/media/R25999/temp/第二轮回归测试说明.docx and b/media/R25999/temp/第二轮回归测试说明.docx differ