Compare commits

..

No commits in common. "cbd860a35e4aa33a68c435374fe292d0caf9750c" and "fe64feac80ab9754acdc81cbb17cd91938f037bd" have entirely different histories.

26 changed files with 92 additions and 509 deletions

View File

@ -98,7 +98,6 @@ import timeTag from '@/components/timeTag'
import Vue from 'vue' import Vue from 'vue'
import i18n from './lang' import i18n from './lang'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent' import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import WHITELIST from "./utils/whiteList"
export default { export default {
name: 'App', name: 'App',
components: { components: {
@ -157,7 +156,7 @@ export default {
// }, // },
methods: { methods: {
getIsLock() { getIsLock() {
if (zzSessionStorage.getItem('isLock') === 'true' && !WHITELIST.includes(this.$route.path)) { if (zzSessionStorage.getItem('isLock') === 'true') {
this.isLock = true this.isLock = true
} else { } else {
this.isLock = false this.isLock = false

View File

@ -480,11 +480,3 @@ export function getNoneDicomMarkList(data) {
data data
}) })
} }
export function getFilterTableQuestion(data) {
return request({
url: `/ReadingImageTask/getFilterTableQuestion`,
method: 'post',
data
})
}

View File

@ -141,10 +141,6 @@ export default {
type: Number, type: Number,
default: 2, default: 2,
}, },
isReading: {
type: Boolean,
default: false,
}
}, },
data() { data() {
return { return {
@ -446,9 +442,6 @@ export default {
let params = { let params = {
TrialImageDownloadId: this.downloadId, TrialImageDownloadId: this.downloadId,
} }
if (this.isReading) {
params.VisitTaskId = this.TaskId
}
await downloadImageSuccess(params) await downloadImageSuccess(params)
} catch (err) { } catch (err) {
console.log(err) console.log(err)

View File

@ -43,8 +43,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<div class="btnBox"> <div class="btnBox">
<!--上传---> <!--上传--->
<form id="inputForm" :ref="`uploadForm_${scope.row.Id}`" enctype="multipart/form-data" <form id="inputForm" :ref="`uploadForm_${scope.row.Id}`" enctype="multipart/form-data" v-if="!forbid">
v-if="!forbid && (!isReading || isDownloaded)">
<div class="form-group" style="margin-right: 10px"> <div class="form-group" style="margin-right: 10px">
<div :id="`directoryInputWrapper_${scope.row.Id}`" class="btn btn-link file-input"> <div :id="`directoryInputWrapper_${scope.row.Id}`" class="btn btn-link file-input">
<el-button circle icon="el-icon-upload2" :disabled="btnLoading" :loading="btnLoading" <el-button circle icon="el-icon-upload2" :disabled="btnLoading" :loading="btnLoading"
@ -71,7 +70,7 @@
</el-table> </el-table>
<div style="margin: 10px 0" class="top"> <div style="margin: 10px 0" class="top">
<span>{{ $t('upload:dicom:uploadTitle') }}</span> <span>{{ $t('upload:dicom:uploadTitle') }}</span>
<div class="btnBox" v-if="!forbid && (!isReading || isDownloaded)"> <div class="btnBox" v-if="!forbid">
<span style="margin-right: 10px">{{ $store.state.trials.uploadTip }}</span> <span style="margin-right: 10px">{{ $store.state.trials.uploadTip }}</span>
<form id="inputForm" ref="uploadForm" enctype="multipart/form-data"> <form id="inputForm" ref="uploadForm" enctype="multipart/form-data">
<div class="form-group"> <div class="form-group">
@ -380,10 +379,6 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
isReading: {
type: Boolean,
default: false,
}
}, },
components: { components: {
'study-view': studyView, 'study-view': studyView,
@ -433,8 +428,7 @@ export default {
openSubjectVisitId: null, openSubjectVisitId: null,
openVisitTaskId: null, openVisitTaskId: null,
TrialModality: [], TrialModality: [],
IsReadingTaskViewInOrder: 2, IsReadingTaskViewInOrder: 2
isDownloaded: false
} }
}, },
async mounted() { async mounted() {
@ -477,10 +471,6 @@ export default {
let res = await getSubjectImageUploadList(params) let res = await getSubjectImageUploadList(params)
this.loading = false this.loading = false
if (res.IsSuccess) { if (res.IsSuccess) {
this.isDownloaded = this.Criterion && this.Criterion.CriterionType && (
this.Criterion.CriterionType == 19 ||
this.Criterion.CriterionType == 20
) ? res.OtherInfo.IsIRImageDownloaded : true
this.TrialModality = res.OtherInfo.TrialModality.split('|') this.TrialModality = res.OtherInfo.TrialModality.split('|')
this.IsReadingTaskViewInOrder = res.OtherInfo.IsReadingTaskViewInOrder || res.OtherInfo.IsReadingTaskViewInOrder === 0 ? res.OtherInfo.IsReadingTaskViewInOrder : 2 this.IsReadingTaskViewInOrder = res.OtherInfo.IsReadingTaskViewInOrder || res.OtherInfo.IsReadingTaskViewInOrder === 0 ? res.OtherInfo.IsReadingTaskViewInOrder : 2
this.StudyInstanceUidList = [] this.StudyInstanceUidList = []

View File

@ -6,13 +6,12 @@
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:dicom')" name="dicom"> <el-tab-pane :label="$t('uploadDicomAndNonedicom:label:dicom')" name="dicom">
<dicomFile v-if="activeName === 'dicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode" <dicomFile v-if="activeName === 'dicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
:Criterion="Criterion" :TaskId="VisitTaskId" :isUpload.sync="isUpload" :Criterion="Criterion" :TaskId="VisitTaskId" :isUpload.sync="isUpload"
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :IsImageSegment="IsImageSegment" :forbid="forbid" :isReadingTaskViewInOrder="isReadingTaskViewInOrder" :IsImageSegment="IsImageSegment" :forbid="forbid" />
:isReading="isReading" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:nonedicom')" name="nonedicom"> <el-tab-pane :label="$t('uploadDicomAndNonedicom:label:nonedicom')" name="nonedicom">
<nonedicomFile v-if="activeName === 'nonedicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode" <nonedicomFile v-if="activeName === 'nonedicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
:Criterion="Criterion" :VisitTaskId="VisitTaskId" :isUpload.sync="isUpload" :IsImageSegment="IsImageSegment" :Criterion="Criterion" :VisitTaskId="VisitTaskId" :isUpload.sync="isUpload" :IsImageSegment="IsImageSegment"
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :forbid="forbid" :isReading="isReading" /> :isReadingTaskViewInOrder="isReadingTaskViewInOrder" :forbid="forbid" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-dialog> </el-dialog>
@ -59,10 +58,6 @@ export default {
IsImageSegment: { IsImageSegment: {
type: Boolean, type: Boolean,
default: false, default: false,
},
isReading: {
type: Boolean,
default: false,
} }
}, },
data() { data() {

View File

@ -111,7 +111,7 @@
:title="$t('upload:nonedicom:button:preview')" @click.stop="handlePreviewNoneDicomFiles(scope.row)" /> :title="$t('upload:nonedicom:button:preview')" @click.stop="handlePreviewNoneDicomFiles(scope.row)" />
<!--上传---> <!--上传--->
<el-button circle icon="el-icon-upload2" :title="$t('upload:nonedicom:button:upload')" v-if="!forbid" <el-button circle icon="el-icon-upload2" :title="$t('upload:nonedicom:button:upload')" v-if="!forbid"
@click.native.prevent="handleUpload(scope.row)" :disabled="isReading && !isDownloaded" /> @click.native.prevent="handleUpload(scope.row)" />
<!--删除---> <!--删除--->
<el-button :disabled="scope.row.UploadedFileCount <= 0 || <el-button :disabled="scope.row.UploadedFileCount <= 0 ||
scope.row.ReadingTaskState === 2 scope.row.ReadingTaskState === 2
@ -270,10 +270,6 @@ export default {
type: Number, type: Number,
default: 0, default: 0,
}, },
isReading: {
type: Boolean,
default: false,
}
}, },
data() { data() {
return { return {
@ -295,8 +291,7 @@ export default {
BodyPart: {}, BodyPart: {},
relationInfo: { relationInfo: {
ImageFormatList: [] ImageFormatList: []
}, }
isDownloaded: false
} }
}, },
watch: { watch: {
@ -353,10 +348,6 @@ export default {
if (res.IsSuccess) { if (res.IsSuccess) {
this.list = res.Result this.list = res.Result
this.relationInfo = res.OtherInfo this.relationInfo = res.OtherInfo
this.isDownloaded = this.Criterion && this.Criterion.CriterionType && (
this.Criterion.CriterionType == 19 ||
this.Criterion.CriterionType == 20
) ? res.OtherInfo.IsIRImageDownloaded : true
this.faccept = [] this.faccept = []
this.relationInfo.ImageFormatList.forEach((item) => { this.relationInfo.ImageFormatList.forEach((item) => {
this.faccept.push(`.${item}`) this.faccept.push(`.${item}`)

View File

@ -149,11 +149,6 @@ export const constantRoutes = [
hidden: true, hidden: true,
component: () => import('@/views/trials/trials-panel/reading/dicoms/none-dicoms') component: () => import('@/views/trials/trials-panel/reading/dicoms/none-dicoms')
}, },
{
path: '/ecrfList',
hidden: true,
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/TableList')
},
{ {
path: '/readingPage', path: '/readingPage',
name: 'readingPage', name: 'readingPage',

View File

@ -11,10 +11,10 @@ function zipFiles(zipName, files) {
store.dispatch('trials/setUnLock', true) store.dispatch('trials/setUnLock', true)
files = formatFiles(files) files = formatFiles(files)
// 创建压缩文件输出流 // 创建压缩文件输出流
let zipFileOutputStream = streamSaver.createWriteStream(zipName); const zipFileOutputStream = streamSaver.createWriteStream(zipName);
// 创建下载文件流 // 创建下载文件流
const fileIterator = files.values(); const fileIterator = files.values();
let readableZipStream = new ZIP({ const readableZipStream = new ZIP({
async pull(ctrl) { async pull(ctrl) {
const fileInfo = fileIterator.next(); const fileInfo = fileIterator.next();
if (fileInfo.done) {//迭代终止 if (fileInfo.done) {//迭代终止
@ -41,13 +41,9 @@ function zipFiles(zipName, files) {
.then(() => { .then(() => {
console.log("同步下载打包结束时间:" + new Date()); console.log("同步下载打包结束时间:" + new Date());
store.dispatch('trials/setUnLock', false) store.dispatch('trials/setUnLock', false)
readableZipStream = null;
zipFileOutputStream = null;
resolve(true) resolve(true)
}).catch(err => { }).catch(err => {
console.log(err); console.log(err);
readableZipStream = null;
zipFileOutputStream = null;
resolve(false) resolve(false)
}); });
} else { } else {
@ -65,16 +61,14 @@ async function updateFile(file, name) {
return new Promise(async resolve => { return new Promise(async resolve => {
try { try {
store.dispatch('trials/setUnLock', true) store.dispatch('trials/setUnLock', true)
let fileOutputStream = streamSaver.createWriteStream(name); const fileOutputStream = streamSaver.createWriteStream(name);
// file = decodeUtf8(file); // file = decodeUtf8(file);
let res = await fetch(file); let res = await fetch(file);
res.body.pipeTo(fileOutputStream).then(() => { res.body.pipeTo(fileOutputStream).then(() => {
store.dispatch('trials/setUnLock', true) store.dispatch('trials/setUnLock', true)
fileOutputStream = null;
resolve(true) resolve(true)
}).catch(err => { }).catch(err => {
console.log(err) console.log(err)
fileOutputStream = null;
resolve(false) resolve(false)
}); });
} catch (err) { } catch (err) {

View File

@ -1,2 +1,2 @@
const WHITELIST = ['/', "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/link_expired', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms', '/ecrfList'] const WHITELIST = ['/', "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/link_expired', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
export default WHITELIST export default WHITELIST

View File

@ -50,9 +50,6 @@
</div> </div>
<div v-if="v.fileType.includes('zip')" class="content flex_col">
<img :title="v.FileName" crossorigin="anonymous" :src="zipImg" height="100%"/>
</div>
</div> </div>
</div> </div>
<div class="Anonymous" v-if="isAnonymous"> <div class="Anonymous" v-if="isAnonymous">
@ -161,7 +158,6 @@ import hardcodedMetaDataProvider from '@/views/trials/trials-panel/reading/visit
import registerWebImageLoader from '@/views/trials/trials-panel/reading/visit-review/js/registerWebImageLoader' import registerWebImageLoader from '@/views/trials/trials-panel/reading/visit-review/js/registerWebImageLoader'
import Note_RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms3D/components/tools/Note_RectangleRoiTool' import Note_RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms3D/components/tools/Note_RectangleRoiTool'
import { noneDicomStudyMaskImage, noneDicomStudyUndoMaskImage } from "@/api/reading" import { noneDicomStudyMaskImage, noneDicomStudyUndoMaskImage } from "@/api/reading"
import zipImg from '@/assets/zip.png'
const { ViewportType } = Enums const { ViewportType } = Enums
const renderingEngineId = 'myRenderingEngine' const renderingEngineId = 'myRenderingEngine'
const { const {
@ -225,7 +221,7 @@ export default {
activeTool: '', activeTool: '',
imageType: ['image/jpeg', 'image/jpg', 'image/bmp', 'image/png'], imageType: ['image/jpeg', 'image/jpg', 'image/bmp', 'image/png'],
loading: false, loading: false,
isFitToWindowMode: true, isFitToWindowMode: false,
trialId: null, trialId: null,
activeName: '1', activeName: '1',
tools: [], tools: [],
@ -235,8 +231,7 @@ export default {
tip: [ tip: [
this.$t('DicomViewer:anonymous:after'), this.$t('DicomViewer:anonymous:after'),
this.$t('DicomViewer:anonymous:before') this.$t('DicomViewer:anonymous:before')
], ]
zipImg
} }
}, },
computed: { computed: {

View File

@ -42,9 +42,6 @@
<el-image v-else-if=" <el-image v-else-if="
!!~k.FileType.indexOf('mp4') !!~k.FileType.indexOf('mp4')
" style="width: 100%; height: 100%" :src="mp4" fit="contain" crossorigin="anonymous" /> " style="width: 100%; height: 100%" :src="mp4" fit="contain" crossorigin="anonymous" />
<el-image v-else-if="
!!~k.FileType.indexOf('zip')
" style="width: 100%; height: 100%" :src="zipImg" fit="contain" crossorigin="anonymous" />
</div> </div>
<div class="file-text" :title="k.FileName"> <div class="file-text" :title="k.FileName">
{{ k.FileName }} {{ k.FileName }}
@ -76,7 +73,6 @@ import { getNoneDicomStudyList, setNodicomStudyState } from '@/api/trials'
import FileNameSorter from "@/utils/customSort" import FileNameSorter from "@/utils/customSort"
import pdf from '@/assets/pdf.png' import pdf from '@/assets/pdf.png'
import mp4 from '@/assets/mp4.png' import mp4 from '@/assets/mp4.png'
import zipImg from '@/assets/zip.jpg'
export default { export default {
name: 'StudyList', name: 'StudyList',
props: { props: {
@ -102,7 +98,6 @@ export default {
studyList: [], studyList: [],
pdf, pdf,
mp4, mp4,
zipImg,
BodyPart: {}, BodyPart: {},
subjectVisitId: '', subjectVisitId: '',
studyId: '', studyId: '',

View File

@ -219,8 +219,8 @@
</div> </div>
</el-tooltip> </el-tooltip>
<el-popover v-model="keySeriesPopoverVisible" placement="bottom" trigger="click" <el-popover v-model="keySeriesPopoverVisible" placement="bottom" trigger="click" popper-class="key-series-popper"
popper-class="key-series-popper" @show="showKeySeriesPanel"> @show="showKeySeriesPanel">
<ul class="key-series-list"> <ul class="key-series-list">
<li v-if="keyStack && keyStack.taskBlindName" class="key-series-header"> <li v-if="keyStack && keyStack.taskBlindName" class="key-series-header">
<div class="key-series-header-top"> <div class="key-series-header-top">
@ -708,10 +708,10 @@
</el-dialog> </el-dialog>
<upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId" <upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId"
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible" :subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible"
:visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" :isReading="true" /> :visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
<download-dicom-and-nonedicom v-if="downloadImageVisible" :subject-id="uploadSubjectId" <download-dicom-and-nonedicom v-if="downloadImageVisible" :subject-id="uploadSubjectId"
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :task-id="taskId" :subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :task-id="taskId"
:visible.sync="downloadImageVisible" :isReading="true" /> :visible.sync="downloadImageVisible" />
<!-- 签名框 --> <!-- 签名框 -->
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px" <el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
custom-class="base-dialog-wrapper"> custom-class="base-dialog-wrapper">

View File

@ -33,21 +33,17 @@
<div v-for="item in qs.Childrens" :key="item.Id"> <div v-for="item in qs.Childrens" :key="item.Id">
<div v-if="item.Type === 'basicTable'" class="flex-row" style="margin:3px 0;"> <div v-if="item.Type === 'basicTable'" class="flex-row" style="margin:3px 0;">
<div class="title">{{ item.QuestionName }}</div> <div class="title">{{ item.QuestionName }}</div>
<div v-if="item.LesionType === 104"> <div v-if="item.LesionType === 104 && readingTaskState < 2">
<div <div class="add-icon" @click.prevent="downloadTpl">
class="add-icon" @click.prevent="downloadTpl" v-if="readingTaskState < 2">
<i class="el-icon-download" /> <i class="el-icon-download" />
</div> </div>
<div class="add-icon" style="margin: 0 5px;" <div class="add-icon" style="margin: 0 5px;"
@click.prevent="uploadTpl(item.LesionType, item.QuestionName)" v-if="readingTaskState < 2"> @click.prevent="uploadTpl(item.LesionType, item.QuestionName)">
<i class="el-icon-upload2" /> <i class="el-icon-upload2" />
</div> </div>
<div class="add-icon" @click.prevent="handleAddOrEdit('add', item)" v-if="readingTaskState < 2"> <div class="add-icon" @click.prevent="handleAddOrEdit('add', item)">
<i class="el-icon-plus" /> <i class="el-icon-plus" />
</div> </div>
<div class="add-icon" @click.prevent="handleView(item)">
<i class="el-icon-view" />
</div>
</div> </div>
</div> </div>
@ -226,7 +222,6 @@
<script> <script>
import { saveTaskQuestion, submitTableQuestion, deleteReadingRowAnswer } from '@/api/trials' import { saveTaskQuestion, submitTableQuestion, deleteReadingRowAnswer } from '@/api/trials'
import { resetReadingTask, getIVUSTemplate } from '@/api/reading' import { resetReadingTask, getIVUSTemplate } from '@/api/reading'
import { getToken } from '@/utils/auth'
import DicomEvent from './../DicomEvent' import DicomEvent from './../DicomEvent'
import store from '@/store' import store from '@/store'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
@ -289,8 +284,7 @@ export default {
sRoiEndDistanceId: '', sRoiEndDistanceId: '',
sRoiDistanceId: '', sRoiDistanceId: '',
rowSaveLoadingMap: {}, rowSaveLoadingMap: {},
dialogSaveLoading: false, dialogSaveLoading: false
childWindows: []
} }
}, },
computed: { computed: {
@ -330,13 +324,11 @@ export default {
DicomEvent.$on('refreshQuestions', _ => { DicomEvent.$on('refreshQuestions', _ => {
this.refreshQuestions() this.refreshQuestions()
}) })
window.addEventListener('beforeunload', this.closeAllChildWindows)
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('setCollapseActive') DicomEvent.$off('setCollapseActive')
DicomEvent.$off('getUnSaveTarget') DicomEvent.$off('getUnSaveTarget')
DicomEvent.$off('refreshQuestions') DicomEvent.$off('refreshQuestions')
window.removeEventListener('beforeunload', this.closeAllChildWindows)
}, },
methods: { methods: {
handleReadingChart(e) { handleReadingChart(e) {
@ -747,24 +739,6 @@ export default {
this.addOrEdit.visible = true this.addOrEdit.visible = true
this.addOrEdit.lesionType = row.LesionType this.addOrEdit.lesionType = row.LesionType
}, },
handleView(item) {
localStorage.setItem('taskBlindName', this.taskBlindName)
localStorage.setItem('isReadingShowSubjectInfo', this.isReadingShowSubjectInfo)
let token = getToken()
let routeData = this.$router.resolve({ path: `/ecrfList?trialId=${this.$route.query.trialId}&visitTaskId=${this.visitTaskId}&questionId=${item.Id}&TokenKey=${token}` })
const win = window.open(routeData.href, '_blank')
if (win) {
this.childWindows.push(win)
}
},
closeAllChildWindows() {
this.childWindows.forEach(win => {
if (win && !win.closed) {
win.close()
}
})
this.childWindows = []
},
async saveFormData() { async saveFormData() {
if (this.dialogSaveLoading) return if (this.dialogSaveLoading) return
this.dialogSaveLoading = true this.dialogSaveLoading = true

View File

@ -33,20 +33,17 @@
<div v-for="item in qs.Childrens" :key="item.Id"> <div v-for="item in qs.Childrens" :key="item.Id">
<div v-if="item.Type === 'basicTable'" class="flex-row" style="margin:3px 0;"> <div v-if="item.Type === 'basicTable'" class="flex-row" style="margin:3px 0;">
<div class="title">{{ item.QuestionName }}</div> <div class="title">{{ item.QuestionName }}</div>
<div v-if="(item.LesionType === 104)"> <div v-if="(item.LesionType === 104) && readingTaskState < 2">
<div class="add-icon" @click.prevent="downloadTpl(item.LesionType)" v-if="readingTaskState < 2"> <div class="add-icon" @click.prevent="downloadTpl(item.LesionType)">
<i class="el-icon-download" /> <i class="el-icon-download" />
</div> </div>
<div class="add-icon" style="margin: 0 5px;" <div class="add-icon" style="margin: 0 5px;"
@click.prevent="uploadTpl(item.LesionType, item.QuestionName)" v-if="readingTaskState < 2"> @click.prevent="uploadTpl(item.LesionType, item.QuestionName)">
<i class="el-icon-upload2" /> <i class="el-icon-upload2" />
</div> </div>
<div class="add-icon" @click.prevent="handleAddOrEdit('add', item)" v-if="readingTaskState < 2"> <div class="add-icon" @click.prevent="handleAddOrEdit('add', item)">
<i class="el-icon-plus" /> <i class="el-icon-plus" />
</div> </div>
<div class="add-icon" @click.prevent="handleView(item)">
<i class="el-icon-view" />
</div>
</div> </div>
</div> </div>
@ -227,7 +224,6 @@ import { saveTaskQuestion, submitTableQuestion, deleteReadingRowAnswer } from '@
import { resetReadingTask, getOCTFCTTemplate, getOCTLipidAngleTemplate } from '@/api/reading' import { resetReadingTask, getOCTFCTTemplate, getOCTLipidAngleTemplate } from '@/api/reading'
import DicomEvent from './../DicomEvent' import DicomEvent from './../DicomEvent'
import store from '@/store' import store from '@/store'
import { getToken } from '@/utils/auth'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import Questions from './../Questions' import Questions from './../Questions'
import QuestionTableFormItem from './QuestionTableFormItem' import QuestionTableFormItem from './QuestionTableFormItem'
@ -289,8 +285,7 @@ export default {
sRoiEndDistanceId: '', sRoiEndDistanceId: '',
sRoiDistanceId: '', sRoiDistanceId: '',
rowSaveLoadingMap: {}, rowSaveLoadingMap: {},
dialogSaveLoading: false, dialogSaveLoading: false
childWindows: []
} }
}, },
computed: { computed: {
@ -330,13 +325,11 @@ export default {
DicomEvent.$on('refreshQuestions', _ => { DicomEvent.$on('refreshQuestions', _ => {
this.refreshQuestions() this.refreshQuestions()
}) })
window.addEventListener('beforeunload', this.closeAllChildWindows)
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('setCollapseActive') DicomEvent.$off('setCollapseActive')
DicomEvent.$off('getUnSaveTarget') DicomEvent.$off('getUnSaveTarget')
DicomEvent.$off('refreshQuestions') DicomEvent.$off('refreshQuestions')
window.removeEventListener('beforeunload', this.closeAllChildWindows)
}, },
methods: { methods: {
handleReadingChart(e) { handleReadingChart(e) {
@ -762,27 +755,6 @@ export default {
this.addOrEdit.visible = true this.addOrEdit.visible = true
this.addOrEdit.lesionType = row.LesionType this.addOrEdit.lesionType = row.LesionType
}, },
handleView(item) {
if (this.openWindow) {
this.openWindow.close()
}
localStorage.setItem('taskBlindName', this.taskBlindName)
localStorage.setItem('isReadingShowSubjectInfo', this.isReadingShowSubjectInfo)
let token = getToken()
let routeData = this.$router.resolve({ path: `/ecrfList?trialId=${this.$route.query.trialId}&visitTaskId=${this.visitTaskId}&questionId=${item.Id}&TokenKey=${token}` })
const win = window.open(routeData.href, '_blank')
if (win) {
this.childWindows.push(win)
}
},
closeAllChildWindows() {
this.childWindows.forEach(win => {
if (win && !win.closed) {
win.close()
}
})
this.childWindows = []
},
async saveFormData() { async saveFormData() {
if (this.dialogSaveLoading) return if (this.dialogSaveLoading) return
this.dialogSaveLoading = true this.dialogSaveLoading = true

View File

@ -1,115 +0,0 @@
<template>
<div class="table-list-container" v-loading="loading">
<h3 v-if="isReadingShowSubjectInfo">
<span v-if="subjectCode">{{ subjectCode }} </span>
<span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<h3 v-if="tableQuestion && tableQuestion.GroupName">
{{ language === 'en' ? tableQuestion.GroupEnName : tableQuestion.GroupName }}
</h3>
<h4 v-if="tableQuestion && tableQuestion.QuestionName">
{{ tableQuestion.QuestionName }}
</h4>
<el-table
v-if="tableQuestion && tableQuestion.Type === 'basicTable' && tableQuestion.TableQuestions"
:ref="tableQuestion.Id"
:data="tableQuestion.TableQuestions.Answers"
height="100%"
>
<el-table-column
v-for="q of tableQuestion.TableQuestions.Questions"
:key="q.Id"
:prop="q.Id"
:label="q.QuestionName"
show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="q.Unit > 0 && !isNaN(parseFloat(scope.row[q.Id]))">
{{ `${scope.row[q.Id]} ${$fd('ValueUnit', parseInt(q.Unit))}` }}
</span>
<span v-else-if="q.DictionaryCode">
{{`${scope.row[q.Id] instanceof Array ? scope.row[q.Id].map(item => $fd(q.DictionaryCode,
parseInt(item))).join(',') : $fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}`}}
</span>
<span v-else-if="q.OptionTypeEnum === 1">
{{ `${scope.row[q.Id] instanceof Array ? scope.row[q.Id].join(',') : scope.row[q.Id]}` }}
</span>
<span v-else>
{{ `${scope.row[q.Id]}` }}
</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { getFilterTableQuestion } from '@/api/reading'
import store from '@/store'
import { mapGetters } from 'vuex'
import { changeURLStatic } from '@/utils/history.js'
export default {
name: 'DicomTableList',
data() {
return {
isReadingShowSubjectInfo: false,
subjectCode: null,
taskBlindName: null,
questionId: null,
tableQuestion: null,
loading: false
}
},
computed: {
...mapGetters(['language'])
},
created() {
if (this.$route.query.TokenKey) {
store.dispatch('user/setToken', this.$route.query.TokenKey)
changeURLStatic('TokenKey', '')
}
this.subjectCode = localStorage.getItem('subjectCode')
this.taskBlindName = localStorage.getItem('taskBlindName')
this.isReadingShowSubjectInfo = localStorage.getItem('isReadingShowSubjectInfo')
this.getList()
},
methods: {
async getList() {
try {
this.loading = true
let params = {
trialId: this.$route.query.trialId,
visitTaskId: this.$route.query.visitTaskId,
questionId: this.$route.query.questionId
}
let res = await getFilterTableQuestion(params)
if (res.IsSuccess) {
this.tableQuestion = res.Result
}
} catch (e) {
console.log(e)
} finally {
this.loading = false
}
},
resetList() {
}
}
}
</script>
<style lang="scss" scoped>
.table-list-container {
height: 100%;
padding: 0 10px;
box-sizing: border-box;
display: flex;
flex-direction: column;
overflow: hidden;
}
h3, h4 {
flex-shrink: 0;
margin: 10px 0 10px;
}
</style>

View File

@ -448,10 +448,10 @@
/> --> /> -->
<upload-dicom-and-nonedicom v-if="uploadImageVisible" :SubjectId="uploadSubjectId" :SubjectCode="uploadSubjectCode" <upload-dicom-and-nonedicom v-if="uploadImageVisible" :SubjectId="uploadSubjectId" :SubjectCode="uploadSubjectCode"
:Criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible" :VisitTaskId="taskId" :Criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible" :VisitTaskId="taskId"
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :isReading="true" /> :isReadingTaskViewInOrder="isReadingTaskViewInOrder" />
<download-dicom-and-nonedicom v-if="downloadImageVisible" :SubjectId="uploadSubjectId" <download-dicom-and-nonedicom v-if="downloadImageVisible" :SubjectId="uploadSubjectId"
:SubjectCode="uploadSubjectCode" :Criterion="uploadTrialCriterion" :TaskId="taskId" :SubjectCode="uploadSubjectCode" :Criterion="uploadTrialCriterion" :TaskId="taskId"
:visible.sync="downloadImageVisible" :isReading="true"/> :visible.sync="downloadImageVisible" />
</div> </div>
</template> </template>
<script> <script>

View File

@ -619,14 +619,6 @@ export default {
} }
} }
::v-deep .el-dialog.cd-dialog-container {
.el-input.is-disabled .el-input__inner {
background-color: rgb(245, 247, 250);
color: #666;
border: 1px solid #dcdfe6;
}
}
} }
::v-deep .dialog-container { ::v-deep .dialog-container {

View File

@ -12,9 +12,7 @@
{ required: true, message: $t('common:ruleMessage:select'), trigger: 'blur' } { required: true, message: $t('common:ruleMessage:select'), trigger: 'blur' }
]"> ]">
<el-select v-model="fusionForm.studyId" clearable @change="handleStudyIdChange"> <el-select v-model="fusionForm.studyId" clearable @change="handleStudyIdChange">
<el-option v-for="item in studyList" :key="item.StudyId" <el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode" :value="item.StudyId" />
:label="taskInfo.IsReadingTaskViewInOrder !== 0 ? item.StudyCode : `${item.Modalities}(${item.SeriesCount})`"
:value="item.StudyId" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 融合图像 --> <!-- 融合图像 -->
@ -113,12 +111,10 @@ export default {
ctSeries: [], ctSeries: [],
petSeries: [], petSeries: [],
petctWindow: null, petctWindow: null,
digitPlaces: 2, digitPlaces: 2
taskInfo: {}
} }
}, },
mounted() { mounted() {
this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo'))
var digitPlaces = Number(localStorage.getItem('digitPlaces')) var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.initForm() this.initForm()

View File

@ -187,7 +187,6 @@ export default {
originalMarkers: [], originalMarkers: [],
markers: { top: '', right: '', bottom: '', left: '' }, markers: { top: '', right: '', bottom: '', left: '' },
playClipState: false, playClipState: false,
clipFramesPerSecond: null,
wwwcIdx: 2, wwwcIdx: 2,
presetName: '', presetName: '',
volumeId: null, volumeId: null,
@ -626,22 +625,6 @@ export default {
} }
}, },
syncViewportStaticState() {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
if (!renderingEngine) return
const viewport = renderingEngine.getViewport(this.viewportId)
if (!viewport) return
this.getOrientationMarker()
const toolGroup =
cornerstoneTools.ToolGroupManager.getToolGroupForViewport(
this.viewportId,
this.renderingEngineId
) || cornerstoneTools.ToolGroupManager.getToolGroup(this.viewportId)
if (toolGroup) {
toolGroup.setToolEnabled('ScaleOverlay')
}
},
setFullScreen(index) { setFullScreen(index) {
setTimeout(() => { setTimeout(() => {
const renderingEngine = getRenderingEngine(this.renderingEngineId) const renderingEngine = getRenderingEngine(this.renderingEngineId)
@ -744,33 +727,14 @@ export default {
} }
}, },
toggleClipPlay(isPlay, framesPerSecond) { toggleClipPlay(isPlay, framesPerSecond) {
this.playClipState = isPlay
const renderingEngine = getRenderingEngine(this.renderingEngineId) const renderingEngine = getRenderingEngine(this.renderingEngineId)
if (!renderingEngine) return
const viewport = renderingEngine.getViewport(this.viewportId) const viewport = renderingEngine.getViewport(this.viewportId)
if (!viewport?.element) return
const parsedFramesPerSecond = Number(framesPerSecond)
const nextFramesPerSecond = Number.isFinite(parsedFramesPerSecond)
? parsedFramesPerSecond
: (this.clipFramesPerSecond || 15)
const isSameSpeedWhilePlaying = this.playClipState &&
isPlay &&
this.clipFramesPerSecond === nextFramesPerSecond
if (isPlay) { if (isPlay) {
if (isSameSpeedWhilePlaying) return cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
cornerstoneTools.utilities.cine.playClip(viewport.element, {
framesPerSecond: nextFramesPerSecond,
loop: true,
waitForRendered: 1
})
this.clipFramesPerSecond = nextFramesPerSecond
this.playClipState = true
} else { } else {
cornerstoneTools.utilities.cine.stopClip(viewport.element) cornerstoneTools.utilities.cine.stopClip(viewport.element)
this.clipFramesPerSecond = null
this.playClipState = false
} }
}, },
scrollPage(type) { scrollPage(type) {
@ -1161,7 +1125,6 @@ export default {
} }
viewport.render() viewport.render()
this.syncViewportStaticState()
if (this.currentVoiUpper > 0) { if (this.currentVoiUpper > 0) {
this.voiChange(this.currentVoiUpper) this.voiChange(this.currentVoiUpper)
} }

View File

@ -284,7 +284,7 @@
<svg-icon icon-class="lastframe" class="svg-icon" /> <svg-icon icon-class="lastframe" class="svg-icon" />
</div> </div>
<select v-model="fps" :title="$t('trials:dicom-show:speed')" class="select-wrapper" <select v-model="fps" :title="$t('trials:dicom-show:speed')" class="select-wrapper"
@change="handleClipFpsChange"> :disabled="clipPlaying">
<!-- 默认值 --> <!-- 默认值 -->
<option :value="5">5</option> <option :value="5">5</option>
<option :value="10">10</option> <option :value="10">10</option>
@ -582,11 +582,10 @@
:renderingEngineId="renderingEngineId" :visitInfo="taskInfo" /> --> :renderingEngineId="renderingEngineId" :visitInfo="taskInfo" /> -->
<upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId" <upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId"
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible" :subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible"
:visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" :isReading="true" /> :visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
<download-dicom-and-nonedicom v-if="downloadImageVisible" :subject-id="uploadSubjectId" <download-dicom-and-nonedicom v-if="downloadImageVisible" :subject-id="uploadSubjectId"
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :task-id="taskId" :subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :task-id="taskId"
:visible.sync="downloadImageVisible" :is-reading-task-view-in-order="isReadingTaskViewInOrder" :visible.sync="downloadImageVisible" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
:isReading="true" />
<readingChart ref="readingChart" /> <readingChart ref="readingChart" />
</div> </div>
</template> </template>
@ -1222,7 +1221,12 @@ export default {
this.selectArr.push(item.VisitTaskId) this.selectArr.push(item.VisitTaskId)
} }
if (item.IsCurrentTask) { if (item.IsCurrentTask) {
this.syncMarkedSeriesIds(annotations) this.markedSeriesIds = []
annotations.map(i => {
if (i.MeasureData && i.MeasureData.seriesId) {
this.markedSeriesIds.push(i.MeasureData.seriesId)
}
})
} }
} }
@ -2048,7 +2052,7 @@ export default {
// this.$refs['ecrf'].setAnnotation({ annotation, toolName: annotation.metadata.toolName }) // this.$refs['ecrf'].setAnnotation({ annotation, toolName: annotation.metadata.toolName })
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].setAnnotation({ annotation, toolName: annotation.metadata.toolName }) this.$refs[`ecrf_${this.lastViewportTaskId}`][0].setAnnotation({ annotation, toolName: annotation.metadata.toolName })
this.syncMarkedSeriesIdsFromState(series.TaskInfo.VisitTaskId) this.markedSeriesIds.push(series.Id)
} }
this.setToolsPassive() this.setToolsPassive()
@ -2083,14 +2087,16 @@ export default {
throw errorMsg throw errorMsg
} }
if (annotation.visitTaskId === this.taskInfo.VisitTaskId && annotation.seriesId) { if (annotation.visitTaskId === this.taskInfo.VisitTaskId && annotation.seriesId) {
this.syncMarkedSeriesIdsFromState(annotation.visitTaskId) const index = this.markedSeriesIds.indexOf(annotation.seriesId)
if (index !== -1) {
this.markedSeriesIds.splice(index, 1)
}
} else { } else {
const errorMsg = { message: 'annotation Not allowed to operate' } const errorMsg = { message: 'annotation Not allowed to operate' }
throw errorMsg throw errorMsg
} }
} catch (e) { } catch (e) {
cornerstoneTools.annotation.state.addAnnotation(annotation) cornerstoneTools.annotation.state.addAnnotation(annotation)
this.syncMarkedSeriesIdsFromState(annotation.visitTaskId)
const renderingEngine = getRenderingEngine(renderingEngineId) const renderingEngine = getRenderingEngine(renderingEngineId)
for (let i = 0; i < this.cells.length; i++) { for (let i = 0; i < this.cells.length; i++) {
const viewportId = `${this.viewportKey}-${i}` const viewportId = `${this.viewportKey}-${i}`
@ -2127,7 +2133,7 @@ export default {
annotation.sliceThickness = series.SliceThickness annotation.sliceThickness = series.SliceThickness
annotation.numberOfFrames = isNaN(parseInt(params.frame)) ? null : parseInt(params.frame) annotation.numberOfFrames = isNaN(parseInt(params.frame)) ? null : parseInt(params.frame)
annotation.markTool = annotation.metadata.toolName annotation.markTool = annotation.metadata.toolName
this.syncMarkedSeriesIdsFromState(series.TaskInfo.VisitTaskId) this.markedSeriesIds.push(series.Id)
const operateStateEnum = this.$refs[`ecrf_${this.taskInfo.VisitTaskId}`][0].operateStateEnum const operateStateEnum = this.$refs[`ecrf_${this.taskInfo.VisitTaskId}`][0].operateStateEnum
const markName = await this.customPrompt(!this.isNumber(operateStateEnum)) const markName = await this.customPrompt(!this.isNumber(operateStateEnum))
@ -2269,7 +2275,10 @@ export default {
if (!res.IsSuccess) throw '' if (!res.IsSuccess) throw ''
} }
} }
this.syncMarkedSeriesIdsFromState(annotation.visitTaskId) const index = this.markedSeriesIds.indexOf(annotation.seriesId)
if (index !== -1) {
this.markedSeriesIds.splice(index, 1)
}
const renderingEngine = getRenderingEngine(renderingEngineId) const renderingEngine = getRenderingEngine(renderingEngineId)
for (let i = 0; i < this.cells.length; i++) { for (let i = 0; i < this.cells.length; i++) {
const viewportId = `${this.viewportKey}-${i}` const viewportId = `${this.viewportKey}-${i}`
@ -2282,7 +2291,6 @@ export default {
} }
} catch (e) { } catch (e) {
cornerstoneTools.annotation.state.addAnnotation(annotation) cornerstoneTools.annotation.state.addAnnotation(annotation)
this.syncMarkedSeriesIdsFromState(annotation.visitTaskId)
const renderingEngine = getRenderingEngine(renderingEngineId) const renderingEngine = getRenderingEngine(renderingEngineId)
for (let i = 0; i < this.cells.length; i++) { for (let i = 0; i < this.cells.length; i++) {
const viewportId = `${this.viewportKey}-${i}` const viewportId = `${this.viewportKey}-${i}`
@ -2359,22 +2367,6 @@ export default {
this.$set(this.visitTaskList[taskIdx], 'Annotations', annotations) this.$set(this.visitTaskList[taskIdx], 'Annotations', annotations)
this.$set(this.visitTaskList[taskIdx], 'AnnotationUIDs', annotationUIDs) this.$set(this.visitTaskList[taskIdx], 'AnnotationUIDs', annotationUIDs)
}, },
collectMarkedSeriesIds(list = []) {
return [...new Set(
list
.map(item => item?.MeasureData?.seriesId || item?.seriesId)
.filter(Boolean)
)]
},
syncMarkedSeriesIds(list = []) {
this.markedSeriesIds = this.collectMarkedSeriesIds(list)
},
syncMarkedSeriesIdsFromState(visitTaskId = this.taskInfo?.VisitTaskId) {
const annotations = cornerstoneTools.annotation.state.getAllAnnotations().filter(item => {
return item.visitTaskId === visitTaskId && item.seriesId
})
this.syncMarkedSeriesIds(annotations)
},
async resetAnnotations(visitTaskId) { async resetAnnotations(visitTaskId) {
if (this.readingTaskState === 2) return if (this.readingTaskState === 2) return
const taskIdx = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId) const taskIdx = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
@ -2409,9 +2401,9 @@ export default {
if (i.MeasureData) { if (i.MeasureData) {
const annotation = i.MeasureData const annotation = i.MeasureData
cornerstoneTools.annotation.state.addAnnotation(annotation) cornerstoneTools.annotation.state.addAnnotation(annotation)
this.markedSeriesIds.push(annotation.seriesId)
} }
}) })
this.syncMarkedSeriesIds(annotations)
const renderingEngine = getRenderingEngine(renderingEngineId) const renderingEngine = getRenderingEngine(renderingEngineId)
for (let i = 0; i < this.cells.length; i++) { for (let i = 0; i < this.cells.length; i++) {
const viewportId = `${this.viewportKey}-${i}` const viewportId = `${this.viewportKey}-${i}`
@ -3423,15 +3415,6 @@ export default {
this.clipPlaying = !this.clipPlaying this.clipPlaying = !this.clipPlaying
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].toggleClipPlay(isPlay, this.fps) this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].toggleClipPlay(isPlay, this.fps)
}, },
handleClipFpsChange() {
if (!this.clipPlaying) return
const activeViewportRef = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`]
const activeViewport = activeViewportRef && activeViewportRef[0]
if (!activeViewport || typeof activeViewport.toggleClipPlay !== 'function') return
activeViewport.toggleClipPlay(true, this.fps)
},
// //
async getWwcTpl() { async getWwcTpl() {
try { try {
@ -4054,10 +4037,8 @@ export default {
} }
} }
} }
if (!this.isActiveViewportAtMeasureLocation(obj.annotation)) {
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series, true) this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series, true)
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex) this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
}
setTimeout(async () => { setTimeout(async () => {
const divForDownloadViewport = document.querySelector( const divForDownloadViewport = document.querySelector(
`div[data-viewport-uid="${this.viewportKey}-${this.activeViewportIndex}"]` `div[data-viewport-uid="${this.viewportKey}-${this.activeViewportIndex}"]`
@ -4068,48 +4049,9 @@ export default {
}, 200) }, 200)
} }
}, },
getMeasureImageLocation(measureData = {}) {
const referencedImageId = measureData?.metadata?.referencedImageId
const referencedImageParams = referencedImageId ? this.getInstanceInfo(referencedImageId) : {}
return {
visitTaskId: measureData.visitTaskId,
studyId: measureData.studyId || measureData.StudyId,
seriesId: measureData.seriesId || measureData.SeriesId,
instanceId: measureData.instanceId || measureData.InstanceId || referencedImageParams.instanceId || null,
frame: measureData.numberOfFrames ?? measureData.NumberOfFrames ?? referencedImageParams.frame
}
},
getActiveViewportImageLocation() {
const viewportRef = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`]?.[0]
const currentSeries = viewportRef?.series
if (!currentSeries) return null
const renderingEngine = getRenderingEngine(renderingEngineId)
const viewport = renderingEngine?.getViewport(`${this.viewportKey}-${this.activeViewportIndex}`)
const currentImageId = viewport?.getCurrentImageId?.()
const currentImageParams = currentImageId ? this.getInstanceInfo(currentImageId) : {}
return {
visitTaskId: currentSeries.TaskInfo?.VisitTaskId,
studyId: currentSeries.StudyId,
seriesId: currentSeries.Id,
instanceId: currentImageParams.instanceId || null,
frame: currentImageParams.frame
}
},
isActiveViewportAtMeasureLocation(measureData) {
const targetLocation = this.getMeasureImageLocation(measureData)
const currentLocation = this.getActiveViewportImageLocation()
if (!currentLocation || !targetLocation.seriesId) return false
if (targetLocation.visitTaskId && currentLocation.visitTaskId !== targetLocation.visitTaskId) return false
if (targetLocation.studyId && currentLocation.studyId !== targetLocation.studyId) return false
if (currentLocation.seriesId !== targetLocation.seriesId) return false
if (targetLocation.instanceId && currentLocation.instanceId !== targetLocation.instanceId) return false
return currentLocation.frame === targetLocation.frame
},
async getScreenshots(measureData, callback) { async getScreenshots(measureData, callback) {
if (measureData) { if (measureData) {
if (!this.isActiveViewportAtMeasureLocation(measureData.annotation)) {
await this.imageLocation(measureData) await this.imageLocation(measureData)
}
const divForDownloadViewport = document.querySelector( const divForDownloadViewport = document.querySelector(
`div[data-viewport-uid="${this.viewportKey}-${this.activeViewportIndex}"]` `div[data-viewport-uid="${this.viewportKey}-${this.activeViewportIndex}"]`
) )

View File

@ -4,8 +4,7 @@
<el-form-item :label="$t('segment:form:label:studyName')" prop="taskBlindName"> <el-form-item :label="$t('segment:form:label:studyName')" prop="taskBlindName">
<el-select v-model="form.studyId" clearable @change="(e) => handleChange(e, 'study')" <el-select v-model="form.studyId" clearable @change="(e) => handleChange(e, 'study')"
@clear="(e) => handleClear(e, 'study')"> @clear="(e) => handleClear(e, 'study')">
<el-option v-for="item in studyList" :key="item.StudyId" <el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode"
:label="taskInfo.IsReadingTaskViewInOrder !== 0 ? item.StudyCode : `${item.Modalities}(${item.SeriesCount})`"
:value="item.StudyId" /> :value="item.StudyId" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -88,13 +87,12 @@ export default {
}, trigger: ['blur', 'change'] }, trigger: ['blur', 'change']
} }
] ]
}, }
taskInfo: {}
} }
}, },
mounted() { // mounted() {
this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo')) // this.init()
}, // },
methods: { methods: {
setSeries(series) { setSeries(series) {
this.series = series this.series = series

View File

@ -804,16 +804,12 @@ export default {
toolGroup.setToolPassive(this.activeTool) toolGroup.setToolPassive(this.activeTool)
} }
this.$emit('update:activeTool', '') this.$emit('update:activeTool', '')
} else if (this.activeTool === name) {
toolGroup.setToolPassive(this.ThresholdTools[1])
this.$emit('update:activeTool', '')
} else { } else {
if (this.activeTool) { if (this.activeTool) {
if (toolName === CrosshairsTool.toolName) { if (toolName === CrosshairsTool.toolName) {
toolGroup.setToolDisabled(this.activeTool) toolGroup.setToolDisabled(this.activeTool)
} else { } else {
toolGroup.setToolPassive(this.activeTool) toolGroup.setToolPassive(this.activeTool)
toolGroup.setToolPassive(this.ThresholdTools[1])
} }
} }
toolGroup.setToolActive(toolName, { toolGroup.setToolActive(toolName, {

View File

@ -150,8 +150,6 @@ export default {
originalMarkers: [], originalMarkers: [],
markers: { top: '', right: '', bottom: '', left: '' }, markers: { top: '', right: '', bottom: '', left: '' },
playClipState: false, playClipState: false,
clipFramesPerSecond: null,
toggleClipPlayTimer: null,
wwwcIdx: 2, wwwcIdx: 2,
loading: false, loading: false,
forceFitToWindow: false, forceFitToWindow: false,
@ -171,10 +169,6 @@ export default {
this.resizeObserver.unobserve(this.element) this.resizeObserver.unobserve(this.element)
this.resizeObserver.disconnect() this.resizeObserver.disconnect()
} }
if (this.toggleClipPlayTimer) {
clearInterval(this.toggleClipPlayTimer)
this.toggleClipPlayTimer = null
}
}, },
methods: { methods: {
initViewport() { initViewport() {
@ -216,11 +210,12 @@ export default {
this.imageInfo.imageOrientationPatient = imagePlaneModule.imageOrientationPatient this.imageInfo.imageOrientationPatient = imagePlaneModule.imageOrientationPatient
this.imageInfo.imagePositionPatient = imagePlaneModule.imagePositionPatient this.imageInfo.imagePositionPatient = imagePlaneModule.imagePositionPatient
this.imageInfo.location = imagePlaneModule.sliceLocation this.imageInfo.location = imagePlaneModule.sliceLocation
// this.imageInfo.wwwc = `${Math.round(detail.image.windowWidth)}/${Math.round(detail.image.windowCenter)}`
this.getOrientationMarker() this.getOrientationMarker()
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(this.viewportId) this.$emit('renderAnnotations', this.series)
if (toolGroup) { const toolGroupId = this.viewportId
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId)
toolGroup.setToolEnabled('ScaleOverlay') toolGroup.setToolEnabled('ScaleOverlay')
}
}, },
imageRendered(e) { imageRendered(e) {
const renderingEngine = getRenderingEngine(this.renderingEngineId) const renderingEngine = getRenderingEngine(this.renderingEngineId)
@ -317,61 +312,14 @@ export default {
} }
}, },
toggleClipPlay(isPlay, framesPerSecond) { toggleClipPlay(isPlay, framesPerSecond) {
this.playClipState = isPlay
const renderingEngine = getRenderingEngine(this.renderingEngineId) const renderingEngine = getRenderingEngine(this.renderingEngineId)
if (!renderingEngine) return
const viewport = renderingEngine.getViewport(this.viewportId) const viewport = renderingEngine.getViewport(this.viewportId)
if (!viewport?.element) return
const parsedFramesPerSecond = Number(framesPerSecond)
const nextFramesPerSecond = Number.isFinite(parsedFramesPerSecond)
? parsedFramesPerSecond
: (this.clipFramesPerSecond || 15)
const isSameSpeedWhilePlaying = this.playClipState &&
isPlay &&
this.clipFramesPerSecond === nextFramesPerSecond
if (isPlay) { if (isPlay) {
if (isSameSpeedWhilePlaying) return cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
cornerstoneTools.utilities.cine.stopClip(viewport.element)
if (this.toggleClipPlayTimer) {
clearInterval(this.toggleClipPlayTimer)
this.toggleClipPlayTimer = null
}
const frameInterval = Math.max(16, Math.round(1000 / nextFramesPerSecond))
this.toggleClipPlayTimer = setInterval(() => {
const imageIds = viewport.getImageIds()
if (!imageIds?.length) return
let index = viewport.getCurrentImageIdIndex() + 1
if (index > imageIds.length - 1) {
index = 0
}
csUtils.jumpToSlice(viewport.element, {
imageIndex: index,
debounceLoading: false
})
}, frameInterval)
this.clipFramesPerSecond = nextFramesPerSecond
this.playClipState = true
} else { } else {
cornerstoneTools.utilities.cine.stopClip(viewport.element) cornerstoneTools.utilities.cine.stopClip(viewport.element)
if (this.toggleClipPlayTimer) {
clearInterval(this.toggleClipPlayTimer)
this.toggleClipPlayTimer = null
}
this.clipFramesPerSecond = null
this.playClipState = false
}
},
syncViewportStaticState() {
this.getOrientationMarker()
this.$emit('renderAnnotations', this.series)
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(this.viewportId)
if (toolGroup) {
toolGroup.setToolEnabled('ScaleOverlay')
} }
}, },
scrollPage(type) { scrollPage(type) {
@ -391,13 +339,7 @@ export default {
} }
// viewport.setImageIdIndex(newImageIdIndex) // viewport.setImageIdIndex(newImageIdIndex)
csUtils.jumpToSlice(viewport.element, { imageIndex: newImageIdIndex }) csUtils.jumpToSlice(viewport.element, { imageIndex: newImageIdIndex })
if (this.toggleClipPlayTimer) {
clearInterval(this.toggleClipPlayTimer)
this.toggleClipPlayTimer = null
}
cornerstoneTools.utilities.cine.stopClip(viewport.element) cornerstoneTools.utilities.cine.stopClip(viewport.element)
this.clipFramesPerSecond = null
this.playClipState = false
}, },
setZoom(ratio) { setZoom(ratio) {
const renderingEngine = getRenderingEngine(this.renderingEngineId) const renderingEngine = getRenderingEngine(this.renderingEngineId)
@ -490,7 +432,6 @@ export default {
} }
this.prefetchMetadataInformation(obj.ImageIds, obj.Modality) this.prefetchMetadataInformation(obj.ImageIds, obj.Modality)
await viewport.setStack(this.series.Stack, obj.SliceIndex) await viewport.setStack(this.series.Stack, obj.SliceIndex)
this.syncViewportStaticState()
viewport.render() viewport.render()
} catch (e) { } catch (e) {

View File

@ -88,21 +88,21 @@
: $t('trials:pendingReadingTasks:button:review') : $t('trials:pendingReadingTasks:button:review')
" icon="el-icon-edit-outline" @click="handleReadImage(scope.row)" /> " icon="el-icon-edit-outline" @click="handleReadImage(scope.row)" />
<!-- 上传 --> <!-- 上传 -->
<!-- <el-button v-if=" <el-button v-if="
item.ImageUploadEnum > 0 && item.ImageUploadEnum > 0 &&
item.IsReadingTaskViewInOrder > 1 && item.IsReadingTaskViewInOrder > 1 &&
!scope.row.IsSubjectJudge !scope.row.IsSubjectJudge
" v-hasPermi="['role:ir']" circle icon="el-icon-upload2" " v-hasPermi="['role:ir']" circle icon="el-icon-upload2"
:title="$t('trials:pendingReadingTasks:button:upload')" :title="$t('trials:pendingReadingTasks:button:upload')"
@click="openUploadImage(scope.row, item, 'upload')" /> --> @click="openUploadImage(scope.row, item, 'upload')" />
<!-- 下载 --> <!-- 下载 -->
<!-- <el-button v-if=" <el-button v-if="
item.ImageDownloadEnum > 0 && item.ImageDownloadEnum > 0 &&
item.IsReadingTaskViewInOrder > 1 && item.IsReadingTaskViewInOrder > 1 &&
!scope.row.IsSubjectJudge !scope.row.IsSubjectJudge
" v-hasPermi="['role:ir']" circle icon="el-icon-download" " v-hasPermi="['role:ir']" circle icon="el-icon-download"
:title="$t('trials:pendingReadingTasks:button:download')" :title="$t('trials:pendingReadingTasks:button:download')"
@click="openUploadImage(scope.row, item, 'download')" /> --> @click="openUploadImage(scope.row, item, 'download')" />
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>

View File

@ -251,7 +251,7 @@ export default {
return i return i
}) })
this.$set(this.visitTaskList[taskIdx], 'Annotations', annotations) this.$set(this.visitTaskList[taskIdx], 'Annotations', annotations)
this.$refs[visitTaskId][0].initCurrentMaredFiles(annotations) this.$refs[visitTaskId][0].initCurrentMaredFiles()
this.$refs.fileViewer.resetAnnotations({ annotations, visitTaskId }) this.$refs.fileViewer.resetAnnotations({ annotations, visitTaskId })
}, },
setReadingTaskState(state) { setReadingTaskState(state) {

View File

@ -97,7 +97,6 @@ export default {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo')) this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId) this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
this.studyList = this.decorateStudyList(this.visitTaskInfo.StudyList || []) this.studyList = this.decorateStudyList(this.visitTaskInfo.StudyList || [])
this.initCurrentMaredFiles(this.visitTaskInfo.Annotations)
if (this.studyList.length === 0) return if (this.studyList.length === 0) return
this.$nextTick(() => { this.$nextTick(() => {
this.activeStudy(this.studyList[0].Id) this.activeStudy(this.studyList[0].Id)
@ -111,26 +110,8 @@ export default {
}) })
} }
}, },
'visitTaskInfo.Annotations': {
handler(annotations) {
this.initCurrentMaredFiles(annotations)
},
deep: true
}
}, },
methods: { methods: {
buildCurrentMarkedFiles(annotations = []) {
return annotations.reduce((result, item) => {
const fileId = item?.NoneDicomFileId
if (!fileId) return result
if (!Object.hasOwn(result, fileId)) {
result[fileId] = { count: 1 }
} else {
result[fileId].count++
}
return result
}, {})
},
decorateStudyList(studyList = []) { decorateStudyList(studyList = []) {
return studyList.map(study => ({ return studyList.map(study => ({
...study, ...study,
@ -223,9 +204,6 @@ export default {
if (type === 'remove') { if (type === 'remove') {
if (Object.hasOwn(this.currentMarkedFiles, fileId)) { if (Object.hasOwn(this.currentMarkedFiles, fileId)) {
this.currentMarkedFiles[fileId].count-- this.currentMarkedFiles[fileId].count--
if (this.currentMarkedFiles[fileId].count <= 0) {
this.$delete(this.currentMarkedFiles, fileId)
}
} }
} else if (type === 'add') { } else if (type === 'add') {
if (!Object.hasOwn(this.currentMarkedFiles, fileId)) { if (!Object.hasOwn(this.currentMarkedFiles, fileId)) {
@ -236,8 +214,15 @@ export default {
} }
}, },
initCurrentMaredFiles(annotations = this.visitTaskInfo.Annotations || []) { initCurrentMaredFiles() {
this.currentMarkedFiles = this.buildCurrentMarkedFiles(annotations) this.currentMarkedFiles = {}
this.visitTaskInfo.Annotations.map(i => {
if (!Object.hasOwn(this.currentMarkedFiles, i.NoneDicomFileId)) {
this.$set(this.currentMarkedFiles, i.NoneDicomFileId, { count: 1 })
} else {
this.currentMarkedFiles[i.NoneDicomFileId].count++
}
})
}, },
} }
} }