完成3月试用问题修改
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -31,7 +31,8 @@ from apps.createSeiTaiDocument.extensions.logger import GenerateLogger
|
||||
# 导入mixins-处理文档片段
|
||||
from apps.createDocument.extensions.mixins import FragementToolsMixin
|
||||
# 导入工具
|
||||
from apps.createDocument.extensions.tools import demand_sort_by_designKey, set_table_border_by_cell_position, set_cell_margins
|
||||
from apps.createDocument.extensions.tools import demand_sort_by_designKey, set_table_border_by_cell_position
|
||||
from apps.createDocument.extensions.table_creator import create_table_context, RoundType, uniform_static_dynamic_response
|
||||
|
||||
# @api_controller("/generate", tags=['生成大纲文档'], auth=JWTAuth(), permissions=[IsAuthenticated])
|
||||
@api_controller("/generate", tags=['生成大纲文档'])
|
||||
@@ -483,101 +484,10 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
|
||||
except PermissionError as e:
|
||||
return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e))
|
||||
|
||||
# 通用生成静态软件项、静态硬件项、动态软件项、动态硬件信息、测评数据的context,包含fontnote和table
|
||||
@classmethod
|
||||
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
|
||||
table = subdoc.add_table(rows=rows, cols=cols)
|
||||
|
||||
# 单元格处理
|
||||
for row in range(rows):
|
||||
for col in range(cols):
|
||||
cell = table.cell(row, col)
|
||||
set_cell_margins(cell, left=100, right=100, top=100, bottom=100)
|
||||
|
||||
# 获取要显示的文本内容(字符串或按行拆分后的列表)
|
||||
if col == 0:
|
||||
# 序号列
|
||||
lines = ["序号"] if row == 0 else [str(row)]
|
||||
else:
|
||||
raw_text = table_data[row][col - 1]
|
||||
# 按换行符 \n 拆分为多个段落
|
||||
lines = raw_text.split('\n') if raw_text else ['']
|
||||
|
||||
# 清空单元格原有段落(add_table 默认有一个段落)
|
||||
cell.text = ""
|
||||
# 删除默认段落,稍后统一添加
|
||||
for para in cell.paragraphs:
|
||||
p = para._element
|
||||
p.getparent().remove(p)
|
||||
|
||||
# 逐个添加段落
|
||||
for i, line in enumerate(lines):
|
||||
if i == 0:
|
||||
para = cell.add_paragraph(line)
|
||||
else:
|
||||
para = cell.add_paragraph(line)
|
||||
|
||||
# 设置段落对齐(第一列居中,其他左对齐,可根据需要调整)
|
||||
if col == 0:
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
else:
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
||||
|
||||
# 对第一行(表头)设置黑体字体
|
||||
if row == 0:
|
||||
for run in para.runs:
|
||||
run.font.name = '黑体'
|
||||
run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
|
||||
run.font.bold = False
|
||||
# 表头段落居中(覆盖前面的 left)
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
|
||||
# 垂直居中
|
||||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||||
|
||||
# 设置序号列宽度
|
||||
for cell in table.columns[0].cells:
|
||||
cell.width = Mm(15)
|
||||
for para in cell.paragraphs:
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
|
||||
# 表格居中
|
||||
table.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
# 设置表格外边框
|
||||
set_table_border_by_cell_position(table)
|
||||
return subdoc
|
||||
|
||||
# 统一静态软件项、静态硬件项、动态软件项、动态硬件信息的word生成 - 模版模式
|
||||
@classmethod
|
||||
def uniform_static_dynamic_response(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():
|
||||
obj = qs.first()
|
||||
table_data = obj.table
|
||||
subdoc = cls.create_table_context(table_data, doc)
|
||||
context = {
|
||||
'fontnote': obj.fontnote,
|
||||
'table': subdoc,
|
||||
}
|
||||
doc.render(context, autoescape=True)
|
||||
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/static_soft', url_name='create-static_soft')
|
||||
def create_static_soft(self, id: int):
|
||||
res = self.uniform_static_dynamic_response(id, '静态软件项_2.docx', '静态软件项.docx', StaticSoftItem)
|
||||
def create_static_soft(self, id: int, current_round: RoundType = "0"):
|
||||
res = uniform_static_dynamic_response(id, '静态软件项_2.docx', '静态软件项.docx', StaticSoftItem, current_round)
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
@@ -592,8 +502,11 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
|
||||
|
||||
# 静态硬件和固件项
|
||||
@route.get('/create/static_hard', url_name='create-static_hard')
|
||||
def create_static_hard(self, id: int):
|
||||
res = self.uniform_static_dynamic_response(id, '静态硬件和固件项_2.docx', '静态硬件和固件项.docx', StaticSoftHardware)
|
||||
def create_static_hard(self, id: int, current_round: RoundType = "0"):
|
||||
res = uniform_static_dynamic_response(id, '静态硬件和固件项_2.docx',
|
||||
'静态硬件和固件项.docx',
|
||||
StaticSoftHardware,
|
||||
current_round)
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
@@ -632,8 +545,8 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
|
||||
|
||||
# 动态软件项
|
||||
@route.get('/create/dynamic_soft', url_name='create-dynamic_soft')
|
||||
def create_dynamic_soft(self, id: int):
|
||||
res = self.uniform_static_dynamic_response(id, '动态软件项_2.docx', '动态软件项.docx', DynamicSoftTable)
|
||||
def create_dynamic_soft(self, id: int, current_round: RoundType = "0"):
|
||||
res = uniform_static_dynamic_response(id, '动态软件项_2.docx', '动态软件项.docx', DynamicSoftTable, current_round)
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
@@ -650,9 +563,9 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
|
||||
|
||||
# 动态硬件项
|
||||
@route.get('/create/dynamic_hard', url_name='create-dynamic_hard')
|
||||
def create_dynamic_hard(self, id: int):
|
||||
res = self.uniform_static_dynamic_response(id, '动态硬件和固件项_2.docx',
|
||||
'动态硬件和固件项.docx', DynamicHardwareTable)
|
||||
def create_dynamic_hard(self, id: int, current_round: RoundType = "0"):
|
||||
res = uniform_static_dynamic_response(id, '动态硬件和固件项_2.docx',
|
||||
'动态硬件和固件项.docx', DynamicHardwareTable, current_round)
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
@@ -667,9 +580,9 @@ 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)
|
||||
def create_test_data(self, id: int, current_round: RoundType = "0"):
|
||||
res = uniform_static_dynamic_response(id, '测评数据_2.docx',
|
||||
'测评数据.docx', EvaluateData, current_round)
|
||||
if res is not None:
|
||||
return res
|
||||
# 老内容
|
||||
@@ -692,7 +605,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
|
||||
if qs.exists():
|
||||
obj = qs.first()
|
||||
table_data = obj.table
|
||||
subdoc = self.create_table_context(table_data, doc)
|
||||
subdoc = create_table_context(table_data, doc)
|
||||
context = {
|
||||
"description": obj.description,
|
||||
"table": subdoc,
|
||||
|
||||
@@ -24,6 +24,9 @@ from apps.createDocument.extensions.content_result_tool import create_influence_
|
||||
from apps.createSeiTaiDocument.extensions.logger import GenerateLogger
|
||||
# 导入排序
|
||||
from apps.createDocument.extensions.tools import demand_sort_by_designKey
|
||||
# 导入静态软件项、静态硬件项、动态软件项、动态硬件项、测评数据辅助函数和模型
|
||||
from apps.createDocument.extensions.table_creator import uniform_static_dynamic_response, RoundType
|
||||
from apps.project.models import StaticSoftItem, StaticSoftHardware, DynamicSoftTable, DynamicHardwareTable, EvaluateData
|
||||
|
||||
chinese_round_name: list = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
|
||||
|
||||
@@ -42,6 +45,38 @@ class GenerateControllerHSM(ControllerBase):
|
||||
except PermissionError:
|
||||
return ChenResponse(code=400, status=400, message='另一个程序正在占用文件,请关闭后重试')
|
||||
|
||||
# ~~~新增5个接口,回归测试说明的~~~
|
||||
# 静态软件项
|
||||
@route.get('/create/static_soft', url_name='create-static_soft-hsm')
|
||||
def create_hsm_static_soft(self, id: int, current_round: RoundType = "0"):
|
||||
return uniform_static_dynamic_response(id, '静态软件项_2.docx', '静态软件项.docx', StaticSoftItem, current_round, isHsm=True)
|
||||
|
||||
# 静态硬件和固件项
|
||||
@route.get('/create/static_hard', url_name='create-static_hard-hsm')
|
||||
def create_hsm_static_hard(self, id: int, current_round: RoundType = "0"):
|
||||
return uniform_static_dynamic_response(id, '静态硬件和固件项_2.docx',
|
||||
'静态硬件和固件项.docx',
|
||||
StaticSoftHardware,
|
||||
current_round)
|
||||
|
||||
# 动态软件项
|
||||
@route.get('/create/dynamic_soft', url_name='create-dynamic_soft-hsm')
|
||||
def create_hsm_dynamic_soft(self, id: int, current_round: RoundType = "0"):
|
||||
return uniform_static_dynamic_response(id, '动态软件项_2.docx', '动态软件项.docx', DynamicSoftTable, current_round, isHsm=True)
|
||||
|
||||
# 动态硬件项
|
||||
@route.get('/create/dynamic_hard', url_name='create-dynamic_hard-hsm')
|
||||
def create_hsm_dynamic_hard(self, id: int, current_round: RoundType = "0"):
|
||||
return uniform_static_dynamic_response(id, '动态硬件和固件项_2.docx',
|
||||
'动态硬件和固件项.docx', DynamicHardwareTable, current_round, isHsm=True)
|
||||
|
||||
# 测试数据
|
||||
@route.get('/create/test_data', url_name='create-test_data-hsm')
|
||||
def create_hsm_test_data(self, id: int, current_round: RoundType = "0"):
|
||||
return uniform_static_dynamic_response(id, '测评数据_2.docx',
|
||||
'测评数据.docx', EvaluateData, current_round, isHsm=True)
|
||||
|
||||
# ~~~5个接口:end~~~
|
||||
@route.get("/create/basicInformation", url_name="create-basicInformation")
|
||||
@transaction.atomic
|
||||
def create_basicInformation(self, id: int):
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,207 +1,209 @@
|
||||
# 本模块主要以项目开始时间、结束时间、轮次开始时间、结束时间计算文档中的各个时间
|
||||
from datetime import timedelta, date
|
||||
from apps.project.models import Project
|
||||
from django.shortcuts import get_object_or_404
|
||||
from ninja.errors import HttpError # 从代码抛出该异常,被ninja截取变为response
|
||||
|
||||
def format_remove_heng(dateT: date) -> str:
|
||||
"""该函数将date对象的横杠-去掉,输出str"""
|
||||
return str(dateT).replace('-', '')
|
||||
|
||||
def times_by_cover_time(cover_time: date) -> dict:
|
||||
"""该函数为每个产品文档根据封面时间,渲染签署页时间、文档变更记录时间"""
|
||||
return {
|
||||
'preparation_time_no_format': cover_time - timedelta(days=2),
|
||||
'preparation_time': format_remove_heng(cover_time - timedelta(days=2)), # 拟制时间:为编制结束时间-2天
|
||||
'inspect_time': format_remove_heng(cover_time - timedelta(days=1)), # 校对时间:为编制时间+1天
|
||||
'auditing_time': format_remove_heng(cover_time),
|
||||
'ratify_time': format_remove_heng(cover_time),
|
||||
'create_doc_time': format_remove_heng(cover_time - timedelta(days=2)),
|
||||
'doc_v1_time': format_remove_heng(cover_time)
|
||||
}
|
||||
|
||||
class DocTime:
|
||||
def __init__(self, project_id: int):
|
||||
self.project = get_object_or_404(Project, id=project_id)
|
||||
# 用户录入时间-项目
|
||||
self.p_start = self.project.beginTime # 被测件接收时间/
|
||||
self.p_end = self.project.endTime # 大纲测评时间周期结束时间/
|
||||
# 遍历轮次时间-多个
|
||||
self.round_count = self.project.pField.count()
|
||||
self.round_time = [] # 轮次按顺序排序
|
||||
for round in self.project.pField.all():
|
||||
self.round_time.append({
|
||||
'start': round.beginTime,
|
||||
'end': round.endTime,
|
||||
'location': round.location
|
||||
})
|
||||
# ~~~~由上面时间二次计算得出时间~~~~ -> TODO:可由用户设置间隔时间!!!!
|
||||
self.dg_bz_start = self.p_start + timedelta(days=1) # 大纲编制开始时间,项目开始时间+1天
|
||||
self.dg_bz_end = self.dg_bz_start + timedelta(days=6) # 大纲编制结束时间,大纲编制开始+6天
|
||||
self.test_sj_start = self.dg_bz_end + timedelta(days=1) # 测评设计与实现时间,在大纲编制结束+1天
|
||||
self.test_sj_end = self.test_sj_start + timedelta(days=5) # 测评设计与实现结束,在开始+5天
|
||||
# ~~~~储存每个文档的cover_time~~~~
|
||||
self.dg_cover_time = self.dg_bz_end
|
||||
self.sm_cover_time = self.test_sj_end
|
||||
self.jl_cover_time = self.round_time[0]['end']
|
||||
self.wtd_cover_time = self.round_time[-1]['end']
|
||||
|
||||
# 该函数生成大纲文档片段-测评时间和地点的时间和地点信息
|
||||
def dg_address_time(self):
|
||||
"""直接返回context去渲染"""
|
||||
# 需要判断round_time是否有值
|
||||
if len(self.round_time) <= 0:
|
||||
raise HttpError(status_code=400, message='您还未创建轮次时间,请填写后生成')
|
||||
return {
|
||||
'start_year': self.p_start.year,
|
||||
'start_month': self.p_start.month,
|
||||
'end_year': self.p_end.year,
|
||||
'end_month': self.p_end.month,
|
||||
'beginTime_strf': format_remove_heng(self.p_start),
|
||||
'dgCompileStart': format_remove_heng(self.dg_bz_start),
|
||||
'dgCompileEnd': format_remove_heng(self.dg_bz_end),
|
||||
'designStart': format_remove_heng(self.test_sj_start),
|
||||
'designEnd': format_remove_heng(self.test_sj_end),
|
||||
'location': self.round_time[0]['location']
|
||||
}
|
||||
|
||||
# 该函数生成报告文档片段-测评时间和地点【注意使用了dg_address_time -> 所以后续有修改注意前导】
|
||||
def bg_address_time(self):
|
||||
if len(self.round_time) <= 0:
|
||||
raise HttpError(status_code=400, message='您还未创建轮次时间,请填写后生成')
|
||||
# 先使用大纲的时间行数作为前三行
|
||||
cname = ['首轮测试', '第二轮测试', '第三轮测试', '第四轮测试', '第五轮测试', '第六轮测试', '第七轮测试',
|
||||
'第八轮测试', '第九轮测试', '第十轮测试']
|
||||
dg_address_time = self.dg_address_time()
|
||||
round_time_list = []
|
||||
index = 0
|
||||
for round_dict in self.round_time:
|
||||
one_dict = {
|
||||
'name': cname[index],
|
||||
'start': format_remove_heng(round_dict['start']),
|
||||
'end': format_remove_heng(round_dict['end']),
|
||||
'location': round_dict['location']
|
||||
}
|
||||
index += 1
|
||||
round_time_list.append(one_dict)
|
||||
return {
|
||||
'begin_year': dg_address_time['start_year'],
|
||||
'begin_month': dg_address_time['start_month'],
|
||||
'end_year': dg_address_time['end_year'],
|
||||
'end_month': dg_address_time['end_month'],
|
||||
'begin_time': dg_address_time['beginTime_strf'],
|
||||
'dg_weave_start_date': dg_address_time['dgCompileStart'],
|
||||
'dg_weave_end_date': dg_address_time['dgCompileEnd'],
|
||||
'sj_weave_start_date': dg_address_time['designStart'],
|
||||
'sj_weave_end_date': dg_address_time['designEnd'],
|
||||
'round_time_list': round_time_list,
|
||||
# 测评总结 -> 依据项目结束时间-7 ~ 项目结束时间
|
||||
'summary_start_date': format_remove_heng(self.p_end - timedelta(days=7)),
|
||||
'summary_end_date': format_remove_heng(self.p_end),
|
||||
}
|
||||
|
||||
# 生成报告中测评完成情况 -> 必须依据其他内容生成时间【注意使用了bg_address_time -> 所以后续有修改注意前导】
|
||||
def bg_completion_situation(self):
|
||||
bg_timer_dict = self.bg_address_time()
|
||||
xq_fx_time_end = self.dg_bz_start + timedelta(days=2)
|
||||
ch_time_start = xq_fx_time_end + timedelta(days=1)
|
||||
ch_time_end = self.dg_bz_end
|
||||
if len(self.round_time) < 1:
|
||||
raise HttpError(status_code=400, message='您还未创建第一轮测试的时间,请填写后再生成')
|
||||
return {
|
||||
'start_time_year': bg_timer_dict['begin_year'],
|
||||
'start_time_month': bg_timer_dict['begin_month'],
|
||||
'xq_fx_time_start_year': self.dg_bz_start.year,
|
||||
'xq_fx_time_start_month': self.dg_bz_start.month,
|
||||
'xq_fx_time_start_day': self.dg_bz_start.day,
|
||||
'xq_fx_time_end_year': xq_fx_time_end.year, # 需求分析结束时间是大纲编制开始+2
|
||||
'xq_fx_time_end_month': xq_fx_time_end.month,
|
||||
'xq_fx_time_end_day': xq_fx_time_end.day,
|
||||
'ch_start_year': ch_time_start.year,
|
||||
'ch_start_month': ch_time_start.month,
|
||||
'ch_start_day': ch_time_start.day,
|
||||
'ch_end_year': ch_time_end.year,
|
||||
'ch_end_month': ch_time_end.month,
|
||||
'ch_end_day': ch_time_end.day,
|
||||
'sj_start_year': self.test_sj_start.year,
|
||||
'sj_start_month': self.test_sj_start.month,
|
||||
'sj_start_day': self.test_sj_start.day,
|
||||
'sj_end_year': self.test_sj_end.year,
|
||||
'sj_end_month': self.test_sj_end.month,
|
||||
'sj_end_day': self.test_sj_end.day,
|
||||
'end_time_year': self.p_end.year,
|
||||
'end_time_month': self.p_end.month,
|
||||
'exec_start_time_year': self.round_time[0]['start'].year,
|
||||
'exec_start_time_month': self.round_time[0]['start'].month,
|
||||
'exec_start_time_day': self.round_time[0]['start'].day,
|
||||
'exec_end_time_year': self.round_time[0]['end'].year,
|
||||
'exec_end_time_month': self.round_time[0]['end'].month,
|
||||
'exec_end_time_day': self.round_time[0]['end'].day,
|
||||
}
|
||||
|
||||
# 该函数生成最终大纲的时间
|
||||
def dg_final_time(self):
|
||||
cover_time = self.dg_bz_end
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
# 新增给大纲模版10.2章节context
|
||||
context.update(basic_line1=cover_time.strftime("%Y年%m月"), basic_line2=self.p_end.strftime("%Y年%m月"))
|
||||
# 新增给大纲模版10.3.2章节的context
|
||||
sm_context = self.sm_final_time()
|
||||
context.update(sm_end_time=sm_context['preparation_time_no_format'].strftime("%Y年%m月"))
|
||||
return context
|
||||
|
||||
# 该函数生成说明文档的时间 -> 依据项目时间而非用户第一轮填写时间!
|
||||
def sm_final_time(self):
|
||||
cover_time = self.test_sj_end # 封面时间:为大纲时间中“测评设计与实现”结束时间
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 该函数生成记录文档的时间 -> 依据第一轮测试用户填写的事件
|
||||
def jl_final_time(self):
|
||||
if len(self.round_time) < 1:
|
||||
raise HttpError(status_code=400, message='您还未创建第一轮测试的时间,请填写后再生成')
|
||||
cover_time = self.round_time[0]['end'] # 封面时间为用户填写第一轮结束时间
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 问题单的时间 -> 依据最后一轮次的结束时间+1天
|
||||
def wtd_final_time(self):
|
||||
if len(self.round_time) < 1:
|
||||
raise HttpError(status_code=400, message='您还未创建第一轮测试的时间,请填写后再生成')
|
||||
cover_time = self.round_time[-1]['end']
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 回归测试说明时间 -> 根据第二轮、第三轮...的开始时间
|
||||
def hsm_final_time(self, round_key: str):
|
||||
if len(self.round_time) < int(round_key) + 1:
|
||||
raise HttpError(status_code=400, message='您填写的回归轮次时间不正确,请填写后再生成')
|
||||
cover_time = self.round_time[int(round_key)]['start']
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 回归测试记录时间 -> 根据第二轮、第三轮...的结束时间
|
||||
def hjl_final_time(self, round_key: str) -> dict:
|
||||
if len(self.round_time) < int(round_key) + 1:
|
||||
raise HttpError(status_code=400, message='您填写的回归轮次时间不正确,请填写后再生成')
|
||||
cover_time = self.round_time[int(round_key)]['end']
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 生成报告非过程时间 -> 根据项目结束时间来定
|
||||
def bg_final_time(self) -> dict:
|
||||
if len(self.round_time) <= 0:
|
||||
raise HttpError(status_code=400, message='您还未创建轮次时间,请填写后生成')
|
||||
cover_time = self.p_end
|
||||
# 这里做判断,如果项目结束时间/最后一轮结束时间
|
||||
if cover_time < self.round_time[-1]['end']:
|
||||
raise HttpError(500, message='项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
# 本模块主要以项目开始时间、结束时间、轮次开始时间、结束时间计算文档中的各个时间
|
||||
from datetime import timedelta, date
|
||||
from apps.project.models import Project
|
||||
from django.shortcuts import get_object_or_404
|
||||
from ninja.errors import HttpError # 从代码抛出该异常,被ninja截取变为response
|
||||
from utils.codes import PROJECT_ENDTIME_ERROR_CODE
|
||||
|
||||
def format_remove_heng(dateT: date) -> str:
|
||||
"""该函数将date对象的横杠-去掉,输出str"""
|
||||
return str(dateT).replace('-', '')
|
||||
|
||||
def times_by_cover_time(cover_time: date) -> dict:
|
||||
"""该函数为每个产品文档根据封面时间,渲染签署页时间、文档变更记录时间"""
|
||||
return {
|
||||
'preparation_time_no_format': cover_time - timedelta(days=2),
|
||||
'preparation_time': format_remove_heng(cover_time - timedelta(days=2)), # 拟制时间:为编制结束时间-2天
|
||||
'inspect_time': format_remove_heng(cover_time - timedelta(days=1)), # 校对时间:为编制时间+1天
|
||||
'auditing_time': format_remove_heng(cover_time),
|
||||
'ratify_time': format_remove_heng(cover_time),
|
||||
'create_doc_time': format_remove_heng(cover_time - timedelta(days=2)),
|
||||
'doc_v1_time': format_remove_heng(cover_time)
|
||||
}
|
||||
|
||||
class DocTime:
|
||||
def __init__(self, project_id: int):
|
||||
self.project = get_object_or_404(Project, id=project_id)
|
||||
# 用户录入时间-项目
|
||||
self.p_start = self.project.beginTime # 被测件接收时间/
|
||||
self.p_end = self.project.endTime # 大纲测评时间周期结束时间/
|
||||
# 遍历轮次时间-多个
|
||||
self.round_count = self.project.pField.count()
|
||||
self.round_time = [] # 轮次按顺序排序
|
||||
for round in self.project.pField.all():
|
||||
self.round_time.append({
|
||||
'start': round.beginTime,
|
||||
'end': round.endTime,
|
||||
'location': round.location
|
||||
})
|
||||
# ~~~~由上面时间二次计算得出时间~~~~ -> TODO:可由用户设置间隔时间!!!!
|
||||
self.dg_bz_start = self.p_start + timedelta(days=1) # 大纲编制开始时间,项目开始时间+1天
|
||||
self.dg_bz_end = self.dg_bz_start + timedelta(days=6) # 大纲编制结束时间,大纲编制开始+6天
|
||||
self.test_sj_start = self.dg_bz_end + timedelta(days=1) # 测评设计与实现时间,在大纲编制结束+1天
|
||||
self.test_sj_end = self.test_sj_start + timedelta(days=5) # 测评设计与实现结束,在开始+5天
|
||||
# ~~~~储存每个文档的cover_time~~~~
|
||||
self.dg_cover_time = self.dg_bz_end
|
||||
self.sm_cover_time = self.test_sj_end
|
||||
self.jl_cover_time = self.round_time[0]['end']
|
||||
self.wtd_cover_time = self.round_time[-1]['end']
|
||||
|
||||
# 该函数生成大纲文档片段-测评时间和地点的时间和地点信息
|
||||
def dg_address_time(self):
|
||||
"""直接返回context去渲染"""
|
||||
# 需要判断round_time是否有值
|
||||
if len(self.round_time) <= 0:
|
||||
raise HttpError(status_code=400, message='您还未创建轮次时间,请填写后生成')
|
||||
return {
|
||||
'start_year': self.p_start.year,
|
||||
'start_month': self.p_start.month,
|
||||
'end_year': self.p_end.year,
|
||||
'end_month': self.p_end.month,
|
||||
'beginTime_strf': format_remove_heng(self.p_start),
|
||||
'dgCompileStart': format_remove_heng(self.dg_bz_start),
|
||||
'dgCompileEnd': format_remove_heng(self.dg_bz_end),
|
||||
'designStart': format_remove_heng(self.test_sj_start),
|
||||
'designEnd': format_remove_heng(self.test_sj_end),
|
||||
'location': self.round_time[0]['location']
|
||||
}
|
||||
|
||||
# 该函数生成报告文档片段-测评时间和地点【注意使用了dg_address_time -> 所以后续有修改注意前导】
|
||||
def bg_address_time(self):
|
||||
if len(self.round_time) <= 0:
|
||||
raise HttpError(status_code=400, message='您还未创建轮次时间,请填写后生成')
|
||||
# 先使用大纲的时间行数作为前三行
|
||||
cname = ['首轮测试', '第二轮测试', '第三轮测试', '第四轮测试', '第五轮测试', '第六轮测试', '第七轮测试',
|
||||
'第八轮测试', '第九轮测试', '第十轮测试']
|
||||
dg_address_time = self.dg_address_time()
|
||||
round_time_list = []
|
||||
index = 0
|
||||
for round_dict in self.round_time:
|
||||
one_dict = {
|
||||
'name': cname[index],
|
||||
'start': format_remove_heng(round_dict['start']),
|
||||
'end': format_remove_heng(round_dict['end']),
|
||||
'location': round_dict['location']
|
||||
}
|
||||
index += 1
|
||||
round_time_list.append(one_dict)
|
||||
return {
|
||||
'begin_year': dg_address_time['start_year'],
|
||||
'begin_month': dg_address_time['start_month'],
|
||||
'end_year': dg_address_time['end_year'],
|
||||
'end_month': dg_address_time['end_month'],
|
||||
'begin_time': dg_address_time['beginTime_strf'],
|
||||
'dg_weave_start_date': dg_address_time['dgCompileStart'],
|
||||
'dg_weave_end_date': dg_address_time['dgCompileEnd'],
|
||||
'sj_weave_start_date': dg_address_time['designStart'],
|
||||
'sj_weave_end_date': dg_address_time['designEnd'],
|
||||
'round_time_list': round_time_list,
|
||||
# 测评总结 -> 依据项目结束时间-7 ~ 项目结束时间
|
||||
'summary_start_date': format_remove_heng(self.p_end - timedelta(days=7)),
|
||||
'summary_end_date': format_remove_heng(self.p_end),
|
||||
}
|
||||
|
||||
# 生成报告中测评完成情况 -> 必须依据其他内容生成时间【注意使用了bg_address_time -> 所以后续有修改注意前导】
|
||||
def bg_completion_situation(self):
|
||||
bg_timer_dict = self.bg_address_time()
|
||||
xq_fx_time_end = self.dg_bz_start + timedelta(days=2)
|
||||
ch_time_start = xq_fx_time_end + timedelta(days=1)
|
||||
ch_time_end = self.dg_bz_end
|
||||
if len(self.round_time) < 1:
|
||||
raise HttpError(status_code=400, message='您还未创建第一轮测试的时间,请填写后再生成')
|
||||
return {
|
||||
'start_time_year': bg_timer_dict['begin_year'],
|
||||
'start_time_month': bg_timer_dict['begin_month'],
|
||||
'xq_fx_time_start_year': self.dg_bz_start.year,
|
||||
'xq_fx_time_start_month': self.dg_bz_start.month,
|
||||
'xq_fx_time_start_day': self.dg_bz_start.day,
|
||||
'xq_fx_time_end_year': xq_fx_time_end.year, # 需求分析结束时间是大纲编制开始+2
|
||||
'xq_fx_time_end_month': xq_fx_time_end.month,
|
||||
'xq_fx_time_end_day': xq_fx_time_end.day,
|
||||
'ch_start_year': ch_time_start.year,
|
||||
'ch_start_month': ch_time_start.month,
|
||||
'ch_start_day': ch_time_start.day,
|
||||
'ch_end_year': ch_time_end.year,
|
||||
'ch_end_month': ch_time_end.month,
|
||||
'ch_end_day': ch_time_end.day,
|
||||
'sj_start_year': self.test_sj_start.year,
|
||||
'sj_start_month': self.test_sj_start.month,
|
||||
'sj_start_day': self.test_sj_start.day,
|
||||
'sj_end_year': self.test_sj_end.year,
|
||||
'sj_end_month': self.test_sj_end.month,
|
||||
'sj_end_day': self.test_sj_end.day,
|
||||
'end_time_year': self.p_end.year,
|
||||
'end_time_month': self.p_end.month,
|
||||
'exec_start_time_year': self.round_time[0]['start'].year,
|
||||
'exec_start_time_month': self.round_time[0]['start'].month,
|
||||
'exec_start_time_day': self.round_time[0]['start'].day,
|
||||
'exec_end_time_year': self.round_time[0]['end'].year,
|
||||
'exec_end_time_month': self.round_time[0]['end'].month,
|
||||
'exec_end_time_day': self.round_time[0]['end'].day,
|
||||
}
|
||||
|
||||
# 该函数生成最终大纲的时间
|
||||
def dg_final_time(self):
|
||||
cover_time = self.dg_bz_end
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
# 新增给大纲模版10.2章节context
|
||||
context.update(basic_line1=cover_time.strftime("%Y年%m月"), basic_line2=self.p_end.strftime("%Y年%m月"))
|
||||
# 新增给大纲模版10.3.2章节的context
|
||||
sm_context = self.sm_final_time()
|
||||
context.update(sm_end_time=sm_context['preparation_time_no_format'].strftime("%Y年%m月"))
|
||||
return context
|
||||
|
||||
# 该函数生成说明文档的时间 -> 依据项目时间而非用户第一轮填写时间!
|
||||
def sm_final_time(self):
|
||||
cover_time = self.test_sj_end # 封面时间:为大纲时间中“测评设计与实现”结束时间
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 该函数生成记录文档的时间 -> 依据第一轮测试用户填写的事件
|
||||
def jl_final_time(self):
|
||||
if len(self.round_time) < 1:
|
||||
raise HttpError(status_code=400, message='您还未创建第一轮测试的时间,请填写后再生成')
|
||||
cover_time = self.round_time[0]['end'] # 封面时间为用户填写第一轮结束时间
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 问题单的时间 -> 依据最后一轮次的结束时间+1天
|
||||
def wtd_final_time(self):
|
||||
if len(self.round_time) < 1:
|
||||
raise HttpError(status_code=400, message='您还未创建第一轮测试的时间,请填写后再生成')
|
||||
cover_time = self.round_time[-1]['end']
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 回归测试说明时间 -> 根据第二轮、第三轮...的开始时间
|
||||
def hsm_final_time(self, round_key: str):
|
||||
if len(self.round_time) < int(round_key) + 1:
|
||||
raise HttpError(status_code=400, message='您填写的回归轮次时间不正确,请填写后再生成')
|
||||
cover_time = self.round_time[int(round_key)]['start']
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 回归测试记录时间 -> 根据第二轮、第三轮...的结束时间
|
||||
def hjl_final_time(self, round_key: str) -> dict:
|
||||
if len(self.round_time) < int(round_key) + 1:
|
||||
raise HttpError(status_code=400, message='您填写的回归轮次时间不正确,请填写后再生成')
|
||||
cover_time = self.round_time[int(round_key)]['end']
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
# 生成报告非过程时间 -> 根据项目结束时间来定
|
||||
def bg_final_time(self) -> dict:
|
||||
if len(self.round_time) <= 0:
|
||||
raise HttpError(status_code=400, message='您还未创建轮次时间,请填写后生成')
|
||||
cover_time = self.p_end
|
||||
# 这里做判断,如果项目结束时间/最后一轮结束时间
|
||||
if cover_time < self.round_time[-1]['end']:
|
||||
# 注意系统对HttpError异常重新处理,所以该处status_code看api.py文件
|
||||
raise HttpError(PROJECT_ENDTIME_ERROR_CODE, message='项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
context = times_by_cover_time(cover_time)
|
||||
context.update(cover_time=cover_time.strftime("%Y年%m月%d日"))
|
||||
return context
|
||||
|
||||
146
apps/createDocument/extensions/table_creator.py
Normal file
146
apps/createDocument/extensions/table_creator.py
Normal file
@@ -0,0 +1,146 @@
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
from docxtpl import DocxTemplate
|
||||
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||
from docx.enum.table import WD_ALIGN_VERTICAL
|
||||
from docx.oxml.ns import qn
|
||||
from docx.shared import Mm
|
||||
from apps.createDocument.extensions.tools import set_table_border_by_cell_position, set_cell_margins
|
||||
from utils.path_utils import project_path
|
||||
from utils.chen_response import ChenResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from apps.project.models import Project, Round
|
||||
from django.db.models import QuerySet
|
||||
|
||||
# 创建当前轮次别名
|
||||
RoundType = Literal["0", "not0", "last"]
|
||||
chinese_round_name: list = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
|
||||
|
||||
# 通用生成静态软件项、静态硬件项、动态软件项、动态硬件信息、测评数据的context,包含fontnote和table
|
||||
def create_table_context(table_data: list[list[str]], doc: DocxTemplate, rounds_map: list[list[str]] = None,
|
||||
current_round: str = None):
|
||||
"""
|
||||
注意:该函数会增加一列序号列,并且支持单元格内回车换行(段落换行)
|
||||
传入当前轮次以及rounds_map来过滤一些其他轮次的数据,为None则不过滤
|
||||
"""
|
||||
# 过滤数据处理
|
||||
if rounds_map is not None and current_round is not None and current_round != 'last':
|
||||
filtered_data = []
|
||||
for i, row in enumerate(table_data):
|
||||
# 第一行作为表头,始终保留
|
||||
if i == 0:
|
||||
filtered_data.append(row)
|
||||
else:
|
||||
# 检查该行是否属于当前轮次
|
||||
if current_round in rounds_map[i]:
|
||||
filtered_data.append(row)
|
||||
# table_data先替换后再执行下方生成表格
|
||||
table_data = filtered_data
|
||||
|
||||
subdoc = doc.new_subdoc()
|
||||
rows = len(table_data)
|
||||
cols = len(table_data[0]) + 1
|
||||
table = subdoc.add_table(rows=rows, cols=cols)
|
||||
|
||||
# 单元格处理
|
||||
for row in range(rows):
|
||||
for col in range(cols):
|
||||
cell = table.cell(row, col) # 从上倒下,从左到右取cell
|
||||
set_cell_margins(cell, left=100, right=100, top=100, bottom=100)
|
||||
|
||||
# 获取要显示的文本内容(字符串或按行拆分后的列表)
|
||||
if col == 0:
|
||||
# 序号列
|
||||
lines = ["序号"] if row == 0 else [str(row)]
|
||||
else:
|
||||
raw_text = table_data[row][col - 1]
|
||||
# 按换行符 \n 拆分为多个段落
|
||||
lines = raw_text.split('\n') if raw_text else ['']
|
||||
|
||||
# 清空单元格原有段落(add_table 默认有一个段落)
|
||||
cell.text = ""
|
||||
# 删除默认段落,稍后统一添加
|
||||
for para in cell.paragraphs:
|
||||
p = para._element
|
||||
p.getparent().remove(p)
|
||||
|
||||
# 逐个添加段落
|
||||
for i, line in enumerate(lines):
|
||||
if i == 0:
|
||||
para = cell.add_paragraph(line)
|
||||
else:
|
||||
para = cell.add_paragraph(line)
|
||||
|
||||
# 设置段落对齐(第一列居中,其他左对齐,可根据需要调整)
|
||||
if col == 0:
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
else:
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
||||
|
||||
# 对第一行(表头)设置黑体字体
|
||||
if row == 0:
|
||||
for run in para.runs:
|
||||
run.font.name = '黑体'
|
||||
run._element.rPr.rFonts.set(qn('w:eastAsia'), '黑体')
|
||||
run.font.bold = False
|
||||
# 表头段落居中(覆盖前面的 left)
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
|
||||
# 垂直居中
|
||||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||||
|
||||
# 设置序号列宽度
|
||||
for cell in table.columns[0].cells:
|
||||
cell.width = Mm(15)
|
||||
for para in cell.paragraphs:
|
||||
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
|
||||
# 表格居中
|
||||
table.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
# 设置表格外边框
|
||||
set_table_border_by_cell_position(table)
|
||||
return subdoc
|
||||
|
||||
# 统一静态软件项、静态硬件项、动态软件项、动态硬件信息、测评数据5个的word生成 - 模版模式
|
||||
def uniform_static_dynamic_response(id: int, filename: str, r_filename: str, model,
|
||||
current_round: str = "0", isHsm: bool = None) -> ChenResponse | None:
|
||||
""" 通过形参isHsm判断是否是回归测试说明 """
|
||||
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():
|
||||
obj = qs.first()
|
||||
table_data = obj.table
|
||||
# 回归测试说明生成多轮次回归测试说明的5个接口分支
|
||||
if isHsm:
|
||||
hround_list: QuerySet[Round] = project_obj.pField.exclude(key='0')
|
||||
for hround in hround_list:
|
||||
round_key = hround.key
|
||||
cname = chinese_round_name[int(round_key)] # 取中文:一、二、三...
|
||||
# key就是current_round,这里就解决文件名和那个的问题
|
||||
subdoc = create_table_context(table_data, doc, obj.rounds_map, round_key)
|
||||
context = {
|
||||
'fontnote': obj.fontnote,
|
||||
'table': subdoc,
|
||||
}
|
||||
doc.render(context, autoescape=True)
|
||||
try:
|
||||
doc.save(Path.cwd() / "media" / project_path(id) / "output_dir/hsm" / "".join([f"第{cname}轮", r_filename]))
|
||||
except PermissionError as e:
|
||||
return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e))
|
||||
return ChenResponse(status=200,code=200,message="多个轮次5接口渲染完毕,文档生成完毕")
|
||||
|
||||
# 新增:传入rounds_map进行渲染
|
||||
subdoc = create_table_context(table_data, doc, obj.rounds_map, current_round)
|
||||
context = {
|
||||
'fontnote': obj.fontnote,
|
||||
'table': subdoc,
|
||||
}
|
||||
doc.render(context, autoescape=True)
|
||||
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
|
||||
Binary file not shown.
Binary file not shown.
@@ -460,7 +460,12 @@ class ProjectController(ControllerBase):
|
||||
item_qs = self.get_model_from_category(category).objects.filter(project=project_obj)
|
||||
if item_qs.exists():
|
||||
item_obj = item_qs.first()
|
||||
return ChenResponse(status=200, code=25001, data={"table": item_obj.table, "fontnote": item_obj.fontnote})
|
||||
if item_obj:
|
||||
return ChenResponse(status=200, code=25001, data={
|
||||
"table": item_obj.table,
|
||||
"fontnote": item_obj.fontnote,
|
||||
"rounds": item_obj.rounds_map or []
|
||||
})
|
||||
return ChenResponse(status=200, code=25002, data=None)
|
||||
|
||||
# ~~~静态软件项、静态硬件项、动态软件项、动态硬件项、测评数据 - 新增或修改~~~
|
||||
@@ -470,10 +475,21 @@ class ProjectController(ControllerBase):
|
||||
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)
|
||||
# 处理rounds_map
|
||||
rounds = data.rounds
|
||||
if rounds is None:
|
||||
rounds = [["0"]] * len(data.table)
|
||||
|
||||
if item_qs.exists():
|
||||
# 如果存在则修改
|
||||
item_qs.delete()
|
||||
model.objects.create(project=project_obj, table=data.table, fontnote=data.fontnote)
|
||||
model.objects.create(
|
||||
project=project_obj,
|
||||
table=data.table,
|
||||
fontnote=data.fontnote,
|
||||
rounds_map=rounds,
|
||||
)
|
||||
return ChenResponse(status=200, code=20000, message="保存成功")
|
||||
|
||||
# ~~~环境差异性分析 - 获取~~~
|
||||
@route.get("/get_env_analysis/")
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 6.0.4 on 2026-04-23 18:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0035_design_is_bidirectional'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='dynamichardwaretable',
|
||||
name='rounds_map',
|
||||
field=models.JSONField(blank=True, default=list, help_text='二维数组,每个内层数组是该行选中的轮次索引(字符串)', verbose_name='轮次数据'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='dynamicsofttable',
|
||||
name='rounds_map',
|
||||
field=models.JSONField(blank=True, default=list, help_text='二维数组,每个内层数组是该行选中的轮次索引(字符串)', verbose_name='轮次数据'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='evaluatedata',
|
||||
name='rounds_map',
|
||||
field=models.JSONField(blank=True, default=list, help_text='二维数组,每个内层数组是该行选中的轮次索引(字符串)', verbose_name='轮次数据'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='staticsofthardware',
|
||||
name='rounds_map',
|
||||
field=models.JSONField(blank=True, default=list, help_text='二维数组,每个内层数组是该行选中的轮次索引(字符串)', verbose_name='轮次数据'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='beginTime',
|
||||
field=models.DateField(blank=True, help_text='开始时间', null=True, verbose_name='开始时间'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='endTime',
|
||||
field=models.DateField(blank=True, help_text='结束时间', null=True, verbose_name='结束时间'),
|
||||
),
|
||||
]
|
||||
18
apps/project/migrations/0037_staticsoftitem_rounds_map.py
Normal file
18
apps/project/migrations/0037_staticsoftitem_rounds_map.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 6.0.4 on 2026-04-23 18:19
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('project', '0036_dynamichardwaretable_rounds_map_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='staticsoftitem',
|
||||
name='rounds_map',
|
||||
field=models.JSONField(blank=True, default=list, help_text='二维数组,每个内层数组是该行选中的轮次索引(字符串)', verbose_name='轮次数据'),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
@@ -499,6 +499,12 @@ class StaticSoftItem(models.Model):
|
||||
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="数据的题注说明")
|
||||
rounds_map = models.JSONField(
|
||||
verbose_name="轮次数据",
|
||||
help_text="二维数组,每个内层数组是该行选中的轮次索引(字符串)",
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_static_soft_item'
|
||||
@@ -511,6 +517,12 @@ class StaticSoftHardware(models.Model):
|
||||
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="数据的题注说明")
|
||||
rounds_map = models.JSONField(
|
||||
verbose_name="轮次数据",
|
||||
help_text="二维数组,每个内层数组是该行选中的轮次索引(字符串)",
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_static_hardware'
|
||||
@@ -523,6 +535,12 @@ class DynamicSoftTable(models.Model):
|
||||
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="数据的题注说明")
|
||||
rounds_map = models.JSONField(
|
||||
verbose_name="轮次数据",
|
||||
help_text="二维数组,每个内层数组是该行选中的轮次索引(字符串)",
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_dynamic_soft_item'
|
||||
@@ -535,6 +553,12 @@ class DynamicHardwareTable(models.Model):
|
||||
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="数据的题注说明")
|
||||
rounds_map = models.JSONField(
|
||||
verbose_name="轮次数据",
|
||||
help_text="二维数组,每个内层数组是该行选中的轮次索引(字符串)",
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_dynamic_hardware'
|
||||
@@ -547,6 +571,12 @@ class EvaluateData(models.Model):
|
||||
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="数据的题注说明")
|
||||
rounds_map = models.JSONField(
|
||||
verbose_name="轮次数据",
|
||||
help_text="二维数组,每个内层数组是该行选中的轮次索引(字符串)",
|
||||
default=list,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
db_table = 'project_evaluate_data'
|
||||
|
||||
Binary file not shown.
@@ -62,6 +62,7 @@ class StaticDynamicData(Schema):
|
||||
category: str
|
||||
table: list[list[str]]
|
||||
fontnote: Optional[str] = ""
|
||||
rounds: Optional[List[List[str]]] = None # 允许不传递
|
||||
|
||||
# ~~~环境差异性分析~~~
|
||||
class EnvAnalysisSchema(Schema):
|
||||
|
||||
Binary file not shown.
@@ -1,9 +1,12 @@
|
||||
from utils.chen_ninja import ChenNinjaAPI
|
||||
from ninja.errors import HttpError
|
||||
# 导入orjson解析器,渲染器,提升性能
|
||||
from cdtestplant_v1.parser import MyParser
|
||||
from cdtestplant_v1.renderer import MyRenderer
|
||||
# swagger-ui配置
|
||||
from ninja import Swagger
|
||||
# 错误码
|
||||
from utils.codes import PROJECT_ENDTIME_ERROR_CODE
|
||||
|
||||
api = ChenNinjaAPI(
|
||||
title="测试管理平台API",
|
||||
@@ -14,5 +17,14 @@ api = ChenNinjaAPI(
|
||||
docs=Swagger({"persistAuthorization": True})
|
||||
)
|
||||
|
||||
# 捕获HttpError - 注意这种方式不过create_response函数,需自己定义
|
||||
@api.exception_handler(HttpError)
|
||||
def in_program_exception_handler(request, exc):
|
||||
# HttpError的status_code这里处理为自定义码,而非HTTP协议的
|
||||
data = {}
|
||||
if exc.status_code is PROJECT_ENDTIME_ERROR_CODE:
|
||||
data['flag'] = PROJECT_ENDTIME_ERROR_CODE
|
||||
return api.create_response(request, status=500, message=exc.message, data=data)
|
||||
|
||||
# 自动寻找每个app下面controllers.py中被@api_controller修饰的类
|
||||
api.auto_discover_controllers()
|
||||
|
||||
342
logs/root_log
342
logs/root_log
@@ -1,27 +1,5 @@
|
||||
[WARNING][2026-04-22 09:45:35,603][log.py:249]Unauthorized: /api/system/getInfo
|
||||
[WARNING][2026-04-22 09:45:35,677][log.py:249]Unauthorized: /api/system/logout
|
||||
[WARNING][2026-04-22 09:45:39,967][backend.py:91]Caught LDAPError looking up user: SERVER_DOWN({'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []})
|
||||
[WARNING][2026-04-22 11:03:49,239][operation.py:136]"PUT - DesignController[update_design] /api/project/editDesignDemand/4030" (1048, "Column 'is_bidirectional' cannot be null")
|
||||
[ERROR][2026-04-22 11:03:49,239][errors.py:131](1048, "Column 'is_bidirectional' cannot be null")
|
||||
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 286, in query
|
||||
_mysql.connection.query(self, query)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
|
||||
MySQLdb.IntegrityError: (1048, "Column 'is_bidirectional' cannot be null")
|
||||
|
||||
The above exception was the direct cause of the following exception:
|
||||
|
||||
[WARNING][2026-04-23 15:28:58,739][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:28:58,748][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, in run
|
||||
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
|
||||
@@ -31,79 +9,43 @@ Traceback (most recent call last):
|
||||
)
|
||||
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\design.py", line 148, in update_design
|
||||
design_qs.save()
|
||||
~~~~~~~~~~~~~~^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 874, in save
|
||||
self.save_base(
|
||||
~~~~~~~~~~~~~~^
|
||||
using=using,
|
||||
^^^^^^^^^^^^
|
||||
...<2 lines>...
|
||||
update_fields=update_fields,
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
)
|
||||
^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 966, in save_base
|
||||
updated = self._save_table(
|
||||
raw,
|
||||
...<4 lines>...
|
||||
update_fields,
|
||||
)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 1110, in _save_table
|
||||
results = self._do_update(
|
||||
base_qs,
|
||||
...<5 lines>...
|
||||
returning_fields,
|
||||
)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 1213, in _do_update
|
||||
return filtered._update(values, returning_fields)
|
||||
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\query.py", line 1327, in _update
|
||||
return query.get_compiler(self.db).execute_returning_sql(returning_fields)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\compiler.py", line 2140, in execute_returning_sql
|
||||
row_count = self.execute_sql(ROW_COUNT)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\compiler.py", line 2111, in execute_sql
|
||||
row_count = super().execute_sql(result_type)
|
||||
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 286, in query
|
||||
_mysql.connection.query(self, query)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
|
||||
django.db.utils.IntegrityError: (1048, "Column 'is_bidirectional' cannot be null")
|
||||
[ERROR][2026-04-22 11:03:49,254][log.py:249]Internal Server Error: /api/project/editDesignDemand/4030
|
||||
[WARNING][2026-04-22 11:23:22,342][operation.py:136]"POST - DesignController[create_design] /api/project/designDemand/save" ("Design() got unexpected keyword arguments: 'forward_source', 'forward_destination', 'forward_description', 'reverse_source', 'reverse_destination', 'reverse_description'",)
|
||||
[ERROR][2026-04-22 11:23:22,342][errors.py:131]Design() got unexpected keyword arguments: 'forward_source', 'forward_destination', 'forward_description', 'reverse_source', 'reverse_destination', 'reverse_description'
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 271, in document_time_show
|
||||
time = time_return_to(id)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\project\tool\timeList.py", line 94, in time_return_to
|
||||
temp_dict = time_parser.bg_final_time()
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\extensions\documentTime.py", line 206, in bg_final_time
|
||||
raise HttpError(PROJECT_ENDTIME_ERROR_CODE, message='项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
ninja.errors.HttpError: 项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
|
||||
response = get_response(request)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\core\handlers\base.py", line 198, in _get_response
|
||||
response = wrapped_callback(request, *callback_args, **callback_kwargs)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja\operation.py", line 661, in sync_view_wrapper
|
||||
return self._sync_view(request, *args, **kwargs)
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 322, in _sync_view
|
||||
return super(PathView, self)._sync_view(request, *args, **kwargs)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja\operation.py", line 673, in _sync_view
|
||||
return operation.run(request, *a, **kw)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 231, in run
|
||||
return self.api.on_exception(request, e)
|
||||
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja\main.py", line 617, in on_exception
|
||||
return handler(request, exc)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\cdtestplant_v1\api.py", line 24, in in_program_exception_handler
|
||||
if exc.detail is PROJECT_ENDTIME_ERROR_CODE:
|
||||
^^^^^^^^^^
|
||||
AttributeError: 'HttpError' object has no attribute 'detail'
|
||||
[WARNING][2026-04-23 15:29:14,430][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:29:14,438][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:30:11,756][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:30:11,772][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, in run
|
||||
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
|
||||
@@ -113,21 +55,88 @@ Traceback (most recent call last):
|
||||
)
|
||||
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\design.py", line 116, in create_design
|
||||
qs = Design.objects.create(**asert_dict)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\manager.py", line 87, in manager_method
|
||||
return getattr(self.get_queryset(), name)(*args, **kwargs)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\query.py", line 667, in create
|
||||
obj = self.model(**kwargs)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 590, in __init__
|
||||
raise TypeError(
|
||||
...<2 lines>...
|
||||
)
|
||||
TypeError: Design() got unexpected keyword arguments: 'forward_source', 'forward_destination', 'forward_description', 'reverse_source', 'reverse_destination', 'reverse_description'
|
||||
[ERROR][2026-04-22 11:23:22,347][log.py:249]Internal Server Error: /api/project/designDemand/save
|
||||
[WARNING][2026-04-22 13:13:59,640][operation.py:136]"GET - GenerateControllerDG[create_interface] /api/generate/create/interface" ("'Design' object has no attribute 'source'",)
|
||||
[ERROR][2026-04-22 13:13:59,640][errors.py:131]'Design' object has no attribute 'source'
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 271, in document_time_show
|
||||
time = time_return_to(id)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\project\tool\timeList.py", line 94, in time_return_to
|
||||
temp_dict = time_parser.bg_final_time()
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\extensions\documentTime.py", line 206, in bg_final_time
|
||||
raise HttpError(PROJECT_ENDTIME_ERROR_CODE, message='项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
ninja.errors.HttpError: 项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
|
||||
response = get_response(request)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\core\handlers\base.py", line 198, in _get_response
|
||||
response = wrapped_callback(request, *callback_args, **callback_kwargs)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja\operation.py", line 661, in sync_view_wrapper
|
||||
return self._sync_view(request, *args, **kwargs)
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 322, in _sync_view
|
||||
return super(PathView, self)._sync_view(request, *args, **kwargs)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja\operation.py", line 673, in _sync_view
|
||||
return operation.run(request, *a, **kw)
|
||||
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 231, in run
|
||||
return self.api.on_exception(request, e)
|
||||
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja\main.py", line 617, in on_exception
|
||||
return handler(request, exc)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\cdtestplant_v1\api.py", line 26, in in_program_exception_handler
|
||||
return api.create_response(request, status=500, message=exc.message)
|
||||
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
TypeError: ChenNinjaAPI.create_response() missing 1 required positional argument: 'data'
|
||||
[WARNING][2026-04-23 15:31:00,940][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:31:00,948][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:31:09,568][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:31:09,578][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:34:41,469][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:34:41,477][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:34:45,816][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:34:45,824][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:34:50,470][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:34:50,480][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:34:55,380][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:34:55,388][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:34:58,806][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:34:58,814][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:35:14,656][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:35:14,664][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:35:41,998][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:35:42,007][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:38:50,737][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:38:50,745][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:43:24,757][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:43:24,765][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:44:02,062][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:44:02,071][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:44:21,790][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:44:21,798][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:44:32,220][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:44:32,227][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:46:42,165][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:46:42,174][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:47:01,501][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:47:01,509][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:47:40,712][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:47:40,722][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:47:43,095][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:47:43,103][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:53:49,660][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:53:49,667][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:54:00,089][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:54:00,097][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:56:58,912][operation.py:136]"GET - ProjectController[document_time_show] /api/testmanage/project/document_time_show" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:56:58,918][log.py:249]Internal Server Error: /api/testmanage/project/document_time_show
|
||||
[WARNING][2026-04-23 15:58:44,243][operation.py:136]"POST - GenerateSeitaiController[create_bgDocument] /api/create/bgDocument" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-23 15:58:44,244][log.py:249]Internal Server Error: /api/create/bgDocument
|
||||
[WARNING][2026-04-24 13:56:12,151][log.py:249]Unauthorized: /api/system/getInfo
|
||||
[WARNING][2026-04-24 13:56:12,209][log.py:249]Unauthorized: /api/system/logout
|
||||
[WARNING][2026-04-24 13:56:16,702][backend.py:91]Caught LDAPError looking up user: SERVER_DOWN({'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []})
|
||||
[WARNING][2026-04-24 14:06:28,243][operation.py:136]"GET - GenerateControllerDG[create_static_soft] /api/generate/create/static_soft" ('GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given',)
|
||||
[ERROR][2026-04-24 14:06:28,243][errors.py:131]GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, in run
|
||||
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
|
||||
@@ -135,8 +144,107 @@ Traceback (most recent call last):
|
||||
result = self.route.view_func(
|
||||
ctx.controller_instance, *args, **ctx.view_func_kwargs
|
||||
)
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 417, in create_interface
|
||||
'source': interface.source,
|
||||
^^^^^^^^^^^^^^^^
|
||||
AttributeError: 'Design' object has no attribute 'source'
|
||||
[ERROR][2026-04-22 13:13:59,650][log.py:249]Internal Server Error: /api/generate/create/interface
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 581, in create_static_soft
|
||||
res = self.uniform_static_dynamic_response(id, '静态软件项_2.docx', '静态软件项.docx', StaticSoftItem)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 565, in uniform_static_dynamic_response
|
||||
subdoc = cls.create_table_context(table_data, doc, obj.rounds_map)
|
||||
TypeError: GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
[ERROR][2026-04-24 14:06:28,258][log.py:249]Internal Server Error: /api/generate/create/static_soft
|
||||
[WARNING][2026-04-24 14:06:28,259][operation.py:136]"GET - GenerateControllerDG[create_static_hard] /api/generate/create/static_hard" ('GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given',)
|
||||
[ERROR][2026-04-24 14:06:28,274][errors.py:131]GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, 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 597, in create_static_hard
|
||||
res = self.uniform_static_dynamic_response(id, '静态硬件和固件项_2.docx', '静态硬件和固件项.docx', StaticSoftHardware)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 565, in uniform_static_dynamic_response
|
||||
subdoc = cls.create_table_context(table_data, doc, obj.rounds_map)
|
||||
TypeError: GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
[ERROR][2026-04-24 14:06:28,278][log.py:249]Internal Server Error: /api/generate/create/static_hard
|
||||
[WARNING][2026-04-24 14:06:28,316][operation.py:136]"GET - GenerateControllerDG[create_dynamic_soft] /api/generate/create/dynamic_soft" ('GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given',)
|
||||
[ERROR][2026-04-24 14:06:28,316][errors.py:131]GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, 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 637, in create_dynamic_soft
|
||||
res = self.uniform_static_dynamic_response(id, '动态软件项_2.docx', '动态软件项.docx', DynamicSoftTable)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 565, in uniform_static_dynamic_response
|
||||
subdoc = cls.create_table_context(table_data, doc, obj.rounds_map)
|
||||
TypeError: GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
[ERROR][2026-04-24 14:06:28,319][log.py:249]Internal Server Error: /api/generate/create/dynamic_soft
|
||||
[WARNING][2026-04-24 14:06:28,324][operation.py:136]"GET - GenerateControllerDG[create_test_data] /api/generate/create/test_data" ('GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given',)
|
||||
[WARNING][2026-04-24 14:06:28,324][operation.py:136]"GET - GenerateControllerDG[create_dynamic_hard] /api/generate/create/dynamic_hard" ('GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given',)
|
||||
[ERROR][2026-04-24 14:06:28,326][errors.py:131]GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, 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 672, in create_test_data
|
||||
res = self.uniform_static_dynamic_response(id, '测评数据_2.docx',
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
|
||||
'测评数据.docx', EvaluateData)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 565, in uniform_static_dynamic_response
|
||||
subdoc = cls.create_table_context(table_data, doc, obj.rounds_map)
|
||||
TypeError: GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
[ERROR][2026-04-24 14:06:28,326][errors.py:131]GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, 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 655, in create_dynamic_hard
|
||||
res = self.uniform_static_dynamic_response(id, '动态硬件和固件项_2.docx',
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
'动态硬件和固件项.docx', DynamicHardwareTable)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 565, in uniform_static_dynamic_response
|
||||
subdoc = cls.create_table_context(table_data, doc, obj.rounds_map)
|
||||
TypeError: GenerateControllerDG.create_table_context() takes 3 positional arguments but 4 were given
|
||||
[ERROR][2026-04-24 14:06:28,336][log.py:249]Internal Server Error: /api/generate/create/dynamic_hard
|
||||
[ERROR][2026-04-24 14:06:28,336][log.py:249]Internal Server Error: /api/generate/create/test_data
|
||||
[WARNING][2026-04-24 14:09:36,188][operation.py:136]"GET - GenerateControllerDG[create_env_diff] /api/generate/create/env_diff" ("GenerateControllerDG.create_table_context() missing 1 required positional argument: 'rounds_map'",)
|
||||
[ERROR][2026-04-24 14:09:36,188][errors.py:131]GenerateControllerDG.create_table_context() missing 1 required positional argument: 'rounds_map': Did you fail to use functools.wraps() in a decorator?
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, 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 697, in create_env_diff
|
||||
subdoc = self.create_table_context(table_data, doc)
|
||||
TypeError: GenerateControllerDG.create_table_context() missing 1 required positional argument: 'rounds_map': Did you fail to use functools.wraps() in a decorator?
|
||||
[ERROR][2026-04-24 14:09:36,192][log.py:249]Internal Server Error: /api/generate/create/env_diff
|
||||
[WARNING][2026-04-24 14:43:28,969][operation.py:136]"POST - GenerateSeitaiController[create_bgDocument] /api/create/bgDocument" (500412, '项目结束时间早于最后一轮次结束时间或等于开始时间,请修改项目结束时间')
|
||||
[ERROR][2026-04-24 14:43:28,969][log.py:249]Internal Server Error: /api/create/bgDocument
|
||||
[WARNING][2026-04-24 15:11:55,484][operation.py:136]"GET - GenerateControllerDG[create_env_diff] /api/generate/create/env_diff" ("'GenerateControllerDG' object has no attribute 'create_table_context'",)
|
||||
[ERROR][2026-04-24 15:11:55,484][errors.py:131]'GenerateControllerDG' object has no attribute 'create_table_context'
|
||||
Traceback (most recent call last):
|
||||
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 217, 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 633, in create_env_diff
|
||||
subdoc = self.create_table_context(table_data, doc)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AttributeError: 'GenerateControllerDG' object has no attribute 'create_table_context'
|
||||
[ERROR][2026-04-24 15:11:55,488][log.py:249]Internal Server Error: /api/generate/create/env_diff
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
media/R2601/final_seitai/第三轮回归测试说明.docx
Normal file
BIN
media/R2601/final_seitai/第三轮回归测试说明.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮动态硬件和固件项.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮动态硬件和固件项.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮动态软件项.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮动态软件项.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮回归测试用例概述.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮回归测试用例概述.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮回归测试需求.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮回归测试需求.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮技术依据文件.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮技术依据文件.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮文档概述.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮文档概述.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮测评数据.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮测评数据.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮测试用例.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮测试用例.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮用例追踪.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮用例追踪.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮被测软件基本信息.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮被测软件基本信息.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮软件更改部分.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮软件更改部分.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第三轮静态软件项.docx
Normal file
BIN
media/R2601/output_dir/hsm/第三轮静态软件项.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第二轮动态硬件和固件项.docx
Normal file
BIN
media/R2601/output_dir/hsm/第二轮动态硬件和固件项.docx
Normal file
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第二轮动态软件项.docx
Normal file
BIN
media/R2601/output_dir/hsm/第二轮动态软件项.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第二轮测评数据.docx
Normal file
BIN
media/R2601/output_dir/hsm/第二轮测评数据.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
media/R2601/output_dir/hsm/第二轮静态软件项.docx
Normal file
BIN
media/R2601/output_dir/hsm/第二轮静态软件项.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user