项目报表
continuous-integration/drone/push Build is passing Details

main
wangxiaoshuang 2025-12-12 16:58:50 +08:00
parent aab9c4576c
commit 726f6499f9
2 changed files with 374 additions and 0 deletions

View File

@ -4382,4 +4382,28 @@ export function setReadKeyFile(data) {
method: 'post',
data
})
}
// 项目报表-访视完成度
export function getTrialVisitFinishedStatList(data) {
return request({
url: `/TrialStat/getTrialVisitFinishedStatList`,
method: 'post',
data
})
}
// 项目报表-质疑统计表
export function getTrialQuestionStatList(data) {
return request({
url: `/TrialStat/getTrialQuestionStatList`,
method: 'post',
data
})
}
// 项目报表-疗效统计表
export function getTrialEfficacyEvaluationStatList(data) {
return request({
url: `/TrialStat/getTrialEfficacyEvaluationStatList`,
method: 'post',
data
})
}

View File

@ -0,0 +1,350 @@
<template>
<div class="reportForms">
<div class="search">
<el-form :inline="true">
<!-- 阅片标准 -->
<el-form-item :label="$t('trials:reportForms:table:Criterion')">
<el-select v-model="searchData.TrialReadingCriterionId" clearable filterable>
<el-option v-for="(item, index) of trialCriterionList" :key="index"
:label="item.TrialReadingCriterionName" :value="item.TrialReadingCriterionId" />
</el-select>
</el-form-item>
</el-form>
</div>
<div class="contentBox">
<div class="chartBox">
<div ref="chartContainer_left" style="width: 100%; height: 100%;" v-loading="loading_left"></div>
</div>
<div class="chartBox">
<div ref="chartContainer_right" style="width: 100%; height: 100%;" v-loading="loading_right"></div>
</div>
<div class="chartBox">
<div ref="chartContainer_bottom" style="width: 100%; height: 100%;" v-loading="loading_bottom"></div>
</div>
</div>
</div>
</template>
<script>
import BaseContainer from '@/components/BaseContainer'
let echarts = require('echarts/lib/echarts');
// require('echarts/lib/chart/line');
require('echarts/lib/chart/funnel');
require('echarts/lib/chart/bar');
//
require('echarts/lib/component/tooltip');
require('echarts/lib/component/title');
require('echarts/lib/component/legend');
require('echarts/lib/component/grid');
require('echarts/lib/component/dataZoom');
import {
getTrialCriterionList,
getTrialVisitFinishedStatList,
getTrialQuestionStatList,
getTrialEfficacyEvaluationStatList
} from '@/api/trials'
export default {
name: 'reportForms',
components: { BaseContainer },
data() {
return {
searchData: {
TrialReadingCriterionId: null
},
trialCriterionList: [],
loading_left: false,
chart_left: null,
loading_right: false,
chart_right: null,
loading_bottom: false,
chart_bottom: null,
}
},
created() {
this.getTrialCriterionList()
},
watch: {
'searchData.TrialReadingCriterionId': {
handler() {
if (this.searchData.TrialReadingCriterionId) {
this.getTrialVisitFinishedStatList()
this.getTrialQuestionStatList()
this.getTrialEfficacyEvaluationStatList()
}
}
}
},
methods: {
getTrialCriterionList() {
getTrialCriterionList(this.$route.query.trialId, false).then(res => {
this.trialCriterionList = res.Result
if (this.trialCriterionList.length > 0) {
this.searchData.TrialReadingCriterionId = this.trialCriterionList[0].TrialReadingCriterionId
}
}).catch(() => { })
},
// 访
async getTrialVisitFinishedStatList() {
try {
let data = {
TrialId: this.$route.query.trialId,
TrialReadingCriterionId: this.searchData.TrialReadingCriterionId
}
this.loading_left = true
let res = await getTrialVisitFinishedStatList(data)
this.loading_left = false
if (res.IsSuccess) {
let obj = {
titleText: this.$t("trials:reportForms:cjart:title:VisitFinishedStat"),
seriesData: [],
legendData: [
this.$t("trials:reportForms:cjart:title:UploadedCount"),
this.$t("trials:reportForms:cjart:title:QCFinishedCount"),
this.$t("trials:reportForms:cjart:title:CheckFinishedCount"),
this.$t("trials:reportForms:cjart:title:ReadingFinishedCount")
]
}
res.Result.ReadingFinishedCount = res.Result.CriterionList[0].ReadingFinishedCount
let keys = ['UploadedCount', 'QCFinishedCount', 'CheckFinishedCount', 'ReadingFinishedCount']
obj.legendData.forEach((item, index) => {
let o = {
name: item,
value: res.Result[keys[index]]
}
obj.seriesData.push(o)
})
this.initChart_left(obj)
}
} catch (err) {
console.log(err)
}
},
initChart_left(obj) {
this.chart_left = echarts.init(this.$refs.chartContainer_left);
// ...
const option = {
title: {
text: obj.titleText
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}'
},
toolbox: {
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {}
}
},
legend: {
data: obj.legendData
},
series: [
{
name: 'Funnel',
type: 'funnel',
left: '10%',
top: 60,
bottom: 60,
width: '80%',
min: 0,
max: 100,
minSize: '0%',
maxSize: '100%',
sort: 'descending',
gap: 2,
label: {
show: true,
position: 'inside'
},
labelLine: {
length: 10,
lineStyle: {
width: 1,
type: 'solid'
}
},
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
emphasis: {
label: {
fontSize: 20
}
},
data: obj.seriesData
}
]
};
// 4. 使
this.chart_left.setOption(option);
},
//
async getTrialQuestionStatList() {
try {
let data = {
TrialId: this.$route.query.trialId,
}
this.loading_right = true
let res = await getTrialQuestionStatList(data)
this.loading_right = false
if (res.IsSuccess) {
let obj = {
titleText: this.$t("trials:reportForms:cjart:title:QuestionStat"),
seriesData: [
{
name: this.$t("trials:reportForms:cjart:data:IngCount"),
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: [res.Result.QCQuestion_IngCount, res.Result.CheckQuestion_IngCount, res.Result.MedicalReviewQuestion_IngCount]
},
{
name: this.$t("trials:reportForms:cjart:data:ClosedCount"),
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: [res.Result.QCQuestion_ClosedCount, res.Result.CheckQuestion_ClosedCount, res.Result.MedicalReviewQuestion_ClosedCount]
}
],
xAxisData: [
this.$t("trials:reportForms:cjart:title:QCQuestion"),
this.$t("trials:reportForms:cjart:title:CheckQuestion"),
this.$t("trials:reportForms:cjart:title:MedicalReviewQuestion"),
],
unit: this.$t("trials:reportForms:cjart:unit:count")
}
this.initChart_right(obj)
}
} catch (err) {
console.log(err)
}
},
initChart_right(obj) {
this.chart_right = echarts.init(this.$refs.chartContainer_right);
// ...
const option = {
title: {
text: obj.titleText
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {},
xAxis: [
{
type: 'category',
data: obj.xAxisData
}
],
yAxis: [
{
name: obj.unit,
type: 'value'
}
],
series: obj.seriesData
};
// 4. 使
this.chart_right.setOption(option);
},
//
async getTrialEfficacyEvaluationStatList() {
try {
let data = {
TrialId: this.$route.query.trialId,
TrialReadingCriterionId: this.searchData.TrialReadingCriterionId
}
this.loading_bottom = true
let res = await getTrialEfficacyEvaluationStatList(data)
this.loading_bottom = false
if (res.IsSuccess) {
let obj = {
xAxisData: [],
seriesData: [],
unit: this.$t("trials:reportForms:cjart:unit:subjectCount"),
titleText: this.$t("trials:reportForms:cjart:title:EfficacyEvaluationStat"),
}
res.Result.forEach(item => {
obj.xAxisData.push(this.$fd(item.DictionaryCode, Number(item.OverallTumorEvaluation)))
obj.seriesData.push(item.SubjectCount)
})
this.initChart_bottom(obj)
}
} catch (err) {
console.log(err)
}
},
initChart_bottom(obj) {
this.chart_bottom = echarts.init(this.$refs.chartContainer_bottom);
// ...
const option = {
title: {
text: obj.titleText
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
type: 'category',
data: obj.xAxisData
},
yAxis: {
name: obj.unit,
type: 'value'
},
series: [
{
data: obj.seriesData,
type: 'bar'
}
]
};
// 4. 使
this.chart_bottom.setOption(option);
},
}
}
</script>
<style lang="scss" scoped>
.reportForms {
width: 100%;
height: 100%;
background-color: #fff;
.search {
padding: 5px;
}
.contentBox {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
width: 100%;
height: calc(100% - 70px);
.chartBox {
box-sizing: border-box;
width: 50%;
height: 50%;
&:last-child {
width: 100%;
}
}
}
}
</style>