trcist1.1新增阅片图表
continuous-integration/drone/push Build encountered an error Details

uat
wangxiaoshuang 2025-12-15 14:07:59 +08:00
parent 365791624e
commit 9da598862a
19 changed files with 565 additions and 69 deletions

View File

@ -294,3 +294,12 @@ export function readingImport(param) {
data: param data: param
}) })
} }
// 阅片获取图表数据
export function getReportsChartData(param) {
return request({
url: `/ReadingImageTask/getReportsChartData`,
method: 'post',
data: param
})
}

View File

@ -0,0 +1,240 @@
<template>
<div :id="key" class="readingChart" v-show="visible" :style="{
'z-index': zIndex
}">
<div ref="chartContainer" style="width: 490px; height: 290px;" v-loading="loading"></div>
</div>
</template>
<script>
import { getReportsChartData } from "@/api/reading"
import moment from "moment"
let echarts = require('echarts/lib/echarts');
//
// require('echarts/lib/chart/bar');
require('echarts/lib/chart/line');
// require('echarts/lib/chart/pie');
// require('echarts/lib/chart/scatter');
//
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');
export default {
name: "readingChart",
props: {
},
data() {
return {
visible: false,
zIndex: 9,
chart: null,
loading: false,
key: 'readingChart'
};
},
methods: {
init(event, obj, zIndex = 9) {
this.loading = true
this.zIndex = zIndex
let { key } = obj
if (key) {
this.key = key
}
this.$nextTick(() => {
this.visible = true
let readingChart = document.querySelector(`#${this.key}`);
let chaY = document.body.clientHeight - event.clientY;
let chaX = document.body.clientWidth - event.clientX;
if (chaY < 250) {
readingChart.style.top = event.clientY - 220 + "px";
} else {
readingChart.style.top = event.clientY + "px";
}
if (chaX < 500) {
readingChart.style.left = event.clientX - 520 + "px";
} else {
readingChart.style.left = event.clientX + 15 + "px";
}
this.getInfo(obj)
})
},
async getInfo(data) {
try {
let { VisitTaskId = null, TrialId = null, QuestionId = null, QuestionName = null, TableQuestionId = null, RowIndex = null, ReportChartTypeEnum = null } = data
let params = {
VisitTaskId, TrialId, QuestionId, TableQuestionId, RowIndex, ReportChartTypeEnum
}
this.loading = true
let res = await getReportsChartData(params)
this.loading = false
if (res.IsSuccess) {
let LatestScanDateList = res.Result.LatestScanDateList.map(item => item.split(" ")[0])
let obj = {
title: QuestionName,
xAxisData: LatestScanDateList || [],
series: [],
unit: this.$fd("ValueUnit", res.Result.Unit),
visitName: res.Result.VisitTaskNameList,
min: null,
max: null
}
res.Result.ChartDataList.forEach((item) => {
let arr = []
item.Value.forEach((d, index) => {
// arr.push([LatestScanDateList[index], d])
arr.push(d)
})
obj.series.push({
name: item.Name,
data: arr,
type: 'line'
})
});
// if (Array.isArray(res.Result.LatestScanDateList) && res.Result.LatestScanDateList.length >= 2) {
// let hours = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'hours');
// let days = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'days');
// let months = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'months');
// console.log(hours, 'hours')
// console.log(days, 'days')
// console.log(months, 'months')
// if (hours < 24) {
// obj.min = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 23:59:59'
// }
// if (days >= 1 && days <= 7) {
// obj.min = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[0]).add(7, 'days').format('YYYY-MM-DD') + ' 23:59:59'
// }
// if (days > 7 && days < 30) {
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[0]).endOf('month').format('YYYY-MM-DD') + ' 23:59:59'
// }
// if (months >= 1 && months <= 3) {
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[0]).add(4, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
// }
// if (months > 3 && months <= 6) {
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[0]).add(7, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
// }
// if (months > 6 && months <= 12) {
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[0]).add(13, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
// }
// if (months > 12) {
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
// obj.max = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).add(1, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
// }
// }
// console.log(obj)
this.initChart(obj)
}
} catch (err) {
this.loading = false
console.log(err)
}
},
foo() {
this.visible = false
this.$emit("foo");
this.dispose()
},
initChart(obj) {
this.chart = echarts.init(this.$refs.chartContainer);
// ...
const option = {
title: {
text: obj.title,
textStyle: {
color: "#fff"
}
},
tooltip: {
trigger: 'axis',
// formatter: function (params) {
// let index = obj.xAxisData.findIndex(item => item === params[0].value[0])
// let result = obj.visitName[index] + ' ' + params[0].value[0] + '<br>'; //
// params.forEach(function (item) {
// result += item.marker + ' ' + item.seriesName + ': ' + item.value[1] + '<br>'; //
// });
// return result;
// }
},
xAxis: {
// type: 'time',
// data: obj.xAxisData,
data: obj.visitName,
axisLine: { // x 线
lineStyle: {
color: '#fff',
}
},
axisLabel: { // x
textStyle: {
color: '#fff'
}
},
// splitLine: {
// show: false // 线
// },
// min: obj.min,
// max: obj.max
},
yAxis: {
name: obj.unit,
type: 'value',
axisLabel: {
textStyle: {
color: '#fff',
}
},
axisLine: {
lineStyle: {
color: '#fff',
}
},
},
series: obj.series
};
// 4. 使
this.chart.setOption(option);
},
resize() {
if (this.chart) {
this.chart.resize()
}
},
dispose() {
if (this.chart) {
this.chart.dispose()
this.chart = null
}
}
},
};
</script>
<style lang="scss" scoped>
.readingChart {
min-width: 500px;
max-width: 500px;
font-size: 14px;
display: inline-block;
background: #000;
border: 1px solid #ebeef5;
border-radius: 4px;
position: fixed;
padding: 10px 6px;
list-style-type: none;
min-height: 300px;
max-height: 80vh;
// overflow: hidden;
// overflow-y: auto;
box-sizing: border-box;
}
</style>

View File

@ -358,3 +358,17 @@ body .el-table th.gutter {
.el-message-box__wrapper { .el-message-box__wrapper {
z-index: 9999 !important; z-index: 9999 !important;
} }
.svg-readingChart {
width: 28px !important;
height: 30px !important;
margin-left: 10px;
cursor: pointer;
}
.svg-readingChart-mini {
width: 18px !important;
height: 20px !important;
vertical-align: -0.4em !important;
cursor: pointer;
}

View File

@ -361,6 +361,13 @@
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<!-- 图表展示-->
<el-form-item v-if="form.Type === 'number' || form.Type === 'calculation'"
:label="$t('trials:readingUnit:qsList:title:ShowChartTypeEnum')" prop="ShowChartTypeEnum">
<el-radio-group v-model="form.ShowChartTypeEnum">
<el-radio v-for="item of $d.ShowChartType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 表格类型标识 --> <!-- 表格类型标识 -->
<el-form-item v-if="form.Type === 'table'" :label="$t('dictionary:template:criterionConfig:table:tableType')" <el-form-item v-if="form.Type === 'table'" :label="$t('dictionary:template:criterionConfig:table:tableType')"
prop="LesionType"> prop="LesionType">
@ -552,6 +559,7 @@ export default {
FileType: [], FileType: [],
ClassifyQuestionId: null, ClassifyQuestionId: null,
ClassifyAlgorithms: null, ClassifyAlgorithms: null,
ShowChartTypeEnum: 0,
OptionTypeEnum: 0 OptionTypeEnum: 0
}, },
rules: { rules: {
@ -879,6 +887,7 @@ export default {
data.HighlightAnswerList = [] data.HighlightAnswerList = []
// data.ExportIdentification = 0 // data.ExportIdentification = 0
data.ExportResult = [] data.ExportResult = []
data.ShowChartTypeEnum = 0
data.FileType = [] data.FileType = []
data.ClassifyQuestionId = null data.ClassifyQuestionId = null
data.ClassifyAlgorithms = null data.ClassifyAlgorithms = null

View File

@ -289,6 +289,13 @@
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<!-- 图表展示-->
<el-form-item v-if="form.Type === 'number' || form.Type === 'calculation'"
:label="$t('trials:readingUnit:qsList:title:ShowChartTypeEnum')" prop="ShowChartTypeEnum">
<el-radio-group v-model="form.ShowChartTypeEnum">
<el-radio v-for="item of $d.ShowChartType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 最大上传个数 --> <!-- 最大上传个数 -->
<el-form-item v-if="form.Type === 'upload'" :label="$t('trials:readingUnit:qsList:title:imageCount')" <el-form-item v-if="form.Type === 'upload'" :label="$t('trials:readingUnit:qsList:title:imageCount')"
prop="ImageCount"> prop="ImageCount">
@ -442,6 +449,7 @@ export default {
// ExportIdentification: 0, // ExportIdentification: 0,
ExportResult: [], ExportResult: [],
DefaultValue: null, DefaultValue: null,
ShowChartTypeEnum: 0,
OptionTypeEnum: 0 OptionTypeEnum: 0
// IsEnable: true // IsEnable: true
}, },
@ -769,6 +777,7 @@ export default {
// form.ExportIdentification = 0 // form.ExportIdentification = 0
form.ExportResult = [] form.ExportResult = []
form.DefaultValue = null form.DefaultValue = null
form.ShowChartTypeEnum = 0
form.OptionTypeEnum = 0 form.OptionTypeEnum = 0
}, },
close() { close() {

View File

@ -475,6 +475,7 @@
:question-form-change-num="questionFormChangeNum" :question-form-change-num="questionFormChangeNum"
:is-show="isShow" :is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :is-reading-show-subject-info="isReadingShowSubjectInfo"
@handleReadingChart="handleReadingChart"
/> />
<IVUSList <IVUSList
@ -1229,6 +1230,9 @@ export default {
}) })
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
getTrialCriterion() { getTrialCriterion() {
getCriterionReadingInfo({ getCriterionReadingInfo({
TrialId: this.trialId || this.$route.query.trialId, TrialId: this.trialId || this.$route.query.trialId,

View File

@ -25,13 +25,22 @@
:class="[question.Type === 'group' ? 'mb' : (question.Type === 'upload' || question.QuestionName.length > 15) ? 'uploadWrapper' : '']"> :class="[question.Type === 'group' ? 'mb' : (question.Type === 'upload' || question.QuestionName.length > 15) ? 'uploadWrapper' : '']">
<template v-if="question.QuestionType === 60 || question.QuestionType === 61"> <template v-if="question.QuestionType === 60 || question.QuestionType === 61">
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;"> <div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
<div style="display: flex;justify-content: space-between;" v-if="question.Type === 'calculation'">
<el-input v-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled <el-input v-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled
style="width: 130px;"> style="width: 130px;">
<template v-if="question.Unit" slot="append"> <template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }} {{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart"
class="svg-icon svg-readingChart" @click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: question.Id,
QuestionName: question.QuestionName
}
})" />
</div>
<!-- 测量 --> <!-- 测量 -->
<el-button v-if="!questionForm[question.Id] && readingTaskState !== 2" size="mini" type="text" <el-button v-if="!questionForm[question.Id] && readingTaskState !== 2" size="mini" type="text"
@click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation') }}</el-button> @click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation') }}</el-button>
@ -55,11 +64,22 @@
<template <template
v-else-if="question.QuestionType === 48 || question.QuestionType === 51 || question.QuestionType === 52 || question.QuestionType === 53"> v-else-if="question.QuestionType === 48 || question.QuestionType === 51 || question.QuestionType === 52 || question.QuestionType === 53">
<div style="display: flex;justify-content: space-between;" v-if="question.Type === 'calculation'">
<el-input v-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled> <el-input v-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled>
<template v-if="question.Unit" slot="append"> <template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }} {{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: question.Id,
QuestionName: question.QuestionName
}
})" />
</div>
</template> </template>
<!-- 输入框 --> <!-- 输入框 -->
@ -146,7 +166,9 @@
:disabled="readingTaskState >= 2 || isFirstChangeTask" :disabled="readingTaskState >= 2 || isFirstChangeTask"
:precision="2" :precision="2"
/> --> /> -->
<template v-else-if="question.Type === 'number'"> <div style="display: flex;justify-content: space-between;"
v-else-if="question.Type === 'number' || question.Type === 'calculation'">
<template v-if="question.Type === 'number'">
<el-input-number v-if="question.ValueType === 0" v-model="questionForm[question.Id]" :precision="0" <el-input-number v-if="question.ValueType === 0" v-model="questionForm[question.Id]" :precision="0"
:disabled="readingTaskState >= 2 || isFirstChangeTask" /> :disabled="readingTaskState >= 2 || isFirstChangeTask" />
<el-input-number v-else-if="question.ValueType === 3" v-model="questionForm[question.Id]" <el-input-number v-else-if="question.ValueType === 3" v-model="questionForm[question.Id]"
@ -160,6 +182,15 @@
{{ $fd('ValueUnit', parseInt(question.Unit)) }} {{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: question.Id,
QuestionName: question.QuestionName
}
})" />
</div>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload v-else-if="question.Type === 'upload'" action :accept="accept" :limit="question.ImageCount" <el-upload v-else-if="question.Type === 'upload'" action :accept="accept" :limit="question.ImageCount"
:on-preview="handlePictureCardPreview" :before-upload="handleBeforeUpload" :http-request="uploadScreenshot" :on-preview="handlePictureCardPreview" :before-upload="handleBeforeUpload" :http-request="uploadScreenshot"

View File

@ -16,6 +16,7 @@
:visit-task-id="visitTaskId" :visit-task-id="visitTaskId"
@setFormItemData="setFormItemData" @setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData" @resetFormItemData="resetFormItemData"
@handleReadingChart="handleReadingChart"
/> />
<el-form-item v-if="readingTaskState < 2 && !isFirstChangeTask"> <el-form-item v-if="readingTaskState < 2 && !isFirstChangeTask">
@ -150,6 +151,9 @@ export default {
} }
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
async getQuestions(visitTaskId, isRefresh = false) { async getQuestions(visitTaskId, isRefresh = false) {
var isChangeVisitTask = this.visitTaskId !== visitTaskId var isChangeVisitTask = this.visitTaskId !== visitTaskId
this.visitTaskId = visitTaskId this.visitTaskId = visitTaskId

View File

@ -36,10 +36,12 @@
:is-exists-clinical-data="isExistsClinicalData" :is-exists-no-dicom-file="isExistsNoDicomFile" :is-exists-clinical-data="isExistsClinicalData" :is-exists-no-dicom-file="isExistsNoDicomFile"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :is-reading-show-subject-info="isReadingShowSubjectInfo"
:is-reading-task-view-in-order="isReadingTaskViewInOrder" :is-exists-manual="isExistsManual" :is-reading-task-view-in-order="isReadingTaskViewInOrder" :is-exists-manual="isExistsManual"
:iseCRFShowInDicomReading="iseCRFShowInDicomReading" @previewCD="previewCD" /> :iseCRFShowInDicomReading="iseCRFShowInDicomReading" @previewCD="previewCD"
@handleReadingChart="handleReadingChart" />
</div> </div>
</div> </div>
<readingChart ref="readingChart" />
</div> </div>
</template> </template>
<script> <script>
@ -54,6 +56,7 @@ import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core' import * as cornerstone from 'cornerstone-core'
import { workSpeedclose } from "@/utils" import { workSpeedclose } from "@/utils"
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import readingChart from '@/components/readingChart'
// import metaDataProvider from '@/utils/metaDataProvider' // import metaDataProvider from '@/utils/metaDataProvider'
// cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 }); // cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
var config = { var config = {
@ -74,7 +77,8 @@ export default {
name: 'ReadPage', name: 'ReadPage',
components: { components: {
DicomViewer, DicomViewer,
StudyList StudyList,
readingChart
}, },
props: { props: {
trialId: { trialId: {
@ -216,6 +220,7 @@ export default {
window.addEventListener('beforeunload', e => { window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache() cornerstone.imageCache.purgeCache()
}) })
document.addEventListener("click", this.foo);
}, },
beforeDestroy() { beforeDestroy() {
cornerstone.imageCache.purgeCache() cornerstone.imageCache.purgeCache()
@ -229,6 +234,21 @@ export default {
workSpeedclose(true) workSpeedclose(true)
}, },
methods: { methods: {
handleReadingChart(row) {
let { e, data } = row
let obj = Object.assign({}, data)
obj.TrialId = this.$route.query.trialId
obj.VisitTaskId = this.visitTaskId
let zIndex = 9
if (obj.RowIndex) {
zIndex = 9999
}
this.$refs.readingChart.init(e, obj, zIndex)
},
foo() {
if (!this.$refs.readingChart) return false
this.$refs.readingChart.foo()
},
async getVisitInfo() { async getVisitInfo() {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })

View File

@ -64,7 +64,7 @@
<!-- 输入框 --> <!-- 输入框 -->
<template v-if="qs.Type==='input' || qs.Type==='number'"> <template v-if="qs.Type==='input' || qs.Type==='number'">
<!-- {{ ((qs.QuestionMark === 6 && isCurrentTaskAdd === 'False') || (qs.QuestionMark === 6 && isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition)) }} --> <div style="display: flex;justify-content: space-between;">
<el-input <el-input
v-if="qs.Type==='input' || qs.Type==='number'" v-if="qs.Type==='input' || qs.Type==='number'"
v-model="questionForm[qs.Id]" v-model="questionForm[qs.Id]"
@ -75,6 +75,17 @@
{{ $fd('ValueUnit', parseInt(qs.Unit)) }} {{ $fd('ValueUnit', parseInt(qs.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="qs.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
TableQuestionId: qs.Id,
RowIndex: questionForm.RowIndex,
QuestionName: qs.QuestionName
}
})" />
</div>
<!-- {{ ((qs.QuestionMark === 6 && isCurrentTaskAdd === 'False') || (qs.QuestionMark === 6 && isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition)) }} -->
</template> </template>
<!-- 多行文本输入框 --> <!-- 多行文本输入框 -->
<el-input <el-input
@ -307,6 +318,9 @@ export default {
DicomEvent.$off('handleImageQualityAbnormal') DicomEvent.$off('handleImageQualityAbnormal')
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
async initForm() { async initForm() {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
this.questions.forEach(item => { this.questions.forEach(item => {

View File

@ -19,7 +19,7 @@
<!-- 非测量问题 --> <!-- 非测量问题 -->
<div class="lesions"> <div class="lesions">
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" /> <Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" @handleReadingChart="handleReadingChart"/>
</div> </div>
<!-- 测量问题 --> <!-- 测量问题 -->
<template v-if="questions.length > 0 && CriterionType !== 10"> <template v-if="questions.length > 0 && CriterionType !== 10">
@ -30,7 +30,16 @@
<div class="lesion_list"> <div class="lesion_list">
<div v-for="item in qs.Childrens" v-show="!(isBaseLineTask && item.LesionType === 2)" :key="item.Id"> <div v-for="item in qs.Childrens" v-show="!(isBaseLineTask && item.LesionType === 2)" :key="item.Id">
<div v-if="item.Type === 'table'" class="flex-row" style="margin:3px 0;"> <div v-if="item.Type === 'table'" class="flex-row" style="margin:3px 0;">
<div class="title">{{ item.QuestionName }}</div> <div class="title">{{ item.QuestionName }}
<svg-icon v-if="item.LesionType === 0" icon-class="readingChart"
class="svg-icon svg-readingChart-mini" @click.stop="(e) => handleReadingChart({
e,
data: {
ReportChartTypeEnum: 0,
QuestionName: item.QuestionName
},
})" />
</div>
<div v-if="readingTaskState<2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon" @click.prevent="handleAdd(item)"> <div v-if="readingTaskState<2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon" @click.prevent="handleAdd(item)">
<i class="el-icon-plus" /> <i class="el-icon-plus" />
</div> </div>
@ -120,6 +129,7 @@
@determineExistsUnsavedLession="determineExistsUnsavedLession" @determineExistsUnsavedLession="determineExistsUnsavedLession"
@resetQuestions="resetQuestions" @resetQuestions="resetQuestions"
@close="close" @close="close"
@handleReadingChart="handleReadingChart"
/> />
</el-collapse-item> </el-collapse-item>
@ -240,6 +250,9 @@ export default {
DicomEvent.$off('getUnSaveTarget') DicomEvent.$off('getUnSaveTarget')
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
async initList() { async initList() {
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId) var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId)
if (i > -1) { if (i > -1) {

View File

@ -69,7 +69,20 @@
width="350px" width="350px"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="scope.row.QuestionName" :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) ? '#f66' : '#fff'}">{{ scope.row.QuestionName }}</span> <span v-if="scope.row.QuestionName" :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) ? '#f66' : '#fff'}">{{ scope.row.QuestionName }}
<svg-icon
v-if="scope.row.ShowChartTypeEnum > 0 || (scope.row.LesionType === 0 && scope.row.ReportLayType === 1) || (scope.row.LesionType === 4 && scope.row.ReportLayType === 1)"
icon-class="readingChart" class="svg-icon svg-readingChart-mini" @click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: scope.row.RowIndex ? null : scope.row.QuestionId,
TableQuestionId: scope.row.RowIndex ? scope.row.TableQuestionId : null,
RowIndex: scope.row.RowIndex ? scope.row.RowIndex : null,
ReportChartTypeEnum: (scope.row.LesionType === 0 && scope.row.ReportLayType === 1) ? 0 : (scope.row.LesionType === 4 && scope.row.ReportLayType === 1) ? 1 : null,
QuestionName: scope.row.QuestionName
}
})" />
</span>
<span <span
v-else v-else
style="font-weight: bold;font-size: 16px;color: #f44336;" style="font-weight: bold;font-size: 16px;color: #f44336;"
@ -266,6 +279,7 @@
</div> </div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" /> <SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog> </el-dialog>
<readingChart ref="readingChart_report" />
</div> </div>
</template> </template>
<script> <script>
@ -280,9 +294,10 @@ import store from '@/store'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import AdditionalAssessment from './AdditionalAssessment' import AdditionalAssessment from './AdditionalAssessment'
import readingChart from '@/components/readingChart'
export default { export default {
name: 'ReportPage', name: 'ReportPage',
components: { SignForm, AdditionalAssessment }, components: { SignForm, AdditionalAssessment, readingChart },
props: { props: {
visitTaskId: { visitTaskId: {
type: String, type: String,
@ -352,6 +367,7 @@ export default {
} }
}) })
this.getReportInfo() this.getReportInfo()
document.addEventListener("click", this.foo);
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('getReportInfo') DicomEvent.$off('getReportInfo')
@ -361,6 +377,22 @@ export default {
} }
}, },
methods: { methods: {
handleReadingChart(row) {
let { e, data } = row
let obj = Object.assign({}, data)
obj.TrialId = this.$route.query.trialId
obj.VisitTaskId = this.visitTaskId
obj.key = 'readingChart_report'
let zIndex = 9
if (obj.RowIndex) {
zIndex = 9999
}
this.$refs.readingChart_report.init(e, obj, zIndex)
},
foo() {
if (!this.$refs.readingChart_report) return false
this.$refs.readingChart_report.foo()
},
myConfirm(msg) { myConfirm(msg) {
return new Promise(resolve => { return new Promise(resolve => {
this.$confirm(msg, { this.$confirm(msg, {

View File

@ -461,6 +461,7 @@
@resetAnnotations="resetAnnotations" @resetAnnotations="resetAnnotations"
@getAnnotations="getAnnotations" @getAnnotations="getAnnotations"
@setToolToTarget="setToolToTarget" @setToolToTarget="setToolToTarget"
@handleReadingChart="handleReadingChart"
/> />
<customize-question-list <customize-question-list
v-else-if="lastViewportTaskId && criterionType === 0 && lastViewportTaskIds.includes(s.VisitTaskId)" v-else-if="lastViewportTaskId && criterionType === 0 && lastViewportTaskIds.includes(s.VisitTaskId)"
@ -590,6 +591,7 @@
:task-id="taskId" :task-id="taskId"
:visible.sync="downloadImageVisible" :visible.sync="downloadImageVisible"
/> />
<readingChart ref="readingChart" />
</div> </div>
</template> </template>
<script> <script>
@ -634,6 +636,7 @@ import RectangleROITool from './tools/RectangleROITool'
import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom' import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom' import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
import { getNetWorkSpeed, setNetWorkSpeedSizeAll, workSpeedclose } from "@/utils" import { getNetWorkSpeed, setNetWorkSpeedSizeAll, workSpeedclose } from "@/utils"
import readingChart from '@/components/readingChart'
const { visibility } = annotation const { visibility } = annotation
const { ViewportType, Events } = Enums const { ViewportType, Events } = Enums
const renderingEngineId = 'myRenderingEngine' const renderingEngineId = 'myRenderingEngine'
@ -706,6 +709,7 @@ export default {
colorMap, colorMap,
downloadDicomAndNonedicom, downloadDicomAndNonedicom,
uploadDicomAndNonedicom, uploadDicomAndNonedicom,
readingChart
}, },
props: { props: {
readingTool: { readingTool: {
@ -912,8 +916,24 @@ export default {
DicomEvent.$on('addNoneDicomMeasureData', data => { DicomEvent.$on('addNoneDicomMeasureData', data => {
this.open.postMessage({ type: 'addNoneDicomMeasureData', data: data }, window.location) this.open.postMessage({ type: 'addNoneDicomMeasureData', data: data }, window.location)
}) })
document.addEventListener("click", this.foo);
}, },
methods: { methods: {
handleReadingChart(row) {
let { e, data } = row
let obj = Object.assign({}, data)
obj.TrialId = this.$route.query.trialId
obj.VisitTaskId = this.taskInfo.VisitTaskId
let zIndex = 9
if (obj.RowIndex) {
zIndex = 9999
}
this.$refs.readingChart.init(e, obj, zIndex)
},
foo() {
if (!this.$refs.readingChart) return false
this.$refs.readingChart.foo()
},
// //
async loadRelatedTasks() { async loadRelatedTasks() {
this.loading = true this.loading = true

View File

@ -65,8 +65,10 @@
{{ val }} {{ val }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<div style="display: flex;justify-content: space-between;"
v-else-if="question.Type === 'number' || question.Type === 'calculation'">
<!-- 数值 --> <!-- 数值 -->
<template v-else-if="question.Type === 'number'"> <template v-if="question.Type === 'number'">
<el-input-number v-if="question.ValueType === 0" v-model="questionForm[question.Id]" :precision="0" <el-input-number v-if="question.ValueType === 0" v-model="questionForm[question.Id]" :precision="0"
:disabled="readingTaskState >= 2" /> :disabled="readingTaskState >= 2" />
<el-input-number v-else-if="question.ValueType === 3" v-model="questionForm[question.Id]" <el-input-number v-else-if="question.ValueType === 3" v-model="questionForm[question.Id]"
@ -79,6 +81,15 @@
{{ $fd('ValueUnit', parseInt(question.Unit)) }} {{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: question.Id,
QuestionName: question.QuestionName
}
})" />
</div>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload v-else-if="question.Type === 'upload'" action :accept="accept" :limit="question.ImageCount" <el-upload v-else-if="question.Type === 'upload'" action :accept="accept" :limit="question.ImageCount"
:on-preview="handlePictureCardPreview" :before-upload="handleBeforeUpload" :http-request="uploadScreenshot" :on-preview="handlePictureCardPreview" :before-upload="handleBeforeUpload" :http-request="uploadScreenshot"
@ -167,6 +178,9 @@ export default {
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
}, },
methods: { methods: {
handleReadingChart(row) {
this.$emit('handleReadingChart', row)
},
formItemChange(v, question) { formItemChange(v, question) {
console.log('formItemChange') console.log('formItemChange')
if (question.Childrens.length > 0) { if (question.Childrens.length > 0) {

View File

@ -20,7 +20,7 @@
<el-form ref="outerForm" size="small" :model="outerForm"> <el-form ref="outerForm" size="small" :model="outerForm">
<question-form-item v-for="outerQs in outerQuestions" :key="outerQs.Id" :question="outerQs" <question-form-item v-for="outerQs in outerQuestions" :key="outerQs.Id" :question="outerQs"
:question-form="outerForm" :reading-task-state="readingTaskState" :visit-task-id="visitTaskId" :question-form="outerForm" :reading-task-state="readingTaskState" :visit-task-id="visitTaskId"
@resetFormItemData="resetOuterFormItemData" @setFormItemData="setOuterFormItemData" /> @resetFormItemData="resetOuterFormItemData" @setFormItemData="setOuterFormItemData" @handleReadingChart="handleReadingChart"/>
<el-form-item v-if="readingTaskState < 2"> <el-form-item v-if="readingTaskState < 2">
<div class="outer_form-footer"> <div class="outer_form-footer">
<i class="el-icon-warning feedback-icon" <i class="el-icon-warning feedback-icon"
@ -40,7 +40,16 @@
<div class="lesion_list"> <div class="lesion_list">
<div v-for="table in qs.Childrens" v-show="!(isBaseLineTask && table.LesionType === 2)" :key="table.Id"> <div v-for="table in qs.Childrens" v-show="!(isBaseLineTask && table.LesionType === 2)" :key="table.Id">
<div v-if="table.Type === 'table'" class="flex-row" style="margin:3px 0;"> <div v-if="table.Type === 'table'" class="flex-row" style="margin:3px 0;">
<div class="title">{{ table.QuestionName }}</div> <div class="title">{{ table.QuestionName }}
<svg-icon v-if="table.LesionType === 0" icon-class="readingChart"
class="svg-icon svg-readingChart-mini" @click.stop="(e) => handleReadingChart({
e,
data: {
ReportChartTypeEnum: 0,
QuestionName: table.QuestionName
},
})" />
</div>
<div v-if="readingTaskState < 2 && (isBaseLineTask || table.LesionType === 2)" class="add-icon" <div v-if="readingTaskState < 2 && (isBaseLineTask || table.LesionType === 2)" class="add-icon"
@click.prevent="addTarget(table)"> @click.prevent="addTarget(table)">
<i class="el-icon-plus" /> <i class="el-icon-plus" />
@ -129,7 +138,7 @@
:answer="answer" :question-form="innerFormData[`${table.Id}_${answer.RowIndex}`]" :answer="answer" :question-form="innerFormData[`${table.Id}_${answer.RowIndex}`]"
:reading-task-state="readingTaskState" :organs="organs" :is-base-line-task="isBaseLineTask" :reading-task-state="readingTaskState" :organs="organs" :is-base-line-task="isBaseLineTask"
:is-current-task="isCurrentTask" @update="innerFormDataUpdate" @close="closeInnerForm" :is-current-task="isCurrentTask" @update="innerFormDataUpdate" @close="closeInnerForm"
@lesionTypeChange="lesionTypeChange" /> @lesionTypeChange="lesionTypeChange" @handleReadingChart="handleReadingChart"/>
<div v-if="readingTaskState < 2" style="text-align:right;margin-top:10px;"> <div v-if="readingTaskState < 2" style="text-align:right;margin-top:10px;">
<!-- 清除标记 --> <!-- 清除标记 -->
<el-button v-if="innerFormData[`${table.Id}_${answer.RowIndex}`].MeasureData" size="mini" <el-button v-if="innerFormData[`${table.Id}_${answer.RowIndex}`].MeasureData" size="mini"
@ -246,6 +255,9 @@ export default {
window.addEventListener('message', this.receiveMsg) window.addEventListener('message', this.receiveMsg)
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
// //
async getOrganList() { async getOrganList() {
try { try {

View File

@ -47,7 +47,7 @@
> >
<!-- 输入框 --> <!-- 输入框 -->
<template v-if="qs.Type==='input' || qs.Type==='number'"> <template v-if="qs.Type==='input' || qs.Type==='number'">
<div style="display: flex;justify-content: space-between;">
<el-input <el-input
v-if="qs.Type==='input' || qs.Type==='number'" v-if="qs.Type==='input' || qs.Type==='number'"
v-model="qsForm[qs.Id]" v-model="qsForm[qs.Id]"
@ -58,6 +58,17 @@
{{ $fd('ValueUnit', parseInt(qs.Unit)) }} {{ $fd('ValueUnit', parseInt(qs.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="qs.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
TableQuestionId: qs.Id,
RowIndex: qsForm.RowIndex,
QuestionName: question.QuestionName
}
})" />
</div>
</template> </template>
<!-- 多行文本输入框 --> <!-- 多行文本输入框 -->
<el-input <el-input
@ -254,6 +265,9 @@ export default {
} }
}, },
methods: { methods: {
handleReadingChart(row) {
this.$emit('handleReadingChart', row)
},
lesionTypeChange(v) { lesionTypeChange(v) {
this.$emit('lesionTypeChange', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, newLesionType: v }) this.$emit('lesionTypeChange', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, newLesionType: v })
}, },

View File

@ -266,6 +266,7 @@
</div> </div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" /> <SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog> </el-dialog>
<readingChart ref="readingChart_report" />
</div> </div>
</template> </template>
<script> <script>
@ -279,9 +280,10 @@ import { getToken } from '@/utils/auth'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import AdditionalAssessment from '@/views/trials/trials-panel/reading/dicoms/components/AdditionalAssessment' import AdditionalAssessment from '@/views/trials/trials-panel/reading/dicoms/components/AdditionalAssessment'
import readingChart from '@/components/readingChart'
export default { export default {
name: 'ReportPage', name: 'ReportPage',
components: { SignForm, AdditionalAssessment }, components: { SignForm, AdditionalAssessment, readingChart },
data() { data() {
return { return {
currentUser: zzSessionStorage.getItem('userName'), currentUser: zzSessionStorage.getItem('userName'),
@ -336,6 +338,7 @@ export default {
this.setScrollTop() this.setScrollTop()
}) })
this.getReportInfo() this.getReportInfo()
document.addEventListener("click", this.foo);
}, },
beforeDestroy() { beforeDestroy() {
if (this.openWindow) { if (this.openWindow) {
@ -343,6 +346,22 @@ export default {
} }
}, },
methods: { methods: {
handleReadingChart(row) {
let { e, data } = row
let obj = Object.assign({}, data)
obj.TrialId = this.$route.query.trialId
obj.VisitTaskId = this.taskInfo.VisitTaskId
obj.key = 'readingChart_report'
let zIndex = 9
if (obj.RowIndex) {
zIndex = 9999
}
this.$refs.readingChart_report.init(e, obj, zIndex)
},
foo() {
if (!this.$refs.readingChart_report) return false
this.$refs.readingChart_report.foo()
},
myConfirm(msg) { myConfirm(msg) {
return new Promise(resolve => { return new Promise(resolve => {
this.$confirm(msg, { this.$confirm(msg, {

View File

@ -469,6 +469,13 @@
}} }}
</div> </div>
</div> </div>
<!-- 图表展示-->
<el-form-item v-if="(form.Type === 'number' || form.Type === 'calculation') && !isFromSystem"
:label="$t('trials:readingUnit:qsList:title:ShowChartTypeEnum')" prop="ShowChartTypeEnum">
<el-radio-group v-model="form.ShowChartTypeEnum">
<el-radio v-for="item of $d.ShowChartType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 影像标记:disabled="form.IsRequired === 0" --> <!-- 影像标记:disabled="form.IsRequired === 0" -->
<el-form-item v-if="form.Type === 'number' && !isFromSystem && readingVersionEnum" <el-form-item v-if="form.Type === 'number' && !isFromSystem && readingVersionEnum"
:label="$t('trials:readingUnit:qsList:title:imageMarkEnum')" prop="ImageMarkEnum"> :label="$t('trials:readingUnit:qsList:title:imageMarkEnum')" prop="ImageMarkEnum">
@ -747,6 +754,7 @@ export default {
ClassifyEditType: null, ClassifyEditType: null,
ClassifyShowType: null, ClassifyShowType: null,
ImageMarkEnum: 0, ImageMarkEnum: 0,
ShowChartTypeEnum: 0,
ImageTool: '', ImageTool: '',
ImageToolAttribute: '', ImageToolAttribute: '',
ExcludeShowVisitList: [], ExcludeShowVisitList: [],
@ -1257,6 +1265,7 @@ export default {
form.ClassifyType = null form.ClassifyType = null
form.ClassifyShowType = null form.ClassifyShowType = null
form.ImageMarkEnum = 0 form.ImageMarkEnum = 0
form.ShowChartTypeEnum = 0
form.ImageTool = '' form.ImageTool = ''
form.ImageToolAttribute = '' form.ImageToolAttribute = ''
form.OptionTypeEnum = 0 form.OptionTypeEnum = 0

View File

@ -271,6 +271,13 @@
$t('trials:readingUnit:qsList:message:msg1') : $t('trials:readingUnit:qsList:message:msg2') }} $t('trials:readingUnit:qsList:message:msg1') : $t('trials:readingUnit:qsList:message:msg2') }}
</div> </div>
</div> </div>
<!-- 图表展示-->
<el-form-item v-if="(form.Type === 'number' || form.Type === 'calculation') && !isFromSystem"
:label="$t('trials:readingUnit:qsList:title:ShowChartTypeEnum')" prop="ShowChartTypeEnum">
<el-radio-group v-model="form.ShowChartTypeEnum">
<el-radio v-for="item of $d.ShowChartType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 影像标记:disabled="form.IsRequired === 0" --> <!-- 影像标记:disabled="form.IsRequired === 0" -->
<el-form-item v-if="form.Type === 'number' && !isFromSystem && readingVersionEnum" <el-form-item v-if="form.Type === 'number' && !isFromSystem && readingVersionEnum"
:label="$t('trials:readingUnit:qsList:title:imageMarkEnum')" prop="ImageMarkEnum"> :label="$t('trials:readingUnit:qsList:title:imageMarkEnum')" prop="ImageMarkEnum">
@ -610,6 +617,7 @@ export default {
ClassifyEditType: null, ClassifyEditType: null,
ClassifyShowType: null, ClassifyShowType: null,
ImageMarkEnum: 0, ImageMarkEnum: 0,
ShowChartTypeEnum: 0,
ImageTool: '', ImageTool: '',
ImageToolAttribute: '', ImageToolAttribute: '',
OptionTypeEnum: 0 OptionTypeEnum: 0
@ -1121,6 +1129,7 @@ export default {
form.ClassifyType = null form.ClassifyType = null
form.ClassifyShowType = null form.ClassifyShowType = null
form.ImageMarkEnum = 0 form.ImageMarkEnum = 0
form.ShowChartTypeEnum = 0
form.ImageTool = '' form.ImageTool = ''
form.ImageToolAttribute = '' form.ImageToolAttribute = ''
form.OptionTypeEnum = 0 form.OptionTypeEnum = 0