57 changed files with 2064 additions and 80 deletions
-
2src/views/xm/core/xmTestPlan/rpt/CompsCard.vue
-
299src/views/xm/core/xmTestPlan/rpt/biz/productWorkItemDayList.vue
-
334src/views/xm/rpt/CompsCard.vue
-
323src/views/xm/rpt/CompsSet.vue
-
375src/views/xm/rpt/branch/branchWorkItemDayList copy.vue
-
53src/views/xm/rpt/branch/branchWorkItemDayList.vue
-
2src/views/xm/rpt/branch/menuDayAccumulate.vue
-
2src/views/xm/rpt/branch/menuDayTrend.vue
-
2src/views/xm/rpt/branch/questionDayAccumulate.vue
-
2src/views/xm/rpt/branch/questionDayTrend.vue
-
10src/views/xm/rpt/common.scss
-
98src/views/xm/rpt/index.scss
-
58src/views/xm/rpt/index.vue
-
4src/views/xm/rpt/iteration/IterationWorkItemDayList.vue
-
2src/views/xm/rpt/iteration/burnout.vue
-
2src/views/xm/rpt/iteration/menuDayAccumulate.vue
-
2src/views/xm/rpt/iteration/menuDayTrend.vue
-
2src/views/xm/rpt/iteration/questionDayAccumulate.vue
-
2src/views/xm/rpt/iteration/questionDayTrend.vue
-
2src/views/xm/rpt/product/menuAgeDist.vue
-
2src/views/xm/rpt/product/menuAttDist.vue
-
6src/views/xm/rpt/product/menuDayAccumulate.vue
-
6src/views/xm/rpt/product/menuDayTrend.vue
-
6src/views/xm/rpt/product/menuSort.vue
-
4src/views/xm/rpt/product/productWorkItemDayList.vue
-
2src/views/xm/rpt/product/questionAgeDist.vue
-
48src/views/xm/rpt/product/questionAskUserSort.vue
-
2src/views/xm/rpt/product/questionAttDist.vue
-
47src/views/xm/rpt/product/questionBugReasonDist.vue
-
48src/views/xm/rpt/product/questionBugSeverityDist.vue
-
48src/views/xm/rpt/product/questionBugStatusDist.vue
-
48src/views/xm/rpt/product/questionBugTypeDist.vue
-
2src/views/xm/rpt/product/questionDayAccumulate.vue
-
2src/views/xm/rpt/product/questionDayTrend.vue
-
48src/views/xm/rpt/product/questionFuncSort.vue
-
48src/views/xm/rpt/product/questionHandlerUserSort.vue
-
48src/views/xm/rpt/product/questionPriorityDist.vue
-
48src/views/xm/rpt/product/questionRepRateDist.vue
-
2src/views/xm/rpt/product/questionRetestDist.vue
-
48src/views/xm/rpt/product/questionSolutionDist.vue
-
2src/views/xm/rpt/product/questionSort.vue
-
3src/views/xm/rpt/project/projectWorkItemDayList.vue
-
2src/views/xm/rpt/project/projectWorkloadSetDayList.vue
-
2src/views/xm/rpt/project/projectWorkloadSetMonthList.vue
-
2src/views/xm/rpt/project/taskAgeDist.vue
-
2src/views/xm/rpt/project/taskAttDist.vue
-
2src/views/xm/rpt/project/taskDayAccumulate.vue
-
2src/views/xm/rpt/project/taskDayTrend.vue
-
2src/views/xm/rpt/project/taskSort.vue
-
2src/views/xm/rpt/reportIndexForIteration.vue
-
2src/views/xm/rpt/reportIndexForProduct.vue
-
2src/views/xm/rpt/reportIndexForProject.vue
-
6src/views/xm/rpt/testCase/testCaseSort.vue
-
6src/views/xm/rpt/testPlan/testCaseToPlanCalc.vue
-
6src/views/xm/rpt/testPlan/testDayTimesCalc.vue
-
6src/views/xm/rpt/testPlan/testPlanCaseExecStatusDist.vue
-
6src/views/xm/rpt/testPlan/testPlanCaseUserDist.vue
@ -0,0 +1,299 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
|
||||
|
<el-row :gutter="5" > |
||||
|
<el-col :span="18"> |
||||
|
<div> |
||||
|
<div class="echart-box" id="productWorkItemDayList" :style="{width:'100%',height:(maxTableHeight>600?600:maxTableHeight)+'px',overflow: 'hidden'}"></div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :span="6" class="border"> |
||||
|
<el-form :model="filters" class="padding" :style="{width:'100%',maxHeight:maxTableHeight+'px',overflow: 'auto'}" ref="filtersRef"> |
||||
|
|
||||
|
<el-form-item label="归属产品" > |
||||
|
<xm-product-select v-if="!xmProductCpd || !xmProductCpd.id" ref="xmProductSelect" style="display:inline;" :auto-select="false" :link-project-id="xmProject?xmProject.id:null" @row-click="onProductSelected" :iterationId="xmIteration?xmIteration.id:null" @clear="onProductClear"></xm-product-select> |
||||
|
<span v-else>{{xmProductCpd.id}} <span v-if="xmProductCpd.productName"><br/>{{ xmProductCpd.productName }} </span> </span> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="日期区间"> |
||||
|
<br> |
||||
|
<mdp-date-range v-model="filters" value-format="yyyy-MM-dd" start-key="startBizDate" end-key="endBizDate"></mdp-date-range> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" icon="el-icon-search" @click="listXmProductStateHis">查询</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import util from '@/common/js/util';//全局公共库 |
||||
|
import { initSimpleDicts } from '@/api/mdp/meta/item';//下拉框数据查询 |
||||
|
import { mapGetters } from 'vuex' |
||||
|
|
||||
|
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//新增界面 |
||||
|
import { listXmProductStateHis } from '@/api/xm/core/xmProductStateHis'; |
||||
|
export default { |
||||
|
|
||||
|
components: { |
||||
|
XmProductSelect, |
||||
|
}, |
||||
|
props:['xmProduct','xmProject'], |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo','roles' |
||||
|
]), |
||||
|
dataSetCpd(){ |
||||
|
return [ |
||||
|
['日期',...this.xmProductStateHiss.map(i=>i.bizDate)], |
||||
|
['未关故事',...this.xmProductStateHiss.map(i=>i.menuCnt-i.menuCloseCnt)], |
||||
|
['已关故事',...this.xmProductStateHiss.map(i=>i.menuCloseCnt)], |
||||
|
['未关任务',...this.xmProductStateHiss.map(i=>i.taskCnt-i.taskCloseCnt)], |
||||
|
['已关任务',...this.xmProductStateHiss.map(i=>i.taskCloseCnt)], |
||||
|
['未关缺陷',...this.xmProductStateHiss.map(i=>i.bugCnt-i.closedBugs)], |
||||
|
['已关缺陷',...this.xmProductStateHiss.map(i=>i.closedBugs)] |
||||
|
] |
||||
|
}, |
||||
|
titleCpd(){ |
||||
|
|
||||
|
var preName="" |
||||
|
if(this.filters.testPlan && this.filters.testPlan.id){ |
||||
|
preName=`测试计划【${this.filters.testPlan.name}】` |
||||
|
}else if(this.filters.testCasedb && this.filters.testCasedb.id){ |
||||
|
preName=`测试库【${this.filters.testCasedb.name}】` |
||||
|
}else if(this.filters.iteration && this.filters.iteration.id){ |
||||
|
preName=`迭代【${this.filters.iteration.iterationName}】` |
||||
|
}else if(this.filters.product && this.filters.product.id){ |
||||
|
if(this.filters.product.productName){ |
||||
|
preName=`产品【${this.filters.product.productName}】` |
||||
|
}else{ |
||||
|
preName=`产品【${this.filters.product.id}】` |
||||
|
} |
||||
|
|
||||
|
}else if(this.filters.project && this.filters.project.id){ |
||||
|
if(this.filters.project.name){ |
||||
|
preName=`项目【${this.filters.project.name}】` |
||||
|
}else{ |
||||
|
preName=`项目【${this.filters.project.id}】` |
||||
|
} |
||||
|
} |
||||
|
return preName+"产品工作项每日分布图" |
||||
|
}, |
||||
|
xmProductCpd(){ |
||||
|
if(this.xmProduct && this.xmProduct.id){ |
||||
|
return this.xmProduct |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
watch: { |
||||
|
dataSetCpd(){ |
||||
|
this.$nextTick(()=>{ |
||||
|
this.drawCharts(); |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
filters:{ |
||||
|
product:null, |
||||
|
project:null, |
||||
|
testPlan:null, |
||||
|
iteration:null, |
||||
|
testCasedb:null, |
||||
|
category:'', |
||||
|
startBizDate:'', |
||||
|
endBizDate:'', |
||||
|
}, |
||||
|
dicts:{},//下拉选择框的所有静态数据 params=[{categoryId:'0001',itemCode:'sex'}] 返回结果 {'sex':[{optionValue:'1',optionName:'男',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'女',seqOrder:'2',fp:'',isDefault:'0'}]} |
||||
|
load:{ list: false, edit: false, del: false, add: false },//查询中... |
||||
|
dateRanger:[], |
||||
|
maxTableHeight:300, |
||||
|
visible:false, |
||||
|
xmProductStateHiss:[], |
||||
|
|
||||
|
}//end return |
||||
|
},//end data |
||||
|
methods: { |
||||
|
listXmProductStateHis(){ |
||||
|
if(!this.filters.product){ |
||||
|
this.$notify({position:'bottom-left',showClose:true,message:'请先选中产品',type:'warning'}) |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var params={productId:this.filters.product.id,orderBy:'biz_date asc'} |
||||
|
if(this.filters.startBizDate && this.filters.endBizDate){ |
||||
|
params.startBizDate=this.filters.startBizDate; |
||||
|
params.endBizDate=this.filters.endBizDate; |
||||
|
} |
||||
|
listXmProductStateHis(params).then(res=>{ |
||||
|
this.xmProductStateHiss=res.data.tips.isOk?res.data.data:this.xmProductStateHiss; |
||||
|
}) |
||||
|
}, |
||||
|
open(){ |
||||
|
this.visible=true; |
||||
|
this.filters.testPlan=this.xmTestPlan |
||||
|
this.filters.product=this.xmProduct |
||||
|
this.filters.project=this.xmProject |
||||
|
this.filters.iteration=this.xmIteration |
||||
|
this.filters.testCasedb=this.xmTestCasedb |
||||
|
this.xmProductStateHiss=[] |
||||
|
if(this.$refs['xmProductSelect'])this.$refs['xmProductSelect'].clearSelect(); |
||||
|
this.$nextTick(()=>{ |
||||
|
this.listXmProductStateHis(); |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
drawCharts() { |
||||
|
this.myChart = this.$echarts.init(document.getElementById("productWorkItemDayList")); |
||||
|
var that=this; |
||||
|
this.myChart.on('updateAxisPointer', function (event) { |
||||
|
const xAxisInfo = event.axesInfo[0]; |
||||
|
if (xAxisInfo) { |
||||
|
const dimension = xAxisInfo.value + 1; |
||||
|
that.myChart.setOption({ |
||||
|
series: { |
||||
|
id: 'pie', |
||||
|
label: { |
||||
|
formatter: '{b}: {@[' + dimension + ']} ({d}%)' |
||||
|
}, |
||||
|
encode: { |
||||
|
value: dimension, |
||||
|
tooltip: dimension |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
this.myChart.setOption({ |
||||
|
|
||||
|
title: { |
||||
|
text: this.titleCpd, |
||||
|
left: 'center' |
||||
|
}, |
||||
|
trigger: 'axis', |
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
}, |
||||
|
barMaxWidth: 100, |
||||
|
toolbox: { |
||||
|
show: true, |
||||
|
top:"5%", |
||||
|
right:"10px", |
||||
|
feature: { |
||||
|
dataView: { show: true, readOnly: false }, |
||||
|
magicType: { show: true, type: ['line', 'bar'] }, |
||||
|
|
||||
|
saveAsImage: { show: true } |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
calculable: true, |
||||
|
legend: { |
||||
|
bottom: 'bottom', |
||||
|
}, |
||||
|
|
||||
|
dataset: { |
||||
|
source: this.dataSetCpd |
||||
|
}, |
||||
|
xAxis: { |
||||
|
type: 'category', |
||||
|
}, |
||||
|
yAxis: { gridIndex: 0 }, |
||||
|
grid: { top: '55%' }, |
||||
|
series: [ |
||||
|
{ name:'未关故事', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ name:'已关故事', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ |
||||
|
name:'未关任务', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ |
||||
|
name:'已关任务', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ name:'未关缺陷', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ name:'已关缺陷', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ |
||||
|
type: 'pie', |
||||
|
id: 'pie', |
||||
|
radius: '30%', |
||||
|
center: ['50%', '30%'], |
||||
|
emphasis: { |
||||
|
focus: 'self' |
||||
|
}, |
||||
|
label: { |
||||
|
formatter: '{b}: {@日期} ({d}%)' |
||||
|
}, |
||||
|
encode: { |
||||
|
itemName: '日期', |
||||
|
value:this.dataSetCpd[0][this.dataSetCpd[0].length-1], |
||||
|
tooltip: '日期' |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
onProductSelected(product){ |
||||
|
this.filters.product=product |
||||
|
this.xmProductStateHiss=[]; |
||||
|
}, |
||||
|
|
||||
|
onProductClear(){ |
||||
|
this.filters.product=null |
||||
|
|
||||
|
this.xmProductStateHiss=[]; |
||||
|
|
||||
|
}, |
||||
|
},//end method |
||||
|
mounted() { |
||||
|
/** |
||||
|
initSimpleDicts('all',['demandSource','demandLvl','demandType','priority','menuStatus'] ).then(res=>{ |
||||
|
this.dicts=res.data.data; |
||||
|
}) |
||||
|
*/ |
||||
|
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.filtersRef.$el) |
||||
|
//this.charts(); |
||||
|
this.open(); |
||||
|
|
||||
|
}//end mounted |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.image { |
||||
|
width: 100%; |
||||
|
display: block; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,334 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row class="padding-left padding-right"> |
||||
|
<el-col :span="6" :style="{height:maxTableHeight+'px',overflow:'auto'}"> |
||||
|
<comps-set :comp-ids="compIds" :category="category" @row-click="onCompSelect"></comps-set> |
||||
|
</el-col> |
||||
|
<el-col :span="18" :style="{height:maxTableHeight+'px',overflow:'auto'}" ref="table" class="border"> |
||||
|
<div> |
||||
|
<div class="empty" v-if="compCfgList.length == 0" > |
||||
|
<el-empty description="暂未选择模块"></el-empty> |
||||
|
</div> |
||||
|
<div v-else> |
||||
|
<grid-layout |
||||
|
:layout.sync="compCfgList" |
||||
|
:col-num="layoutColNum" |
||||
|
:row-height="120" |
||||
|
:is-draggable="true" |
||||
|
:is-resizable="true" |
||||
|
:is-mirrored="false" |
||||
|
:vertical-compact="true" |
||||
|
:margin="[10, 10]" |
||||
|
:use-css-transforms="true" |
||||
|
> |
||||
|
<grid-item |
||||
|
v-for="(item,index) in compCfgList" |
||||
|
:x="item.x" |
||||
|
:y="item.y" |
||||
|
:w="item.w" |
||||
|
:h="item.h" |
||||
|
:i="item.i" |
||||
|
:key="index" @resize="sizeAutoChange(item)"> |
||||
|
<component :is="item.compId" :xm-test-plan="xmTestPlan" :xm-product="xmProduct" :xm-project="xmProject" :xm-iteration="xmIteration" :xm-test-casedb="xmTestCasedb" :category="category" :cfg="item.cfg" :ref="item.id" @delete="doDelete" :init-group-by="item.initGroupBy" :id="item.id" :show-tool-bar="showToolBar" :show-params="showParams"></component> |
||||
|
</grid-item> |
||||
|
</grid-layout> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
<el-row v-if="printVisible" class="page-center border" style="width:1000px;"> |
||||
|
<el-row> |
||||
|
<span style="float:right;"><el-button @click="printVisible=false">取消打印</el-button> <el-button v-print="'#printBody'">打印</el-button></span> |
||||
|
</el-row> |
||||
|
<el-row id="printBody"> |
||||
|
<el-row v-for="(item,index) in compCfgList" :key="index"> |
||||
|
<component :is="item.compId" :xm-test-plan="xmTestPlan" :comp-cfg="item" :ref="item.id" @delete="doDelete"></component> |
||||
|
</el-row> |
||||
|
</el-row> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import util from '@/common/js/util';//全局公共库 |
||||
|
import seq from '@/common/js/sequence';//全局公共库 |
||||
|
import VueGridLayout from 'vue-grid-layout'; |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import CompsSet from '@/views/xm/rpt/CompsSet' |
||||
|
|
||||
|
|
||||
|
import { initDicts,listXmRptConfig, delXmRptConfig,editXmRptConfig,addXmRptConfig,batchDelXmRptConfig,editSomeFieldsXmRptConfig } from '@/api/xm/core/xmRptConfig'; |
||||
|
|
||||
|
export default { |
||||
|
components: { |
||||
|
GridLayout: VueGridLayout.GridLayout, |
||||
|
GridItem: VueGridLayout.GridItem, |
||||
|
CompsSet, |
||||
|
xmTestRptOverview:()=>import("../core/xmTestPlan/xmTestRptOverview.vue"), |
||||
|
xmMenuDayTrend:()=>import("./product/menuDayTrend.vue"), |
||||
|
xmMenuDayAccumulate:()=>import("./product/menuDayTrend.vue"), |
||||
|
xmMenuAttDist:()=>import('./product/menuAttDist'), |
||||
|
xmMenuAgeDist:()=>import('./product/menuAgeDist.vue'), |
||||
|
xmMenuSort:()=>import('./product/menuSort.vue'), |
||||
|
xmMenuFuncSort:()=>import('./product/menuSort.vue'), |
||||
|
xmMenuProductSort:()=>import('./product/menuSort.vue'), |
||||
|
xmMenuIterationSort:()=>import('./product/menuSort.vue'), |
||||
|
xmProductWorkItemDayList:()=>import('./product/productWorkItemDayList.vue'), |
||||
|
|
||||
|
|
||||
|
xmTaskDayTrend:()=>import('./project/taskDayTrend.vue'), |
||||
|
xmTaskDayAccumulate:()=>import('./project/taskDayAccumulate.vue'), |
||||
|
xmTaskAttDist:()=>import('./project/taskAttDist.vue'), |
||||
|
xmTaskAgeDist:()=>import('./project/taskAgeDist.vue'), |
||||
|
xmTaskSort:()=>import('./project/taskSort.vue'), |
||||
|
xmProjectWorkItemDayList:()=>import('./project/projectWorkItemDayList.vue'), |
||||
|
xmProjectWorkloadSetDayList:()=>import('./project/projectWorkloadSetDayList.vue'), |
||||
|
xmProjectWorkloadSetMonthList:()=>import('./project/projectWorkloadSetMonthList.vue'), |
||||
|
|
||||
|
xmQuestionDayTrend:()=>import('./product/questionDayTrend.vue'), |
||||
|
xmQuestionDayAccumulate:()=>import('./product/questionDayAccumulate.vue'), |
||||
|
xmQuestionAttDist:()=>import('./product/questionAttDist.vue'), |
||||
|
xmQuestionStateDist:()=>import('./product/questionAttDist.vue'), |
||||
|
xmQuestionAgeDist:()=>import('./product/questionAgeDist.vue'), |
||||
|
xmQuestionSort:()=>import('./product/questionSort.vue'), |
||||
|
xmQuestionAskUserSort:()=>import('./product/questionSort.vue'), |
||||
|
xmQuestionHandlerUserSort:()=>import('./product/questionSort.vue'), |
||||
|
xmQuestionFuncSort:()=>import('./product/questionSort.vue'), |
||||
|
xmQuestionMenuSort:()=>import('./product/questionSort.vue'), |
||||
|
xmQuestionRetestDist:()=>import('./product/questionRetestDist.vue'), |
||||
|
|
||||
|
|
||||
|
xmTestPlanCaseExecStatusDist:()=>import('./testPlan/testPlanCaseExecStatusDist.vue'), |
||||
|
xmTestPlanCaseUserDist:()=>import('./testPlan/testPlanCaseUserDist.vue'), |
||||
|
xmTestDayTimesCalc:()=>import('./testPlan/testDayTimesCalc.vue'), |
||||
|
xmTestCaseToPlanCalc:()=>import('./testPlan/testCaseToPlanCalc.vue'), |
||||
|
xmTestCaseSort:()=>import('./testCase/testCaseSort.vue'), |
||||
|
xmTestCaseCuserSort:()=>import('./testCase/testCaseSort.vue'), |
||||
|
xmTestCaseFuncSort:()=>import('./testCase/testCaseSort.vue'), |
||||
|
xmTestCaseMenuSort:()=>import('./testCase/testCaseSort.vue'), |
||||
|
|
||||
|
|
||||
|
xmIterationMenuDayTrend:()=>import('./iteration/menuDayTrend.vue'), |
||||
|
xmIterationMenuDayAccumulate:()=>import('./iteration/menuDayAccumulate.vue'), |
||||
|
xmIterationBurnout:()=>import('./iteration/burnout.vue'), |
||||
|
xmIterationWorkItemDayList:()=>import('./iteration/iterationWorkItemDayList.vue'), |
||||
|
xmIterationQuestionDayTrend:()=>import('./iteration/questionDayTrend.vue'), |
||||
|
xmIterationQuestionDayAccumulate:()=>import('./iteration/questionDayAccumulate.vue'), |
||||
|
|
||||
|
|
||||
|
xmBranchWorkItemDayList:()=>import('./branch/branchWorkItemDayList.vue'), |
||||
|
xmBranchQuestionDayTrend:()=>import('./branch/questionDayTrend.vue'), |
||||
|
xmBranchQuestionDayAccumulate:()=>import('./branch/questionDayAccumulate.vue'), |
||||
|
xmBranchMenuDayTrend:()=>import('./branch/menuDayTrend.vue'), |
||||
|
xmBranchMenuDayAccumulate:()=>import('./branch/menuDayAccumulate.vue'), |
||||
|
|
||||
|
}, |
||||
|
props:['xmTestCasedb','xmTestPlan','xmProduct','xmProject','xmIteration','showToolBar','category','showParams','isRptCfg','printVisible'], |
||||
|
computed: { |
||||
|
...mapGetters(['userInfo']), |
||||
|
compIds(){ |
||||
|
return this.compCfgList.map(k=>k.compId) |
||||
|
}, |
||||
|
rptConfigParamsCpd(){ |
||||
|
//业务类型1-产品报告,2-迭代报告,3-测试计划报告,4-项目报告,5-企业报告 |
||||
|
var params={bizType:'5',bizId:this.userInfo.branchId} |
||||
|
if(this.category=='企业级'){ |
||||
|
params.bizType='5'; |
||||
|
params.bizId=this.userInfo.branchId |
||||
|
}else if(this.category=='产品级'){ |
||||
|
params.bizType='1'; |
||||
|
params.bizId=this.userInfo.branchId |
||||
|
}else if(this.category=='迭代级'){ |
||||
|
params.bizType='2'; |
||||
|
params.bizId=this.userInfo.branchId |
||||
|
}else if(this.category=='项目级'){ |
||||
|
params.bizType='4'; |
||||
|
params.bizId=this.userInfo.branchId |
||||
|
}else if(this.category=='测试级'){ |
||||
|
params.bizType='3'; |
||||
|
params.bizId=this.userInfo.branchId |
||||
|
}else { |
||||
|
return params; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
xmRptConfig:{ |
||||
|
handler(){ |
||||
|
this.initCompCfgList(); |
||||
|
}, |
||||
|
deep:true, |
||||
|
}, |
||||
|
isRptCfg(){ |
||||
|
if(this.isRptCfg==true){ |
||||
|
this.$nextTick(()=>{ |
||||
|
this.compCfgList.forEach(k=>{ |
||||
|
this.sizeAutoChange(k); |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
rptConfigParamsCpd(){ |
||||
|
if(this.isRptCfg){ |
||||
|
this.getXmRptConfig() |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
xmRptConfig:null, |
||||
|
compCfgList:[], |
||||
|
maxTableHeight:300, |
||||
|
// 布局位置数据 |
||||
|
initCompCfg: [ |
||||
|
|
||||
|
{ i:0, x: 0, y: 12, w: 12, h: 6, name:'测试计划总览',compId:'xmTestRptOverview', params:{} }, |
||||
|
{ i: 1, x: 0, y: 12, w: 12, h: 6, name:'用例规划分析', compId:'xmTestCaseToPlanCalc', }, |
||||
|
{ i: 2, x: 0, y: 12, w: 12, h: 6, name:'用例每日执行统计', compId:'xmTestDayTimesCalc', }, |
||||
|
{ i: 3, x: 0, y: 12, w: 12, h: 6, name:'用例执行结果分布', compId:'xmTestPlanCaseExecStatusDist', }, |
||||
|
{ i: 4, x: 0, y: 12, w: 12, h: 6, name:'用例执行人情况分布', compId:'xmTestPlanCaseUserDist', }, |
||||
|
{ i:5, x: 0, y: 12, w: 12, h: 6, name:'缺陷需求分布', compId:'xmQuestionMenuSort', }, |
||||
|
{ i: 6, x: 0, y: 12, w: 12, h: 6, name:'缺陷模块分布', compId:'xmQuestionFuncSort', }, |
||||
|
{ i: 7, x: 0, y: 12, w: 12, h: 6, name:'缺陷状态分布',compId:'xmQuestionBugStatusDist', }, |
||||
|
{ i:8, x: 0, y: 12, w: 12, h: 6, name:'缺陷年龄分布',compId:'xmQuestionAgeDist', params:{} }, |
||||
|
{ i:9, x: 0, y: 12, w: 12, h: 6, name:'缺陷原因分布',compId:'xmQuestionBugReasonDist', params:{} }, |
||||
|
{ i:10, x: 0, y: 12, w: 12, h: 6, name:'缺陷紧急程度分布',compId:'xmQuestionPriorityDist', params:{} }, |
||||
|
{ i: 11, x: 0, y: 12, w: 12, h: 6, name:'缺陷提出人排行榜', compId:'xmQuestionAskUserSort', }, |
||||
|
{ i: 12, x: 0, y: 12, w: 12, h: 6, name:'缺陷负责人排行榜',compId:'xmQuestionHandlerUserSort', }, |
||||
|
|
||||
|
|
||||
|
], |
||||
|
// 布局列数 |
||||
|
layoutColNum: 12, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
initData(){ |
||||
|
this.getXmRptConfig(); |
||||
|
}, |
||||
|
getXmRptConfig(){ |
||||
|
if(!this.isRptCfg){ |
||||
|
return; |
||||
|
} |
||||
|
listXmRptConfig(this.rptConfigParamsCpd).then(res=>{ |
||||
|
this.xmRptConfig=res.data.data[0] |
||||
|
}) |
||||
|
}, |
||||
|
initCompCfgList(){ |
||||
|
if(this.xmRptConfig && this.xmRptConfig.cfg){ |
||||
|
var cfgJson=JSON.parse(this.xmRptConfig.cfg) |
||||
|
this.compCfgList=cfgJson; |
||||
|
}else{ |
||||
|
this.compCfgList=JSON.parse(JSON.stringify(this.initCompCfg)) |
||||
|
} |
||||
|
}, |
||||
|
onCompSelect(comp){ |
||||
|
if(!comp.id){ |
||||
|
comp.id=comp.compId |
||||
|
} |
||||
|
if(this.compCfgList.some(k=>k.compId==comp.compId)){ |
||||
|
var compCfg=this.compCfgList.find(k=>k.compId==comp.compId) |
||||
|
this.$nextTick(()=>{ |
||||
|
this.scrollToComp(compCfg) |
||||
|
}) |
||||
|
return; |
||||
|
} |
||||
|
var compCfgListTemp=JSON.parse(JSON.stringify(this.compCfgList)) |
||||
|
compCfgListTemp.sort((i1,i2)=>{ |
||||
|
return i2.i-i1.i |
||||
|
}) |
||||
|
var maxI=(compCfgListTemp.length>0?(compCfgListTemp[0].i+1):1); |
||||
|
compCfgListTemp.sort((i1,i2)=>{ |
||||
|
return i2.y-i1.y |
||||
|
}) |
||||
|
var maxY=(compCfgListTemp.length>0?(compCfgListTemp[0].y+6):0); |
||||
|
var compCfg={...comp,i:maxI, x: 0, y: maxY, w: 12, h: 6,id:comp.compId+seq.sn()} |
||||
|
this.compCfgList.push(compCfg) |
||||
|
this.$nextTick(()=>{ |
||||
|
setTimeout(()=>{ |
||||
|
this.scrollToComp(compCfg) |
||||
|
},100) |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
scrollToComp(compCfg){ |
||||
|
var doc=document.getElementById(compCfg.id) |
||||
|
if(doc){ |
||||
|
doc.scrollIntoView(false) |
||||
|
} |
||||
|
}, |
||||
|
submitXmPrtConfig(callback){ |
||||
|
|
||||
|
if(this.xmRptConfig==null){ |
||||
|
var xmRptConfig={name:this.xmTestPlan.name,bizId:this.xmTestPlan.id,cfg:[]} |
||||
|
var compCfgList=JSON.parse(JSON.stringify(this.compCfgList)) |
||||
|
compCfgList.forEach(k=>{ |
||||
|
if(this.$refs[k.id] && this.$refs[k.id][0].$refs && this.$refs[k.id][0].$refs[k.id]){ |
||||
|
k.params=this.$refs[k.id][0].$refs[k.id].filters |
||||
|
}else{ |
||||
|
k.params=this.$refs[k.id][0].filters |
||||
|
} |
||||
|
|
||||
|
}) |
||||
|
xmRptConfig.cfg=JSON.stringify(compCfgList) |
||||
|
addXmRptConfig(xmRptConfig).then(res=>{ |
||||
|
this.xmRptConfig=xmRptConfig; |
||||
|
callback() |
||||
|
}) |
||||
|
}else{ |
||||
|
var xmRptConfig={id:this.xmRptConfig.id,name:this.xmTestPlan.name,bizId:this.xmTestPlan.id,cfg:[]} |
||||
|
var compCfgList=JSON.parse(JSON.stringify(this.compCfgList)) |
||||
|
compCfgList.forEach(k=>{ |
||||
|
if(this.$refs[k.id] && this.$refs[k.id][0].$refs && this.$refs[k.id][0].$refs[k.id]){ |
||||
|
k.params=this.$refs[k.id][0].$refs[k.id].filters |
||||
|
}else{ |
||||
|
k.params=this.$refs[k.id][0].filters |
||||
|
} |
||||
|
}) |
||||
|
xmRptConfig.cfg=JSON.stringify(compCfgList) |
||||
|
editXmRptConfig(xmRptConfig).then(res=>{ |
||||
|
this.xmRptConfig=xmRptConfig; |
||||
|
callback() |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
doDelete(compCfg){ |
||||
|
if(this.isRptCfg==false){ |
||||
|
this.$notify({ position:'bottom-left', showClose:true, message: "当前报告为预览模式,不能删除,请切换为配置报告模式", type: 'error' }); |
||||
|
return; |
||||
|
} |
||||
|
var index=this.compCfgList.findIndex(k=>k.id==compCfg.id) |
||||
|
if(index>=0){ |
||||
|
this.compCfgList.splice(index,1) |
||||
|
} |
||||
|
}, |
||||
|
sizeAutoChange(k){ |
||||
|
if(this.$refs[k.id] && this.$refs[k.id][0].$refs && this.$refs[k.id][0].$refs[k.id]){ |
||||
|
this.$refs[k.id][0].$refs[k.id].sizeAutoChange(); |
||||
|
}else{ |
||||
|
this.$refs[k.id][0].sizeAutoChange(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
this.$nextTick(() => { |
||||
|
this.initData(); |
||||
|
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el) |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
|
||||
|
</style> |
||||
@ -0,0 +1,323 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<el-select v-model="filters.category" clearable @change="onCategroySelect" style="width:100%;" :disabled="!!category"> |
||||
|
<el-option v-for="(item,index) in categorys" :label="item" :value="item" :key="index"></el-option> |
||||
|
</el-select> |
||||
|
</el-row> |
||||
|
<el-row ref="table"> |
||||
|
<div class="moduleset-lg hidden-md-and-down"> |
||||
|
<div class="nav"> |
||||
|
<div class="nav_item" :class="{itemActive: item.isChecked}" v-for="(item, index) in compsCpd" :key="index" @click="selectItem(item, index)"> |
||||
|
<img :src="item.img" alt=""> |
||||
|
<div class="desc"> |
||||
|
<p>{{index+1}} {{item.rptName}}</p> |
||||
|
<span> |
||||
|
{{item.desc}} |
||||
|
</span> |
||||
|
</div> |
||||
|
<i v-if="item.isChecked" class="el-icon-success"></i> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="moduleset-sm hidden-lg-and-up"> |
||||
|
<div class="nav"> |
||||
|
<div class="nav_item" :class="{itemActive: item.isChecked}" v-for="(item, index) in compsCpd" :key="index" @click="selectItem(item, index)"> |
||||
|
<div class="title"><p>{{index+1}} {{item.rptName}}</p></div> |
||||
|
<div class="context"> |
||||
|
<img :src="item.img" alt=""></img> |
||||
|
<div class="desc"> |
||||
|
<span>{{item.desc}}</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<i v-if="item.isChecked" class="el-icon-success"></i> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import pieSimple from './images/pie-simple.png' |
||||
|
import lineStack from './images/line-stack.png' |
||||
|
import areaStack from './images/area-stack.png' |
||||
|
import ranjintu from './images/ranjintu.png' |
||||
|
import datasetLink from './images/dataset-link.png' |
||||
|
import bar from './images/bar.png' |
||||
|
|
||||
|
import { mapGetters } from 'vuex' |
||||
|
import store from '@/store' |
||||
|
|
||||
|
export default { |
||||
|
props: ['compIds','category' ], |
||||
|
computed: { |
||||
|
...mapGetters(['userInfo']), |
||||
|
compsCpd(){ |
||||
|
var comps=this.rptListCpd; |
||||
|
if(this.compIds && this.compIds.length>0){ |
||||
|
comps.forEach(i=>{ |
||||
|
i.isChecked=this.compIds.some(k=>k==i.compId) |
||||
|
}) |
||||
|
} |
||||
|
return comps; |
||||
|
}, |
||||
|
rptListCpd(){ |
||||
|
if(!this.filters.category){ |
||||
|
return this.comps; |
||||
|
}else{ |
||||
|
return this.comps.filter(i=>i.category.indexOf(this.filters.category)>=0) |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
categorys:function(){ |
||||
|
var map={}; |
||||
|
var list=[]; |
||||
|
this.comps.forEach(e => { |
||||
|
var cateList=e.category.split(",") |
||||
|
cateList.forEach(cate=>{ |
||||
|
if(!map[cate]){ |
||||
|
list.push(cate); |
||||
|
map[cate]=cate |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
}); |
||||
|
return list; |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
filters:{ |
||||
|
category:'企业级' |
||||
|
}, |
||||
|
comps: [ |
||||
|
{isChecked:false,rptName:'迭代燃尽图',category:'迭代级',compId:'xmIterationBurnout',desc:'跟踪迭代的剩余工作量按日期变化趋势,识别迭代当前进度情况',img:ranjintu }, |
||||
|
{isChecked:false,rptName:'需求每日趋势',category:'迭代级',compId:'xmIterationMenuDayTrend',desc:'跟踪未开始、执行中、已完成、已关闭状态的需求数量按日期变化趋势,识别需求工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'需求每日累积',category:'迭代级',compId:'xmIterationMenuDayAccumulate',desc:'跟踪未开始、执行中、已完成、已关闭状态的需求数量按日期累积情况,识别需求工作的瓶颈',img:areaStack }, |
||||
|
{isChecked:false,rptName:'迭代工作项每日趋势',category:'迭代级',compId:'xmIterationWorkItemDayList',desc:'统计迭代每日工作项数量分布情况',img:datasetLink }, |
||||
|
{isChecked:false,rptName:'迭代缺陷每日趋势',category:'迭代级',compId:'xmIterationQuestionDayTrend',desc:'跟踪新提出、执行中、已解决、已关闭状态的缺陷数量按日期变化趋势,识别缺陷处理工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'迭代缺陷每日累积',category:'迭代级',compId:'xmIterationQuestionDayAccumulate',desc:'跟踪一段时间内,各种程度和类别的缺陷累积情况,监控缺陷的变化趋势',img:areaStack }, |
||||
|
|
||||
|
//企业级报表 |
||||
|
{isChecked:false,rptName:'企业缺陷每日趋势',category:'企业级',compId:'xmBranchQuestionDayTrend',desc:'跟踪新提出、执行中、已解决、已关闭状态的缺陷数量按日期变化趋势,识别缺陷处理工作情况',img:lineStack }, |
||||
|
|
||||
|
{isChecked:false,rptName:'企业工作项每日趋势',category:'企业级',compId:'xmBranchWorkItemDayList',desc:'统计迭代每日工作项数量分布情况',img:datasetLink }, |
||||
|
//{isChecked:false,rptName:'企业缺陷每日趋势',category:'企业级',compId:'xmBranchQuestionDayTrend',desc:'跟踪新提出、执行中、已解决、已关闭状态的缺陷数量按日期变化趋势,识别缺陷处理工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'企业缺陷每日累积',category:'企业级',compId:'xmBranchQuestionDayAccumulate',desc:'跟踪一段时间内,各种程度和类别的缺陷累积情况,监控缺陷的变化趋势',img:areaStack }, |
||||
|
{isChecked:false,rptName:'需求每日趋势',category:'企业级',compId:'xmBranchMenuDayTrend',desc:'跟踪未开始、执行中、已完成、已关闭状态的需求数量按日期变化趋势,识别需求工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'需求每日累积',category:'企业级',compId:'xmBranchMenuDayAccumulate',desc:'跟踪未开始、执行中、已完成、已关闭状态的需求数量按日期累积情况,识别需求工作的瓶颈',img:areaStack }, |
||||
|
|
||||
|
//产品报表 |
||||
|
{isChecked:false,rptName:'产品工作项每日趋势',category:'产品级',compId:'xmProductWorkItemDayList',desc:'统计产品每日工作项数量分布情况',img:datasetLink }, |
||||
|
{isChecked:false,rptName:'需求每日趋势',category:'产品级',compId:'xmMenuDayTrend',desc:'跟踪未开始、执行中、已完成、已关闭状态的需求数量按日期变化趋势,识别需求工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'需求每日累积',category:'产品级',compId:'xmMenuDayAccumulate',desc:'跟踪未开始、执行中、已完成、已关闭状态的需求数量按日期累积情况,识别需求工作的瓶颈',img:areaStack }, |
||||
|
{isChecked:false,rptName:'需求属性分布',category:'产品级,迭代级,企业级',compId:'xmMenuAttDist',desc:'统计所有需求任意属性数量分布情况(实时数据)',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'需求年龄分布',category:'产品级,迭代级,企业级',compId:'xmMenuAgeDist',desc:'统计所有需求年龄分布情况(实时数据)',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'需求排行榜',category:'产品级,迭代级,企业级',compId:'xmMenuSort',desc:'按提出人、负责人、迭代、产品等维度统计用户故事数量按高到低进行排行(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'模块需求数量统计',category:'产品级,迭代级,企业级',compId:'xmMenuFuncSort',initGroupBy:'func_id',desc:'统计每个模块当前的需求数量(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'迭代需求数量统计',category:'产品级,迭代级,企业级',compId:'xmMenuIterationSort',initGroupBy:'iteration_id',desc:'统计每个迭代当前的需求数量(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'产品需求数量统计',category:'产品级,企业级',compId:'xmMenuProductSort',initGroupBy:'product_id',desc:'统计每个产品当前的需求数量(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'产品缺陷每日趋势',category:'产品级',compId:'xmQuestionDayTrend',desc:'跟踪新提出、执行中、已解决、已关闭状态的缺陷数量按日期变化趋势,识别缺陷处理工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'产品缺陷每日累积',category:'产品级',compId:'xmQuestionDayAccumulate',desc:'跟踪一段时间内,各种程度和类别的缺陷累积情况,监控缺陷的变化趋势',img:areaStack }, |
||||
|
|
||||
|
//项目报表 |
||||
|
{isChecked:false,rptName:'项目工作项每日趋势',category:'项目级',compId:'xmProjectWorkItemDayList',desc:'统计项目每日工作项数量分布情况',img:datasetLink }, |
||||
|
{isChecked:false,rptName:'任务每日趋势',category:'项目级',compId:'xmTaskDayTrend',desc:'跟踪未开始、执行中、已完成、已关闭状态的任务数量按日期变化趋势,识别任务工作情况',img:lineStack }, |
||||
|
{isChecked:false,rptName:'任务每日累积',category:'项目级',compId:'xmTaskDayAccumulate',desc:'跟踪未开始、执行中、已完成、已关闭状态的任务数量按日期累积情况,识别任务工作的瓶颈',img:areaStack }, |
||||
|
{isChecked:false,rptName:'任务属性分布',category:'项目级,企业级',compId:'xmTaskAttDist',desc:'统计所有任务任意属性数量分布情况(实时数据)',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'任务年龄分布',category:'项目级,企业级',compId:'xmTaskAgeDist',desc:'统计所有任务年龄分布情况(实时数据)',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'任务排行榜',category:'项目级,企业级',compId:'xmTaskSort',desc:'任务提出人、负责人的用户故事数量排行(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'项目结算工时每日趋势',category:'项目级',compId:'xmProjectWorkloadSetDayList',desc:'统计项目每日登记工时、结算工时数量分布情况',img:datasetLink }, |
||||
|
{isChecked:false,rptName:'项目结算工时每月趋势',category:'项目级',compId:'xmProjectWorkloadSetMonthList',desc:'统计项目每月登记工时、结算工时数量分布情况',img:datasetLink }, |
||||
|
|
||||
|
|
||||
|
//测试级报表 |
||||
|
{isChecked:false,rptName:'测试用例规划分析',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestCaseToPlanCalc',desc:'显示用例被规划到测试计划中的次数统计',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'测试用例需求覆盖分析',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestCaseMenuSort',initGroupBy:'menu_id',desc:'统计测试用例需求覆盖情况',img:bar }, |
||||
|
{isChecked:false,rptName:'测试用例模块覆盖分析',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestCaseFuncSort',initGroupBy:'func_id',desc:'统计测试用例覆盖各个模块的情况',img:bar }, |
||||
|
{isChecked:false,rptName:'测试用例负责人排行榜',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestCaseCuserSort',initGroupBy:'cuserid',desc:'统计测试团队每个人负责的测试用例数并进行排序',img:bar }, |
||||
|
|
||||
|
{isChecked:false,rptName:'测试用例执行状态分布',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestPlanCaseExecStatusDist',desc:'按测试用例执行结果统计,通过、失败、忽略、阻塞',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'测试用例执行用户分布',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestPlanCaseUserDist',desc:'统计测试用例负责人用例执行情况',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷回归分布',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionRetestDist',desc:'统计项目中缺陷在回归测试中分布情况,跟踪缺陷的重新打开率;',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'测试次数每日统计',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmTestDayTimesCalc',desc:'统计每日测试用例执行数量',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷状态分布',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionStateDist',desc:'跟踪新提出、执行中、已解决、已关闭状态的缺陷数量按日期变化趋势,识别缺陷处理工作情况',img:pieSimple }, |
||||
|
|
||||
|
{isChecked:false,rptName:'缺陷排行榜',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionSort',desc:'从缺陷提出人、创建人、负责人、故事等维度统计缺陷数量排行榜(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷提出人排行榜',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionAskUserSort',initGroupBy:'ask_userid',desc:'从缺陷提出人、创建人、负责人、故事等维度统计缺陷数量排行榜(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷负责人排行榜',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionHandlerUserSort',initGroupBy:'handler_userid',desc:'从缺陷提出人、创建人、负责人、故事等维度统计缺陷数量排行榜(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷模块排行榜',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionFuncSort',initGroupBy:'func_id',desc:'从缺陷提出人、创建人、负责人、故事等维度统计缺陷数量排行榜(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷需求排行榜',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionMenuSort',initGroupBy:'menu_id',desc:'从缺陷提出人、创建人、负责人、故事等维度统计缺陷数量排行榜(实时数据)',img:bar }, |
||||
|
{isChecked:false,rptName:'缺陷属性分布',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionAttDist',desc:'统计所有缺陷任意属性数量分布情况(实时数据)',img:pieSimple }, |
||||
|
{isChecked:false,rptName:'缺陷年龄分布',category:'测试级,项目级,产品级,迭代级,企业级',compId:'xmQuestionAgeDist',desc:'统计所有缺陷按照年龄的分布情况,跟踪缺陷的生命周期和响应情况',img:pieSimple }, |
||||
|
|
||||
|
], |
||||
|
maxTableHeight:300, |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
onCategroySelect(){ |
||||
|
this.selectItem(this.rptListCpd[0]) |
||||
|
}, |
||||
|
selectItem(item){ |
||||
|
this.$emit("row-click",item) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
}, |
||||
|
mounted(){ |
||||
|
this.comps.forEach(k=>k.id=k.id?k.id:k.compId) |
||||
|
if(this.category){ |
||||
|
this.filters.category=this.category |
||||
|
}else{ |
||||
|
if(this.xmIteration && this.xmIteration.id){ |
||||
|
this.filters.category="迭代级" |
||||
|
}else if(this.xmTestCasedb && this.xmTestCasedb.id){ |
||||
|
this.filters.category="测试级" |
||||
|
}else if(this.xmProject && this.xmProject.id){ |
||||
|
this.filters.category="项目级" |
||||
|
}else if(this.xmProduct && this.xmProduct.id){ |
||||
|
this.filters.category="产品级" |
||||
|
}else{ |
||||
|
this.filters.category="企业级" |
||||
|
store.dispatch("toggleSideBar",false) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
|
||||
|
|
||||
|
.moduleset-lg { |
||||
|
|
||||
|
.nav { |
||||
|
overflow: hidden; |
||||
|
display:flex; |
||||
|
align-items:center; |
||||
|
justify-content: space-between; |
||||
|
flex-wrap:wrap; |
||||
|
padding-right: 5px; |
||||
|
.nav_item { |
||||
|
padding:5px; |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
border: 2px solid #EDF0F9; |
||||
|
box-shadow: 0px 3px 4px 0px rgba(186, 184, 184, 0.1); |
||||
|
border-radius: 8px; |
||||
|
align-items: center; |
||||
|
position: relative; |
||||
|
cursor: pointer; |
||||
|
margin-top: 10px; |
||||
|
width:100%; |
||||
|
img { |
||||
|
object-fit:cover; |
||||
|
max-width: 25%; |
||||
|
max-height: 100%; |
||||
|
margin-right: 5px; |
||||
|
} |
||||
|
p { |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #7D7D7D; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
span { |
||||
|
font-size: 14px; |
||||
|
color: #7D7D7D; |
||||
|
line-height: 16px; |
||||
|
} |
||||
|
i { |
||||
|
position: absolute; |
||||
|
top: 5px; |
||||
|
right: 5px; |
||||
|
font-size: 30px; |
||||
|
color: #90B1F4; |
||||
|
} |
||||
|
} |
||||
|
.itemActive { |
||||
|
border: 2px solid #90B1F4; |
||||
|
box-shadow: 0px 3px 4px 0px rgba(186, 184, 184, 0.1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.moduleset-sm { |
||||
|
|
||||
|
.nav { |
||||
|
overflow: hidden; |
||||
|
display:flex; |
||||
|
align-items:center; |
||||
|
justify-content: space-between; |
||||
|
flex-wrap:wrap; |
||||
|
padding-right: 5px; |
||||
|
.nav_item { |
||||
|
padding:2px; |
||||
|
flex-direction: row; |
||||
|
border: 2px solid #EDF0F9; |
||||
|
box-shadow: 0px 3px 4px 0px rgba(186, 184, 184, 0.1); |
||||
|
border-radius: 8px; |
||||
|
align-items: center; |
||||
|
position: relative; |
||||
|
cursor: pointer; |
||||
|
margin-top: 5px; |
||||
|
width:100%; |
||||
|
.title{ |
||||
|
width:100%; |
||||
|
p { |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
color: #7D7D7D; |
||||
|
margin-bottom: 5px; |
||||
|
margin-top: 5px; |
||||
|
} |
||||
|
} |
||||
|
.context{ |
||||
|
display: flex; |
||||
|
width: 100%; |
||||
|
padding: 2px; |
||||
|
img { |
||||
|
object-fit:cover; |
||||
|
max-width: 25%; |
||||
|
max-height: 100%; |
||||
|
padding: 2px; |
||||
|
} |
||||
|
.desc{ |
||||
|
width:75%; |
||||
|
span { |
||||
|
font-size: 10px; |
||||
|
color: #7D7D7D; |
||||
|
line-height: 12px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
i { |
||||
|
position: absolute; |
||||
|
top: 5px; |
||||
|
right: 5px; |
||||
|
font-size: 20px; |
||||
|
color: #90B1F4; |
||||
|
} |
||||
|
} |
||||
|
.itemActive { |
||||
|
border: 2px solid #90B1F4; |
||||
|
box-shadow: 0px 3px 4px 0px rgba(186, 184, 184, 0.1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,375 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row :gutter="5" > |
||||
|
<el-col :span="18"> |
||||
|
<div class="rpt-box"> |
||||
|
<el-row v-if="isRptCfg"> |
||||
|
<el-row class="row-box padding-top"> |
||||
|
<span class="title">{{title?title:'请输入标题'}}</span><el-input class="input" v-model="title" placeholder="请输入标题"></el-input> |
||||
|
</el-row> |
||||
|
<el-row class="row-box"> |
||||
|
<el-row class="remark"><div v-html="remark?remark:'请输入说明'"></div></el-row> |
||||
|
<el-row ><el-input class="input" type="textarea" :rows="4" v-model="remark" placeholder="请输入说明"></el-input></el-row> |
||||
|
</el-row> |
||||
|
</el-row> |
||||
|
<el-row v-else-if="cfg && cfg.id"> |
||||
|
<el-row v-if="title" class="row-box"> |
||||
|
<span class="title">{{title}}</span> |
||||
|
</el-row> |
||||
|
<el-row v-if="remark" class="row-box"> |
||||
|
<span class="remark">{{remark}}</span> |
||||
|
</el-row> |
||||
|
</el-row> |
||||
|
<el-row> |
||||
|
<div class="echart-box" id="iterationWorkItemDayList"></div> |
||||
|
</el-row> |
||||
|
</div> |
||||
|
</el-col> |
||||
|
<el-col :span="6" class="border" v-if="isRptCfg"> |
||||
|
<el-row v-if="showToolBar"> |
||||
|
<el-button type="danger" icon="el-icon-delete" @click="doDelete">从报告移除该报表</el-button> |
||||
|
</el-row> |
||||
|
<el-row v-if="showParams"> |
||||
|
<el-form :model="params" class="padding" :style="{width:'100%',maxHeight:maxTableHeight+'px',overflow: 'auto'}" ref="filtersRef"> |
||||
|
|
||||
|
<el-form-item label="日期区间"> |
||||
|
<br> |
||||
|
<mdp-date-range v-model="params" value-format="yyyy-MM-dd" start-key="startBizDate" end-key="endBizDate"></mdp-date-range> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" icon="el-icon-search" @click="listXmBranchStateHis">查询</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
</el-row> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import util from '@/common/js/util';//全局公共库 |
||||
|
import { initSimpleDicts } from '@/api/mdp/meta/item';//下拉框数据查询 |
||||
|
import { mapGetters } from 'vuex' |
||||
|
|
||||
|
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//产品选择界面 |
||||
|
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect';//迭代选择界面 |
||||
|
import { listXmBranchStateHis } from '@/api/xm/core/xmBranchStateHis'; |
||||
|
export default { |
||||
|
|
||||
|
components: { |
||||
|
XmIterationSelect,XmProductSelect, |
||||
|
}, |
||||
|
props:['id','xmProduct','xmProject','xmIteration','cfg','category','showToolBar','showParams','isRptCfg'], |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo','roles' |
||||
|
]), |
||||
|
dataSetCpd(){ |
||||
|
return [ |
||||
|
['日期',...this.xmProductStateHiss.map(i=>i.bizDate)], |
||||
|
['未关故事',...this.xmProductStateHiss.map(i=>i.menuCnt-i.menuCloseCnt)], |
||||
|
['已关故事',...this.xmProductStateHiss.map(i=>i.menuCloseCnt)], |
||||
|
['未关任务',...this.xmProductStateHiss.map(i=>i.taskCnt-i.taskCloseCnt)], |
||||
|
['已关任务',...this.xmProductStateHiss.map(i=>i.taskCloseCnt)], |
||||
|
['未关缺陷',...this.xmProductStateHiss.map(i=>i.bugCnt-i.closedBugs)], |
||||
|
['已关缺陷',...this.xmProductStateHiss.map(i=>i.closedBugs)] |
||||
|
] |
||||
|
}, |
||||
|
titleCpd(){ |
||||
|
return "企业工作项每日趋势图" |
||||
|
|
||||
|
}, |
||||
|
xmProductCpd(){ |
||||
|
if(this.xmIteration && this.xmIteration.id){ |
||||
|
return {id:this.xmIteration.productId,productName:this.xmIteration.productName} |
||||
|
} |
||||
|
if(this.xmProduct && this.xmProduct.id){ |
||||
|
return this.xmProduct |
||||
|
} |
||||
|
if(this.cfg && this.cfg.params && this.cfg.params.productId){ |
||||
|
return {id:this.cfg.params.productId} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
watch: { |
||||
|
dataSetCpd(){ |
||||
|
this.$nextTick(()=>{ |
||||
|
this.drawCharts(); |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
filters:{ |
||||
|
category:'', |
||||
|
product:null, |
||||
|
project:null, |
||||
|
testPlan:null, |
||||
|
iteration:null, |
||||
|
testCasedb:null, |
||||
|
startBizDate:'', |
||||
|
endBizDate:'', |
||||
|
}, |
||||
|
params:{ |
||||
|
|
||||
|
}, |
||||
|
title:'',//报表配置项 |
||||
|
remark:'', //报表配置项 |
||||
|
|
||||
|
dicts:{},//下拉选择框的所有静态数据 params=[{categoryId:'0001',itemCode:'sex'}] 返回结果 {'sex':[{optionValue:'1',optionName:'男',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'女',seqOrder:'2',fp:'',isDefault:'0'}]} |
||||
|
load:{ list: false, edit: false, del: false, add: false },//查询中... |
||||
|
dateRanger:[], |
||||
|
maxTableHeight:300, |
||||
|
visible:false, |
||||
|
xmProductStateHiss:[], |
||||
|
|
||||
|
}//end return |
||||
|
},//end data |
||||
|
methods: { |
||||
|
listXmBranchStateHis(){ |
||||
|
var params=this.params |
||||
|
listXmBranchStateHis(params).then(res=>{ |
||||
|
this.xmProductStateHiss=res.data.tips.isOk?res.data.data:this.xmProductStateHiss; |
||||
|
}) |
||||
|
}, |
||||
|
open(){ |
||||
|
this.visible=true; |
||||
|
this.filters.testPlan=this.xmTestPlan |
||||
|
this.filters.product=this.xmProduct |
||||
|
this.filters.project=this.xmProject |
||||
|
this.filters.iteration=this.xmIteration |
||||
|
this.filters.testCasedb=this.xmTestCasedb |
||||
|
|
||||
|
if( this.filters.testPlan && this.filters.testPlan.id){ |
||||
|
this.params.planId= this.filters.testPlan.id |
||||
|
} |
||||
|
|
||||
|
if( this.filters.product && this.filters.product.id){ |
||||
|
this.params.productId= this.filters.product.id |
||||
|
} |
||||
|
|
||||
|
if( this.filters.project && this.filters.project.id){ |
||||
|
this.params.projectId= this.filters.project.id |
||||
|
} |
||||
|
|
||||
|
if( this.filters.iteration && this.filters.iteration.id){ |
||||
|
this.params.iterationId= this.filters.iteration.id |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if( this.filters.testCasedb && this.filters.testCasedb.id){ |
||||
|
this.params.casedbId= this.filters.testCasedb.id |
||||
|
} |
||||
|
if(this.cfg && this.cfg.id){ |
||||
|
this.params=this.cfg.params |
||||
|
this.title=this.cfg.title |
||||
|
this.remark=this.cfg.remark |
||||
|
} |
||||
|
if(this.showToolBar && !this.title){ |
||||
|
this.title="企业工作项每日趋势图" |
||||
|
} |
||||
|
this.xmProductStateHiss=[] |
||||
|
if(this.$refs['xmProductSelect'])this.$refs['xmProductSelect'].clearSelect(); |
||||
|
if(this.$refs['xmIterationSelect'])this.$refs['xmIterationSelect'].clearSelect(); |
||||
|
this.$nextTick(()=>{ |
||||
|
this.listXmBranchStateHis(); |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
drawCharts() { |
||||
|
this.myChart = this.$echarts.init(document.getElementById("iterationWorkItemDayList")); |
||||
|
var that=this; |
||||
|
this.myChart.on('updateAxisPointer', function (event) { |
||||
|
const xAxisInfo = event.axesInfo[0]; |
||||
|
if (xAxisInfo) { |
||||
|
const dimension = xAxisInfo.value + 1; |
||||
|
that.myChart.setOption({ |
||||
|
series: { |
||||
|
id: 'pie', |
||||
|
label: { |
||||
|
formatter: '{b}: {@[' + dimension + ']} ({d}%)' |
||||
|
}, |
||||
|
encode: { |
||||
|
value: dimension, |
||||
|
tooltip: dimension |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
this.myChart.setOption({ |
||||
|
|
||||
|
title: { |
||||
|
text: this.titleCpd, |
||||
|
left: 'center' |
||||
|
}, |
||||
|
|
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
}, |
||||
|
barMaxWidth: 100, |
||||
|
toolbox: { |
||||
|
show: true, |
||||
|
top:"5%", |
||||
|
right:"10px", |
||||
|
feature: { |
||||
|
dataView: { show: true, readOnly: false }, |
||||
|
magicType: { show: true, type: ['line', 'bar'] }, |
||||
|
|
||||
|
saveAsImage: { show: true } |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
calculable: true, |
||||
|
legend: { |
||||
|
bottom: 'bottom', |
||||
|
}, |
||||
|
|
||||
|
dataset: { |
||||
|
source: this.dataSetCpd |
||||
|
}, |
||||
|
xAxis: { |
||||
|
type: 'category', |
||||
|
}, |
||||
|
yAxis: { gridIndex: 0 }, |
||||
|
grid: { top: '55%' }, |
||||
|
series: [ |
||||
|
{ name:'未关故事', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ name:'已关故事', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ |
||||
|
name:'未关任务', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ |
||||
|
name:'已关任务', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ name:'未关缺陷', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ name:'已关缺陷', |
||||
|
type: 'line', |
||||
|
seriesLayoutBy: 'row', |
||||
|
smooth:true, |
||||
|
emphasis: { focus: 'series' }, |
||||
|
}, |
||||
|
{ |
||||
|
type: 'pie', |
||||
|
id: 'pie', |
||||
|
radius: '30%', |
||||
|
center: ['50%', '30%'], |
||||
|
emphasis: { |
||||
|
focus: 'self' |
||||
|
}, |
||||
|
label: { |
||||
|
formatter: '{b}: {@日期} ({d}%)' |
||||
|
}, |
||||
|
encode: { |
||||
|
itemName: '日期', |
||||
|
value:this.dataSetCpd[0][this.dataSetCpd[0].length-1], |
||||
|
tooltip: '日期' |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
|
||||
|
this.myChart.resize(); |
||||
|
}, |
||||
|
|
||||
|
onProductSelected(product){ |
||||
|
this.filters.product=product |
||||
|
this.xmProductStateHiss=[]; |
||||
|
}, |
||||
|
|
||||
|
onProductClear(){ |
||||
|
this.filters.product=null |
||||
|
|
||||
|
this.xmProductStateHiss=[]; |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
onIterationSelected(iteration){ |
||||
|
this.filters.iteration=iteration |
||||
|
}, |
||||
|
|
||||
|
onIterationClear(){ |
||||
|
this.filters.iteration=null |
||||
|
} |
||||
|
},//end method |
||||
|
mounted() { |
||||
|
/** |
||||
|
initSimpleDicts('all',['demandSource','demandLvl','demandType','priority','menuStatus'] ).then(res=>{ |
||||
|
this.dicts=res.data.data; |
||||
|
}) |
||||
|
*/ |
||||
|
this.maxTableHeight = this.$refs.filtersRef?util.calcTableMaxHeight(this.$refs.filtersRef.$el):this.maxTableHeight; |
||||
|
//this.charts(); |
||||
|
this.open(); |
||||
|
|
||||
|
}//end mounted |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.image { |
||||
|
width: 100%; |
||||
|
display: block; |
||||
|
} |
||||
|
.row-box{ |
||||
|
.title{ |
||||
|
font-weight: 600; |
||||
|
font-size: large; |
||||
|
visibility: visible; |
||||
|
} |
||||
|
.remark{ |
||||
|
font-size:medium; |
||||
|
visibility: visible; |
||||
|
} |
||||
|
.input { |
||||
|
visibility: hidden; |
||||
|
z-index: 10000; |
||||
|
top: 0%; |
||||
|
left:0%; |
||||
|
position:absolute; |
||||
|
} |
||||
|
} |
||||
|
.row-box:hover{ |
||||
|
.title{ |
||||
|
display:none; |
||||
|
} |
||||
|
.remark{ |
||||
|
display:none; |
||||
|
} |
||||
|
.input{ |
||||
|
visibility: visible; |
||||
|
} |
||||
|
} |
||||
|
.rpt-box{ |
||||
|
margin-left: 10px; |
||||
|
margin-right: 10px; |
||||
|
border: 1px solid #e8e8e8; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,10 @@ |
|||||
|
.m_container { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
background: rgb(238, 238, 238); |
||||
|
.m_content { |
||||
|
padding:30px 18px 18px 18px; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
.m_top { |
||||
|
background: #fff; |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
height: 100px; |
||||
|
align-items: center; |
||||
|
border: 1px solid #ebeef5; |
||||
|
margin: 0 10px; |
||||
|
.m_avatar { |
||||
|
width: 52px; |
||||
|
height: 52px; |
||||
|
margin-left: 34px; |
||||
|
} |
||||
|
.m_msg { |
||||
|
margin-left: 22px; |
||||
|
p:nth-child(1) { |
||||
|
font-size: 20px; |
||||
|
font-weight: bold; |
||||
|
color: #7D7D7D; |
||||
|
opacity: 0.92; |
||||
|
} |
||||
|
p:nth-child(2) { |
||||
|
margin-top: 12px; |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
color: #7D7D7D; |
||||
|
opacity: 0.53; |
||||
|
} |
||||
|
} |
||||
|
.m_btn { |
||||
|
margin-left: auto; |
||||
|
margin-right: 20px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.m_middle { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
margin-top: 20px; |
||||
|
height: 280px; |
||||
|
.m_left, .m_right { |
||||
|
flex: 1; |
||||
|
padding: 30px; |
||||
|
background: #fff; |
||||
|
border: 1px solid #ebeef5; |
||||
|
} |
||||
|
.m_left { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
margin-right: 10px; |
||||
|
margin-left: 10px; |
||||
|
.m_left_1 { |
||||
|
flex: 1.5; |
||||
|
p { |
||||
|
font-size: 18px; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
span { |
||||
|
font-size: 15px; |
||||
|
line-height: 42px; |
||||
|
color: #7D7D7D; |
||||
|
} |
||||
|
} |
||||
|
.m_left_2 { |
||||
|
flex: 1; |
||||
|
img { |
||||
|
width: 100%; |
||||
|
margin-left: 20px; |
||||
|
margin-top: 10px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.m_right { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
flex-wrap: wrap; |
||||
|
margin-right: 10px; |
||||
|
.m_right_menu { |
||||
|
display: flex; |
||||
|
width: 33.3%; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
font-size: 16px; |
||||
|
cursor: pointer; |
||||
|
img { |
||||
|
width: 58px; |
||||
|
height: 58px; |
||||
|
} |
||||
|
span { |
||||
|
margin-top: 12px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,58 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row v-if="rptConfigVisible"> |
||||
|
<span style="float:right;"> <el-button @click="rptConfigVisible=false">取消配置</el-button><el-button @click="saveXmRptConfig" type="primary">保存配置</el-button></span> |
||||
|
</el-row> |
||||
|
<el-row> |
||||
|
<comps-card ref="compsCard" :category="category" :xm-test-plan="xmTestPlan" :xm-product="xmProduct" :xm-project="xmProject" :xm-iteration="xmIteration" :xm-test-casedb="xmTestCasedb" :rpt-config-visible="rptConfigVisible"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import NProgress from 'nprogress' // progress bar |
||||
|
|
||||
|
import compsCard from './CompsCard' |
||||
|
import compsSet from './CompsSet' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['xmProduct','xmIteration','xmProject','xmTestCasedb','xmTestPlan','category'], |
||||
|
components: {compsSet, compsCard}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
saveXmRptConfig(){ |
||||
|
var callback=()=>{ |
||||
|
this.rptConfigVisible=false; |
||||
|
} |
||||
|
this.$refs['compsCard'].submitXmPrtConfig(callback) |
||||
|
}, |
||||
|
showPrint(){ |
||||
|
this.$refs.compsCard.printVisible=true; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-sort :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'ask_userid'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionSort from './questionSort' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionSort}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,47 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'bug_reason'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'bug_severity'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'bug_status'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'bug_type'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-sort :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'func_id'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionSort from './questionSort' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionSort}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-sort :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'handler_userid'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionSort from './questionSort' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionSort}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'bug_type'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'rep_rate'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
@ -0,0 +1,48 @@ |
|||||
|
<template> |
||||
|
<section> |
||||
|
<el-row> |
||||
|
<question-att-dist :ref="compCfg.id" :xm-test-plan="xmTestPlan" :comp-cfg="compCfg" :rpt-config-visible="rptConfigVisible" :group-by="'solution'" @delete="$emit('delete',$event)"/> |
||||
|
</el-row> |
||||
|
</section> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
|
||||
|
import questionAttDist from './questionAttDist' |
||||
|
import { mapGetters } from 'vuex' |
||||
|
import dayjs from 'dayjs' |
||||
|
|
||||
|
export default { |
||||
|
props:['id','xmTestPlan','compCfg'], |
||||
|
components: {questionAttDist}, |
||||
|
computed: { |
||||
|
...mapGetters([ |
||||
|
'userInfo' |
||||
|
]), |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
rptConfigVisible:false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
|
||||
|
sizeAutoChange(){ |
||||
|
this.refs[this.compCfg.id].sizeAutoChange() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
mounted() { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue