添加测试说明生成
This commit is contained in:
@@ -101,7 +101,7 @@ export default {
|
|||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns 生成测评大纲-被测软件性能
|
* @returns 生成测评大纲-被测软件基本信息
|
||||||
*/
|
*/
|
||||||
createBaseInformation(params = {}) {
|
createBaseInformation(params = {}) {
|
||||||
return request({
|
return request({
|
||||||
@@ -110,6 +110,17 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns 生成软硬件环境output_dir
|
||||||
|
*/
|
||||||
|
createEnvironment(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/generate/create/environment`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns 生成测评大纲-测试总体要求
|
* @returns 生成测评大纲-测试总体要求
|
||||||
@@ -209,4 +220,15 @@ export default {
|
|||||||
params
|
params
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns 生成-主要战技指标
|
||||||
|
*/
|
||||||
|
createMainTech(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/generate/create/mainTech`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,5 +10,16 @@ export default {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 如果缺少部分文件给与提示
|
||||||
|
* @returns 根据output_dir以及output_dir/sm中文档生成测试说明
|
||||||
|
*/
|
||||||
|
createShuomingSeiTai(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/create/smDocument`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
47
cdTMP/src/api/generate/smGenerate.js
Normal file
47
cdTMP/src/api/generate/smGenerate.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { request } from "@/api/request"
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns 大纲测试项数据
|
||||||
|
*/
|
||||||
|
createSMTechyiju(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/generateSM/create/techyiju`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns 生成测试用例
|
||||||
|
*/
|
||||||
|
createSMCaseList(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/generateSM/create/caseList`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns 生成测试用例那个表-测试名称/标识/测试用例综述
|
||||||
|
*/
|
||||||
|
createSMCaseBreifList(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/generateSM/create/caseBreifList`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns 生成说明追踪
|
||||||
|
*/
|
||||||
|
createSMTrack(params = {}) {
|
||||||
|
return request({
|
||||||
|
url: `/generateSM/create/smtrack`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,12 +6,10 @@
|
|||||||
<template #operationBeforeExtend="{ record }">
|
<template #operationBeforeExtend="{ record }">
|
||||||
<a-link @click="enterWorkPlant(record)">进入工作区</a-link>
|
<a-link @click="enterWorkPlant(record)">进入工作区</a-link>
|
||||||
<a-link @click="previewRef.open(record, crudColumns)"><icon-eye />预览</a-link>
|
<a-link @click="previewRef.open(record, crudColumns)"><icon-eye />预览</a-link>
|
||||||
<a-link @click="createItem(record)">生成测试项</a-link>
|
<a-link @click="createDgItem(record)">大纲二段文档</a-link>
|
||||||
<a-link @click="createYiju(record)"><icon-eye />[测试]生成依据文件</a-link>
|
<a-link @click="createSmItem(record)">说明二段文档</a-link>
|
||||||
<a-link @click="createContact(record)"><icon-eye />[测试]联系方式</a-link>
|
|
||||||
<a-link @click="createInter(record)"><icon-eye />[测试]生成接口</a-link>
|
|
||||||
<a-link @click="createZhuiZ(record)"><icon-eye />[测试]研总追踪</a-link>
|
|
||||||
<a-link @click="createSeitaiDagang(record)"><icon-eye />[测试]生成最后大纲</a-link>
|
<a-link @click="createSeitaiDagang(record)"><icon-eye />[测试]生成最后大纲</a-link>
|
||||||
|
<a-link @click="createSeitaiShuoming(record)"><icon-eye />[测试]生成最后说明</a-link>
|
||||||
</template>
|
</template>
|
||||||
</ma-crud>
|
</ma-crud>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,7 +23,8 @@ import { useRoute, useRouter } from "vue-router"
|
|||||||
import projectApi from "@/api/testmanage/project"
|
import projectApi from "@/api/testmanage/project"
|
||||||
import preview from "./cpns/preview.vue"
|
import preview from "./cpns/preview.vue"
|
||||||
import dgGenerateApi from "@/api/generate/dgGenerate"
|
import dgGenerateApi from "@/api/generate/dgGenerate"
|
||||||
import dgSeitaiGenerateApi from "@/api/generate/dgSeitaiGenerate"
|
import seitaiGenerateApi from "@/api/generate/seitaiGenerate"
|
||||||
|
import smGenerateApi from "@/api/generate/smGenerate"
|
||||||
import { Message } from "@arco-design/web-vue"
|
import { Message } from "@arco-design/web-vue"
|
||||||
import Progress from "./cpns/progress.vue"
|
import Progress from "./cpns/progress.vue"
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -44,13 +43,20 @@ const isComplete = ref(false)
|
|||||||
const handleModalConfirmClick = () => {
|
const handleModalConfirmClick = () => {
|
||||||
visible.value = false
|
visible.value = false
|
||||||
}
|
}
|
||||||
// ~~~~~~~~测试生成文档~~~~~~~~
|
// ~~~~~~~~测试说明生成文档~~~~~~~~
|
||||||
|
const createSeitaiShuoming = async (record) => {
|
||||||
|
const st = await seitaiGenerateApi.createShuomingSeiTai({ id: record.id })
|
||||||
|
|
||||||
|
Message.success(st.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~~~~~测试大纲生成文档~~~~~~~~
|
||||||
const createSeitaiDagang = async (record) => {
|
const createSeitaiDagang = async (record) => {
|
||||||
// 根据一系列文档生成大纲 - 这里有进度条组件、a-modal组件
|
// 根据一系列文档生成大纲 - 这里有进度条组件、a-modal组件
|
||||||
// 1.打开进度条组件
|
// 1.打开进度条组件
|
||||||
visible.value = true
|
visible.value = true
|
||||||
isComplete.value = false
|
isComplete.value = false
|
||||||
const st = await dgSeitaiGenerateApi.createDagangSeiTai({ id: record.id }).catch((err) => {
|
const st = await seitaiGenerateApi.createDagangSeiTai({ id: record.id }).catch((err) => {
|
||||||
isComplete.value = true
|
isComplete.value = true
|
||||||
visible.value = false
|
visible.value = false
|
||||||
})
|
})
|
||||||
@@ -58,15 +64,39 @@ const createSeitaiDagang = async (record) => {
|
|||||||
Message.success(st.message)
|
Message.success(st.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
const createItem = async (record) => {
|
// 说明生成二级文档
|
||||||
|
const createSmItem = async (record) => {
|
||||||
|
// 生成测评对象 - 和大纲一样 - 可能会删除
|
||||||
|
const st = await dgGenerateApi.createSoftComposition({ id: record.id })
|
||||||
|
// 生成被测软件功能 - 和大纲重复 - 可能会删除
|
||||||
|
const st1 = await dgGenerateApi.createFuncList({ id: record.id })
|
||||||
|
// 生成被测软件接口 - 和大纲重复 - 可能会删除
|
||||||
|
const st2 = await dgGenerateApi.createInterface({ id: record.id })
|
||||||
|
// 生成被测软件性能 - 和大纲重复 - 可能会删除
|
||||||
|
const st3 = await dgGenerateApi.createPerformance({ id: record.id })
|
||||||
|
// 生成被测软件基本信息 - 和大纲重复 - 可能会删除
|
||||||
|
const st4 = await dgGenerateApi.createBaseInformation({ id: record.id })
|
||||||
|
// 生成标准类引用文档 - 和大纲重复 - 可能会删除
|
||||||
|
const st5 = await dgGenerateApi.createYiju({ id: record.id })
|
||||||
|
// 生成技术类引用文档列表 -> 在大纲基础上添加《测评大纲》
|
||||||
|
const st6 = await smGenerateApi.createSMTechyiju({ id: record.id })
|
||||||
|
// 生成软硬件环境(注意标题级别不一样,这个在最后处理)
|
||||||
|
const st7 = await dgGenerateApi.createEnvironment({ id: record.id })
|
||||||
|
// 生成用例全
|
||||||
|
const st8 = await smGenerateApi.createSMCaseList({ id: record.id })
|
||||||
|
// 生成用例列表-那个表格
|
||||||
|
const st9 = await smGenerateApi.createSMCaseBreifList({ id: record.id })
|
||||||
|
// 生成说明追踪
|
||||||
|
const st10 = await smGenerateApi.createSMTrack({ id: record.id })
|
||||||
|
|
||||||
|
Message.success(st10.message)
|
||||||
|
}
|
||||||
|
// 大纲生成二级文档
|
||||||
|
const createDgItem = async (record) => {
|
||||||
// 生成测试项文档
|
// 生成测试项文档
|
||||||
const st = await dgGenerateApi.createTestDemand({ id: record.id })
|
const st = await dgGenerateApi.createTestDemand({ id: record.id })
|
||||||
Message.success(st.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
const createYiju = async (record) => {
|
|
||||||
// 标准依据文件
|
// 标准依据文件
|
||||||
const st = await dgGenerateApi.createYiju({ id: record.id })
|
const st1 = await dgGenerateApi.createYiju({ id: record.id })
|
||||||
// 技术依据文件
|
// 技术依据文件
|
||||||
const st2 = await dgGenerateApi.createTechYiju({ id: record.id })
|
const st2 = await dgGenerateApi.createTechYiju({ id: record.id })
|
||||||
// 生成时间和地点
|
// 生成时间和地点
|
||||||
@@ -75,58 +105,37 @@ const createYiju = async (record) => {
|
|||||||
const st4 = await dgGenerateApi.createFuncList({ id: record.id })
|
const st4 = await dgGenerateApi.createFuncList({ id: record.id })
|
||||||
// 生成测评对象-软件组成
|
// 生成测评对象-软件组成
|
||||||
const st5 = await dgGenerateApi.createSoftComposition({ id: record.id })
|
const st5 = await dgGenerateApi.createSoftComposition({ id: record.id })
|
||||||
Message.success(st.message)
|
|
||||||
Message.success(st2.message)
|
|
||||||
Message.success(st3.message)
|
|
||||||
Message.success(st4.message)
|
|
||||||
Message.success(st5.message)
|
|
||||||
}
|
|
||||||
const createContact = async (record) => {
|
|
||||||
// 生成联系人和方式
|
// 生成联系人和方式
|
||||||
const st = await dgGenerateApi.createContact({ id: record.id })
|
const st6 = await dgGenerateApi.createContact({ id: record.id })
|
||||||
// 生成测试充分性(adequancy)和有效性(effectiveness)说明
|
// 生成测试充分性(adequancy)和有效性(effectiveness)说明
|
||||||
const st2 = await dgGenerateApi.createAdequacyEffectiveness({ id: record.id })
|
const st7 = await dgGenerateApi.createAdequacyEffectiveness({ id: record.id })
|
||||||
// 生成测评组织及分工
|
// 生成测评组织及分工
|
||||||
const st3 = await dgGenerateApi.createGroup({ id: record.id })
|
const st8 = await dgGenerateApi.createGroup({ id: record.id })
|
||||||
// 生成测评保障
|
// 生成测评保障
|
||||||
const st4 = await dgGenerateApi.createGuarantee({ id: record.id })
|
const st9 = await dgGenerateApi.createGuarantee({ id: record.id })
|
||||||
// 生成缩略语
|
// 生成缩略语
|
||||||
const st5 = await dgGenerateApi.createAbbreviation({ id: record.id })
|
const st10 = await dgGenerateApi.createAbbreviation({ id: record.id })
|
||||||
Message.success(st.message)
|
|
||||||
Message.success(st2.message)
|
|
||||||
Message.success(st3.message)
|
|
||||||
Message.success(st4.message)
|
|
||||||
Message.success(st5.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
const createInter = async (record) => {
|
|
||||||
// 生成-被测软件接口
|
// 生成-被测软件接口
|
||||||
const st = await dgGenerateApi.createInterface({ id: record.id })
|
const st11 = await dgGenerateApi.createInterface({ id: record.id })
|
||||||
// 生成-被测软件性能
|
// 生成-被测软件性能
|
||||||
const st2 = await dgGenerateApi.createPerformance({ id: record.id })
|
const st12 = await dgGenerateApi.createPerformance({ id: record.id })
|
||||||
// 生成-被测软件基本信息
|
// 生成-被测软件基本信息
|
||||||
const st3 = await dgGenerateApi.createBaseInformation({ id: record.id })
|
const st13 = await dgGenerateApi.createBaseInformation({ id: record.id })
|
||||||
// 生成-测试总体要求
|
// 生成-测试总体要求
|
||||||
const st4 = await dgGenerateApi.createRequirement({ id: record.id })
|
const st14 = await dgGenerateApi.createRequirement({ id: record.id })
|
||||||
Message.success(st.message)
|
|
||||||
Message.success(st2.message)
|
|
||||||
Message.success(st3.message)
|
|
||||||
Message.success(st4.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
const createZhuiZ = async (record) => {
|
|
||||||
// 生成-研总-测试项对照表
|
// 生成-研总-测试项对照表
|
||||||
const st = await dgGenerateApi.createYzComparison({ id: record.id })
|
const st15 = await dgGenerateApi.createYzComparison({ id: record.id })
|
||||||
// 生成-需求规格说明-测试项对照表
|
// 生成-需求规格说明-测试项对照表
|
||||||
const st2 = await dgGenerateApi.createXqComparison({ id: record.id })
|
const st16 = await dgGenerateApi.createXqComparison({ id: record.id })
|
||||||
// 生成-反向测试项-需求规格说明对照表
|
// 生成-反向测试项-需求规格说明对照表
|
||||||
const st3 = await dgGenerateApi.createFanXqComparison({ id: record.id })
|
const st17 = await dgGenerateApi.createFanXqComparison({ id: record.id })
|
||||||
// 生成-代码质量度量分析表
|
// 生成-代码质量度量分析表
|
||||||
const st4 = await dgGenerateApi.createCodeQuality({ id: record.id })
|
const st18 = await dgGenerateApi.createCodeQuality({ id: record.id })
|
||||||
Message.success(st.message)
|
// 生成-软硬件环境
|
||||||
Message.success(st2.message)
|
const st19 = await dgGenerateApi.createEnvironment({ id: record.id })
|
||||||
Message.success(st3.message)
|
// 生成-主要战技指标
|
||||||
Message.success(st4.message)
|
const st20 = await dgGenerateApi.createMainTech({ id: record.id })
|
||||||
|
Message.success(st20.message)
|
||||||
}
|
}
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -538,3 +547,4 @@ const crudColumns = ref([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@/api/generate/seitaiGenerate
|
||||||
|
|||||||
154
cdTMP/temp.py
Normal file
154
cdTMP/temp.py
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
from ninja_extra import api_controller, route, ControllerBase
|
||||||
|
from django.db import transaction
|
||||||
|
from pathlib import Path
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
# 文档处理相关库
|
||||||
|
from docxtpl import DocxTemplate
|
||||||
|
from docx import Document
|
||||||
|
from docx.text.paragraph import Paragraph
|
||||||
|
from docx.table import Table
|
||||||
|
from docx.oxml.table import CT_Tbl
|
||||||
|
from docx.oxml.text.paragraph import CT_P
|
||||||
|
from docx.oxml.text.run import CT_R
|
||||||
|
from docx.oxml.shape import CT_Picture
|
||||||
|
from docx.parts.image import ImagePart
|
||||||
|
from docx.text.run import Run
|
||||||
|
from docx.shared import Cm
|
||||||
|
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
|
||||||
|
|
||||||
|
@route.get('/smDocument', url_name='create-smDocument')
|
||||||
|
@transaction.atomic
|
||||||
|
def create_smDocument(self, id: int):
|
||||||
|
"""生成最后说明文档"""
|
||||||
|
# 获取项目对象
|
||||||
|
project_obj = get_object_or_404(Project, id=id)
|
||||||
|
# 首先第二层模版所需变量
|
||||||
|
member = project_obj.member[0] if len(project_obj.member) > 0 else project_obj.duty_person
|
||||||
|
context = {'name': project_obj.name, 'is_JD': False, 'ident': project_obj.ident, 'sec_title': "公开",
|
||||||
|
'duty_person': project_obj.duty_person, 'member': member}
|
||||||
|
if project_obj.report_type == '9':
|
||||||
|
context['is_JD'] = True
|
||||||
|
# 提取第一轮测试中源代码 - 用户标识
|
||||||
|
round_1 = project_obj.pField.filter(key='0').first()
|
||||||
|
duty_so = round_1.rdField.filter(type='SO').first()
|
||||||
|
if not duty_so:
|
||||||
|
return ChenResponse(code=400, status=400, message="未找到第一轮测试中源代码被测件请添加")
|
||||||
|
context['user_ident'] = duty_so.ref
|
||||||
|
|
||||||
|
# ~~~~~~定义模版路径~~~~~~~
|
||||||
|
## 定义说明最后模版
|
||||||
|
sm_template_file = Path.cwd() / 'media' / 'form_template' / 'products' / '测试说明.docx'
|
||||||
|
# docx生成后给docxtpl文件路径
|
||||||
|
sm_to_tpl_file = Path.cwd() / 'media' / 'temp' / '测试说明.docx'
|
||||||
|
# 生成最后文档路径
|
||||||
|
sm_seitai_final_file = Path.cwd() / 'media' / 'final_seitai' / '测试说明.docx'
|
||||||
|
# output_dir根路径
|
||||||
|
output_files_path = Path.cwd() / 'media' / 'output_dir'
|
||||||
|
# 获取可能使用的被复制的docx文件
|
||||||
|
dg_copied_files = []
|
||||||
|
sm_copied_files = []
|
||||||
|
for file in output_files_path.iterdir():
|
||||||
|
if file.is_file():
|
||||||
|
if file.suffix == '.docx':
|
||||||
|
dg_copied_files.append(file)
|
||||||
|
elif file.is_dir():
|
||||||
|
if file.stem == 'sm':
|
||||||
|
for f in file.iterdir():
|
||||||
|
if f.suffix == '.docx':
|
||||||
|
sm_copied_files.append(f)
|
||||||
|
# 打开文档找到所有的“域”
|
||||||
|
doc = Document(sm_template_file.as_posix())
|
||||||
|
body = doc.element.body
|
||||||
|
sdt_element_list = body.xpath('./w:sdt')
|
||||||
|
# 找到sdt域的名称 -> 为了对应output_dir文件 / 储存所有output_dir图片
|
||||||
|
area_name_list = []
|
||||||
|
image_part_list = []
|
||||||
|
# 遍历所有控件 -> 放入area_name_list【这里准备提取公共代码】
|
||||||
|
for sdt_ele in sdt_element_list:
|
||||||
|
for elem in sdt_ele.iterchildren():
|
||||||
|
# 获取“域”的名称
|
||||||
|
if elem.tag.endswith('sdtPr'):
|
||||||
|
for el in elem.getchildren():
|
||||||
|
if el.tag.endswith('alias'):
|
||||||
|
if len(el.attrib.values()) > 0:
|
||||||
|
area_name = el.attrib.values()[0]
|
||||||
|
area_name_list.append(area_name)
|
||||||
|
# 开始替换里面的“域”
|
||||||
|
if elem.tag.endswith('sdtContent'):
|
||||||
|
elem.clear()
|
||||||
|
if len(area_name_list) > 0:
|
||||||
|
area_pop_name = area_name_list.pop(0)
|
||||||
|
# 取到“域名称”,这里先去找media/output_dir/sm下文件,然后找media/output下文件
|
||||||
|
copied_file_path = ""
|
||||||
|
for file in sm_copied_files:
|
||||||
|
if file.stem == area_pop_name:
|
||||||
|
copied_file_path = file
|
||||||
|
# 这里判断是否copied_file_path没取到文件,然后遍历output_dir下文件
|
||||||
|
if not copied_file_path:
|
||||||
|
for file in dg_copied_files:
|
||||||
|
if file.stem == area_pop_name:
|
||||||
|
copied_file_path = file
|
||||||
|
# 找到所需的文件,将其数据复制到对应area_name的“域”
|
||||||
|
if copied_file_path:
|
||||||
|
doc_copied = Document(copied_file_path)
|
||||||
|
copied_element_list = []
|
||||||
|
element_list = doc_copied.element.body.inner_content_elements
|
||||||
|
for elet in element_list:
|
||||||
|
if isinstance(elet, CT_P):
|
||||||
|
copied_element_list.append(Paragraph(elet, doc_copied))
|
||||||
|
if isinstance(elet, CT_Tbl):
|
||||||
|
copied_element_list.append(Table(elet, doc_copied))
|
||||||
|
for para_copied in copied_element_list:
|
||||||
|
elem.append(para_copied._element)
|
||||||
|
|
||||||
|
# 下面代码就是将图片全部提取到image_part_list,以便后续插入
|
||||||
|
doc_copied = Document(copied_file_path) # 需要重新获取否则namespace错误
|
||||||
|
copied_body = doc_copied.element.body
|
||||||
|
img_node_list = copied_body.xpath('.//pic:pic')
|
||||||
|
if not img_node_list:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
for img_node in img_node_list:
|
||||||
|
img: CT_Picture = img_node
|
||||||
|
# 根据节点找到图片的关联id
|
||||||
|
embed = img.xpath('.//a:blip/@r:embed')[0]
|
||||||
|
# 这里得到ImagePart -> 马上要给新文档添加
|
||||||
|
related_part: ImagePart = doc_copied.part.related_parts[embed]
|
||||||
|
# doc_copied.part.related_parts是一个字典
|
||||||
|
image_part_list.append(related_part)
|
||||||
|
|
||||||
|
# 新文档添加sdt_element_list的图片
|
||||||
|
graph_node_list = body.xpath('.//pic:pic')
|
||||||
|
img_count = 0
|
||||||
|
if len(graph_node_list) == len(image_part_list):
|
||||||
|
for graph_node in graph_node_list:
|
||||||
|
image_run_node = getParentRunNode(graph_node)
|
||||||
|
image_run_node.clear()
|
||||||
|
copied_bytes_io = BytesIO(image_part_list[img_count].image.blob)
|
||||||
|
r_element = Run(image_run_node, doc)
|
||||||
|
inline_shape = r_element.add_picture(copied_bytes_io)
|
||||||
|
# 设置图片位置尺寸
|
||||||
|
source_width = inline_shape.width
|
||||||
|
inline_shape.width = Cm(12)
|
||||||
|
inline_shape.height = int(inline_shape.height * (inline_shape.width / source_width))
|
||||||
|
# 设置图片所在段落居中对齐
|
||||||
|
r_element.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
|
||||||
|
img_count += 1
|
||||||
|
else:
|
||||||
|
return ChenResponse(code=400, status=400, message='注意模版里面有自定义图片,请删除后重试!!!')
|
||||||
|
|
||||||
|
try:
|
||||||
|
doc.save(sm_to_tpl_file)
|
||||||
|
except PermissionError as e:
|
||||||
|
return ChenResponse(status=400, code=400, message="注意你打开了生成的文档,请关闭后再试,{0}".format(e))
|
||||||
|
|
||||||
|
doc = DocxTemplate(sm_to_tpl_file)
|
||||||
|
start = time.time()
|
||||||
|
doc.render(context) # 耗时最长,TODO:异步任务处理?或前端等待?
|
||||||
|
end = time.time()
|
||||||
|
print('渲染耗时:', end - start)
|
||||||
|
try:
|
||||||
|
doc.save(sm_seitai_final_file)
|
||||||
|
return ChenResponse(status=200, code=200, message="最终大纲生成成功!")
|
||||||
|
except PermissionError as e:
|
||||||
|
return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e))
|
||||||
Reference in New Issue
Block a user