This commit is contained in:
2024-03-29 19:03:35 +08:00
parent 84a2eab9ad
commit 8cdcb7a073
15 changed files with 485 additions and 146 deletions

View File

@@ -0,0 +1,146 @@
import { request } from "@/api/request"
export default {
/**
* 生成技术依据文件
* @returns
*/
createBgTechYiju(params = {}) {
return request({
url: `/generateBG/create/techyiju`,
method: "get",
params
})
},
/**
* 生成测评时间和地点
* @returns
*/
createBgTimeaddress(params = {}) {
return request({
url: `/generateBG/create/timeaddress`,
method: "get",
params
})
},
/**
* 在报告生成多个版本被测软件基本信息
* @returns
*/
createBgBaseInformation(params = {}) {
return request({
url: `/generateBG/create/baseInformation`,
method: "get",
params
})
},
/**
* 生成测评完成情况
* @returns
*/
createBgCompletionstatus(params = {}) {
return request({
url: `/generateBG/create/completionstatus`,
method: "get",
params
})
},
/**
* 生成综述
* @returns
*/
createBgSummary(params = {}) {
return request({
url: `/generateBG/create/summary`,
method: "get",
params
})
},
/**
* 生成测试内容和结果[报告非常关键的一环-大模块]
* @returns
*/
createBgContentandresults1(params = {}) {
return request({
url: `/generateBG/create/contentandresults_1`,
method: "get",
params
})
},
/**
* 查询除第一轮以外,生成其他轮次测试内容和结果
* @returns
*/
createBgContentandresults2(params = {}) {
return request({
url: `/generateBG/create/contentandresults_2`,
method: "get",
params
})
},
/**
* 测试有效性充分性说明
* @returns
*/
createBgEffectAndAdquacy(params = {}) {
return request({
url: `/generateBG/create/effect_and_adquacy`,
method: "get",
params
})
},
/**
* 需求指标符合性情况
* @returns
*/
createBgDemandEffective(params = {}) {
return request({
url: `/generateBG/create/demand_effective`,
method: "get",
params
})
},
/**
* 软件质量评价
* @returns
*/
createBgQualityEvaluate(params = {}) {
return request({
url: `/generateBG/create/quality_evaluate`,
method: "get",
params
})
},
/**
* 软件总体结论
* @returns
*/
createBgEntire(params = {}) {
return request({
url: `/generateBG/create/entire`,
method: "get",
params
})
},
/**
* 研总需求追踪 - 注意生成每个轮次的追踪 # TODO优先完成回归测试说明文档
* @returns
*/
createBgYzxqTrack(params = {}) {
return request({
url: `/generateBG/create/yzxq_track`,
method: "get",
params
})
},
/**
* 生成问题汇总表
* @returns
*/
createBgProblemsSummary(params = {}) {
return request({
url: `/generateBG/create/problems_summary`,
method: "get",
params
})
},
}

View File

@@ -32,5 +32,16 @@ export default {
method: "get",
params
})
}
},
/**
* TODO:如果缺少部分文件给与提示
* @returns 根据output_dir以及output_dir/bg中文档生成测评报告
*/
createBgDocument(params = {}) {
return request({
url: `/create/bgDocument`,
method: "get",
params
})
},
}

View File

@@ -45,4 +45,26 @@ export default {
data
})
},
/**
* 查询是否存在第一轮是否存在源代码dut
* @returns {bool} 第一轮是否存在源代码dut
*/
getSoExists(params = {}) {
return request({
url: "/project/dut/soExist",
method: "get",
params
})
},
/**
* 强制弹窗提交的第一轮源代码被测件-新增接口
* @returns
*/
createR1SoDut(params = {}) {
return request({
url: "/project/dut/createR1Sodut",
method: "post",
data: params
})
}
}

View File

@@ -0,0 +1,14 @@
import { request } from "@/api/request"
export default {
/**
* 传入用户选中的节点请求复制到第二轮
* @returns 是否复制成功,并通知刷新节点树
*/
copyCheckedNode(params = {}) {
return request({
url: `/treeOperation/copy`,
method: "get",
params
})
}
}

View File

@@ -1,5 +1,12 @@
<template>
<a-modal v-model:visible="modal.visible" :on-before-ok="modal.submit" unmount-on-close @cancel="modal.cancel" :width="width">
<a-modal
v-model:visible="modal.visible"
:on-before-ok="modal.submit"
unmount-on-close
@cancel="modal.cancel"
:width="width"
:on-before-cancel="modal.customCancel"
>
<template #title>
{{ prop.title }}
</template>
@@ -25,7 +32,9 @@ const prop = defineProps({
default_visible: { type: Boolean, default: false }, // 默认隐藏
options: { type: Object, default: {} }, // ma-form 属性
submit: { type: Function, default: () => {} },
width :{ type:String, default:("1000"+'px')}
width: { type: String, default: "1000" + "px" },
// 自定义异步取消参数
customCancel: { type: Function, default: null }
})
const maFormRef = ref()
@@ -50,6 +59,12 @@ const modal = reactive({
}
return prop.submit(form._rawValue)
},
customCancel() {
if(prop.customCancel){
return prop.customCancel()
}
return true
},
cancel() {
emit("cancel")
}

View File

@@ -14,16 +14,21 @@
<a-button type="primary" @click="toggleExpanded" class="mb-1">
{{ expandedKeys?.length ? "全部收缩" : "全部展开" }}
</a-button>
<a-popconfirm type="warning" @ok="handleCopyNode" content="是否确定根据选中节点进行创建?">
<a-button type="primary" class="ml-2"> 复制选中节点创建第二轮 </a-button>
</a-popconfirm>
<a-tree
class="h-10/12 select-none"
:data="treeData"
size="small"
checkable
block-node
animation
@select="pointNode"
:load-more="loadMore"
v-model:expanded-keys="expandedKeys"
v-model:selected-keys="selectedKeys"
v-model:checked-keys="checkedKeys"
showLine
ref="treeRef"
border
@@ -100,6 +105,21 @@
width="800px"
:submit="handleRoundSubmit"
></ma-form-modal>
<!-- 如果没有第一轮的SO_dut则弹窗 -->
<ma-form-modal
ref="soDutFormRef"
title="新增第一轮源代码被测件"
:column="soDutColumn"
width="800px"
:submit="handleSoDutSubmit"
:custom-cancel="handleSoDutCancel"
></ma-form-modal>
<Progress
:visible="visible"
:isComplete="isComplete"
:text="ptext"
@clickConfirm="handleModalConfirmClick"
></Progress>
</template>
<script setup>
@@ -109,12 +129,46 @@ import PageLayout from "@/layout/page-layout.vue"
import MaFormModal from "@/components/ma-form-modal/index.vue"
import projectApi from "@/api/project/project"
import roundApi from "@/api/project/round"
import { Message } from "@arco-design/web-vue"
import dutApi from "@/api/project/dut"
import copyApi from "@/api/treeOperation/copy"
import { Message, Notification } from "@arco-design/web-vue"
import { useRoute } from "vue-router"
import { useRouter } from "vue-router"
import { useTreeDataStore } from "@/store"
import { storeToRefs } from "pinia"
import dayjs from "dayjs"
import Progress from "@/views/testmanage/projmanage/cpns/progress.vue"
/// 初始化round轮次数据
const treeDataStore = useTreeDataStore()
const route = useRoute()
const router = useRouter()
const treeRef = ref()
const { treeData, currentNode } = storeToRefs(treeDataStore)
const projectInfo = ref({ ...route.query })
const projectId = ref(route.query.id)
//~~~~ 复制粘贴流程
const checkedKeys = ref([])
/// 点击复制按钮
const handleCopyNode = async () => {
// 打印下checked节点key
console.log(checkedKeys.value)
visible.value = true
isComplete.value = false
const st = await copyApi.copyCheckedNode().catch((err) => {
isComplete.value = true
visible.value = false
})
isComplete.value = true
Message.success(st.message)
}
/// 进度条变量
const visible = ref(false)
const isComplete = ref(false)
const ptext = ref("第二轮数据")
const handleModalConfirmClick = () => {
visible.value = false
}
//~~~~ 缩小后的menu菜单
const drawerVisible = ref(false)
provide("toggleDrawerMenu", () => {
@@ -123,6 +177,13 @@ provide("toggleDrawerMenu", () => {
//~~~~ 搜索绑定与搜索按钮点击
const searchKey = ref("")
const handleSearchTreeDataClick = () => {
if (!treeDataStore.originTreeData) {
return
}
if (searchKey.value.match(/^[ ]*$/)) {
treeData.value = treeDataStore.originTreeData
return
}
const loop = (itemdata) => {
const result = []
itemdata.forEach((item) => {
@@ -149,17 +210,40 @@ const handleSearchTreeDataClick = () => {
}
}
//~~~~ 树状组件
/// 初始化round轮次数据
const treeDataStore = useTreeDataStore()
const route = useRoute()
const router = useRouter()
const treeRef = ref()
const { treeData, currentNode } = storeToRefs(treeDataStore)
const projectInfo = ref({ ...route.query })
const projectId = ref(route.query.id)
// ~~~~定义弹出a-form-modal的submit方法~~~
const handleSoDutSubmit = async (data) => {
// 只有一个参数就是被提交的数据然后返回false阻止弹窗消失
const input_data = { ...data, project_id: projectId.value }
const res = await dutApi.createR1SoDut(input_data)
if (res.code == 200) {
treeDataStore.updateDutTreeData(res.data, projectId.value)
Message.success("添加成功...")
setTimeout(() => {
location.reload()
}, 500)
return
}
return false
}
// ~~~~定义弹出a-form-modal的cancel方法-返回false则无法关闭弹窗~~~~
const handleSoDutCancel = () => {
Notification.error("必须添加第一轮源代码信息,无法关闭!")
return false
}
// 初始化树状数据
// so_dut弹窗ref对象
const soDutFormRef = ref()
onMounted(async () => {
treeDataStore.initTreeData(projectId.value)
// 检查是否存在第一轮的源代码dut
/// 主动后端请求
const res = await dutApi.getSoExists({ id: projectId.value })
/// 如果包含第一轮源代码则不处理不包含则弹窗必须添加dut
if (!res.data.exists) {
// 这里就必须让用户选择添加了
Message.warning("识别到您未添加第一轮源代码的信息,此信息必填")
soDutFormRef.value.open({})
}
})
// v-model绑定选中节点
const selectedKeys = ref([])
@@ -254,13 +338,12 @@ const pointNode = (value, data) => {
}
/// 动态加载函数-参数1:树node对象
const loadMore = (nodeData) => {
console.log("动态加载的节点为:", nodeData) // 输出点击节点的key,以及添加上去的level属性
if (nodeData.level == "0") {
return new Promise(async (resolve) => {
const res = await projectApi.getDutInfo(projectInfo.value.id, nodeData.key, nodeData.level)
nodeData.children = res.data
resolve()
})
}).catch()
}
if (nodeData.level == "1") {
return new Promise(async (resolve) => {
@@ -319,9 +402,7 @@ const handleRoundDelClick = async (value) => {
await roundApi.delete(projectId.value, value)
Message.success("删除成功!")
treeDataStore.resetTreeData(projectId.value)
} catch {
Message.error("删除失败!")
}
} catch {}
}
/// Ma-form-Modal的提交按钮
const handleRoundSubmit = async (value) => {
@@ -482,6 +563,64 @@ const roundColumn = ref([
const roundOption = ref({
customClass: [""]
})
// 源代码so_dut的弹窗
const soDutColumn = ref([
{
title: "代码版本",
dataIndex: "version",
placeholder: "请输入代码版本",
rules: [{ required: true, message: "代码版本必填" }]
},
{
title: "用户标识",
dataIndex: "userRef",
placeholder: "请输入用户标识"
},
{
title: "单位",
dataIndex: "unit",
placeholder: "请选择单位名称",
formType: "select",
dict: { url: "system/contact/index", props: { label: "name", value: "name" }, translation: true },
rules: [{ required: true, message: "单位必选" }]
},
{
title: "发布时间",
dataIndex: "date",
rules: [{ required: true, message: "时间必填" }],
formType: "date"
},
{
title: "空行",
dataIndex: "black_line",
formType: "input-number"
},
{
title: "纯注释?",
dataIndex: "pure_code_line",
formType: "input-number"
},
{
title: "混合行?",
dataIndex: "mix_line",
formType: "input-number"
},
{
title: "总注释",
dataIndex: "total_comment_line",
formType: "input-number"
},
{
title: "总代码",
dataIndex: "total_code_line",
formType: "input-number"
},
{
title: "总行数",
dataIndex: "total_line",
formType: "input-number"
}
])
</script>
<style lang="less" scoped>

View File

@@ -6,14 +6,15 @@ const useTreeDataStore = defineStore("treeDataStore", {
return {
treeData: [],
originTreeData: [],
currentNode: undefined
currentNode: undefined,
isInit: false
}
},
actions: {
// 不能使用箭头函数无法绑定this
async initTreeData(projectId) {
// 获取localStorage的treeData数据
if(localStorage.getItem("tree_local_data")){
if (localStorage.getItem("tree_local_data")) {
this.treeData = JSON.parse(localStorage.getItem("tree_local_data"))
}
if (this.treeData.length === 0) {
@@ -23,8 +24,8 @@ const useTreeDataStore = defineStore("treeDataStore", {
}
// 将用户关闭页面数据储存于localStorage中 -> 注意用户打开其他项目 -> 务必清除localStorage的tree_local_data数据
// 暂定在点击进入工作台时清除!!!
window.addEventListener("beforeunload",()=>{
localStorage.setItem("tree_local_data",JSON.stringify(this.treeData))
window.addEventListener("beforeunload", () => {
localStorage.setItem("tree_local_data", JSON.stringify(this.treeData))
})
},
// 用于新增轮次后显示

View File

@@ -138,6 +138,13 @@ const crudOptions = ref({
{
dataIndex: "suggest"
},
{
formType: "divider",
title: "解决问题"
},
{
dataIndex: "solve"
},
{
formType: "divider",
title: "人员信息"
@@ -322,14 +329,48 @@ const columns = ref([
dataIndex: "suggest",
addDefaultValue: ""
},
{
title: "处理方式",
hide: true,
dataIndex: "solve",
addDefaultValue: "",
formType: "textarea"
},
{
title: "提单人",
dataIndex: "postPerson",
search: true,
hide: true,
formType: "select",
commonRules: [{ required: true, message: "提单人必填" }],
dict: { url: "system/user/list", translation: true, props: { label: "name", value: "name" } }
},
{
title: "悬挂状态",
dataIndex: "hang",
search: false,
addDisplay: false,
editDisplay: false,
align: "center",
customRender: ({ record }) => {
// 判断是否为悬挂状态record.hang[Boolean]
let tagObj
if (record.hang) {
tagObj = (
<a-tag size="small" bordered color="green">
有关联用例
</a-tag>
)
} else {
tagObj = (
<a-tag size="small" bordered color="red">
悬挂
</a-tag>
)
}
return <a-space size="mini">{tagObj}</a-space>
}
},
{
title: "是否关联",
dataIndex: "related",

View File

@@ -149,6 +149,13 @@ const crudOptions = ref({
{
dataIndex: "suggest"
},
{
formType: "divider",
title: "解决问题"
},
{
dataIndex: "solve"
},
{
formType: "divider",
title: "人员信息"
@@ -327,6 +334,13 @@ const crudColumns = ref([
dataIndex: "suggest",
addDefaultValue: ""
},
{
title: "处理方式",
hide: true,
dataIndex: "solve",
addDefaultValue: "",
formType: "textarea"
},
{
title: "提单人",
dataIndex: "postPerson",

View File

@@ -213,14 +213,14 @@ const crudColumns = ref([
formType: "input-number"
},
{
title: "纯注释",
title: "纯注释?",
hide: true,
align: "center",
dataIndex: "pure_code_line",
formType: "input-number"
},
{
title: "混合行",
title: "混合行?",
hide: true,
align: "center",
dataIndex: "mix_line",

View File

@@ -28,7 +28,16 @@ const projectId = ref(route.query.id)
// 标识显示字段
const showType = (record) => {
let key_string = parseInt(record.key.substring(record.key.lastIndexOf("-") + 1)) + 1
return "YL-" + record.ident + "-" + key_string.toString().padStart(3, "0")
let k_string_array = record.key.split("-")
let demand_key = parseInt(k_string_array.slice(-2)[0]) + 1
return (
"YL-" +
record.ident +
"-" +
demand_key.toString().padStart(3, "0") +
"-" +
key_string.toString().padStart(3, "0")
)
}
// crud设置
const crudOptions = ref({
@@ -38,7 +47,7 @@ const crudOptions = ref({
delete: { show: true, api: caseApi.delete },
// 处理新增删除后树状图显示
beforeOpenAdd: function () {
let key_split = route.query.key.split("-")
let key_split = route.query.key.split("-")
let round_key = key_split[0]
let dut_key = key_split[1]
let design_key = key_split[2]
@@ -51,7 +60,7 @@ const crudOptions = ref({
return true
},
beforeOpenEdit: function (record) {
let key_split = route.query.key.split("-")
let key_split = route.query.key.split("-")
let round_key = key_split[0]
let dut_key = key_split[1]
let design_key = key_split[2]

View File

@@ -41,7 +41,7 @@ const handleClickConfirmButton = () => {
}
Notification.warning({
title: "无法关闭",
content: "生成大纲未完成,请等待生成完成后再关闭"
content: `生成${props.text}未完成,请等待生成完成后再关闭`
})
return false
}

View File

@@ -0,0 +1,14 @@
import { Message } from "@arco-design/web-vue"
export default {
async create_entire_doc(visible, isComplete, api, record_id) {
visible.value = true
isComplete.value = false
const st = await api({ id: record_id }).catch((err) => {
isComplete.value = true
visible.value = false
})
isComplete.value = true
Message.success(st.message)
}
}

View File

@@ -15,6 +15,7 @@
<p><a-link @click="createDgItem(record)">大纲二段文档</a-link></p>
<p><a-link @click="createSmItem(record)">说明二段文档</a-link></p>
<p><a-link @click="createJLItem(record)">记录二级文档</a-link></p>
<p><a-link @click="createBgItem(record)">报告二级文档</a-link></p>
<p>
<a-link @click="createSeitaiDagang(record)"><icon-eye />[测试]生成最后大纲</a-link>
</p>
@@ -24,6 +25,9 @@
<p>
<a-link @click="createSeitaiJilu(record)"><icon-eye />[测试]生成最后记录</a-link>
</p>
<p>
<a-link @click="createSeitaiBaogao(record)"><icon-eye />[测试]生成测评报告</a-link>
</p>
</template>
</a-popover>
<a-link @click="enterWorkPlant(record)">进入工作区</a-link>
@@ -49,8 +53,10 @@ import dgGenerateApi from "@/api/generate/dgGenerate"
import seitaiGenerateApi from "@/api/generate/seitaiGenerate"
import smGenerateApi from "@/api/generate/smGenerate"
import jlGenerateApi from "@/api/generate/jlGenerate"
import bgGenerateApi from "@/api/generate/bgGenerate"
import { Message } from "@arco-design/web-vue"
import Progress from "./cpns/progress.vue"
import hoosk from "@/views/testmanage/projmanage/hooks.js"
const router = useRouter()
// 定义预览组件的Ref
const previewRef = ref(null)
@@ -71,14 +77,7 @@ const handleModalConfirmClick = () => {
// ~~~~~~~~测试说明生成文档~~~~~~~~
const createSeitaiShuoming = async (record) => {
ptext.value = "测试说明"
visible.value = true
isComplete.value = false
const st = await seitaiGenerateApi.createShuomingSeiTai({ id: record.id }).catch((err) => {
isComplete.value = true
visible.value = false
})
isComplete.value = true
Message.success(st.message)
hoosk.create_entire_doc(visible, isComplete, seitaiGenerateApi.createShuomingSeiTai, record.id)
}
// ~~~~~~~~测试大纲生成文档~~~~~~~~
@@ -86,26 +85,18 @@ const createSeitaiDagang = async (record) => {
// 根据一系列文档生成大纲 - 这里有进度条组件、a-modal组件
// 1.打开进度条组件
ptext.value = "测评大纲"
visible.value = true
isComplete.value = false
const st = await seitaiGenerateApi.createDagangSeiTai({ id: record.id }).catch((err) => {
isComplete.value = true
visible.value = false
})
isComplete.value = true
Message.success(st.message)
hoosk.create_entire_doc(visible, isComplete, seitaiGenerateApi.createDagangSeiTai, record.id)
}
// ~~~~~~~~记录生成文档~~~~~~~~
const createSeitaiJilu = async (record) => {
ptext.value = "测试记录"
visible.value = true
isComplete.value = false
const st = await seitaiGenerateApi.createJiluSeiTai({ id: record.id }).catch((err) => {
isComplete.value = true
visible.value = false
})
isComplete.value = true
Message.success(st.message)
hoosk.create_entire_doc(visible, isComplete, seitaiGenerateApi.createJiluSeiTai, record.id)
}
// ~~~~~~~~报告生成文档~~~~~~~~
const createSeitaiBaogao = async (record) => {
ptext.value = "测评报告"
hoosk.create_entire_doc(visible, isComplete, seitaiGenerateApi.createBgDocument, record.id)
}
// 记录生成二级文档
@@ -114,7 +105,6 @@ const createJLItem = async (record) => {
Message.success(st.message)
}
// 说明生成二级文档
const createSmItem = async (record) => {
// 生成测评对象 - 和大纲一样 - 可能会删除
@@ -187,6 +177,23 @@ const createDgItem = async (record) => {
const st20 = await dgGenerateApi.createMainTech({ id: record.id })
Message.success(st20.message)
}
// 报告生成二级文档
const createBgItem = async (record) => {
const st1 = await bgGenerateApi.createBgTechYiju({ id: record.id })
const st2 = await bgGenerateApi.createBgTimeaddress({ id: record.id })
const st3 = await bgGenerateApi.createBgBaseInformation({ id: record.id })
const st4 = await bgGenerateApi.createBgCompletionstatus({ id: record.id })
const st5 = await bgGenerateApi.createBgSummary({ id: record.id })
const st6 = await bgGenerateApi.createBgContentandresults1({ id: record.id })
const st7 = await bgGenerateApi.createBgContentandresults2({ id: record.id })
const st8 = await bgGenerateApi.createBgEffectAndAdquacy({ id: record.id })
const st9 = await bgGenerateApi.createBgDemandEffective({ id: record.id })
const st10 = await bgGenerateApi.createBgQualityEvaluate({ id: record.id })
const st11 = await bgGenerateApi.createBgEntire({ id: record.id })
const st12 = await bgGenerateApi.createBgYzxqTrack({ id: record.id })
const st13 = await bgGenerateApi.createBgProblemsSummary({ id: record.id })
Message.success(st13.message)
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CRUD-OPTIONS

View File

@@ -1,94 +0,0 @@
[{
'title':'功能测试_5',
'demand_list': [{
'name': '测试项1',
'total_count': 1,
'exe_count': 1,
'not_exe_count': 0,
'pass_count': 1,
'not_pass_count': 0,
'conclusion': '通过',
'problems': '/'
}, {
'name': '测试项3',
'total_count': 1,
'exe_count': 1,
'not_exe_count': 0,
'pass_count': 1,
'not_pass_count': 0,
'conclusion': '通过',
'problems': '/'
}, {
'name': '一个YZ对应的测试项',
'total_count': 0,
'exe_count': 0,
'not_exe_count': 0,
'pass_count': 0,
'not_pass_count': 0,
'conclusion': '通过',
'problems': '/'
}, {
'name': '调试台功能测试1号',
'total_count': 2,
'exe_count': 2,
'not_exe_count': 0,
'pass_count': 0,
'not_pass_count': 2,
'conclusion': '未通过',
'problems': 'PT_R2233_004\x07PT_R2233_001\x07PT_R2233_002\x07PT_R2233_003'
}, {
'name': '开始了功能测试',
'total_count': 1,
'exe_count': 1,
'not_exe_count': 0,
'pass_count': 1,
'not_pass_count': 0,
'conclusion': '通过',
'problems': '/'
}, {
'name': '串口调试1号测试项',
'total_count': 2,
'exe_count': 1,
'not_exe_count': 1,
'pass_count': 1,
'not_pass_count': 1,
'conclusion': '未通过',
'problems': '/'
}]
}, {
'title':'接口测试_6',
'demand_list': [{
'name': '串口调试的接口功能测试项',
'total_count': 1,
'exe_count': 1,
'not_exe_count': 0,
'pass_count': 1,
'not_pass_count': 0,
'conclusion': '通过',
'problems': '/'
}]
}, {
'title':'安全性测试_8',
'demand_list': [{
'name': '研总主要关联的测试项,另外还有需求关联它',
'total_count': 0,
'exe_count': 0,
'not_exe_count': 0,
'pass_count': 0,
'not_pass_count': 0,
'conclusion': '通过',
'problems': '/'
}]
}, {
'title':'功耗分析_16',
'demand_list': [{
'name': '测试项2',
'total_count': 1,
'exe_count': 0,
'not_exe_count': 1,
'pass_count': 0,
'not_pass_count': 1,
'conclusion': '未通过',
'problems': '/'
}]
}]