非dicom图像阅片更改
parent
e7dcdb33c4
commit
734d6dc1a5
|
@ -3940,8 +3940,6 @@ export function updateTrialUserRole(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 获取报表配置
|
// 获取报表配置
|
||||||
export function getTrialQuestionExportResult(data) {
|
export function getTrialQuestionExportResult(data) {
|
||||||
return request({
|
return request({
|
||||||
|
@ -3965,4 +3963,29 @@ export function trialUserSendJoinEmail(data) {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取非Dicom标记
|
||||||
|
export function getNoneDicomMarkListOutDto(data) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingImageTask/getNoneDicomMarkListOutDto`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 添加非Dicom标记
|
||||||
|
export function addNoneDicomMark(data) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingImageTask/addNoneDicomMark`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 删除非Dicom标记
|
||||||
|
export function deleteTrialFileType(id) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingImageTask/deleteTrialFileType/${id}`,
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,15 @@ import 'nprogress/nprogress.css'
|
||||||
import { getToken, removeToken } from '@/utils/auth'
|
import { getToken, removeToken } from '@/utils/auth'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { OSSclient } from './utils/oss'
|
import { OSSclient } from './utils/oss'
|
||||||
import WHITELIST from "./utils/whiteList"
|
import WHITELIST from './utils/whiteList'
|
||||||
import { getTrialExtralConfig } from '@/api/trials'
|
import { getTrialExtralConfig } from '@/api/trials'
|
||||||
// import getPageTitle from '@/utils/get-page-title'
|
// import getPageTitle from '@/utils/get-page-title'
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false })
|
NProgress.configure({ showSpinner: false })
|
||||||
|
|
||||||
const whiteList = WHITELIST
|
const whiteList = WHITELIST
|
||||||
store.state.trials.whiteList = whiteList;
|
store.state.trials.whiteList = whiteList
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async(to, from, next) => {
|
||||||
NProgress.start()
|
NProgress.start()
|
||||||
// 设置页面标题
|
// 设置页面标题
|
||||||
// document.title = getPageTitle(to.meta.title) store.state.trials.whiteList.indexOf(to.path) === -1
|
// document.title = getPageTitle(to.meta.title) store.state.trials.whiteList.indexOf(to.path) === -1
|
||||||
|
@ -27,13 +27,13 @@ router.beforeEach(async (to, from, next) => {
|
||||||
to.query.trialId !==
|
to.query.trialId !==
|
||||||
store.state.trials.config.trialId
|
store.state.trials.config.trialId
|
||||||
) {
|
) {
|
||||||
let res = await getTrialExtralConfig({
|
const res = await getTrialExtralConfig({
|
||||||
TrialId: to.query.trialId,
|
TrialId: to.query.trialId
|
||||||
})
|
})
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
store.dispatch('trials/setConfig', {
|
store.dispatch('trials/setConfig', {
|
||||||
trialId: to.query.trialId,
|
trialId: to.query.trialId,
|
||||||
...res.Result,
|
...res.Result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,13 +45,13 @@ router.beforeEach(async (to, from, next) => {
|
||||||
to.query.trialId !==
|
to.query.trialId !==
|
||||||
store.state.trials.config.trialId
|
store.state.trials.config.trialId
|
||||||
) {
|
) {
|
||||||
let res = await getTrialExtralConfig({
|
const res = await getTrialExtralConfig({
|
||||||
TrialId: to.query.trialId,
|
TrialId: to.query.trialId
|
||||||
})
|
})
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
store.dispatch('trials/setConfig', {
|
store.dispatch('trials/setConfig', {
|
||||||
trialId: to.query.trialId,
|
trialId: to.query.trialId,
|
||||||
...res.Result,
|
...res.Result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,12 +72,12 @@ router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else if (from.path === '/researchForm') {
|
} else if (from.path === '/researchForm') {
|
||||||
removeToken()
|
removeToken()
|
||||||
let lang = to.query.lang || zzSessionStorage.getItem('lang')
|
const lang = to.query.lang || zzSessionStorage.getItem('lang')
|
||||||
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
|
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else if (from.path === '/researchDetail_m') {
|
} else if (from.path === '/researchDetail_m') {
|
||||||
removeToken()
|
removeToken()
|
||||||
let lang = to.query.lang || zzSessionStorage.getItem('lang')
|
const lang = to.query.lang || zzSessionStorage.getItem('lang')
|
||||||
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
|
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,7 +107,7 @@ router.beforeEach(async (to, from, next) => {
|
||||||
/* has no token*/
|
/* has no token*/
|
||||||
if (whiteList.indexOf(to.path) !== -1) {
|
if (whiteList.indexOf(to.path) !== -1) {
|
||||||
if (to.path === '/researchLogin') {
|
if (to.path === '/researchLogin') {
|
||||||
let lang = to.query.lang || zzSessionStorage.getItem('lang')
|
const lang = to.query.lang || zzSessionStorage.getItem('lang')
|
||||||
const flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
|
const flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
|
||||||
if (flag) {
|
if (flag) {
|
||||||
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
|
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
|
||||||
|
@ -123,11 +123,11 @@ router.beforeEach(async (to, from, next) => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (to.path === '/researchForm') {
|
if (to.path === '/researchForm') {
|
||||||
let lang = to.query.lang || zzSessionStorage.getItem('lang')
|
const lang = to.query.lang || zzSessionStorage.getItem('lang')
|
||||||
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
|
next(`/researchLogin?trialId=${to.query.trialId}&lang=${lang}`)
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else if (to.path === '/researchDetail_m') {
|
} else if (to.path === '/researchDetail_m') {
|
||||||
let lang = to.query.lang || zzSessionStorage.getItem('lang')
|
const lang = to.query.lang || zzSessionStorage.getItem('lang')
|
||||||
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
|
next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${lang}`)
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
} else if (to.path === '/ReviewersResearchForm') {
|
} else if (to.path === '/ReviewersResearchForm') {
|
||||||
|
|
|
@ -0,0 +1,347 @@
|
||||||
|
<template>
|
||||||
|
<div ref="container" v-loading="loading" class="none-dicom-reading-container">
|
||||||
|
<!-- 访视阅片 -->
|
||||||
|
<div v-if="isShow && readingCategory && readingCategory=== 1" class="reading-wrapper">
|
||||||
|
<el-tabs v-model="activeName" :before-leave="beforeLeave">
|
||||||
|
<!-- 阅片 -->
|
||||||
|
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||||
|
<VisitReview
|
||||||
|
:trial-id="trialId"
|
||||||
|
:subject-id="subjectId"
|
||||||
|
:subject-code="subjectCode"
|
||||||
|
:visit-task-id="visitTaskId"
|
||||||
|
:task-blind-name="taskBlindName"
|
||||||
|
:reading-category="readingCategory"
|
||||||
|
:readingTool="readingTool"
|
||||||
|
:criterionType="criterionType"
|
||||||
|
:isExistsClinicalData="isExistsClinicalData"
|
||||||
|
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
|
||||||
|
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||||
|
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||||
|
@previewCD="previewCD"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<!-- 报告 -->
|
||||||
|
<el-tab-pane :label="$t('trials:reading:tabTitle:report')" name="report" v-if="!iseCRFShowInDicomReading">
|
||||||
|
<Report
|
||||||
|
v-if="tabs.includes('report')"
|
||||||
|
ref="reportPage"
|
||||||
|
:trialId="trialId"
|
||||||
|
:visit-task-id="visitTaskId"
|
||||||
|
:subject-id="subjectId"
|
||||||
|
:readingTool="readingTool"
|
||||||
|
:criterionType="criterionType"
|
||||||
|
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 全局阅片 -->
|
||||||
|
<GlobalReview
|
||||||
|
v-else-if="isShow && readingCategory && readingCategory === 2"
|
||||||
|
:trial-id="trialId"
|
||||||
|
:subject-id="subjectId"
|
||||||
|
:visit-task-id="visitTaskId"
|
||||||
|
:reading-category="readingCategory"
|
||||||
|
:subject-code="subjectCode"
|
||||||
|
:task-blind-name="taskBlindName"
|
||||||
|
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||||
|
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
||||||
|
:is-exists-clinical-data="isExistsClinicalData"
|
||||||
|
/>
|
||||||
|
<!-- 裁判阅片 -->
|
||||||
|
<AdReview
|
||||||
|
v-else-if="isShow && readingCategory && readingCategory === 4"
|
||||||
|
:trial-id="trialId"
|
||||||
|
:subject-id="subjectId"
|
||||||
|
:visit-task-id="visitTaskId"
|
||||||
|
:reading-category="readingCategory"
|
||||||
|
:subject-code="subjectCode"
|
||||||
|
:task-blind-name="taskBlindName"
|
||||||
|
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||||
|
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
||||||
|
:is-exists-clinical-data="isExistsClinicalData"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 肿瘤学阅片 -->
|
||||||
|
<OncologyReview
|
||||||
|
v-else-if="isShow && readingCategory && readingCategory === 5"
|
||||||
|
:trial-id="trialId"
|
||||||
|
:subject-id="subjectId"
|
||||||
|
:visit-task-id="visitTaskId"
|
||||||
|
:reading-category="readingCategory"
|
||||||
|
:subject-code="subjectCode"
|
||||||
|
:task-blind-name="taskBlindName"
|
||||||
|
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||||
|
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
||||||
|
:is-exists-clinical-data="isExistsClinicalData"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
:custom-class="isFullscreen?'full-dialog-container':'dialog-container'"
|
||||||
|
:show-close="false"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:fullscreen="isFullscreen"
|
||||||
|
>
|
||||||
|
<span slot="title" class="dialog-footer">
|
||||||
|
<!-- 当前阅片任务存在临床数据,请查看。若已查看,请点击“确认” -->
|
||||||
|
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
|
||||||
|
<div style="position: absolute;right: 20px;top: 10px;">
|
||||||
|
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isFullscreen=!isFullscreen" />
|
||||||
|
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="dialogVisible = false" />
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<div style="height: 100%;margin:0;display: flex;flex-direction: column;">
|
||||||
|
<ClinicalData
|
||||||
|
v-if="dialogVisible"
|
||||||
|
style="flex: 1"
|
||||||
|
:trial-id="trialId"
|
||||||
|
:subject-id="subjectId"
|
||||||
|
:visit-task-id="cdVisitTaskId"
|
||||||
|
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||||
|
/>
|
||||||
|
<div v-if="!closeCDVisible" style="text-align:right">
|
||||||
|
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getNextTask, readClinicalData } from '@/api/trials'
|
||||||
|
import store from '@/store'
|
||||||
|
import { changeURLStatic } from '@/utils/history.js'
|
||||||
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
|
import Report from './components/Report'
|
||||||
|
import VisitReview from './components/VisitReview'
|
||||||
|
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
|
||||||
|
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
|
||||||
|
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
||||||
|
// import { getToken } from '@/utils/auth'
|
||||||
|
import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
|
||||||
|
export default {
|
||||||
|
name: 'NoneDicomReading',
|
||||||
|
components: {
|
||||||
|
VisitReview,
|
||||||
|
Report,
|
||||||
|
AdReview,
|
||||||
|
GlobalReview,
|
||||||
|
OncologyReview,
|
||||||
|
ClinicalData
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
readingCategory: null,
|
||||||
|
subjectId: '',
|
||||||
|
visitTaskId: '',
|
||||||
|
trialId: '',
|
||||||
|
subjectCode: '',
|
||||||
|
taskBlindName: '',
|
||||||
|
isReadingShowSubjectInfo: false,
|
||||||
|
isReadingShowPreviousResults: false,
|
||||||
|
isReadingTaskViewInOrder: false,
|
||||||
|
isExistsClinicalData: false,
|
||||||
|
isNeedReadClinicalData: false,
|
||||||
|
isReadClinicalData: false,
|
||||||
|
iseCRFShowInDicomReading: false,
|
||||||
|
criterionType: null,
|
||||||
|
readingTool: null,
|
||||||
|
isNewSubject: null,
|
||||||
|
dialogVisible: false,
|
||||||
|
closeCDVisible: false,
|
||||||
|
cdVisitTaskId: '',
|
||||||
|
isFullscreen: false,
|
||||||
|
// dialogH: 0,
|
||||||
|
isShow: false,
|
||||||
|
activeName:'',
|
||||||
|
tabs: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
DicomEvent.$on('getNextTask', () => {
|
||||||
|
this.getTaskInfo()
|
||||||
|
})
|
||||||
|
this.trialId = this.$router.currentRoute.query.trialId
|
||||||
|
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||||
|
this.subjectId = this.$router.currentRoute.query.subjectId
|
||||||
|
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
||||||
|
this.isReadingShowSubjectInfo = this.$router.currentRoute.query.isReadingShowSubjectInfo
|
||||||
|
this.isReadingShowPreviousResults = this.$router.currentRoute.query.isReadingShowPreviousResults
|
||||||
|
this.isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||||
|
this.criterionType = this.$router.currentRoute.query.criterionType
|
||||||
|
this.readingTool = this.$router.currentRoute.query.readingTool
|
||||||
|
this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
||||||
|
if (this.isNewSubject && this.isReadingTaskViewInOrder) {
|
||||||
|
const message = this.$t('trials:reading:noneDicom:message:startRead').replace('xxx', this.subjectCode)
|
||||||
|
this.$message.success(message)
|
||||||
|
changeURLStatic('isNewSubject', '')
|
||||||
|
}
|
||||||
|
if (this.$router.currentRoute.query.TokenKey) {
|
||||||
|
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
||||||
|
changeURLStatic('TokenKey', '')
|
||||||
|
}
|
||||||
|
this.getTaskInfo()
|
||||||
|
this.dialogH = this.$refs['container'].clientHeight - 250 + 'px'
|
||||||
|
window.addEventListener('resize', () => { this.dialogH = this.$refs['container'].clientHeight - 250 + 'px' })
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
DicomEvent.$off('getNextTask')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getTaskInfo() {
|
||||||
|
this.loading = true
|
||||||
|
var param = {
|
||||||
|
subjectId: this.subjectId,
|
||||||
|
trialId: this.trialId,
|
||||||
|
subjectCode: this.subjectCode,
|
||||||
|
visitTaskId: this.$router.currentRoute.query.visitTaskId,
|
||||||
|
trialReadingCriterionId: this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
}
|
||||||
|
this.isShow = false
|
||||||
|
getNextTask(param).then(res => {
|
||||||
|
this.readingCategory = res.Result.ReadingCategory
|
||||||
|
// if (this.subjectId !== res.Result.SubjectId && this.isReadingTaskViewInOrder) {
|
||||||
|
// store.dispatch('reading/resetVisitTasks')
|
||||||
|
// var token = getToken()
|
||||||
|
// window.location.href = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${res.Result.SubjectCode}&subjectId=${res.Result.SubjectId}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&isNewSubject=1&isReadingTaskViewInOrder=${res.Result.IsReadingTaskViewInOrder}&TokenKey=${token}`
|
||||||
|
// }
|
||||||
|
if (res.Result.ReadingCategory === 1) {
|
||||||
|
this.activeName = 'read'
|
||||||
|
this.tabs = [this.activeName]
|
||||||
|
}
|
||||||
|
this.subjectId = res.Result.SubjectId
|
||||||
|
this.visitTaskId = res.Result.VisitTaskId
|
||||||
|
this.subjectCode = res.Result.SubjectCode
|
||||||
|
this.taskBlindName = res.Result.TaskBlindName
|
||||||
|
this.isExistsClinicalData = res.Result.IsExistsClinicalData
|
||||||
|
this.isReadClinicalData = res.Result.IsReadClinicalData
|
||||||
|
this.isNeedReadClinicalData = res.Result.IsNeedReadClinicalData
|
||||||
|
this.iseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
|
||||||
|
this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
|
||||||
|
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
|
||||||
|
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
|
||||||
|
this.digitPlaces = res.Result.DigitPlaces
|
||||||
|
localStorage.setItem('digitPlaces', 2)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.isExistsClinicalData && this.isNeedReadClinicalData && !this.isReadClinicalData) {
|
||||||
|
this.isFullscreen = false
|
||||||
|
this.dialogVisible = true
|
||||||
|
this.cdVisitTaskId = this.visitTaskId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.isShow = true
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => { this.loading = false })
|
||||||
|
},
|
||||||
|
previewCD(taskId) {
|
||||||
|
this.closeCDVisible = true
|
||||||
|
this.isFullscreen = false
|
||||||
|
this.dialogVisible = true
|
||||||
|
this.cdVisitTaskId = taskId
|
||||||
|
this.dialogVisible = true
|
||||||
|
},
|
||||||
|
async handleConfirmCD() {
|
||||||
|
this.loading = true
|
||||||
|
var visitTaskId = this.visitTaskId
|
||||||
|
try {
|
||||||
|
await readClinicalData({ visitTaskId })
|
||||||
|
this.loading = false
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.isReadClinicalData = true
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeLeave(activeName, oldActiveName) {
|
||||||
|
if (!this.tabs.includes(activeName)) {
|
||||||
|
this.tabs.push(activeName)
|
||||||
|
}
|
||||||
|
if (oldActiveName === 'read') {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.reportPage) {
|
||||||
|
// DicomEvent.$emit('getReportInfo', true)
|
||||||
|
this.$refs.reportPage.setScrollTop(1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Promise.resolve(true)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.none-dicom-reading-container{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.el-dialog{
|
||||||
|
margin-top: 0px !important;
|
||||||
|
::v-deep .el-dialog__wrapper{
|
||||||
|
margin-top: 0px !important;
|
||||||
|
}
|
||||||
|
::v-deep .el-dialog__body{
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.reading-wrapper{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
::v-deep.el-tabs{
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.el-tabs__item{
|
||||||
|
// color: #fff;
|
||||||
|
}
|
||||||
|
.el-tabs__header{
|
||||||
|
height: 50px;
|
||||||
|
margin:0px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.el-tabs__content{
|
||||||
|
flex: 1;
|
||||||
|
margin:0px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.el-tabs__item{
|
||||||
|
// color: #fff;
|
||||||
|
}
|
||||||
|
.el-tab-pane{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep.dialog-container{
|
||||||
|
margin-top: 50px !important;
|
||||||
|
width:75%;
|
||||||
|
height:80%;
|
||||||
|
}
|
||||||
|
::v-deep.el-dialog__body{
|
||||||
|
padding: 20px 20px 0 20px;
|
||||||
|
height: calc(100% - 70px);
|
||||||
|
}
|
||||||
|
.el-dialog__header{
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-dialog-container{
|
||||||
|
::v-deep.is-fullscreen .el-dialog__body{
|
||||||
|
height: calc(100% - 70px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,76 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-loading="loading" class="reading-viewer-container">
|
|
||||||
<!-- 访视阅片 -->
|
|
||||||
<visit-review v-if="taskInfo && taskInfo.ReadingCategory=== 1" />
|
|
||||||
<!-- 全局阅片 -->
|
|
||||||
<global-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 2" />
|
|
||||||
<!-- 裁判阅片 -->
|
|
||||||
<ad-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 4" />
|
|
||||||
<!-- 肿瘤学阅片 -->
|
|
||||||
<oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { getNextTask } from '@/api/trials'
|
|
||||||
import store from '@/store'
|
|
||||||
import VisitReview from '@/views/trials/trials-panel/reading/visit-review'
|
|
||||||
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
|
|
||||||
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
|
|
||||||
import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
|
|
||||||
export default {
|
|
||||||
name: 'ReadingViewer',
|
|
||||||
components: {
|
|
||||||
VisitReview,
|
|
||||||
GlobalReview,
|
|
||||||
AdReview,
|
|
||||||
OncologyReview
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
taskInfo: null,
|
|
||||||
loading: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.getTaskInfo()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async getTaskInfo() {
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
const params = {
|
|
||||||
subjectId: this.$route.query.subjectId,
|
|
||||||
trialId: this.$route.query.trialId,
|
|
||||||
subjectCode: this.$route.query.subjectCode,
|
|
||||||
visitTaskId: this.$route.query.visitTaskId,
|
|
||||||
trialReadingCriterionId: this.$route.query.TrialReadingCriterionId
|
|
||||||
}
|
|
||||||
const res = await getNextTask(params)
|
|
||||||
this.taskInfo = res.Result
|
|
||||||
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
|
||||||
// if (res.Result.IsExistsClinicalData && res.Result.IsNeedReadClinicalData && !res.Result.IsReadClinicalData) {
|
|
||||||
// this.isFullscreen = false
|
|
||||||
// this.dialogVisible = true
|
|
||||||
// this.cdVisitTaskId = res.Result.visitTaskId
|
|
||||||
// }
|
|
||||||
// this.$nextTick(() => {
|
|
||||||
// if (res.Result.IsFirstChangeTask && res.Result.ReadingTaskState === 0) {
|
|
||||||
// this.tipVisible = true
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
this.loading = false
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
store.dispatch('reading/setCurrentReadingTaskState', 2)
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.reading-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,347 +1,76 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="container" v-loading="loading" class="none-dicom-reading-container">
|
<div v-loading="loading" class="reading-viewer-container">
|
||||||
<!-- 访视阅片 -->
|
<!-- 访视阅片 -->
|
||||||
<div v-if="isShow && readingCategory && readingCategory=== 1" class="reading-wrapper">
|
<visit-review v-if="taskInfo && taskInfo.ReadingCategory=== 1" />
|
||||||
<el-tabs v-model="activeName" :before-leave="beforeLeave">
|
|
||||||
<!-- 阅片 -->
|
|
||||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
|
||||||
<VisitReview
|
|
||||||
:trial-id="trialId"
|
|
||||||
:subject-id="subjectId"
|
|
||||||
:subject-code="subjectCode"
|
|
||||||
:visit-task-id="visitTaskId"
|
|
||||||
:task-blind-name="taskBlindName"
|
|
||||||
:reading-category="readingCategory"
|
|
||||||
:readingTool="readingTool"
|
|
||||||
:criterionType="criterionType"
|
|
||||||
:isExistsClinicalData="isExistsClinicalData"
|
|
||||||
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
|
|
||||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
|
||||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
|
||||||
@previewCD="previewCD"
|
|
||||||
/>
|
|
||||||
</el-tab-pane>
|
|
||||||
<!-- 报告 -->
|
|
||||||
<el-tab-pane :label="$t('trials:reading:tabTitle:report')" name="report" v-if="!iseCRFShowInDicomReading">
|
|
||||||
<Report
|
|
||||||
v-if="tabs.includes('report')"
|
|
||||||
ref="reportPage"
|
|
||||||
:trialId="trialId"
|
|
||||||
:visit-task-id="visitTaskId"
|
|
||||||
:subject-id="subjectId"
|
|
||||||
:readingTool="readingTool"
|
|
||||||
:criterionType="criterionType"
|
|
||||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
|
||||||
/>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 全局阅片 -->
|
<!-- 全局阅片 -->
|
||||||
<GlobalReview
|
<global-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 2" />
|
||||||
v-else-if="isShow && readingCategory && readingCategory === 2"
|
|
||||||
:trial-id="trialId"
|
|
||||||
:subject-id="subjectId"
|
|
||||||
:visit-task-id="visitTaskId"
|
|
||||||
:reading-category="readingCategory"
|
|
||||||
:subject-code="subjectCode"
|
|
||||||
:task-blind-name="taskBlindName"
|
|
||||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
|
||||||
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
|
||||||
:is-exists-clinical-data="isExistsClinicalData"
|
|
||||||
/>
|
|
||||||
<!-- 裁判阅片 -->
|
<!-- 裁判阅片 -->
|
||||||
<AdReview
|
<ad-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 4" />
|
||||||
v-else-if="isShow && readingCategory && readingCategory === 4"
|
|
||||||
:trial-id="trialId"
|
|
||||||
:subject-id="subjectId"
|
|
||||||
:visit-task-id="visitTaskId"
|
|
||||||
:reading-category="readingCategory"
|
|
||||||
:subject-code="subjectCode"
|
|
||||||
:task-blind-name="taskBlindName"
|
|
||||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
|
||||||
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
|
||||||
:is-exists-clinical-data="isExistsClinicalData"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 肿瘤学阅片 -->
|
<!-- 肿瘤学阅片 -->
|
||||||
<OncologyReview
|
<oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" />
|
||||||
v-else-if="isShow && readingCategory && readingCategory === 5"
|
|
||||||
:trial-id="trialId"
|
|
||||||
:subject-id="subjectId"
|
|
||||||
:visit-task-id="visitTaskId"
|
|
||||||
:reading-category="readingCategory"
|
|
||||||
:subject-code="subjectCode"
|
|
||||||
:task-blind-name="taskBlindName"
|
|
||||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
|
||||||
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
|
||||||
:is-exists-clinical-data="isExistsClinicalData"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
:visible.sync="dialogVisible"
|
|
||||||
:custom-class="isFullscreen?'full-dialog-container':'dialog-container'"
|
|
||||||
:show-close="false"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:fullscreen="isFullscreen"
|
|
||||||
>
|
|
||||||
<span slot="title" class="dialog-footer">
|
|
||||||
<!-- 当前阅片任务存在临床数据,请查看。若已查看,请点击“确认” -->
|
|
||||||
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
|
|
||||||
<div style="position: absolute;right: 20px;top: 10px;">
|
|
||||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isFullscreen=!isFullscreen" />
|
|
||||||
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="dialogVisible = false" />
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<div style="height: 100%;margin:0;display: flex;flex-direction: column;">
|
|
||||||
<ClinicalData
|
|
||||||
v-if="dialogVisible"
|
|
||||||
style="flex: 1"
|
|
||||||
:trial-id="trialId"
|
|
||||||
:subject-id="subjectId"
|
|
||||||
:visit-task-id="cdVisitTaskId"
|
|
||||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
|
||||||
/>
|
|
||||||
<div v-if="!closeCDVisible" style="text-align:right">
|
|
||||||
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getNextTask, readClinicalData } from '@/api/trials'
|
import { getNextTask } from '@/api/trials'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { changeURLStatic } from '@/utils/history.js'
|
import VisitReview from '@/views/trials/trials-panel/reading/visit-review'
|
||||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
|
||||||
import Report from './components/Report'
|
|
||||||
import VisitReview from './components/VisitReview'
|
|
||||||
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
|
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
|
||||||
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
|
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
|
||||||
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
|
||||||
// import { getToken } from '@/utils/auth'
|
|
||||||
import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
|
import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
|
||||||
export default {
|
export default {
|
||||||
name: 'NoneDicomReading',
|
name: 'ReadingViewer',
|
||||||
components: {
|
components: {
|
||||||
VisitReview,
|
VisitReview,
|
||||||
Report,
|
|
||||||
AdReview,
|
|
||||||
GlobalReview,
|
GlobalReview,
|
||||||
OncologyReview,
|
AdReview,
|
||||||
ClinicalData
|
OncologyReview
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
taskInfo: null,
|
||||||
readingCategory: null,
|
loading: false
|
||||||
subjectId: '',
|
|
||||||
visitTaskId: '',
|
|
||||||
trialId: '',
|
|
||||||
subjectCode: '',
|
|
||||||
taskBlindName: '',
|
|
||||||
isReadingShowSubjectInfo: false,
|
|
||||||
isReadingShowPreviousResults: false,
|
|
||||||
isReadingTaskViewInOrder: false,
|
|
||||||
isExistsClinicalData: false,
|
|
||||||
isNeedReadClinicalData: false,
|
|
||||||
isReadClinicalData: false,
|
|
||||||
iseCRFShowInDicomReading: false,
|
|
||||||
criterionType: null,
|
|
||||||
readingTool: null,
|
|
||||||
isNewSubject: null,
|
|
||||||
dialogVisible: false,
|
|
||||||
closeCDVisible: false,
|
|
||||||
cdVisitTaskId: '',
|
|
||||||
isFullscreen: false,
|
|
||||||
// dialogH: 0,
|
|
||||||
isShow: false,
|
|
||||||
activeName:'',
|
|
||||||
tabs: []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
DicomEvent.$on('getNextTask', () => {
|
|
||||||
this.getTaskInfo()
|
|
||||||
})
|
|
||||||
this.trialId = this.$router.currentRoute.query.trialId
|
|
||||||
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
|
||||||
this.subjectId = this.$router.currentRoute.query.subjectId
|
|
||||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
|
||||||
this.isReadingShowSubjectInfo = this.$router.currentRoute.query.isReadingShowSubjectInfo
|
|
||||||
this.isReadingShowPreviousResults = this.$router.currentRoute.query.isReadingShowPreviousResults
|
|
||||||
this.isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
|
||||||
this.criterionType = this.$router.currentRoute.query.criterionType
|
|
||||||
this.readingTool = this.$router.currentRoute.query.readingTool
|
|
||||||
this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
|
||||||
if (this.isNewSubject && this.isReadingTaskViewInOrder) {
|
|
||||||
const message = this.$t('trials:reading:noneDicom:message:startRead').replace('xxx', this.subjectCode)
|
|
||||||
this.$message.success(message)
|
|
||||||
changeURLStatic('isNewSubject', '')
|
|
||||||
}
|
|
||||||
if (this.$router.currentRoute.query.TokenKey) {
|
|
||||||
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
|
||||||
changeURLStatic('TokenKey', '')
|
|
||||||
}
|
|
||||||
this.getTaskInfo()
|
this.getTaskInfo()
|
||||||
this.dialogH = this.$refs['container'].clientHeight - 250 + 'px'
|
|
||||||
window.addEventListener('resize', () => { this.dialogH = this.$refs['container'].clientHeight - 250 + 'px' })
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
DicomEvent.$off('getNextTask')
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getTaskInfo() {
|
async getTaskInfo() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var param = {
|
|
||||||
subjectId: this.subjectId,
|
|
||||||
trialId: this.trialId,
|
|
||||||
subjectCode: this.subjectCode,
|
|
||||||
visitTaskId: this.$router.currentRoute.query.visitTaskId,
|
|
||||||
trialReadingCriterionId: this.$router.currentRoute.query.TrialReadingCriterionId
|
|
||||||
}
|
|
||||||
this.isShow = false
|
|
||||||
getNextTask(param).then(res => {
|
|
||||||
this.readingCategory = res.Result.ReadingCategory
|
|
||||||
// if (this.subjectId !== res.Result.SubjectId && this.isReadingTaskViewInOrder) {
|
|
||||||
// store.dispatch('reading/resetVisitTasks')
|
|
||||||
// var token = getToken()
|
|
||||||
// window.location.href = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${res.Result.SubjectCode}&subjectId=${res.Result.SubjectId}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&isNewSubject=1&isReadingTaskViewInOrder=${res.Result.IsReadingTaskViewInOrder}&TokenKey=${token}`
|
|
||||||
// }
|
|
||||||
if (res.Result.ReadingCategory === 1) {
|
|
||||||
this.activeName = 'read'
|
|
||||||
this.tabs = [this.activeName]
|
|
||||||
}
|
|
||||||
this.subjectId = res.Result.SubjectId
|
|
||||||
this.visitTaskId = res.Result.VisitTaskId
|
|
||||||
this.subjectCode = res.Result.SubjectCode
|
|
||||||
this.taskBlindName = res.Result.TaskBlindName
|
|
||||||
this.isExistsClinicalData = res.Result.IsExistsClinicalData
|
|
||||||
this.isReadClinicalData = res.Result.IsReadClinicalData
|
|
||||||
this.isNeedReadClinicalData = res.Result.IsNeedReadClinicalData
|
|
||||||
this.iseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
|
|
||||||
this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
|
|
||||||
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
|
|
||||||
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
|
|
||||||
this.digitPlaces = res.Result.DigitPlaces
|
|
||||||
localStorage.setItem('digitPlaces', 2)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.isExistsClinicalData && this.isNeedReadClinicalData && !this.isReadClinicalData) {
|
|
||||||
this.isFullscreen = false
|
|
||||||
this.dialogVisible = true
|
|
||||||
this.cdVisitTaskId = this.visitTaskId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.isShow = true
|
|
||||||
this.loading = false
|
|
||||||
}).catch(() => { this.loading = false })
|
|
||||||
},
|
|
||||||
previewCD(taskId) {
|
|
||||||
this.closeCDVisible = true
|
|
||||||
this.isFullscreen = false
|
|
||||||
this.dialogVisible = true
|
|
||||||
this.cdVisitTaskId = taskId
|
|
||||||
this.dialogVisible = true
|
|
||||||
},
|
|
||||||
async handleConfirmCD() {
|
|
||||||
this.loading = true
|
|
||||||
var visitTaskId = this.visitTaskId
|
|
||||||
try {
|
try {
|
||||||
await readClinicalData({ visitTaskId })
|
const params = {
|
||||||
|
subjectId: this.$route.query.subjectId,
|
||||||
|
trialId: this.$route.query.trialId,
|
||||||
|
subjectCode: this.$route.query.subjectCode,
|
||||||
|
visitTaskId: this.$route.query.visitTaskId,
|
||||||
|
trialReadingCriterionId: this.$route.query.TrialReadingCriterionId
|
||||||
|
}
|
||||||
|
const res = await getNextTask(params)
|
||||||
|
this.taskInfo = res.Result
|
||||||
|
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
||||||
|
// if (res.Result.IsExistsClinicalData && res.Result.IsNeedReadClinicalData && !res.Result.IsReadClinicalData) {
|
||||||
|
// this.isFullscreen = false
|
||||||
|
// this.dialogVisible = true
|
||||||
|
// this.cdVisitTaskId = res.Result.visitTaskId
|
||||||
|
// }
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// if (res.Result.IsFirstChangeTask && res.Result.ReadingTaskState === 0) {
|
||||||
|
// this.tipVisible = true
|
||||||
|
// }
|
||||||
|
// })
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.dialogVisible = false
|
|
||||||
this.isReadClinicalData = true
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
store.dispatch('reading/setCurrentReadingTaskState', 2)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
beforeLeave(activeName, oldActiveName) {
|
|
||||||
if (!this.tabs.includes(activeName)) {
|
|
||||||
this.tabs.push(activeName)
|
|
||||||
}
|
|
||||||
if (oldActiveName === 'read') {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.reportPage) {
|
|
||||||
// DicomEvent.$emit('getReportInfo', true)
|
|
||||||
this.$refs.reportPage.setScrollTop(1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return Promise.resolve(true)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.none-dicom-reading-container{
|
.reading-viewer-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.el-dialog{
|
|
||||||
margin-top: 0px !important;
|
|
||||||
::v-deep .el-dialog__wrapper{
|
|
||||||
margin-top: 0px !important;
|
|
||||||
}
|
|
||||||
::v-deep .el-dialog__body{
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.reading-wrapper{
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0 10px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
::v-deep.el-tabs{
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.el-tabs__item{
|
|
||||||
// color: #fff;
|
|
||||||
}
|
|
||||||
.el-tabs__header{
|
|
||||||
height: 50px;
|
|
||||||
margin:0px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.el-tabs__content{
|
|
||||||
flex: 1;
|
|
||||||
margin:0px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.el-tabs__item{
|
|
||||||
// color: #fff;
|
|
||||||
}
|
|
||||||
.el-tab-pane{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::v-deep.dialog-container{
|
|
||||||
margin-top: 50px !important;
|
|
||||||
width:75%;
|
|
||||||
height:80%;
|
|
||||||
}
|
|
||||||
::v-deep.el-dialog__body{
|
|
||||||
padding: 20px 20px 0 20px;
|
|
||||||
height: calc(100% - 70px);
|
|
||||||
}
|
|
||||||
.el-dialog__header{
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-dialog-container{
|
|
||||||
::v-deep.is-fullscreen .el-dialog__body{
|
|
||||||
height: calc(100% - 70px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,17 +2,75 @@
|
||||||
<div class="none-dicom-viewer">
|
<div class="none-dicom-viewer">
|
||||||
<!-- tools -->
|
<!-- tools -->
|
||||||
<div class="tools-wrapper">
|
<div class="tools-wrapper">
|
||||||
<el-dropdown @command="handleCommand">
|
<!-- 布局 -->
|
||||||
<span class="el-dropdown-link">
|
<div class="tool-item" :title="$t('trials:reading:button:layout')">
|
||||||
<i class="el-icon-menu" /><i class="el-icon-arrow-down el-icon--right" />
|
<el-dropdown @command="handleCommand">
|
||||||
</span>
|
<span class="el-dropdown-link">
|
||||||
<el-dropdown-menu slot="dropdown">
|
<svg-icon icon-class="layout" class="svg-icon" /><i class="el-icon-arrow-down el-icon--right" />
|
||||||
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
|
</span>
|
||||||
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
|
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
|
||||||
</el-dropdown>
|
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
<!-- 缩放 -->
|
||||||
|
<div
|
||||||
|
:class="['tool-item', activeTool === 'Zoom' ? 'tool-item-active' : '']"
|
||||||
|
:title="$t('trials:reading:button:zoom')"
|
||||||
|
@click.prevent="setToolActive('Zoom')"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="magnifier" class="svg-icon" />
|
||||||
|
</div>
|
||||||
|
<!-- 移动 -->
|
||||||
|
<div
|
||||||
|
:class="['tool-item', activeTool === 'Pan' ? 'tool-item-active' : '']"
|
||||||
|
:title="$t('trials:reading:button:move')"
|
||||||
|
@click.prevent="setToolActive('Pan')"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="move" class="svg-icon" />
|
||||||
|
</div>
|
||||||
|
<!-- 旋转 -->
|
||||||
|
<div
|
||||||
|
:class="['tool-item', activeTool === 'PlanarRotate' ? 'tool-item-active' : '']"
|
||||||
|
:title="$t('trials:reading:button:rotate')"
|
||||||
|
@click.prevent="setToolActive('PlanarRotate')"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="rotate" class="svg-icon" />
|
||||||
|
</div>
|
||||||
|
<!-- 箭头工具 -->
|
||||||
|
<div
|
||||||
|
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'ArrowAnnotate' ? 'tool-item-active' : '']"
|
||||||
|
:title="$t('trials:reading:button:arrowAnnotate')"
|
||||||
|
@click.prevent="setAnnotateToolActive('ArrowAnnotate')"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="arrow" class="svg-icon" />
|
||||||
|
</div>
|
||||||
|
<!-- 清除标注 -->
|
||||||
|
<div
|
||||||
|
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']"
|
||||||
|
:title="$t('trials:dicom-show:Eraser')"
|
||||||
|
@click.prevent="setAnnotateToolActive('Eraser')"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="clear" class="svg-icon" />
|
||||||
|
</div>
|
||||||
|
<!-- 截图 -->
|
||||||
|
<!-- <div
|
||||||
|
class="tool-item"
|
||||||
|
:title="$t('trials:reading:button:screenShot')"
|
||||||
|
@click.prevent="saveImage"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="image" class="svg-icon" />
|
||||||
|
</div> -->
|
||||||
|
<!-- 重置 -->
|
||||||
|
<div
|
||||||
|
class="tool-item"
|
||||||
|
:title="$t('trials:reading:button:reset')"
|
||||||
|
@click.prevent="resetViewport"
|
||||||
|
>
|
||||||
|
<svg-icon icon-class="refresh" class="svg-icon" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- viewports -->
|
<!-- viewports -->
|
||||||
<div class="viewports-wrapper">
|
<div class="viewports-wrapper">
|
||||||
|
@ -22,9 +80,11 @@
|
||||||
v-show="index < cells.length"
|
v-show="index < cells.length"
|
||||||
:key="index"
|
:key="index"
|
||||||
:style="cellStyle"
|
:style="cellStyle"
|
||||||
:class="['grid-cell', index === activeCanvasIndex?'cell_active':'']"
|
:class="['grid-cell', index === activeCanvasIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||||
|
@dblclick="toggleFullScreen($event, index)"
|
||||||
@click="activeCanvas(index)"
|
@click="activeCanvas(index)"
|
||||||
@dblclick="toggleFullScreen(index)"
|
@mouseup="sliderMouseup($event, index)"
|
||||||
|
@mousemove="sliderMousemove($event, index)"
|
||||||
>
|
>
|
||||||
<div :ref="`canvas-${index}`" class="content">
|
<div :ref="`canvas-${index}`" class="content">
|
||||||
<div class="left-top-text">
|
<div class="left-top-text">
|
||||||
|
@ -70,6 +130,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div :ref="`sliderBox-${index}`" class="right-slider-box" @click.stop="clickSlider($event, index)">
|
||||||
|
<div :style="{top: v.height + '%'}" class="slider" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event, index)" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -77,12 +140,14 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import { addNoneDicomMark, deleteTrialFileType } from '@/api/trials'
|
||||||
import {
|
import {
|
||||||
RenderingEngine,
|
RenderingEngine,
|
||||||
Enums,
|
Enums,
|
||||||
imageLoader,
|
imageLoader,
|
||||||
metaData,
|
metaData,
|
||||||
getRenderingEngine
|
getRenderingEngine,
|
||||||
|
eventTarget
|
||||||
} from '@cornerstonejs/core'
|
} from '@cornerstonejs/core'
|
||||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||||
import initLibraries from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/initLibraries'
|
import initLibraries from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/initLibraries'
|
||||||
|
@ -92,8 +157,17 @@ import { mapGetters } from 'vuex'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
const { ViewportType } = Enums
|
const { ViewportType } = Enums
|
||||||
const renderingEngineId = 'myRenderingEngine'
|
const renderingEngineId = 'myRenderingEngine'
|
||||||
const { ToolGroupManager, Enums: csToolsEnums, StackScrollTool } = cornerstoneTools
|
const {
|
||||||
const { MouseBindings } = csToolsEnums
|
ToolGroupManager,
|
||||||
|
Enums: csToolsEnums,
|
||||||
|
StackScrollTool,
|
||||||
|
PanTool,
|
||||||
|
ZoomTool,
|
||||||
|
PlanarRotateTool,
|
||||||
|
ArrowAnnotateTool,
|
||||||
|
EraserTool
|
||||||
|
} = cornerstoneTools
|
||||||
|
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||||
export default {
|
export default {
|
||||||
name: 'ImageViewer',
|
name: 'ImageViewer',
|
||||||
props: {
|
props: {
|
||||||
|
@ -114,7 +188,10 @@ export default {
|
||||||
layout: '1*2',
|
layout: '1*2',
|
||||||
cellsMax: 4,
|
cellsMax: 4,
|
||||||
viewportInfos: [],
|
viewportInfos: [],
|
||||||
taskInfo: null
|
taskInfo: null,
|
||||||
|
activeTool: '',
|
||||||
|
readingTaskState: 2,
|
||||||
|
renderHistoryAnnotationTaskIds: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -151,6 +228,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||||
|
this.readingTaskState = this.taskInfo.ReadingTaskState
|
||||||
if (this.taskInfo.VisitNum > 0) {
|
if (this.taskInfo.VisitNum > 0) {
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
this.cols = 2
|
this.cols = 2
|
||||||
|
@ -159,12 +237,18 @@ export default {
|
||||||
this.viewportInfos = Array.from({ length: this.cellsMax }, (_, index) => ({
|
this.viewportInfos = Array.from({ length: this.cellsMax }, (_, index) => ({
|
||||||
index: index,
|
index: index,
|
||||||
taskInfo: '',
|
taskInfo: '',
|
||||||
|
studyId: '',
|
||||||
currentImageIdIndex: 0,
|
currentImageIdIndex: 0,
|
||||||
viewportId: `canvas-${index}`,
|
viewportId: `canvas-${index}`,
|
||||||
currentFileName: '',
|
currentFileName: '',
|
||||||
imageIds: []
|
imageIds: [],
|
||||||
|
oldB: null,
|
||||||
|
oldM: null,
|
||||||
|
isMove: false,
|
||||||
|
height: 0
|
||||||
}))
|
}))
|
||||||
this.initLoader()
|
this.initLoader()
|
||||||
|
console.log(cornerstoneTools)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 初始化加载器
|
// 初始化加载器
|
||||||
|
@ -221,17 +305,48 @@ export default {
|
||||||
]
|
]
|
||||||
const viewportIds = ['canvas-0', 'canvas-1', 'canvas-2', 'canvas-3']
|
const viewportIds = ['canvas-0', 'canvas-1', 'canvas-2', 'canvas-3']
|
||||||
renderingEngine.setViewports(viewportInputArray)
|
renderingEngine.setViewports(viewportInputArray)
|
||||||
|
this.addAnnotationListeners()
|
||||||
cornerstoneTools.addTool(StackScrollTool)
|
cornerstoneTools.addTool(StackScrollTool)
|
||||||
|
cornerstoneTools.addTool(PanTool)
|
||||||
|
cornerstoneTools.addTool(ZoomTool)
|
||||||
|
cornerstoneTools.addTool(PlanarRotateTool)
|
||||||
|
cornerstoneTools.addTool(ArrowAnnotateTool)
|
||||||
|
|
||||||
|
cornerstoneTools.addTool(EraserTool)
|
||||||
|
|
||||||
viewportIds.forEach((viewportId, i) => {
|
viewportIds.forEach((viewportId, i) => {
|
||||||
const toolGroupId = `canvas-${i}`
|
const toolGroupId = `canvas-${i}`
|
||||||
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
|
||||||
toolGroup.addViewport(viewportId, renderingEngineId)
|
toolGroup.addViewport(viewportId, renderingEngineId)
|
||||||
toolGroup.addTool(StackScrollTool.toolName)
|
toolGroup.addTool(StackScrollTool.toolName)
|
||||||
|
toolGroup.addTool(PanTool.toolName)
|
||||||
|
toolGroup.addTool(ZoomTool.toolName)
|
||||||
|
toolGroup.addTool(PlanarRotateTool.toolName)
|
||||||
|
toolGroup.addTool(ArrowAnnotateTool.toolName, {
|
||||||
|
arrowHeadStyle: 'standard',
|
||||||
|
changeTextCallback: async(data, eventData, doneChangingTextCallback) => {
|
||||||
|
return doneChangingTextCallback(await this.customPrompt())
|
||||||
|
},
|
||||||
|
getTextCallback: async(doneChangingTextCallback) => {
|
||||||
|
return doneChangingTextCallback(await this.customPrompt())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
toolGroup.addTool(EraserTool.toolName)
|
||||||
toolGroup.setToolActive(StackScrollTool.toolName, {
|
toolGroup.setToolActive(StackScrollTool.toolName, {
|
||||||
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||||
})
|
})
|
||||||
|
toolGroup.setToolPassive(PanTool.toolName)
|
||||||
|
toolGroup.setToolPassive(ZoomTool.toolName)
|
||||||
|
toolGroup.setToolPassive(PlanarRotateTool.toolName)
|
||||||
|
if (this.readingTaskState < 2) {
|
||||||
|
toolGroup.setToolPassive(ArrowAnnotateTool.toolName)
|
||||||
|
} else {
|
||||||
|
toolGroup.setToolEnabled(ArrowAnnotateTool.toolName)
|
||||||
|
}
|
||||||
|
toolGroup.setToolPassive(EraserTool.toolName)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 加载图片回调
|
// 加载图片回调
|
||||||
stackNewImage(e) {
|
stackNewImage(e) {
|
||||||
const { detail } = e
|
const { detail } = e
|
||||||
|
@ -241,6 +356,25 @@ export default {
|
||||||
const obj = this.viewportInfos[i].fileList[detail.imageIdIndex]
|
const obj = this.viewportInfos[i].fileList[detail.imageIdIndex]
|
||||||
if (!obj) return
|
if (!obj) return
|
||||||
this.viewportInfos[i].currentFileName = obj.FileName
|
this.viewportInfos[i].currentFileName = obj.FileName
|
||||||
|
this.viewportInfos[i].height = (this.viewportInfos[i].currentImageIdIndex) * 100 / (this.viewportInfos[i].imageIds.length - 1)
|
||||||
|
this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: detail.imageIdIndex })
|
||||||
|
this.renderHistoryAnnotations(this.viewportInfos[i].taskInfo)
|
||||||
|
},
|
||||||
|
renderHistoryAnnotations(obj) {
|
||||||
|
if (this.renderHistoryAnnotationTaskIds.includes(obj.VisitTaskId)) return
|
||||||
|
this.renderHistoryAnnotationTaskIds.push(obj.VisitTaskId)
|
||||||
|
const arr = []
|
||||||
|
obj.Annotations.map(i => {
|
||||||
|
if (typeof i.MeasureData === 'string') {
|
||||||
|
const annotation = JSON.parse(i.MeasureData)
|
||||||
|
annotation.annotationId = i.Id
|
||||||
|
arr.push(annotation)
|
||||||
|
cornerstoneTools.annotation.state.addAnnotation(annotation)
|
||||||
|
if (obj.ReadingTaskState === 2) {
|
||||||
|
cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// 渲染图片
|
// 渲染图片
|
||||||
async renderImage(imageIds, canvasIndex, sliceIndex) {
|
async renderImage(imageIds, canvasIndex, sliceIndex) {
|
||||||
|
@ -256,10 +390,12 @@ export default {
|
||||||
if (!obj || Object.keys(obj).length === 0) return
|
if (!obj || Object.keys(obj).length === 0) return
|
||||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||||
if (i === -1) return
|
if (i === -1) return
|
||||||
if (obj.visitTaskInfo.VisitTaskId === this.viewportInfos[i].taskInfo.VisitTaskId) {
|
if (obj.studyId === this.viewportInfos[i].studyId) {
|
||||||
this.sliceIndex(obj.fileIndex)
|
this.sliceIndex(obj.fileIndex)
|
||||||
} else {
|
} else {
|
||||||
this.updateViewportInfos(this.activeCanvasIndex, obj)
|
this.updateViewportInfos(this.activeCanvasIndex, obj)
|
||||||
|
}
|
||||||
|
if (this.activeCanvasIndex === this.cells.length - 1) {
|
||||||
store.dispatch('noneDicomReview/setLastViewportTaskId', obj.visitTaskInfo.VisitTaskId)
|
store.dispatch('noneDicomReview/setLastViewportTaskId', obj.visitTaskInfo.VisitTaskId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -268,9 +404,12 @@ export default {
|
||||||
if (this.activeCanvasIndex === index) return
|
if (this.activeCanvasIndex === index) return
|
||||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||||
if (i === -1) return
|
if (i === -1) return
|
||||||
store.dispatch('noneDicomReview/setLastViewportTaskId', this.viewportInfos[i].taskInfo.VisitTaskId)
|
|
||||||
this.activeCanvasIndex = index
|
this.activeCanvasIndex = index
|
||||||
// this.$emit('toggleTask', this.viewportInfos[i].taskInfo)
|
if (index === this.cells.length - 1) {
|
||||||
|
store.dispatch('noneDicomReview/setLastViewportTaskId', this.viewportInfos[i].taskInfo.VisitTaskId)
|
||||||
|
}
|
||||||
|
this.$emit('toggleTask', this.viewportInfos[i].taskInfo)
|
||||||
|
this.setToolsPassive()
|
||||||
},
|
},
|
||||||
// 更新视图信息
|
// 更新视图信息
|
||||||
updateViewportInfos(index, obj) {
|
updateViewportInfos(index, obj) {
|
||||||
|
@ -280,6 +419,7 @@ export default {
|
||||||
this.viewportInfos[i].currentImageIdIndex = obj.fileIndex
|
this.viewportInfos[i].currentImageIdIndex = obj.fileIndex
|
||||||
this.viewportInfos[i].currentFileName = obj.fileInfo.FileName
|
this.viewportInfos[i].currentFileName = obj.fileInfo.FileName
|
||||||
this.viewportInfos[i].fileList = obj.fileList
|
this.viewportInfos[i].fileList = obj.fileList
|
||||||
|
this.viewportInfos[i].studyId = obj.studyId
|
||||||
const imageIds = []
|
const imageIds = []
|
||||||
for (let i = 0; i < obj.fileList.length; i++) {
|
for (let i = 0; i < obj.fileList.length; i++) {
|
||||||
const path = obj.fileList[i].Path
|
const path = obj.fileList[i].Path
|
||||||
|
@ -304,6 +444,7 @@ export default {
|
||||||
},
|
},
|
||||||
// 更改视图布局
|
// 更改视图布局
|
||||||
handleCommand(command) {
|
handleCommand(command) {
|
||||||
|
this.fullScreenIndex = null
|
||||||
this.layout = command
|
this.layout = command
|
||||||
this.rows = parseInt(command.split('*')[0])
|
this.rows = parseInt(command.split('*')[0])
|
||||||
this.cols = parseInt(command.split('*')[1])
|
this.cols = parseInt(command.split('*')[1])
|
||||||
|
@ -386,8 +527,9 @@ export default {
|
||||||
// })
|
// })
|
||||||
},
|
},
|
||||||
// 切换全屏
|
// 切换全屏
|
||||||
toggleFullScreen(index) {
|
toggleFullScreen(e, index) {
|
||||||
this.fullScreenIndex = this.fullScreenIndex === index ? null : index
|
this.fullScreenIndex = this.fullScreenIndex === index ? null : index
|
||||||
|
this.activeCanvasIndex = index
|
||||||
},
|
},
|
||||||
// 切换任务
|
// 切换任务
|
||||||
toggleTask(evt, visitTaskNum, i) {
|
toggleTask(evt, visitTaskNum, i) {
|
||||||
|
@ -400,6 +542,178 @@ export default {
|
||||||
evt.stopPropagation()
|
evt.stopPropagation()
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
},
|
},
|
||||||
|
// 激活工具
|
||||||
|
setToolActive(toolName) {
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||||
|
if (i === -1) return
|
||||||
|
const toolGroupId = `canvas-${this.viewportInfos[i].index}`
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (this.activeTool === toolName) {
|
||||||
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
|
this.activeTool = ''
|
||||||
|
} else {
|
||||||
|
if (this.activeTool) {
|
||||||
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
|
}
|
||||||
|
toolGroup.setToolActive(toolName, {
|
||||||
|
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||||
|
})
|
||||||
|
this.activeTool = toolName
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 激活标注工具
|
||||||
|
setAnnotateToolActive(toolName) {
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||||
|
if (i === -1) return
|
||||||
|
if (this.viewportInfos[i].taskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
|
const toolGroupId = `canvas-${this.viewportInfos[i].index}`
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (this.activeTool === toolName) {
|
||||||
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
|
this.activeTool = ''
|
||||||
|
} else {
|
||||||
|
if (this.activeTool) {
|
||||||
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
|
}
|
||||||
|
toolGroup.setToolActive(toolName, {
|
||||||
|
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||||
|
})
|
||||||
|
this.activeTool = toolName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setToolsPassive() {
|
||||||
|
if (!this.activeTool) return
|
||||||
|
const toolGroupIds = ['canvas-0', 'canvas-1', 'canvas-2', 'canvas-3']
|
||||||
|
toolGroupIds.forEach(toolGroupId => {
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
|
})
|
||||||
|
this.activeTool = ''
|
||||||
|
},
|
||||||
|
addAnnotationListeners() {
|
||||||
|
eventTarget.addEventListener(
|
||||||
|
toolsEvents.ANNOTATION_MODIFIED,
|
||||||
|
this.annotationModifiedListener
|
||||||
|
)
|
||||||
|
eventTarget.addEventListener(
|
||||||
|
toolsEvents.ANNOTATION_COMPLETED,
|
||||||
|
this.annotationModifiedListener
|
||||||
|
)
|
||||||
|
eventTarget.addEventListener(
|
||||||
|
toolsEvents.ANNOTATION_REMOVED,
|
||||||
|
this.annotationRemovedListener
|
||||||
|
)
|
||||||
|
},
|
||||||
|
async annotationRemovedListener(e) {
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
|
const { annotation } = e.detail
|
||||||
|
if (!annotation) return
|
||||||
|
if (!annotation.annotationId) return
|
||||||
|
await deleteTrialFileType(annotation.annotationId)
|
||||||
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
|
||||||
|
viewport.render()
|
||||||
|
// 删除成功
|
||||||
|
},
|
||||||
|
async annotationModifiedListener(e) {
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
|
const { annotation } = e.detail
|
||||||
|
if (!annotation) return
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||||
|
if (i === -1) return
|
||||||
|
if (this.viewportInfos[i].taskInfo.VisitTaskId !== this.taskInfo.VisitTaskId) return
|
||||||
|
const fileName = this.viewportInfos[i].currentFileName
|
||||||
|
const fileList = this.viewportInfos[i].fileList
|
||||||
|
const fileIndex = fileList.findIndex(f => f.FileName === fileName)
|
||||||
|
if (fileIndex === -1) return
|
||||||
|
const params = {
|
||||||
|
id: annotation.annotationId ? annotation.annotationId : '',
|
||||||
|
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
|
||||||
|
studyId: this.viewportInfos[i].studyId,
|
||||||
|
noneDicomFileId: fileList[fileIndex].Id,
|
||||||
|
path: fileList[fileIndex].Path,
|
||||||
|
measureData: JSON.stringify(annotation)
|
||||||
|
}
|
||||||
|
const res = await addNoneDicomMark(params)
|
||||||
|
if (annotation.annotationId) return
|
||||||
|
annotation.annotationId = res.Result
|
||||||
|
// 保存成功
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
},
|
||||||
|
// 重置视图
|
||||||
|
resetViewport() {
|
||||||
|
this.setToolsPassive()
|
||||||
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewportId = `canvas-${this.activeCanvasIndex}`
|
||||||
|
const viewport = (renderingEngine.getViewport(viewportId))
|
||||||
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
|
renderingEngine.render()
|
||||||
|
},
|
||||||
|
// 箭头工具输入标记名称自定义弹窗
|
||||||
|
async customPrompt() {
|
||||||
|
try {
|
||||||
|
const { value } = await this.$prompt('请输入标记名称')
|
||||||
|
return value
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 滚动条
|
||||||
|
clickSlider(e, index) {
|
||||||
|
const height = e.offsetY * 100 / this.$refs[`sliderBox-${index}`][0].clientHeight
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||||
|
if (i === -1) return
|
||||||
|
this.viewportInfos[i].height = height
|
||||||
|
let sliceIdx = Math.trunc(this.viewportInfos[i].imageIds.length * height / 100)
|
||||||
|
sliceIdx = sliceIdx >= this.viewportInfos[i].imageIds.length ? this.viewportInfos[i].imageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||||
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(
|
||||||
|
this.viewportInfos[i].viewportId
|
||||||
|
)
|
||||||
|
viewport.setImageIdIndex(sliceIdx)
|
||||||
|
viewport.render()
|
||||||
|
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
|
||||||
|
},
|
||||||
|
sliderMouseup(e, index) {
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||||
|
if (i === -1) return
|
||||||
|
this.viewportInfos[i].isMove = false
|
||||||
|
},
|
||||||
|
sliderMousemove(e, index) {
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||||
|
if (i === -1) return
|
||||||
|
if (!this.viewportInfos[i].isMove) return
|
||||||
|
const delta = this.viewportInfos[i].oldB - (this.viewportInfos[i].oldM - e.clientY)
|
||||||
|
const boxHeight = this.$refs[`sliderBox-${index}`][0].clientHeight
|
||||||
|
if (delta < 0) return
|
||||||
|
if (delta > boxHeight) return
|
||||||
|
const height = delta * 100 / boxHeight
|
||||||
|
let sliceIdx = Math.trunc(this.viewportInfos[i].imageIds.length * height / 100)
|
||||||
|
sliceIdx = sliceIdx >= this.viewportInfos[i].imageIds.length ? this.viewportInfos[i].imageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||||
|
this.viewportInfos[i].height = height
|
||||||
|
if (this.viewportInfos[i].currentImageIdIndex !== i) {
|
||||||
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(
|
||||||
|
this.viewportInfos[i].viewportId
|
||||||
|
)
|
||||||
|
viewport.setImageIdIndex(sliceIdx)
|
||||||
|
viewport.render()
|
||||||
|
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sliderMousedown(e, index) {
|
||||||
|
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||||
|
if (i === -1) return
|
||||||
|
const boxHeight = this.$refs[`sliderBox-${index}`][0].clientHeight
|
||||||
|
this.viewportInfos[i].oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
||||||
|
this.viewportInfos[i].oldM = e.clientY
|
||||||
|
this.viewportInfos[i].isMove = true
|
||||||
|
e.stopImmediatePropagation()
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
},
|
||||||
preventDefault(e) {
|
preventDefault(e) {
|
||||||
e.stopImmediatePropagation()
|
e.stopImmediatePropagation()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
@ -420,8 +734,26 @@ export default {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
.tools-wrapper {
|
.tools-wrapper {
|
||||||
height: 60px;
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
border-bottom: 1px solid #727272;
|
border-bottom: 1px solid #727272;
|
||||||
|
color: #ddd;
|
||||||
|
.tool-item {
|
||||||
|
padding: 5px;
|
||||||
|
margin: 0 5px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.tool-item-active {
|
||||||
|
background-color: #607d8b;
|
||||||
|
}
|
||||||
|
.tool-disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.viewports-wrapper {
|
.viewports-wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -441,17 +773,9 @@ export default {
|
||||||
.cell_active {
|
.cell_active {
|
||||||
border-color: #fafa00!important;
|
border-color: #fafa00!important;
|
||||||
}
|
}
|
||||||
.full-screen {
|
.cell-full-screen {
|
||||||
position: fixed;
|
grid-column: 1 / -1;
|
||||||
top: 0;
|
grid-row: 1 / -1;
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: white;
|
|
||||||
z-index: 1000;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
@ -502,6 +826,35 @@ export default {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.right-slider-box {
|
||||||
|
position: absolute;
|
||||||
|
right: 1px;
|
||||||
|
height: calc(100% - 140px);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
top: calc(50% - 30px);
|
||||||
|
width: 10px;
|
||||||
|
background: #333;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.right-slider-box:after{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -20px;
|
||||||
|
left: 0;
|
||||||
|
height: 20px;
|
||||||
|
width: 100%;
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
.slider {
|
||||||
|
height: 20px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
z-index:10;
|
||||||
|
background: #9e9e9e;
|
||||||
|
cursor: move
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
:related-study-info="relatedStudyInfo"
|
:related-study-info="relatedStudyInfo"
|
||||||
@toggleTaskByViewer="toggleTaskByViewer"
|
@toggleTaskByViewer="toggleTaskByViewer"
|
||||||
@toggleTask="toggleTask"
|
@toggleTask="toggleTask"
|
||||||
|
@toggleImage="toggleImage"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- 表单 -->
|
<!-- 表单 -->
|
||||||
|
@ -70,7 +71,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getRelatedVisitTask, getReadingImageFile } from '@/api/trials'
|
import { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto } from '@/api/trials'
|
||||||
import StudyList from './StudyList'
|
import StudyList from './StudyList'
|
||||||
import ImageViewer from './ImageViewer'
|
import ImageViewer from './ImageViewer'
|
||||||
import EcrfList from './EcrfList'
|
import EcrfList from './EcrfList'
|
||||||
|
@ -114,7 +115,7 @@ export default {
|
||||||
const idx = this.visitTaskList.findIndex(i => i.VisitTaskId === id)
|
const idx = this.visitTaskList.findIndex(i => i.VisitTaskId === id)
|
||||||
if (idx === -1) return
|
if (idx === -1) return
|
||||||
this.currentVisitInfo = this.visitTaskList[idx]
|
this.currentVisitInfo = this.visitTaskList[idx]
|
||||||
this.activeTaskVisitId = id
|
// this.activeTaskVisitId = id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -134,7 +135,8 @@ export default {
|
||||||
const res = await getRelatedVisitTask(params)
|
const res = await getRelatedVisitTask(params)
|
||||||
this.visitTaskList = res.Result.map((item) => ({
|
this.visitTaskList = res.Result.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
StudyList: []
|
StudyList: [],
|
||||||
|
Annotations: []
|
||||||
}))
|
}))
|
||||||
const idx = res.Result.findIndex(i => i.IsCurrentTask)
|
const idx = res.Result.findIndex(i => i.IsCurrentTask)
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
|
@ -147,10 +149,14 @@ export default {
|
||||||
const i = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
|
const i = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
await this.getReadingImageFile(res.Result[i].VisitTaskId, i)
|
await this.getReadingImageFile(res.Result[i].VisitTaskId, i)
|
||||||
|
await this.getAnnotations(res.Result[i].VisitTaskId, i)
|
||||||
const studyList = this.visitTaskList[i].StudyList
|
const studyList = this.visitTaskList[i].StudyList
|
||||||
if (studyList.length > 0) {
|
if (studyList.length > 0) {
|
||||||
const fileInfo = studyList[0].NoneDicomStudyFileList[0]
|
const fileInfo = studyList[0].NoneDicomStudyFileList[0]
|
||||||
this.relatedStudyInfo = { fileInfo, visitTaskInfo: this.visitTaskList[i], fileList: studyList[0].NoneDicomStudyFileList, fileIndex: 0, studyId: studyList[0].Id }
|
this.relatedStudyInfo = { fileInfo, visitTaskInfo: this.visitTaskList[i], fileList: studyList[0].NoneDicomStudyFileList, fileIndex: 0, studyId: studyList[0].Id }
|
||||||
|
if (!this.selectArr.includes(res.Result[i].VisitTaskId)) {
|
||||||
|
this.selectArr.push(res.Result[i].VisitTaskId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,10 +166,6 @@ export default {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 获取初始化渲染检查信息
|
|
||||||
getInitStudyList() {
|
|
||||||
// 有序阅片且非基线
|
|
||||||
},
|
|
||||||
// 获取任务关联的文件信息
|
// 获取任务关联的文件信息
|
||||||
getReadingImageFile(visitTaskId, visitTaskIdx) {
|
getReadingImageFile(visitTaskId, visitTaskIdx) {
|
||||||
return new Promise(async(resolve, reject) => {
|
return new Promise(async(resolve, reject) => {
|
||||||
|
@ -185,10 +187,36 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 获取任务关联的标注信息
|
||||||
|
getAnnotations(visitTaskId, visitTaskIdx) {
|
||||||
|
return new Promise(async(resolve, reject) => {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
visitTaskId: visitTaskId
|
||||||
|
}
|
||||||
|
const res = await getNoneDicomMarkListOutDto(params)
|
||||||
|
this.$set(this.visitTaskList[visitTaskIdx], 'Annotations', res.Result.NoneDicomMarkList)
|
||||||
|
this.loading = false
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
this.loading = false
|
||||||
|
reject(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
// 切换任务
|
// 切换任务
|
||||||
toggleTask(taskInfo) {
|
toggleTask(taskInfo) {
|
||||||
this.setActiveTaskVisitId(taskInfo.VisitTaskId)
|
this.setActiveTaskVisitId(taskInfo.VisitTaskId)
|
||||||
},
|
},
|
||||||
|
// 视图触发任务切换
|
||||||
|
async toggleTaskByViewer(visitTaskNum) {
|
||||||
|
const i = this.visitTaskList.findIndex(v => v.VisitTaskNum === visitTaskNum)
|
||||||
|
if (i === -1) return
|
||||||
|
const visistTaskId = this.visitTaskList[i].VisitTaskId
|
||||||
|
this.setActiveTaskVisitId(visistTaskId, true)
|
||||||
|
},
|
||||||
// 设置激活的访视
|
// 设置激活的访视
|
||||||
async setActiveTaskVisitId(id, isInitActiveFile = false) {
|
async setActiveTaskVisitId(id, isInitActiveFile = false) {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
|
@ -199,6 +227,7 @@ export default {
|
||||||
if (idx === -1) return
|
if (idx === -1) return
|
||||||
if (this.visitTaskList[idx].StudyList.length === 0) {
|
if (this.visitTaskList[idx].StudyList.length === 0) {
|
||||||
await this.getReadingImageFile(id, idx)
|
await this.getReadingImageFile(id, idx)
|
||||||
|
await this.getAnnotations(id, idx)
|
||||||
}
|
}
|
||||||
this.activeTaskVisitId = id
|
this.activeTaskVisitId = id
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
@ -207,12 +236,9 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 视图触发任务切换
|
// 切换图片
|
||||||
async toggleTaskByViewer(visitTaskNum) {
|
toggleImage(obj) {
|
||||||
const i = this.visitTaskList.findIndex(v => v.VisitTaskNum === visitTaskNum)
|
this.$refs[obj.taskId][0].activeImage(obj)
|
||||||
if (i === -1) return
|
|
||||||
const visistTaskId = this.visitTaskList[i].VisitTaskId
|
|
||||||
this.setActiveTaskVisitId(visistTaskId, true)
|
|
||||||
},
|
},
|
||||||
selectFile(obj) {
|
selectFile(obj) {
|
||||||
this.$refs['imageViewer'].setActiveCanvasImages(obj)
|
this.$refs['imageViewer'].setActiveCanvasImages(obj)
|
||||||
|
|
|
@ -1,3 +1,797 @@
|
||||||
<template>
|
<template>
|
||||||
<div>报告页</div>
|
<div class="report-wrapper">
|
||||||
|
<el-card v-loading="loading" shadow="never" style="display:flex;flex-direction: column;">
|
||||||
|
<div slot="header" class="clearfix report-header">
|
||||||
|
<h3 style="margin:0;padding:0;">{{ $t('trials:readingReport:title:eicrf') }}</h3>
|
||||||
|
<div style="margin-left:auto">
|
||||||
|
<el-button
|
||||||
|
v-if="readingTaskState<2"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="skipTask"
|
||||||
|
>
|
||||||
|
<!-- 跳过 -->
|
||||||
|
{{ $t('trials:readingReport:button:skip') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="getReportInfo">{{ $t('trials:readingReport:button:refresh') }}</el-button>
|
||||||
|
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleSave(true)">{{ $t('common:button:save') }}</el-button>
|
||||||
|
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleConfirm">{{ $t('common:button:submit') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="flex: 1">
|
||||||
|
<el-table
|
||||||
|
v-if="taskQuestions.length > 0"
|
||||||
|
ref="reportList"
|
||||||
|
v-adaptive="{bottomOffset:0}"
|
||||||
|
:data="taskQuestions"
|
||||||
|
row-key="Id"
|
||||||
|
border
|
||||||
|
default-expand-all
|
||||||
|
height="100"
|
||||||
|
:tree-props="{children: 'Childrens', hasChildren: 'hasChildren'}"
|
||||||
|
size="mini"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
prop=""
|
||||||
|
label=""
|
||||||
|
show-overflow-tooltip
|
||||||
|
width="350px"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-if="scope.row.QuestionName">{{ scope.row.BlindName ? scope.row.QuestionName : scope.row.QuestionName }}</span>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
style="font-weight: bold;font-size: 16px;color: #f44336;"
|
||||||
|
>
|
||||||
|
{{ scope.row.GroupName }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="task in visitTaskList"
|
||||||
|
:key="task.VisitTaskId"
|
||||||
|
prop="date"
|
||||||
|
show-overflow-tooltip
|
||||||
|
width="200px"
|
||||||
|
>
|
||||||
|
<template slot="header">
|
||||||
|
<div v-if="task.IsCurrentTask">
|
||||||
|
{{ task.BlindName }}
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div>
|
||||||
|
{{ task.BlindName }}
|
||||||
|
<el-button type="text" size="small" @click="previewDicoms(task)">
|
||||||
|
<span class="el-icon-view" />
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<template v-if="readingTaskState<2 && task.VisitTaskId === visitTaskId && (scope.row.Type==='input' || scope.row.Type==='number' || scope.row.Type==='select' || scope.row.Type==='textarea' || scope.row.Type==='radio')">
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<div>
|
||||||
|
<template v-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)" />
|
||||||
|
<el-input
|
||||||
|
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||||
|
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea')">
|
||||||
|
{{ questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId] }}
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
v-else-if="(scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||||
|
v-model="questionForm[scope.row.QuestionId]"
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<span v-else-if="scope.row.Type==='input' || scope.row.Type==='textarea'">
|
||||||
|
{{ questionForm[scope.row.QuestionId] }}
|
||||||
|
</span>
|
||||||
|
<el-select
|
||||||
|
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||||
|
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||||
|
size="mini"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<template>
|
||||||
|
<el-option
|
||||||
|
v-for="val in scope.row.TypeValue.split('|')"
|
||||||
|
:key="val"
|
||||||
|
:label="val"
|
||||||
|
:value="val"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='select'">
|
||||||
|
{{ questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId] }}
|
||||||
|
</span>
|
||||||
|
<el-select
|
||||||
|
v-else-if="(scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||||
|
v-model="questionForm[scope.row.QuestionId]"
|
||||||
|
size="mini"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<template>
|
||||||
|
<el-option
|
||||||
|
v-for="val in scope.row.TypeValue.split('|')"
|
||||||
|
:key="val"
|
||||||
|
:label="val"
|
||||||
|
:value="val"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
<span v-else-if="scope.row.Type==='select' || scope.row.Type==='radio'">
|
||||||
|
{{ questionForm[scope.row.QuestionId] }}
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
v-else-if="scope.row.DataSource !== 1 && questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='number' && (scope.row.xfIndex || scope.row.xfIndex === 0) && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||||
|
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||||
|
:disabled="scope.row.DataSource === 1"
|
||||||
|
size="mini"
|
||||||
|
@blur="limitBlur(questionForm[scope.row.QuestionId][scope.row.xfIndex], scope.row.TableQuestionId, scope.row.ValueType)"
|
||||||
|
@focus="() => {questionId = scope.row.QuestionId}"
|
||||||
|
>
|
||||||
|
<template v-if="scope.row.Unit !== 0" slot="append">{{ scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit }}</template>
|
||||||
|
<template v-else-if="scope.row.ValueType === 2" slot="append">%</template>
|
||||||
|
</el-input>
|
||||||
|
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='number' && (scope.row.xfIndex || scope.row.xfIndex === 0)">
|
||||||
|
<template v-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||||
|
{{ isNaN(parseInt(questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]))? questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]:`${questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row.ValueType === 2">
|
||||||
|
{{ isNaN(parseInt(questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId])) ? questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]:`${questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]} %` }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ isNaN(parseInt(questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId])) ? questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]:`${questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}` }}
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
v-else-if="scope.row.DataSource !== 1 && scope.row.Type==='number' && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||||
|
v-model="questionForm[scope.row.QuestionId]"
|
||||||
|
:disabled="scope.row.DataSource === 1"
|
||||||
|
size="mini"
|
||||||
|
@blur="limitBlur(questionForm, scope.row.QuestionId, scope.row.ValueType)"
|
||||||
|
@focus="() => {questionId = scope.row.QuestionId}"
|
||||||
|
>
|
||||||
|
<template v-if="scope.row.Unit !== 0" slot="append">{{ scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit }}</template>
|
||||||
|
<template v-else-if="scope.row.ValueType === 2" slot="append">%</template>
|
||||||
|
</el-input>
|
||||||
|
<span v-else-if="scope.row.Type==='number'">
|
||||||
|
<template v-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||||
|
{{ isNaN(parseInt(questionForm[scope.row.QuestionId]))? questionForm[scope.row.QuestionId]:`${questionForm[scope.row.QuestionId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row.ValueType === 2">
|
||||||
|
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId]:`${questionForm[scope.row.QuestionId]} %` }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId] : questionForm[scope.row.QuestionId] }}
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row.DictionaryCode">
|
||||||
|
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="criterionType === 10">
|
||||||
|
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]}` }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)" />
|
||||||
|
<template v-else-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||||
|
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row.ValueType === 2">
|
||||||
|
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId])) ? scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]} %` }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="scope.row.Answers && scope.row.Answers.hasOwnProperty(task.VisitTaskId)">
|
||||||
|
{{ scope.row.Answers[task.VisitTaskId] }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 签名框 -->
|
||||||
|
<el-dialog
|
||||||
|
v-if="signVisible"
|
||||||
|
:visible.sync="signVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
width="600px"
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
|
<div slot="title">
|
||||||
|
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
||||||
|
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
|
||||||
|
</div>
|
||||||
|
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script>
|
||||||
|
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
|
||||||
|
import { setSkipReadingCache } from '@/api/reading'
|
||||||
|
// import UploadFile from './UploadFile'
|
||||||
|
import const_ from '@/const/sign-code'
|
||||||
|
import SignForm from '@/views/trials/components/newSignForm'
|
||||||
|
import { getToken } from '@/utils/auth'
|
||||||
|
import store from '@/store'
|
||||||
|
export default {
|
||||||
|
name: 'ReportPage',
|
||||||
|
components: { SignForm },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
trialId: '',
|
||||||
|
visitTaskId: '',
|
||||||
|
subjectId: '',
|
||||||
|
readingTool: 1,
|
||||||
|
criterionType: null,
|
||||||
|
isReadingTaskViewInOrder: false,
|
||||||
|
currentUser: zzSessionStorage.getItem('userName'),
|
||||||
|
signVisible: false,
|
||||||
|
signCode: null,
|
||||||
|
visitTaskList: [],
|
||||||
|
taskQuestions: [],
|
||||||
|
loading: false,
|
||||||
|
answers: [],
|
||||||
|
readingTaskState: 2,
|
||||||
|
answerArr: [],
|
||||||
|
questions: [],
|
||||||
|
CalculationList: [],
|
||||||
|
TrialReadingCriterionId: null,
|
||||||
|
tableAnswers: {},
|
||||||
|
questionForm: {},
|
||||||
|
questionId: null,
|
||||||
|
taskInfo: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
questionForm: {
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
handler(v, oldv) {
|
||||||
|
try {
|
||||||
|
if (!v[this.questionId] || !oldv[this.questionId]) return
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
this.formItemNumberChange(this.questionId, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||||
|
this.trialId = this.$route.query.trialId
|
||||||
|
this.visitTaskId = this.taskInfo.VisitTaskId
|
||||||
|
this.subjectId = this.taskInfo.SubjectId
|
||||||
|
this.criterionType = this.taskInfo.CriterionType
|
||||||
|
this.digitPlaces = this.taskInfo.DigitPlaces
|
||||||
|
this.TrialReadingCriterionId = this.taskInfo.TrialReadingCriterionId
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
this.handleResize()
|
||||||
|
})
|
||||||
|
await this.getQuestionCalculateRelation()
|
||||||
|
this.getReportInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
limitBlur(questionForm, id, valueType) {
|
||||||
|
const value = questionForm[id]
|
||||||
|
if (valueType === 0) {
|
||||||
|
this.$set(questionForm, id, parseInt(value))
|
||||||
|
} else if (valueType === 3) {
|
||||||
|
this.$set(questionForm, id, parseFloat(value))
|
||||||
|
} else {
|
||||||
|
this.$set(questionForm, id, parseFloat(value).toFixed(this.digitPlaces))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setImageUrl(qid, index, tqid, url, RowId) {
|
||||||
|
if (index || index === 0) {
|
||||||
|
// 表格问题
|
||||||
|
this.$set(this.questionForm[qid][index], tqid, url)
|
||||||
|
this.$set(this.questionForm[qid][index], tqid + '_RowId', RowId)
|
||||||
|
// this.questionForm[qid][index][tqid] = url
|
||||||
|
} else {
|
||||||
|
// 非表格问题
|
||||||
|
this.questionForm[qid] = url
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getTagterAnswers(list, questionId) {
|
||||||
|
list.forEach(v => {
|
||||||
|
if (v.QuestionId === questionId) {
|
||||||
|
return Object.assign({}, v.Answers)
|
||||||
|
} else if (v.Childrens.length > 0) {
|
||||||
|
return this.getTagterAnswers(v.Childrens, questionId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
formItemNumberChange(questionId, isTable) {
|
||||||
|
if (isTable) {
|
||||||
|
this.CalculationList.forEach((v, i) => {
|
||||||
|
var find = v.CalculateQuestionList.filter(o => {
|
||||||
|
return o.QuestionId === questionId
|
||||||
|
})
|
||||||
|
// find的自动计算值number
|
||||||
|
if (find) {
|
||||||
|
var num = this.logic(v)
|
||||||
|
if (num !== false) {
|
||||||
|
this.$set(this.questionForm, v.QuestionId, num)
|
||||||
|
// this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.CalculationList.forEach(v => {
|
||||||
|
var find = v.CalculateQuestionList.filter(o => {
|
||||||
|
return o.TableQuestionId === questionId
|
||||||
|
})
|
||||||
|
// find的自动计算值number
|
||||||
|
if (find) {
|
||||||
|
var num = this.logic(v)
|
||||||
|
if (num !== false) {
|
||||||
|
this.$set(this.questionForm, v.QuestionId, num)
|
||||||
|
// this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// this.$emit('formItemNumberChange')
|
||||||
|
},
|
||||||
|
getTableAnswers(QuestionId, list) {
|
||||||
|
var arr = []
|
||||||
|
window.xfList = list
|
||||||
|
list.forEach((v, i) => {
|
||||||
|
var obj = {}
|
||||||
|
v.Childrens.forEach((o) => {
|
||||||
|
this.$set(o, 'xfIndex', i)
|
||||||
|
obj[o.TableQuestionId + '_RowId'] = o.RowId
|
||||||
|
obj[o.TableQuestionId] = o.Answers[this.visitTaskId]
|
||||||
|
})
|
||||||
|
arr.push(obj)
|
||||||
|
})
|
||||||
|
return arr
|
||||||
|
},
|
||||||
|
InitVisitTaskQuestionForm() {
|
||||||
|
this.taskQuestions.map((v, i) => {
|
||||||
|
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return
|
||||||
|
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') {
|
||||||
|
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId])
|
||||||
|
}
|
||||||
|
if (v.Type === 'table') {
|
||||||
|
var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i)
|
||||||
|
this.$set(this.questionForm, v.QuestionId, tableAnswers)
|
||||||
|
// this.$set(v, 'xfIndex', i)
|
||||||
|
}
|
||||||
|
if (v.Type === 'number') {
|
||||||
|
let val = null
|
||||||
|
if (v.ValueType === 0) {
|
||||||
|
val = parseInt(v.Answers[this.visitTaskId])
|
||||||
|
} else if (v.ValueType === 3) {
|
||||||
|
val = v.Answers[this.visitTaskId]
|
||||||
|
} else {
|
||||||
|
val = v.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : v.Answers[this.visitTaskId]
|
||||||
|
}
|
||||||
|
this.$set(this.questionForm, v.QuestionId, val)
|
||||||
|
}
|
||||||
|
if (v.Childrens.length > 0) {
|
||||||
|
this.setChild(v.Childrens)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.formItemNumberChange(this.questionId, false)
|
||||||
|
},
|
||||||
|
setChild(obj) {
|
||||||
|
obj.forEach((i, index) => {
|
||||||
|
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table') {
|
||||||
|
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId])
|
||||||
|
}
|
||||||
|
if (i.Type === 'table') {
|
||||||
|
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
|
||||||
|
this.$set(this.questionForm, i.QuestionId, tableAnswers)
|
||||||
|
}
|
||||||
|
if (i.Type === 'number') {
|
||||||
|
let val = null
|
||||||
|
if (i.ValueType === 0) {
|
||||||
|
val = parseInt(i.Answers[this.visitTaskId])
|
||||||
|
} else if (i.ValueType === 3) {
|
||||||
|
val = i.Answers[this.visitTaskId]
|
||||||
|
} else {
|
||||||
|
val = i.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : i.Answers[this.visitTaskId]
|
||||||
|
}
|
||||||
|
this.$set(this.questionForm, i.QuestionId, val)
|
||||||
|
}
|
||||||
|
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table') {
|
||||||
|
this.setChild(i.Childrens)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getQuestionCalculateRelation() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
getQuestionCalculateRelation({
|
||||||
|
TrialReadingCriterionId: this.TrialReadingCriterionId
|
||||||
|
}).then(res => {
|
||||||
|
this.CalculationList = res.Result
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
logic(rules, num = 0) {
|
||||||
|
try {
|
||||||
|
if (rules.CalculateQuestionList.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
rules.CalculateQuestionList.forEach((o, i) => {
|
||||||
|
if (i === 0) {
|
||||||
|
if (rules.CustomCalculateMark > 4) {
|
||||||
|
switch (rules.CustomCalculateMark) {
|
||||||
|
case 5:
|
||||||
|
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||||
|
if (qi === 0) {
|
||||||
|
num = parseFloat(q[o.TableQuestionId])
|
||||||
|
} else {
|
||||||
|
num *= parseFloat(q[o.TableQuestionId])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 6:
|
||||||
|
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||||
|
if (qi === 0) {
|
||||||
|
num = isNaN(parseFloat(q[o.TableQuestionId])) ? null : parseFloat(q[o.TableQuestionId])
|
||||||
|
} else {
|
||||||
|
num += isNaN(parseFloat(q[o.TableQuestionId])) ? null : parseFloat(q[o.TableQuestionId])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 7:
|
||||||
|
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||||
|
if (qi === 0) {
|
||||||
|
num = parseFloat(q[o.TableQuestionId])
|
||||||
|
} else {
|
||||||
|
num += parseFloat(q[o.TableQuestionId])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
|
||||||
|
break
|
||||||
|
case 8:
|
||||||
|
var arr = []
|
||||||
|
this.questionForm[o.QuestionId].forEach(q => {
|
||||||
|
arr.push(q[o.TableQuestionId])
|
||||||
|
})
|
||||||
|
num = arr.length === 0 ? 0 : Math.max(...arr)
|
||||||
|
break
|
||||||
|
case 9:
|
||||||
|
// eslint-disable-next-line no-redeclare
|
||||||
|
var arr = []
|
||||||
|
this.questionForm[o.QuestionId].forEach(q => {
|
||||||
|
arr.push(q[o.TableQuestionId])
|
||||||
|
})
|
||||||
|
num = arr.length === 0 ? 0 : Math.min(...arr)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
num = parseFloat(this.questionForm[o.TableQuestionId])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (rules.CustomCalculateMark) {
|
||||||
|
case 1:
|
||||||
|
num += parseFloat(this.questionForm[o.TableQuestionId])
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
num -= parseFloat(this.questionForm[o.TableQuestionId])
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
num *= parseFloat(this.questionForm[o.TableQuestionId])
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||||
|
// num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
|
||||||
|
if (rules.ValueType === 2) {
|
||||||
|
num = num * 100
|
||||||
|
}
|
||||||
|
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(digitPlaces) : '∞'
|
||||||
|
},
|
||||||
|
getReportInfo() {
|
||||||
|
this.loading = true
|
||||||
|
var params = {
|
||||||
|
visitTaskId: this.visitTaskId,
|
||||||
|
trialId: this.trialId
|
||||||
|
}
|
||||||
|
this.taskQuestions = []
|
||||||
|
getReadingReportEvaluation(params).then(res => {
|
||||||
|
this.readingTaskState = res.Result.ReadingTaskState
|
||||||
|
this.answerArr = []
|
||||||
|
this.questions = res.Result.TaskQuestions.concat()
|
||||||
|
var taskQuestions = this.getQuestions(res.Result.TaskQuestions)
|
||||||
|
taskQuestions.forEach(item => {
|
||||||
|
this.$set(this.taskQuestions, this.taskQuestions.length, item)
|
||||||
|
})
|
||||||
|
this.visitTaskList = res.Result.VisitTaskList
|
||||||
|
this.InitVisitTaskQuestionForm()
|
||||||
|
this.handleResize()
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => { this.loading = false })
|
||||||
|
},
|
||||||
|
getQuestions(questions) {
|
||||||
|
const arr = []
|
||||||
|
if (questions.length !== 0) {
|
||||||
|
questions.forEach((item) => {
|
||||||
|
const obj = item
|
||||||
|
this.$set(obj, 'Answers', {})
|
||||||
|
|
||||||
|
var digitPlaces = parseInt(localStorage.getItem('digitPlaces')) || 0
|
||||||
|
item.Answer.forEach(i => {
|
||||||
|
if (item.DictionaryCode) {
|
||||||
|
this.$set(obj.Answers, i.VisitTaskId, i.Answer ? parseInt(i.Answer) : null)
|
||||||
|
// obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
||||||
|
} else {
|
||||||
|
if (item.Type === 'number') {
|
||||||
|
let val = null
|
||||||
|
if (item.ValueType === 0) {
|
||||||
|
val = parseInt(i.Answer)
|
||||||
|
} else if (item.ValueType === 3) {
|
||||||
|
val = i.Answer
|
||||||
|
} else {
|
||||||
|
val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(digitPlaces)
|
||||||
|
}
|
||||||
|
this.$set(obj.Answers, i.VisitTaskId, val)
|
||||||
|
} else {
|
||||||
|
this.$set(obj.Answers, i.VisitTaskId, i.Answer)
|
||||||
|
}
|
||||||
|
// obj.Answers[i.VisitTaskId] = i.Answer
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (item.Childrens.length >= 1) {
|
||||||
|
obj.Childrens = this.getQuestions(item.Childrens)
|
||||||
|
}
|
||||||
|
arr.push(obj)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
},
|
||||||
|
handleShowDetail(val) {
|
||||||
|
this.getReportInfo()
|
||||||
|
// this.taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null)
|
||||||
|
},
|
||||||
|
async handleConfirm() {
|
||||||
|
await this.handleSave(false)
|
||||||
|
await this.verifyVisitTaskQuestions()
|
||||||
|
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||||
|
this.signCode = ImageAssessmentReportConfirmation
|
||||||
|
this.signVisible = true
|
||||||
|
},
|
||||||
|
verifyVisitTaskQuestions() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.loading = true
|
||||||
|
verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId }).then(res => {
|
||||||
|
this.loading = false
|
||||||
|
resolve()
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleResize() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.reportList ? this.$refs.reportList.doLayout() : ''
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 关闭签名框
|
||||||
|
closeSignDialog(isSign, signInfo) {
|
||||||
|
if (isSign) {
|
||||||
|
this.signConfirm(signInfo)
|
||||||
|
} else {
|
||||||
|
this.signVisible = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 签名并确认
|
||||||
|
signConfirm(signInfo) {
|
||||||
|
this.loading = true
|
||||||
|
var params = {
|
||||||
|
data: {
|
||||||
|
visitTaskId: this.visitTaskId
|
||||||
|
},
|
||||||
|
signInfo: signInfo
|
||||||
|
}
|
||||||
|
submitDicomVisitTask(params).then(res => {
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
if (this.$refs['signForm']) {
|
||||||
|
this.$refs['signForm'].btnLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.signVisible = false
|
||||||
|
// window.location.reload()
|
||||||
|
// window.opener.postMessage('refreshTaskList', window.location)
|
||||||
|
|
||||||
|
// 设置当前任务阅片状态为已读
|
||||||
|
this.readingTaskState = 2
|
||||||
|
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
|
||||||
|
// DicomEvent.$emit('setReadingState', 2)
|
||||||
|
window.opener.postMessage('refreshTaskList', window.location)
|
||||||
|
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
|
||||||
|
type: 'warning',
|
||||||
|
distinguishCancelAndClose: true
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// var token = getToken()
|
||||||
|
// var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||||
|
// var subjectId = this.$router.currentRoute.query.subjectId
|
||||||
|
// var trialId = this.$router.currentRoute.query.trialId
|
||||||
|
|
||||||
|
// this.$router.push({
|
||||||
|
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
|
||||||
|
// })
|
||||||
|
// DicomEvent.$emit('getNextTask')
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
.catch(action => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
|
||||||
|
this.$refs['signForm'].btnLoading = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
previewDicoms(task) {
|
||||||
|
var token = getToken()
|
||||||
|
// var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||||
|
var subjectCode = localStorage.getItem('subjectCode')
|
||||||
|
var subjectId = this.subjectId
|
||||||
|
var trialId = this.trialId
|
||||||
|
var isReadingTaskViewInOrder = this.isReadingTaskViewInOrder
|
||||||
|
var criterionType = this.criterionType
|
||||||
|
var readingTool = this.readingTool
|
||||||
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
var path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
const routeData = this.$router.resolve({ path })
|
||||||
|
window.open(routeData.href, '_blank')
|
||||||
|
},
|
||||||
|
handleSave(isPrompt) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.loading = true
|
||||||
|
var answers = []
|
||||||
|
var tableQuestionAnswer = []
|
||||||
|
for (const k in this.questionForm) {
|
||||||
|
if (this.questionForm[k] instanceof Array) {
|
||||||
|
this.questionForm[k].forEach((v, i) => {
|
||||||
|
Object.keys(v).forEach(o => {
|
||||||
|
if (o.indexOf('_RowId') === -1) {
|
||||||
|
tableQuestionAnswer.push({
|
||||||
|
questionId: k,
|
||||||
|
answer: v[o],
|
||||||
|
tableQuestionId: o,
|
||||||
|
rowId: v[o + '_RowId']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// tableQuestionAnswer.push({})
|
||||||
|
} else {
|
||||||
|
answers.push({ questionId: k, answer: this.questionForm[k].toString() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var params = {
|
||||||
|
visitTaskId: this.visitTaskId,
|
||||||
|
questionAnswer: answers,
|
||||||
|
tableQuestionAnswer: tableQuestionAnswer
|
||||||
|
}
|
||||||
|
changeCalculationAnswer(params).then(res => {
|
||||||
|
if (isPrompt) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
// DicomEvent.$emit('refreshQuestionAnswer')
|
||||||
|
this.loading = false
|
||||||
|
resolve()
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async skipTask() {
|
||||||
|
try {
|
||||||
|
// 是否确认跳过?
|
||||||
|
const confirm = await this.$confirm(
|
||||||
|
this.$t('trials:readingReport:message:skipConfirm'),
|
||||||
|
{
|
||||||
|
type: 'warning',
|
||||||
|
distinguishCancelAndClose: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (confirm !== 'confirm') return
|
||||||
|
this.loading = true
|
||||||
|
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
|
||||||
|
this.loading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-wrapper{
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
// background-color: #fff;
|
||||||
|
background-color: #000;
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 10px;
|
||||||
|
// background: #d0d0d0;
|
||||||
|
}
|
||||||
|
.report-header{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.el-card{
|
||||||
|
background-color: #000;
|
||||||
|
color: #ffffff;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
::v-deep .el-table--border th.gutter:last-of-type{
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
::v-deep .el-table, .el-table__expanded-cell {
|
||||||
|
background-color: #000;
|
||||||
|
color: #fff;
|
||||||
|
border-color:#444444;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-table th, .el-table tr {
|
||||||
|
background-color: #000;
|
||||||
|
color: #fff;
|
||||||
|
border-color:#444444;
|
||||||
|
}
|
||||||
|
::v-deep .el-table__body tr > td{
|
||||||
|
background-color:#000 !important;
|
||||||
|
color: #fff;
|
||||||
|
border-color:#444444;
|
||||||
|
}
|
||||||
|
::v-deep .el-table__body tr:hover > td{
|
||||||
|
background-color:#858282 !important;
|
||||||
|
color: #fff;
|
||||||
|
border-color:#444444;
|
||||||
|
}
|
||||||
|
::v-deep .el-table--border th.gutter:last-of-type{
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
::v-deep .el-card__header{
|
||||||
|
border: none;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
::v-deep .el-upload-list--picture-card .el-upload-list__item{
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
::v-deep .el-upload--picture-card{
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .el-switch__label.is-active{
|
||||||
|
color: #428bca;
|
||||||
|
}
|
||||||
|
.uploadWrapper{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.Id}`" :name="`${study.Id}`">
|
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.Id}`" :name="`${study.Id}`">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div
|
<div
|
||||||
|
v-if="!study.IsCriticalSequence"
|
||||||
class="dicom-desc"
|
class="dicom-desc"
|
||||||
>
|
>
|
||||||
<div>{{ study.CodeView }}</div>
|
<div>{{ study.CodeView }}</div>
|
||||||
|
@ -27,6 +28,10 @@
|
||||||
<span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
|
<span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<!-- 关键序列 -->
|
||||||
|
关键文件
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="series">
|
<div class="series">
|
||||||
<div
|
<div
|
||||||
|
@ -90,6 +95,14 @@ export default {
|
||||||
this.activeFileIndex = fileIndex
|
this.activeFileIndex = fileIndex
|
||||||
const fileList = study.NoneDicomStudyFileList
|
const fileList = study.NoneDicomStudyFileList
|
||||||
this.$emit('selectFile', { fileInfo: fileList[fileIndex], fileList, visitTaskInfo: this.visitTaskInfo, fileIndex: fileIndex, studyId: study.Id })
|
this.$emit('selectFile', { fileInfo: fileList[fileIndex], fileList, visitTaskInfo: this.visitTaskInfo, fileIndex: fileIndex, studyId: study.Id })
|
||||||
|
},
|
||||||
|
activeImage(obj) {
|
||||||
|
if (this.studyList.length === 0) return
|
||||||
|
const i = this.studyList.findIndex(i => i.Id === obj.studyId)
|
||||||
|
if (i === -1) return
|
||||||
|
this.activeNames.push(obj.studyId)
|
||||||
|
this.activeStudyIndex = i
|
||||||
|
this.activeFileIndex = obj.imageIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
:label="$t('trials:reading:tabTitle:report')"
|
:label="$t('trials:reading:tabTitle:report')"
|
||||||
name="report"
|
name="report"
|
||||||
>
|
>
|
||||||
<report-page />
|
<report-page v-if="activeName === 'report'" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue