阅片及影像预览页更新

main
caiyiling 2024-11-21 09:50:58 +08:00
parent 1491d7ee78
commit 62533db147
77 changed files with 17309 additions and 6567 deletions

View File

@ -13,13 +13,6 @@
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7" "i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
}, },
"dependencies": { "dependencies": {
"@cornerstonejs/calculate-suv": "^1.1.0",
"@cornerstonejs/core": "^1.27.4",
"@cornerstonejs/dicom-image-loader": "^1.27.4",
"@cornerstonejs/streaming-image-volume-loader": "1.23.2",
"@cornerstonejs/tools": "^1.27.4",
"@ffmpeg/core": "^0.10.0",
"@ffmpeg/ffmpeg": "^0.10.1",
"@microsoft/signalr": "^6.0.8", "@microsoft/signalr": "^6.0.8",
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"ali-oss": "^6.17.1", "ali-oss": "^6.17.1",
@ -27,10 +20,10 @@
"babel-eslint": "7.2.3", "babel-eslint": "7.2.3",
"copy-webpack-plugin": "^4.5.2", "copy-webpack-plugin": "^4.5.2",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"cornerstone-core": "^2.3.0", "cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.8", "cornerstone-math": "^0.1.10",
"cornerstone-tools": "^6.0.8", "cornerstone-tools": "^6.0.10",
"cornerstone-wado-image-loader": "^3.1.2", "cornerstone-wado-image-loader": "^4.13.2",
"dcmjs": "^0.29.8", "dcmjs": "^0.29.8",
"dicom-parser": "^1.8.9", "dicom-parser": "^1.8.9",
"dicomedit": "^0.1.0", "dicomedit": "^0.1.0",
@ -44,7 +37,6 @@
"jszip": "^3.7.1", "jszip": "^3.7.1",
"moment": "^2.27.0", "moment": "^2.27.0",
"node-polyfill-webpack-plugin": "^2.0.1", "node-polyfill-webpack-plugin": "^2.0.1",
"streamsaver": "^2.0.6",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"normalize.css": "7.0.0", "normalize.css": "7.0.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
@ -54,6 +46,7 @@
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"screenfull": "^4.2.0", "screenfull": "^4.2.0",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",
"streamsaver": "^2.0.6",
"v-viewer": "^1.6.4", "v-viewer": "^1.6.4",
"vcrontab": "^0.3.5", "vcrontab": "^0.3.5",
"vue": "^2.6.11", "vue": "^2.6.11",

View File

@ -226,3 +226,17 @@ export function confirmTaskReminder(param) {
data: param data: param
}) })
} }
export function setSkipReadingCache(param) {
return request({
url: `/ReadingImageTask/setSkipReadingCache`,
method: 'post',
data: param
})
}
export function resetReadingTask(param) {
return request({
url: `/ReadingImageTask/resetReadingTask`,
method: 'post',
data: param
})
}

View File

@ -8,7 +8,6 @@
style="width:100%;height:100%;position:relative;" style="width:100%;height:100%;position:relative;"
class="cornerstone-element" class="cornerstone-element"
@contextmenu.prevent="onContextmenu" @contextmenu.prevent="onContextmenu"
@mousemove="sliderMousemove"
@mouseup="sliderMouseup" @mouseup="sliderMouseup"
> >
<div v-show="dicomInfo.series" class="info-series"> <div v-show="dicomInfo.series" class="info-series">
@ -54,7 +53,7 @@
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> --> <!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</div> --> <!-- <div>{{ dicomInfo.time }}</div> -->
</div> </div>
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer"> <div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer" @click.stop="goViewer($event)">
<div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @mousedown="sliderMousedown($event)" /> <div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @mousedown="sliderMousedown($event)" />
</div> </div>
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;"> <div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
@ -82,16 +81,25 @@
<!-- <div v-show="stack.firstImageLoading" class="load-indicator"> <!-- <div v-show="stack.firstImageLoading" class="load-indicator">
Loading Series #{{ stack.seriesNumber }}... Loading Series #{{ stack.seriesNumber }}...
</div>--> </div>-->
<el-dialog
v-if="dcmTag.visible"
:visible.sync="dcmTag.visible"
:close-on-click-modal="false"
:title="dcmTag.title"
width="1000px"
custom-class="base-dialog-wrapper"
append-to-body
>
<DicomTags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import Vue from 'vue'
import Contextmenu from 'vue-contextmenujs'
Vue.use(Contextmenu)
import * as cornerstone from 'cornerstone-core' import * as cornerstone from 'cornerstone-core'
import * as cornerstoneMath from 'cornerstone-math' import * as cornerstoneMath from 'cornerstone-math'
import * as cornerstoneTools from 'cornerstone-tools' import * as cornerstoneTools from 'cornerstone-tools'
const scroll = cornerstoneTools.import('util/scrollToIndex') const scroll = cornerstoneTools.import('util/scrollToIndex')
import Hammer from 'hammerjs' import Hammer from 'hammerjs'
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString' import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
@ -109,8 +117,10 @@ cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)')
// cornerstoneTools.init({ showSVGCursors: true }) // cornerstoneTools.init({ showSVGCursors: true })
cornerstoneTools.init() cornerstoneTools.init()
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
import DicomTags from './DicomTags'
export default { export default {
name: 'DicomCanvas', name: 'DicomCanvas',
components: { DicomTags },
data() { data() {
return { return {
loading: false, loading: false,
@ -163,7 +173,10 @@ export default {
isMove: false isMove: false
}, },
mousePosition: { x: '', y: '', mo: '' }, mousePosition: { x: '', y: '', mo: '' },
markers: { top: '', right: '', bottom: '', left: '' } markers: { top: '', right: '', bottom: '', left: '' },
orientationMarkers: [],
originalMarkers: [],
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') }
} }
}, },
@ -186,6 +199,9 @@ export default {
document.addEventListener('mouseup', () => { document.addEventListener('mouseup', () => {
this.sliderMouseup() this.sliderMouseup()
}) })
document.addEventListener('mousemove', (e) => {
this.sliderMousemove(e)
})
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback) this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
}, },
@ -196,7 +212,7 @@ export default {
this.stack.seriesId = dicomSeries.seriesId this.stack.seriesId = dicomSeries.seriesId
this.stack.seriesNumber = dicomSeries.seriesNumber this.stack.seriesNumber = dicomSeries.seriesNumber
this.stack.imageIds = dicomSeries.imageIds this.stack.imageIds = dicomSeries.imageIds
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex ? dicomSeries.imageIdIndex : 0 this.stack.currentImageIdIndex = dicomSeries.imageIdIndex && dicomSeries.imageIdIndex < dicomSeries.imageIds.length ? dicomSeries.imageIdIndex : 0
this.stack.firstImageLoading = true this.stack.firstImageLoading = true
this.stack.description = dicomSeries.description this.stack.description = dicomSeries.description
this.toolState.viewportInvert = false this.toolState.viewportInvert = false
@ -205,15 +221,19 @@ export default {
var instanceId = imageId.split('/')[imageId.split('/').length - 1] var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0] instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId this.stack.instanceId = instanceId
if (this.toolState.clipPlaying) this.toggleClipPlay() this.toolState.clipPlaying = false
const element = this.$refs.canvas const element = this.$refs.canvas
cornerstone.enable(element) cornerstone.enable(element)
cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false
this.loading = true this.loading = true
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex]) cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(image => { .then(image => {
this.loading = false this.loading = false
this.onFirstImageLoaded(image) if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
this.onFirstImageLoaded(image)
}
}).catch((error) => { }).catch((error) => {
this.loading = false this.loading = false
if (error.error && error.error.message) { if (error.error && error.error.message) {
@ -242,7 +262,13 @@ export default {
apiTool apiTool
) )
if (!toolAlreadyAddedToElement) { if (!toolAlreadyAddedToElement) {
cornerstoneTools.addToolForElement(element, apiTool) if (toolName === 'RectangleRoi') {
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true, showStatsText: true}})
} else if (toolName === 'EllipticalRoi') {
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true}})
} else {
cornerstoneTools.addToolForElement(element, apiTool)
}
} }
} }
// Setup button listener // Setup button listener
@ -356,6 +382,12 @@ export default {
if (this.dicomInfo.thick) { if (this.dicomInfo.thick) {
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2) this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
} }
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === e.detail.image.imageId)
if (newImageIdIndex === -1) return
this.stack.currentImageIdIndex = newImageIdIndex
this.stack.imageIdIndex = newImageIdIndex
this.series.imageIdIndex = newImageIdIndex
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
}, },
stackScrollCallback(e) { stackScrollCallback(e) {
const { detail } = e const { detail } = e
@ -403,6 +435,7 @@ export default {
this.dicomInfo.location = position this.dicomInfo.location = position
}, },
getOrientationMarker(element) { getOrientationMarker(element) {
console.log('getOrientationMarker')
const enabledElement = cornerstone.getEnabledElement(element) const enabledElement = cornerstone.getEnabledElement(element)
const imagePlane = cornerstone.metaData.get( const imagePlane = cornerstone.metaData.get(
'imagePlaneModule', 'imagePlaneModule',
@ -426,6 +459,7 @@ export default {
if (!markers) { if (!markers) {
return return
} }
this.orientationMarkers = [oppositeColumn, row, column, oppositeRow] this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
this.originalMarkers = [oppositeColumn, row, column, oppositeRow] this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
this.setMarkers() this.setMarkers()
@ -438,10 +472,10 @@ export default {
} }
}, },
onImageLoaded(e) { onImageLoaded(e) {
var image = e.detail.image // var image = e.detail.image
// var seriesIndex = -1 // // var seriesIndex = -1
var seriesUid = image.data.string('x0020000e') // var seriesUid = image.data.string('x0020000e')
console.log(seriesUid) // console.log(seriesUid)
}, },
getToolForElement(toolName) { getToolForElement(toolName) {
var isExist = false var isExist = false
@ -521,6 +555,9 @@ export default {
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100 this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
this.sliderInfo.oldM = e.clientY this.sliderInfo.oldM = e.clientY
this.sliderInfo.isMove = true this.sliderInfo.isMove = true
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
}, },
sliderMousemove(e) { sliderMousemove(e) {
if (!this.sliderInfo.isMove) return if (!this.sliderInfo.isMove) return
@ -540,6 +577,13 @@ export default {
sliderMouseup(e) { sliderMouseup(e) {
this.sliderInfo.isMove = false this.sliderInfo.isMove = false
}, },
goViewer(e) {
// console.log(this.$refs['sliderBox'].clientHeight)
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
this.height = height
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
scroll(this.canvas, index)
},
onClipStopped() { onClipStopped() {
this.toolState.clipPlaying = false this.toolState.clipPlaying = false
}, },
@ -610,6 +654,7 @@ export default {
enabledElement.renderingTools.renderCanvasData = renderCanvasData enabledElement.renderingTools.renderCanvasData = renderCanvasData
}, },
scrollPage(offset) { scrollPage(offset) {
if (this.loading) return
var index = this.stack.currentImageIdIndex + offset var index = this.stack.currentImageIdIndex + offset
if (index < 0) index = 0 if (index < 0) index = 0
else if (index >= this.stack.imageIds.length) { else if (index >= this.stack.imageIds.length) {
@ -621,6 +666,7 @@ export default {
}, },
toggleClipPlay() { toggleClipPlay() {
if (this.loading) return
if (this.toolState.clipPlaying) { if (this.toolState.clipPlaying) {
cornerstoneTools.stopClip(this.canvas) cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false this.toolState.clipPlaying = false
@ -640,7 +686,7 @@ export default {
resetWwwc() { resetWwwc() {
this.toolState.viewportInvert = false this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = false // viewport.invert = false
var image = cornerstone.getImage(this.canvas) var image = cornerstone.getImage(this.canvas)
viewport.voi.windowWidth = image.windowWidth viewport.voi.windowWidth = image.windowWidth
viewport.voi.windowCenter = image.windowCenter viewport.voi.windowCenter = image.windowCenter
@ -675,8 +721,11 @@ export default {
}, },
resetRotate() { resetRotate() {
this.orientationMarkers = [...this.originalMarkers] if (this.originalMarkers.length > 0) {
this.setMarkers() this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
viewport.hflip = false viewport.hflip = false
viewport.vflip = false viewport.vflip = false
@ -685,24 +734,26 @@ export default {
}, },
setRotate(hflip, vflip, angle, type) { setRotate(hflip, vflip, angle, type) {
var markers = [...this.orientationMarkers] if (this.orientationMarkers.length > 0) {
if (type === 2) { var markers = [...this.orientationMarkers]
// if (type === 2) {
this.orientationMarkers[1] = markers[3] //
this.orientationMarkers[1] = markers[3]
this.orientationMarkers[3] = markers[1] this.orientationMarkers[3] = markers[1]
} else if (type === 3) { } else if (type === 3) {
// //
this.orientationMarkers[0] = markers[2] this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0] this.orientationMarkers[2] = markers[0]
} else if (type === 4) { } else if (type === 4) {
// 90 // 90
this.orientationMarkers = markers.slice(1, 4).concat(markers[0]) this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) { } else if (type === 5) {
// 90 // 90
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3)) this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
} }
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
if (hflip) viewport.hflip = !viewport.hflip if (hflip) viewport.hflip = !viewport.hflip
if (vflip) viewport.vflip = !viewport.vflip if (vflip) viewport.vflip = !viewport.vflip
@ -714,6 +765,9 @@ export default {
var uid = cornerstone.getImage(this.canvas).data.string('x00080018') var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`) cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
}, },
showTags() {
this.dcmTag.visible = true
},
fitToWindow() { fitToWindow() {
if (this.stack.seriesNumber) { if (this.stack.seriesNumber) {
cornerstone.fitToWindow(this.canvas) cornerstone.fitToWindow(this.canvas)
@ -840,194 +894,197 @@ export default {
synchronizer.remove(this.$refs.canvas) synchronizer.remove(this.$refs.canvas)
this.setAllToolsPassive() this.setAllToolsPassive()
}, },
onContextmenu(event) { onContextmenu(e) {
const colormapsList = cornerstone.colors.getColormapsList() e.stopImmediatePropagation()
const colorItems = [] e.stopPropagation()
colorItems.push({ e.preventDefault()
label: '默认值', // const colormapsList = cornerstone.colors.getColormapsList()
onClick: () => { // const colorItems = []
this.setColormap() // colorItems.push({
} // label: '',
}) // onClick: () => {
colormapsList.forEach(colormap => { // this.setColormap()
const item = {} // }
item.label = colormap.name // })
item.onClick = () => { // colormapsList.forEach(colormap => {
this.setColormap(colormap.id) // const item = {}
} // item.label = colormap.name
colorItems.push(item) // item.onClick = () => {
}) // this.setColormap(colormap.id)
this.$contextmenu({ // }
items: [ // colorItems.push(item)
{ // })
label: '移动', // this.$contextmenu({
divided: true, // items: [
onClick: () => { // {
this.setToolActive('Pan') // label: '',
} // divided: true,
}, // onClick: () => {
{ // this.setToolActive('Pan')
label: '缩放', // }
divided: true, // },
children: [ // {
{ // label: '',
label: '自由缩放', // divided: true,
onClick: () => { // children: [
this.setToolActive('Zoom') // {
} // label: '',
}, // onClick: () => {
{ // this.setToolActive('Zoom')
label: '适应图像', // }
onClick: () => { // },
this.fitToWindow() // {
} // label: '',
}, // onClick: () => {
{ // this.fitToWindow()
label: '适应窗口', // }
onClick: () => { // },
this.fitToImage() // {
} // label: '',
} // onClick: () => {
] // this.fitToImage()
}, // }
{ // }
label: '透镜', // ]
divided: true, // },
onClick: () => { // {
this.setToolActive('Magnify') // label: '',
} // divided: true,
}, // onClick: () => {
{ // this.setToolActive('Magnify')
label: '旋转', // }
divided: true, // },
children: [ // {
{ // label: '',
label: '默认值', // divided: true,
onClick: () => { // children: [
this.resetRotate() // {
} // label: '',
}, // onClick: () => {
{ // this.resetRotate()
label: '自由旋转', // }
onClick: () => { // },
this.setToolActive('Rotate') // {
} // label: '',
}, // onClick: () => {
{ // this.setToolActive('Rotate')
label: '水平翻转', // }
onClick: () => { // },
this.setRotate(true, false, 0) // {
} // label: '',
}, // onClick: () => {
{ // this.setRotate(true, false, 0)
label: '垂直翻转', // }
onClick: () => { // },
this.setRotate(false, true, 0) // {
} // label: '',
}, // onClick: () => {
{ // this.setRotate(false, true, 0)
label: '左转90度', // }
onClick: () => { // },
this.setRotate(false, false, -90) // {
} // label: '90',
}, // onClick: () => {
{ // this.setRotate(false, false, -90)
label: '右转90度', // }
onClick: () => { // },
this.setRotate(false, false, 90) // {
} // label: '90',
} // onClick: () => {
] // this.setRotate(false, false, 90)
}, // }
// }
// ]
// },
{ // {
label: '测量', // label: '',
divided: true, // divided: true,
minWidth: 0, // minWidth: 0,
children: [ // children: [
{ // {
label: '探针', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('Probe') // this.setToolActive('Probe')
} // }
}, // },
{ // {
label: '长度测量', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('Length') // this.setToolActive('Length')
} // }
}, // },
{ // {
label: '角度测量', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('Angle') // this.setToolActive('Angle')
} // }
}, // },
{ // {
label: 'Cobb测量', // label: 'Cobb',
onClick: () => { // onClick: () => {
this.setToolActive('CobbAngle') // this.setToolActive('CobbAngle')
} // }
}, // },
{ // {
label: '椭圆测量', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('EllipticalRoi') // this.setToolActive('EllipticalRoi')
} // }
}, // },
{ // {
label: '矩形测量', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('RectangleRoi') // this.setToolActive('RectangleRoi')
} // }
}, // },
{ // {
label: '多边形标记', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('FreehandRoi') // this.setToolActive('FreehandRoi')
} // }
}, // },
{ // {
label: '十字线', // label: '线',
onClick: () => { // onClick: () => {
this.setToolActive('Bidirectional') // this.setToolActive('Bidirectional')
} // }
}, // },
{ // {
label: '文字标注', // label: '',
onClick: () => { // onClick: () => {
this.setToolActive('ArrowAnnotate') // this.setToolActive('ArrowAnnotate')
} // }
} // }
] // ]
}, // },
{ // {
label: '调窗', // label: '',
divided: true, // divided: true,
onClick: () => { // onClick: () => {
this.setToolActive('Wwwc') // this.setToolActive('Wwwc')
} // }
}, // },
{ // {
label: '反色', // label: '',
divided: true, // divided: true,
onClick: () => { // onClick: () => {
this.toggleInvert() // this.toggleInvert()
} // }
}, // },
{ // {
label: '伪彩', // label: '',
children: colorItems // children: colorItems
} // }
], // ],
event, // event,
// x: event.clientX, // // x: event.clientX,
// y: event.clientY, // // y: event.clientY,
customClass: 'class-a', // customClass: 'class-a',
zIndex: 3, // zIndex: 3,
minWidth: 100 // minWidth: 100
}) // })
return false // return false
}, },
getToolSate() { getToolSate() {
const toolROITypes = [ const toolROITypes = [

View File

@ -0,0 +1,287 @@
<template>
<div class="dcm-tag">
<el-input
v-model="search"
size="mini"
:placeholder="$t('trials:dicom-tag:keywords')"
style="width:200px"
/>
<el-table
:data="filterList(list)"
row-key="id"
default-expand-all
:tree-props="{children: 'child', hasChildren: 'hasChildren'}"
:default-sort="{prop: 'tagCode', order: 'ascending'}"
height="500"
>
<el-table-column
prop="tagCode"
label="Tag"
min-width="120"
sortable
/>
<el-table-column
prop="tagName"
label="Description"
min-width="150"
show-overflow-tooltip
sortable
/>
<el-table-column
prop="vr"
label="VR"
min-width="50"
show-overflow-tooltip
sortable
/>
<el-table-column
prop="tagLength"
label="Length"
min-width="80"
show-overflow-tooltip
sortable
/>
<el-table-column
prop="value"
label="Value"
min-width="200"
show-overflow-tooltip
sortable
/>
</el-table>
</div>
</template>
<script>
import TAG_DICT from './dataDictionary'
import * as cornerstone from 'cornerstone-core'
import dicomParser from 'dicom-parser'
export default {
name: 'DicomTags',
props: {
imageId: {
type: String,
required: true
}
},
data() {
return {
list: [],
idx: 0,
search: ''
}
},
async mounted() {
const image = await cornerstone.loadAndCacheImage(this.imageId)
var dataSet = dicomParser.parseDicom(image.data.byteArray)
var output = []
this.dumpDataSet(dataSet, output)
this.list = output
},
methods: {
filterList(list) {
if (list.length === 0) return []
if (!this.search) {
return list
} else {
const search = isNaN(parseFloat(this.search)) ? this.search.toLowerCase() : String(this.search)
const arr = list.filter(data => {
if (data.tagCode && data.tagCode.toLowerCase().includes(search)) {
return data
} else if (data.tagName && data.tagName.toLowerCase().includes(search)) {
return data
} else if (data.value) {
let v = ''
if (!isNaN(parseFloat(data.value))) {
v = String(data.value)
} else {
v = data.value.toLowerCase()
}
if (v.includes(search)) {
return data
}
}
})
return arr
}
},
dumpDataSet(dataSet, output) {
try {
for (const propertyName in dataSet.elements) {
const elementObject = {}
const element = dataSet.elements[propertyName]
const tag = this.getTag(element.tag)
elementObject.id = `${this.idx++}${new Date().getTime()}`
if (!tag) {
const group = element.tag.substring(1, 5)
const el = element.tag.substring(5, 9)
elementObject.tagCode = ('(' + group + ',' + el + ')').toUpperCase()
} else {
elementObject.tagCode = tag ? tag.tag : ''
elementObject.tagName = tag ? tag.name : ''
}
elementObject.tagLength = element.length
elementObject.value = ''
elementObject.child = []
if (element.items) {
element.items.forEach(item => {
const childOutput = []
this.dumpDataSet(item.dataSet, childOutput)
elementObject.child.push(...childOutput)
})
} else if (element.fragments) {
//
} else {
var vr
if (element.vr !== undefined) {
vr = element.vr
} else {
if (tag !== undefined) {
vr = tag.vr
}
}
elementObject.vr = vr
if (element.length < 128) {
// const str = dataSet.string(propertyName)
// if (elementObject.tagCode === 'x00280010') {
// console.log(str)
// }
// const stringIsAscii = this.isASCII(str)
// if (stringIsAscii && str !== undefined) {
// elementObject.value = str
// }
if (element.vr === undefined && tag === undefined) {
if (element.length === 2) {
elementObject.value = dataSet.uint16(propertyName)
} else if (element.length === 4) {
elementObject.value = dataSet.uint32(propertyName)
}
const str = dataSet.string(propertyName)
const stringIsAscii = this.isASCII(str)
if (stringIsAscii) {
if (str !== undefined) {
elementObject.value = str
}
} else {
if (element.length !== 2 && element.length !== 4) {
// elementObject.value = 'binary data'
}
}
} else {
if (this.isStringVr(vr)) {
const str = dataSet.string(propertyName)
const stringIsAscii = this.isASCII(str)
if (stringIsAscii) {
if (str !== undefined) {
elementObject.value = str
}
} else {
if (element.length !== 2 && element.length !== 4) {
// elementObject.value = 'binary data'
}
}
} else if (vr === 'US') {
let text = dataSet.uint16(propertyName)
for (let i = 1; i < dataSet.elements[propertyName].length / 2; i++) {
text += '\\' + dataSet.uint16(propertyName, i)
}
elementObject.value = text
} else if (vr === 'SS') {
let text = dataSet.int16(propertyName)
for (let i = 1; i < dataSet.elements[propertyName].length / 2; i++) {
text += '\\' + dataSet.int16(propertyName, i)
}
elementObject.value = text
} else if (vr === 'UL') {
let text = dataSet.uint32(propertyName)
for (let i = 1; i < dataSet.elements[propertyName].length / 4; i++) {
text += '\\' + dataSet.uint32(propertyName, i)
}
elementObject.value = text
} else if (vr === 'SL') {
let text = dataSet.int32(propertyName)
for (let i = 1; i < dataSet.elements[propertyName].length / 4; i++) {
text += '\\' + dataSet.int32(propertyName, i)
}
elementObject.value = text
} else if (vr === 'FD') {
let text = dataSet.double(propertyName)
for (let i = 1; i < dataSet.elements[propertyName].length / 8; i++) {
text += '\\' + dataSet.double(propertyName, i)
}
elementObject.value = text
} else if (vr === 'FL') {
let text = dataSet.float(propertyName)
for (let i = 1; i < dataSet.elements[propertyName].length / 4; i++) {
text += '\\' + dataSet.float(propertyName, i)
}
elementObject.value = text
} else if (vr === 'OB' || vr === 'OW' || vr === 'UN' || vr === 'OF' || vr === 'UT') {
if (element.length === 2) {
elementObject.value = dataSet.uint16(propertyName)
} else if (element.length === 4) {
elementObject.value = dataSet.uint32(propertyName)
} else {
}
} else if (vr === 'AT') {
// var group = dataSet.uint16(propertyName, 0);
// var groupHexStr = ("0000" + group.toString(16)).substr(-4);
// var element = dataSet.uint16(propertyName, 1);
// var elementHexStr = ("0000" + element.toString(16)).substr(-4);
// text += "x" + groupHexStr + elementHexStr;
} else if (vr === 'SQ') {
} else {
// no display code for VR yet, sorry!
}
}
}
}
output.push(elementObject)
}
} catch (err) {
const ex = {
exception: err,
output: output
}
console.log(ex)
}
},
getTag(tag) {
var group = tag.substring(1, 5)
var element = tag.substring(5, 9)
var tagIndex = ('(' + group + ',' + element + ')').toUpperCase()
var attr = TAG_DICT[tagIndex]
return attr
},
isASCII(str) {
return /^[\x00-\x7F]*$/.test(str)
},
isStringVr(vr) {
if (vr === 'AT' || vr === 'FL' || vr === 'FD' || vr === 'OB' || vr === 'OF' || vr === 'OW' || vr === 'SI' || vr === 'SQ' || vr === 'SS' || vr === 'UL' || vr === 'US') {
return false
}
return true
}
}
}
</script>
<style lang="scss" scoped>
.dcm-tag{
// user-select: none;
::-webkit-scrollbar {
width: 8px;
height: 15px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
}
</style>

View File

@ -162,6 +162,19 @@
<button :title="$t('trials:dicom-show:lens')" class="btn-link" data-tool="Magnify" @click="setToolActive($event,'Magnify')"> <button :title="$t('trials:dicom-show:lens')" class="btn-link" data-tool="Magnify" @click="setToolActive($event,'Magnify')">
<svg-icon icon-class="zoom" style="font-size:20px;" /> <svg-icon icon-class="zoom" style="font-size:20px;" />
</button> </button>
<button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
<svg-icon icon-class="rotate" style="font-size:20px;" />
<div class="dropdown-content">
<div @click.stop="setDicomCanvasRotate(1)">{{ $t('trials:reading:button:rotateDefault') }}</div>
<div @click.stop="setDicomCanvasRotate(2)">{{ $t('trials:reading:button:rotateHorizontal') }}</div>
<div @click.stop="setDicomCanvasRotate(3)">{{ $t('trials:reading:button:rotateVertical') }}</div>
<div @click.stop="setDicomCanvasRotate(4)">{{ $t('trials:reading:button:rotateTurnLeft') }}</div>
<div @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</div>
</div>
</button>
<button :title="$t('trials:reading:button:move')" class="btn-link" data-tool="Pan" @click="setToolActive($event,'Pan')">
<svg-icon icon-class="move" style="font-size:20px;" />
</button>
<button :title="$t('trials:reading:button:fitWindow')" class="btn-link" data-tool="fitToWindow" @click="fitToType($event,'fitToWindow')"> <button :title="$t('trials:reading:button:fitWindow')" class="btn-link" data-tool="fitToWindow" @click="fitToType($event,'fitToWindow')">
<svg-icon icon-class="fitToWindow" style="font-size:20px;" /> <svg-icon icon-class="fitToWindow" style="font-size:20px;" />
</button> </button>
@ -169,19 +182,7 @@
<svg-icon icon-class="fitToImage" style="font-size:20px;" /> <svg-icon icon-class="fitToImage" style="font-size:20px;" />
</button> </button>
<!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> --> <!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> -->
<button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
<svg-icon icon-class="rotate" style="font-size:20px;" />
<div class="dropdown-content">
<p @click.stop="setDicomCanvasRotate(1)">{{ $t('trials:reading:button:rotateDefault') }}</p>
<p @click.stop="setDicomCanvasRotate(2)">{{ $t('trials:reading:button:rotateHorizontal') }}</p>
<p @click.stop="setDicomCanvasRotate(3)">{{ $t('trials:reading:button:rotateVertical') }}</p>
<p @click.stop="setDicomCanvasRotate(4)">{{ $t('trials:reading:button:rotateTurnLeft') }}</p>
<p @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</p>
</div>
</button>
<button :title="$t('trials:reading:button:move')" class="btn-link" data-tool="Pan" @click="setToolActive($event,'Pan')">
<svg-icon icon-class="move" style="font-size:20px;" />
</button>
</div> </div>
</div> </div>
<!-- 测量标注 --> <!-- 测量标注 -->
@ -232,6 +233,10 @@
<button :title="$t('trials:dicom-show:image')" class="btn-link" @click="currentDicomCanvas.saveImage()"> <button :title="$t('trials:dicom-show:image')" class="btn-link" @click="currentDicomCanvas.saveImage()">
<svg-icon icon-class="image" style="font-size:20px;" /> <svg-icon icon-class="image" style="font-size:20px;" />
</button> </button>
<!-- 标签 -->
<button :title="$t('trials:dicom-show:tags')" class="btn-link" @click="currentDicomCanvas.showTags()">
<svg-icon icon-class="dictionary" style="font-size:20px;" />
</button>
</div> </div>
</div> </div>
<div class="measureTool-wrapper"> <div class="measureTool-wrapper">
@ -247,7 +252,7 @@
<svg-icon icon-class="previousframe" style="font-size:20px;" /> <svg-icon icon-class="previousframe" style="font-size:20px;" />
</button> </button>
<!-- 播放 --> <!-- 播放 -->
<button class="btn-link" :title="$t('trials:dicom-show:play')" @click="currentDicomCanvas.toggleClipPlay()"> <button class="btn-link" :title="$t('trials:dicom-show:play')" @click="clipPlay">
<svg-icon <svg-icon
:icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'" :icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'"
style="font-size:20px;" style="font-size:20px;"
@ -261,9 +266,10 @@
<button class="btn-link" :title="$t('trials:dicom-show:lastframe')" @click="currentDicomCanvas.scrollPage(9999)"> <button class="btn-link" :title="$t('trials:dicom-show:lastframe')" @click="currentDicomCanvas.scrollPage(9999)">
<svg-icon icon-class="lastframe" style="font-size:20px;" /> <svg-icon icon-class="lastframe" style="font-size:20px;" />
</button> </button>
<select class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)"> <select v-model="fps" class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)">
<!-- 默认值 --> <!-- 默认值 -->
<option :value="10">{{ $t('trials:dicom-show:default') }}</option> <option :value="5">5</option>
<option :value="10">10</option>
<option :value="15">15</option> <option :value="15">15</option>
<option :value="20">20</option> <option :value="20">20</option>
<option :value="30">30</option> <option :value="30">30</option>
@ -386,7 +392,8 @@ export default {
wwwcList: [], wwwcList: [],
layout: null, layout: null,
seriesList: [], seriesList: [],
customWwc: { visible: false, title: null } customWwc: { visible: false, title: null },
fps: 15
} }
}, },
mounted() { mounted() {
@ -400,8 +407,10 @@ export default {
methods: { methods: {
loadImageStack(dicomSeries) { loadImageStack(dicomSeries) {
this.currentDicomCanvas.toolState.clipPlaying = false
this.$nextTick(() => { this.$nextTick(() => {
this.currentDicomCanvas.loadImageStack(dicomSeries) const series = Object.assign({}, dicomSeries)
this.currentDicomCanvas.loadImageStack(series)
}) })
}, },
loadOtherImageStack(seriesList) { loadOtherImageStack(seriesList) {
@ -411,7 +420,8 @@ export default {
Array.from(elements).forEach((element, index) => { Array.from(elements).forEach((element, index) => {
const canvasIndex = element.getAttribute('data-index') const canvasIndex = element.getAttribute('data-index')
if (index < seriesList.length && element.style.display !== 'none') { if (index < seriesList.length && element.style.display !== 'none') {
this.$refs[`dicomCanvas${canvasIndex}`].loadImageStack(seriesList[index]) const series = Object.assign({}, seriesList[index])
this.$refs[`dicomCanvas${canvasIndex}`].loadImageStack(series)
} }
}) })
}) })
@ -565,6 +575,10 @@ export default {
setDicomCanvasfps(event) { setDicomCanvasfps(event) {
this.currentDicomCanvas.setFps(event.target.value) this.currentDicomCanvas.setFps(event.target.value)
}, },
clipPlay() {
this.currentDicomCanvas.setFps(this.fps)
this.currentDicomCanvas.toggleClipPlay()
},
fitToType(e, type) { fitToType(e, type) {
const toolButtons = document.querySelectorAll('[data-tool]') const toolButtons = document.querySelectorAll('[data-tool]')
Array.from(toolButtons).forEach((toolBtn) => { Array.from(toolButtons).forEach((toolBtn) => {
@ -879,13 +893,19 @@ export default {
background-color: #323232; background-color: #323232;
min-width: 80px; min-width: 80px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
border: 1px solid #4e4e4e;
padding: 5px; padding: 5px;
} }
.dicom-wrapper .dropdown:hover .dropdown-content { .dicom-wrapper .dropdown:hover .dropdown-content {
display: block; display: block;
} }
.dicom-wrapper .dropdown-content p{ .dicom-wrapper .dropdown-content div{
height: 25px;
line-height: 25px;
cursor:point; cursor:point;
} }
.dicom-wrapper .dropdown-content div:hover{
background-color: #16477b90;
}
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -23,11 +23,11 @@
</template> </template>
<script> <script>
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg' // import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
const ffmpeg = createFFmpeg({ // const ffmpeg = createFFmpeg({
log: true, // log: true,
corePath: './ffmpeg-core.js' // corePath: './ffmpeg-core.js'
}) // })
export default { export default {
props: { props: {
@ -73,41 +73,41 @@ export default {
async videoToMp4() { async videoToMp4() {
// //
// https // https
if (!window.isSecureContext) { // if (!window.isSecureContext) {
this.$alert(this.$t('components:uploadvideo:message:xf3')) // this.$alert(this.$t('components:uploadvideo:message:xf3'))
return // return
} // }
// // //
if (!window.crossOriginIsolated) { // if (!window.crossOriginIsolated) {
this.$alert(this.$t('components:uploadvideo:message:xf4')) // this.$alert(this.$t('components:uploadvideo:message:xf4'))
return // return
} // }
this.$message.success(this.$t('components:uploadvideo:message:xf5')) // this.$message.success(this.$t('components:uploadvideo:message:xf5'))
if (!ffmpeg.isLoaded()) { // if (!ffmpeg.isLoaded()) {
await ffmpeg.load() // await ffmpeg.load()
} // }
this.percentage = 0 // this.percentage = 0
this.isVideoToMp4 = true // this.isVideoToMp4 = true
ffmpeg.setProgress(({ ratio }) => { // ffmpeg.setProgress(({ ratio }) => {
console.log(ratio) // console.log(ratio)
if (ratio * 100 < 1) { // if (ratio * 100 < 1) {
this.percentage = parseInt(0) // this.percentage = parseInt(0)
} else { // } else {
this.percentage = parseInt(ratio * 100) // this.percentage = parseInt(ratio * 100)
} // }
}) // })
ffmpeg.FS('writeFile', 'input.mp4', await fetchFile(this.videoSrc)) // ffmpeg.FS('writeFile', 'input.mp4', await fetchFile(this.videoSrc))
await ffmpeg.run('-i', 'input.mp4', 'output.mp4') // await ffmpeg.run('-i', 'input.mp4', 'output.mp4')
this.videoSrc = null // this.videoSrc = null
const data = ffmpeg.FS('readFile', 'output.mp4') // const data = ffmpeg.FS('readFile', 'output.mp4')
this.dataBuffer = new Blob([data.buffer], { type: 'video/mp4' }) // this.dataBuffer = new Blob([data.buffer], { type: 'video/mp4' })
this.$message.success(this.$t('components:uploadvideo:message:xf6')) // this.$message.success(this.$t('components:uploadvideo:message:xf6'))
setTimeout(() => { // setTimeout(() => {
this.videoSrc = URL.createObjectURL(this.dataBuffer) // this.videoSrc = URL.createObjectURL(this.dataBuffer)
this.isVideoToMp4 = false // this.isVideoToMp4 = false
this.isNeedToMp4 = false // this.isNeedToMp4 = false
process.exit(0) // process.exit(0)
}, 50) // }, 50)
}, },
fileChange(e) { fileChange(e) {
this.videoSrc = null this.videoSrc = null

View File

@ -30,30 +30,55 @@ const getDefaultState = () => {
activeSeries: {}, activeSeries: {},
lastCanvasTaskId: '', lastCanvasTaskId: '',
imageQuality: null, imageQuality: null,
imageQualityIssues: null imageQualityIssues: null,
currentLoadIns: []
} }
} }
function getQuestions(questions) { function getQuestions(questions) {
const criterionType = parseInt(localStorage.getItem('CriterionType'))
questions.forEach(item => { questions.forEach(item => {
if (item.Type === 'table' && item.TableQuestions && item.TableQuestions.Answers.length > 0) { if ((item.Type === 'table' || item.Type === 'basicTable') && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
item.TableQuestions.Answers.forEach(answerObj => { item.TableQuestions.Answers.forEach(answerObj => {
answerObj.lesionPart = getQuestionAnswer(item.TableQuestions.Questions, 8, answerObj)
answerObj.loctation = getQuestionAnswer(item.TableQuestions.Questions, 6, answerObj)
answerObj.lesionLength = getQuestionAnswer(item.TableQuestions.Questions, 0, answerObj)
answerObj.lesionShort = getQuestionAnswer(item.TableQuestions.Questions, 1, answerObj)
answerObj.isDicomReading = answerObj.IsDicomReading === 'True' answerObj.isDicomReading = answerObj.IsDicomReading === 'True'
var isLymphLesion = getQuestionAnswer(item.TableQuestions.Questions, 2, answerObj)
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
answerObj.isLymphLesion = isLymphLesion
answerObj.lesionState = getQuestionAnswer(item.TableQuestions.Questions, 7, answerObj)
var lesionNum = getQuestionAnswer(item.TableQuestions.Questions, 11, answerObj)
answerObj.lesionNum = lesionNum
if (answerObj.RowId) { if (answerObj.RowId) {
var idx = item.TableQuestions.Questions.findIndex(i => i.QuestionMark === 11) if (criterionType === 10) {
if (idx > -1) {
// pcwg // pcwg
var lesionNum = getQuestionAnswer(item.TableQuestions.Questions, 11, answerObj)
answerObj.lesionNum = lesionNum
answerObj.saveTypeEnum = isNaN(parseInt(answerObj.lesionNum)) ? 1 : 2 answerObj.saveTypeEnum = isNaN(parseInt(answerObj.lesionNum)) ? 1 : 2
} else if (criterionType === 19) {
// ivus
answerObj.area1 = getQuestionAnswer(item.TableQuestions.Questions, 1001, answerObj)
answerObj.area2 = getQuestionAnswer(item.TableQuestions.Questions, 1002, answerObj)
const v = getQuestionAnswer(item.TableQuestions.Questions, 1003, answerObj)
answerObj.diff = v
answerObj.saveTypeEnum = isNaN(parseFloat(v)) ? 1 : 2
} else if (criterionType === 20) {
// oct
if (item.LesionType === 101) {
answerObj.l1 = getQuestionAnswer(item.TableQuestions.Questions, 1011, answerObj)
answerObj.l2 = getQuestionAnswer(item.TableQuestions.Questions, 1012, answerObj)
answerObj.l3 = getQuestionAnswer(item.TableQuestions.Questions, 1013, answerObj)
const min = getQuestionAnswer(item.TableQuestions.Questions, 1014, answerObj)
answerObj.min = min
const mean = getQuestionAnswer(item.TableQuestions.Questions, 1015, answerObj)
answerObj.mean = mean
answerObj.saveTypeEnum = (isNaN(parseFloat(min)) || isNaN(parseFloat(mean))) ? 1 : 2
} else if (item.LesionType === 103) {
const angle = getQuestionAnswer(item.TableQuestions.Questions, 1016, answerObj)
answerObj.angle = angle
answerObj.saveTypeEnum = isNaN(parseFloat(angle)) ? 1 : 2
}
} else { } else {
answerObj.lesionPart = getQuestionAnswer(item.TableQuestions.Questions, 8, answerObj)
answerObj.loctation = getQuestionAnswer(item.TableQuestions.Questions, 6, answerObj)
answerObj.lesionLength = getQuestionAnswer(item.TableQuestions.Questions, 0, answerObj)
answerObj.lesionShort = getQuestionAnswer(item.TableQuestions.Questions, 1, answerObj)
let isLymphLesion = getQuestionAnswer(item.TableQuestions.Questions, 2, answerObj)
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
answerObj.isLymphLesion = isLymphLesion
answerObj.lesionState = getQuestionAnswer(item.TableQuestions.Questions, 7, answerObj)
answerObj.saveTypeEnum = isNaN(parseInt(answerObj.lesionState)) ? 1 : 2 answerObj.saveTypeEnum = isNaN(parseInt(answerObj.lesionState)) ? 1 : 2
} }
} else { } else {
@ -69,7 +94,7 @@ function getQuestions(questions) {
} }
function findQuestionAndRemoveLesion(questions, obj) { function findQuestionAndRemoveLesion(questions, obj) {
for (var i = 0; i < questions.length; i++) { for (var i = 0; i < questions.length; i++) {
if (questions[i].Type === 'table' && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType) && questions[i].TableQuestions.Answers.length > 0) { if ((questions[i].Type === 'table' || questions[i].Type === 'basicTable') && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType) && questions[i].TableQuestions.Answers.length > 0) {
var idx = questions[i].TableQuestions.Answers.findIndex(i => String(i.RowIndex) === String(obj.rowIndex)) var idx = questions[i].TableQuestions.Answers.findIndex(i => String(i.RowIndex) === String(obj.rowIndex))
if (idx > -1) { if (idx > -1) {
questions[i].TableQuestions.Answers.splice(idx, 1) questions[i].TableQuestions.Answers.splice(idx, 1)
@ -85,7 +110,7 @@ function findQuestionAndRemoveLesion(questions, obj) {
function findQuestionAndUpdateLesion(questions, obj) { function findQuestionAndUpdateLesion(questions, obj) {
for (var i = 0; i < questions.length; i++) { for (var i = 0; i < questions.length; i++) {
var item = questions[i] var item = questions[i]
if (item.Type === 'table' && item.Id === obj.questionId) { if ((item.Type === 'table' || item.Type === 'basicTable') && item.Id === obj.questionId) {
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex) var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
item.TableQuestions.Answers[idx].isLymphLesion = obj.isLymphLesion item.TableQuestions.Answers[idx].isLymphLesion = obj.isLymphLesion
item.TableQuestions.Answers[idx].loctation = obj.lesionOrgan item.TableQuestions.Answers[idx].loctation = obj.lesionOrgan
@ -114,10 +139,10 @@ function findQuestionAndUpdateLesion(questions, obj) {
} }
function findQuestionAndAddLesion(questions, obj) { function findQuestionAndAddLesion(questions, obj) {
for (var i = 0; i < questions.length; i++) { for (var i = 0; i < questions.length; i++) {
if (questions[i].Type === 'table' && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType)) { if ((questions[i].Type === 'table' || questions[i].Type === 'basicTable') && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType)) {
var sourceObj = {} var sourceObj = {}
questions[i].TableQuestions.Questions.forEach(item => { questions[i].TableQuestions.Questions.forEach(item => {
sourceObj[item.Id] = '' sourceObj[item.Id] = null
}) })
var targetObj = Object.assign(sourceObj, obj.lesionObj) var targetObj = Object.assign(sourceObj, obj.lesionObj)
targetObj.IsCurrentTaskAdd = 'True' targetObj.IsCurrentTaskAdd = 'True'
@ -139,6 +164,22 @@ function getQuestionAnswer(questions, questionMark, answers) {
return '' return ''
} }
} }
// function getKeySeriesInfo(keyInstance, series) {
// const obj = {}
// const set = new Set()
// var instances = series.instanceList.concat(keyInstance).filter((item) => {
// if (set.has(item)) {
// return true
// } else {
// set.add(item)
// return false
// }
// })
// instances.map(item => {
// obj[item] = { seriesId: series.seriesId, studyIndex: series.studyIndex, seriesIndex: series.seriesIndex }
// })
// return obj
// }
const state = getDefaultState const state = getDefaultState
@ -190,6 +231,7 @@ const actions = {
}, },
getMasterSeries({ state }, obj) { getMasterSeries({ state }, obj) {
return new Promise(resolve => { return new Promise(resolve => {
console.log('getMasterSeries')
var seriesInfo = {} var seriesInfo = {}
var i = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId) var i = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
getReadingVisitStudyList(obj.trialId, obj.visitId, obj.visitTaskId).then(res => { getReadingVisitStudyList(obj.trialId, obj.visitId, obj.visitTaskId).then(res => {
@ -209,14 +251,28 @@ const actions = {
var seriesList = [] var seriesList = []
study.SeriesList.forEach((series, index) => { study.SeriesList.forEach((series, index) => {
const imageIds = [] const imageIds = []
const instanceList = []
series.InstancePathList.forEach((path) => { // series.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`) // imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
// })
series.InstanceInfoList.forEach(instance => {
if (instance.NumberOfFrames && instance.NumberOfFrames > 1) {
for (let i = 0; i < instance.NumberOfFrames; i++) {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=0|0`
imageIds.push(imageId)
}
} else {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=0|0`
imageIds.push(imageId)
}
instance.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=0|0`
instanceList.push(instance.Id)
}) })
seriesList.push({ seriesList.push({
isDicom: study.IsDicom, isDicom: study.IsDicom,
imageIds: imageIds, imageIds: imageIds,
instanceList: series.InstanceList, instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
seriesId: series.Id, seriesId: series.Id,
imageIdIndex: 0, imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid, seriesUid: series.SeriesInstanceUid,
@ -481,24 +537,28 @@ const actions = {
return new Promise(async resolve => { return new Promise(async resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId) var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
var measureData = state.visitTaskList[index].MeasureData var measureData = state.visitTaskList[index].MeasureData
console.log('removeCustomizeMeasuredData', obj, state.visitTaskList[index].MeasureData)
// var uuid = obj.measureData.data.uuid // var uuid = obj.measureData.data.uuid
// var idx = measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid) // var idx = measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
console.log(obj, measureData) // console.log(obj, measureData)
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id) if (obj.questionInfo.Id) {
console.log('idx', idx) var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
if (idx > -1) { console.log('idx', idx)
if (measureData[idx].FristAddTaskId) { if (idx > -1) {
measureData[idx].MeasureData = '' if (measureData[idx].FristAddTaskId) {
console.log('清除标记成功', idx) measureData[idx].MeasureData = ''
} else { console.log('清除标记成功', idx)
measureData.splice(idx, 1) } else {
console.log('移除标记成功', idx) measureData.splice(idx, 1)
console.log('移除标记成功', idx)
}
if (obj.questionInfo.Id && state.currentReadingTaskState < 2) {
await deleteCustomTag(obj.questionInfo.Id)
}
state.visitTaskList[index].MeasureData = measureData
} }
await deleteCustomTag(obj.questionInfo.Id)
state.visitTaskList[index].MeasureData = measureData
} else if (obj.orderMarkName) { } else if (obj.orderMarkName) {
const i = measureData.findIndex(item => item.QuestionId === obj.questionId && item.OrderMarkName === obj.orderMarkName) const i = measureData.findIndex(item => item.MeasureData.data.remark === obj.orderMarkName)
if (i > -1) { if (i > -1) {
if (measureData[i].FristAddTaskId) { if (measureData[i].FristAddTaskId) {
measureData[i].MeasureData = '' measureData[i].MeasureData = ''
@ -508,7 +568,9 @@ const actions = {
console.log('移除标记成功', i) console.log('移除标记成功', i)
} }
} }
await deleteCustomTag(obj.questionInfo.Id) if (obj.questionInfo.Id && state.currentReadingTaskState < 2) {
await deleteCustomTag(obj.questionInfo.Id)
}
state.visitTaskList[index].MeasureData = measureData state.visitTaskList[index].MeasureData = measureData
} }
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '') // sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
@ -590,6 +652,7 @@ const actions = {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId) var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
var measureData = state.visitTaskList[index].MeasureData var measureData = state.visitTaskList[index].MeasureData
console.log('addOrUpdateNonTargetMeasuredData') console.log('addOrUpdateNonTargetMeasuredData')
// item.MeasureData.data.remark === obj.orderMarkName
var idx = measureData.findIndex(item => item.QuestionId === obj.data.QuestionId && item.OrderMarkName === obj.data.OrderMarkName) var idx = measureData.findIndex(item => item.QuestionId === obj.data.QuestionId && item.OrderMarkName === obj.data.OrderMarkName)
if (idx > -1) { if (idx > -1) {
for (const k in state.visitTaskList[index].MeasureData[idx]) { for (const k in state.visitTaskList[index].MeasureData[idx]) {
@ -632,29 +695,39 @@ const actions = {
var measureData = state.visitTaskList[index].MeasureData var measureData = state.visitTaskList[index].MeasureData
console.log(measureData, obj) console.log(measureData, obj)
// var idx = measureData.findIndex(item => item.MeasureData.uuid === obj.data.MeasureData.data.uuid) // var idx = measureData.findIndex(item => item.MeasureData.uuid === obj.data.MeasureData.data.uuid)
if (!obj.questionInfo) { // if (!obj.questionInfo) {
state.visitTaskList[index].MeasureData.push({ // state.visitTaskList[index].MeasureData.push({
MeasureData: obj, // MeasureData: obj,
SeriesId: obj.seriesId, // SeriesId: obj.seriesId,
StudyId: obj.studyId, // StudyId: obj.studyId,
InstanceId: obj.instanceId, // InstanceId: obj.instanceId,
Id: obj.Id // Id: obj.Id
}) // })
console.log('新增标记成功') // console.log('新增标记成功')
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '') // resolve()
resolve() // }
} var idx = measureData.findIndex(item => item.MeasureData.data.remark === obj.measureData.data.remark)
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
if (idx > -1) { if (idx > -1) {
for (const k in state.visitTaskList[index].MeasureData[idx]) { // state.visitTaskList[index].MeasureData[idx].InstanceId = obj.instanceId
if (k !== 'Id' && obj.MeasureData.data[k]) { state.visitTaskList[index].MeasureData[idx].MeasureData = obj.measureData
state.visitTaskList[index].MeasureData[idx][k] = obj.MeasureData.data[k] // state.visitTaskList[index].MeasureData[idx].SeriesId = obj.seriesId
} // state.visitTaskList[index].MeasureData[idx].StudyId = obj.studyId
} // for (const k in state.visitTaskList[index].MeasureData[idx]) {
// if (k !== 'Id' && obj.MeasureData.data[k]) {
// state.visitTaskList[index].MeasureData[idx][k] = obj.MeasureData.data[k]
// }
// }
// state.visitTaskList[index].MeasureData[idx].MeasureData = obj.data.MeasureData // state.visitTaskList[index].MeasureData[idx].MeasureData = obj.data.MeasureData
console.log('更新标记成功', idx) console.log('更新标记成功', idx)
} else { } else {
state.visitTaskList[index].MeasureData.push(obj.MeasureData.data) // state.visitTaskList[index].MeasureData.push(obj.MeasureData.data)
state.visitTaskList[index].MeasureData.push({
MeasureData: obj.measureData,
SeriesId: obj.measureData.seriesId,
StudyId: obj.measureData.studyId,
InstanceId: obj.measureData.instanceId,
Id: obj.id
})
console.log('新增标记成功') console.log('新增标记成功')
} }
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '') // sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
@ -720,15 +793,24 @@ const actions = {
}) })
}, },
getStudyInfo({ state }, obj) { getStudyInfo({ state }, obj) {
console.log('getStudyInfo')
return new Promise(resolve => { return new Promise(resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId) var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
if (state.visitTaskList[index].studyListInit) { if (state.visitTaskList[index].studyListInit) {
resolve() resolve()
} else { } else {
var studyList = [] var studyList = []
// getVisitStudyList var keyImages = []
// getReadingVisitStudyList
getReadingVisitStudyList(obj.trialId, obj.subjectVisitId, obj.visitTaskId).then(res => { getReadingVisitStudyList(obj.trialId, obj.subjectVisitId, obj.visitTaskId).then(res => {
const i = res.Result.findIndex(i => i.IsCriticalSequence)
if (i > -1) {
const seriesList = res.Result[i].SeriesList && res.Result[i].SeriesList
seriesList.map(i => {
i.InstanceInfoList.map(k => {
keyImages.push({ instanceId: k.Id })
})
})
}
res.Result.forEach((study, studyIndex) => { res.Result.forEach((study, studyIndex) => {
const data = {} const data = {}
data.StudyId = study.StudyId data.StudyId = study.StudyId
@ -743,19 +825,47 @@ const actions = {
var seriesList = [] var seriesList = []
study.SeriesList.forEach((series, seriesIndex) => { study.SeriesList.forEach((series, seriesIndex) => {
const imageIds = [] const imageIds = []
try { const instanceList = []
// if (~window.location.href.indexOf('3c210000-3e2c-0016-4247-08dabf28e96b')) { // try {
series.InstancePathList.forEach((path) => { // series.InstancePathList.forEach((path) => {
// var path = id.split('/')[id.split('/').length - 1] // imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`) // })
}) // } catch (e) {
} catch (e) { // console.log(e)
console.log(e) // }
} series.InstanceInfoList.forEach(instance => {
if (instance.NumberOfFrames && instance.NumberOfFrames > 1) {
if (study.IsCriticalSequence && instance.KeyFramesList.length > 0) {
instance.KeyFramesList.map(i => {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
imageIds.push(imageId)
})
} else {
for (let i = 0; i < instance.NumberOfFrames; i++) {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
imageIds.push(imageId)
}
}
instance.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${0}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
} else {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
imageIds.push(imageId)
instance.ImageId = imageId
}
if (!study.IsCriticalSequence && series.IsBeMark) {
const i = keyImages.findIndex(i => i.instanceId === instance.Id)
if (i > -1) {
keyImages[i].studyIndex = studyIndex
keyImages[i].seriesIndex = seriesIndex
}
}
instanceList.push(instance.Id)
})
seriesList.push({ seriesList.push({
isDicom: study.IsDicom, isDicom: study.IsDicom,
imageIds: imageIds, imageIds: imageIds,
instanceList: series.InstanceList, instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
seriesId: series.Id, seriesId: series.Id,
imageIdIndex: 0, imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid, seriesUid: series.SeriesInstanceUid,
@ -782,7 +892,8 @@ const actions = {
isLoading: false, isLoading: false,
isBeMark: series.IsBeMark, isBeMark: series.IsBeMark,
ww: series.WindowWidth, ww: series.WindowWidth,
wc: series.WindowCenter wc: series.WindowCenter,
isExistMutiFrames: series.IsExistMutiFrames
}) })
}) })
data.SeriesList = seriesList data.SeriesList = seriesList
@ -790,6 +901,7 @@ const actions = {
}) })
state.visitTaskList[index].StudyList = studyList state.visitTaskList[index].StudyList = studyList
state.visitTaskList[index].studyListInit = true state.visitTaskList[index].studyListInit = true
state.visitTaskList[index].KeyImages = keyImages
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '') // sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve() resolve()
}).catch(() => { resolve() }) }).catch(() => { resolve() })
@ -848,6 +960,115 @@ const actions = {
resolve() resolve()
}) })
}, },
setImageLoadedProgress({ state }, obj) {
const studyIndex = parseInt(obj.idx.split('|')[0])
const seriesIndex = parseInt(obj.idx.split('|')[1])
const visitTaskIndex = parseInt(obj.idx.split('|')[2])
let pStudyIndex = null
let pSeriesIndex = null
let pSeries = null
try {
const study = state.visitTaskList[visitTaskIndex].StudyList[studyIndex]
const series = state.visitTaskList[visitTaskIndex].StudyList[studyIndex].SeriesList[seriesIndex]
const keyImages = state.visitTaskList[visitTaskIndex].KeyImages
if (study.IsCriticalSequence) {
const i = keyImages.findIndex(i => i.instanceId === obj.instanceId)
if (i > -1) {
pStudyIndex = keyImages[i].studyIndex
pSeriesIndex = keyImages[i].seriesIndex
}
} else if (series.isBeMark) {
if (keyImages.length > 0) {
pStudyIndex = 0
pSeriesIndex = 0
}
}
if (pStudyIndex !== null && pSeriesIndex !== null) {
pSeries = state.visitTaskList[visitTaskIndex].StudyList[pStudyIndex].SeriesList[pSeriesIndex]
}
var prefetchInstanceCount = series.prefetchInstanceCount
var instanceCount = series.instanceCount
var prefetchInstanceCount2 = pSeries ? pSeries.prefetchInstanceCount : null
var instanceCount2 = pSeries ? pSeries.instanceCount : null
if (series.imageloadedArr.indexOf(obj.instanceId) < 0) {
const i = state.currentLoadIns.findIndex(i => i.instanceId === obj.instanceId)
if (i > -1) {
prefetchInstanceCount = prefetchInstanceCount + obj.percentComplete - state.currentLoadIns[i].percentComplete
prefetchInstanceCount2 = prefetchInstanceCount2 !== null ? prefetchInstanceCount2 + obj.percentComplete - state.currentLoadIns[i].percentComplete : null
state.currentLoadIns[i].percentComplete = obj.percentComplete
if (obj.percentComplete >= 100) {
state.currentLoadIns.splice(i, 1)
}
} else {
if (obj.percentComplete !== 100) {
state.currentLoadIns.push({ instanceId: obj.instanceId, percentComplete: obj.percentComplete })
}
prefetchInstanceCount = prefetchInstanceCount + obj.percentComplete
prefetchInstanceCount2 = prefetchInstanceCount2 !== null ? prefetchInstanceCount2 + obj.percentComplete : null
}
series.prefetchInstanceCount = prefetchInstanceCount
if (pSeries) {
pSeries.prefetchInstanceCount = prefetchInstanceCount2
}
if (obj.percentComplete >= 100) {
series.imageloadedArr.push(obj.instanceId)
if (pSeries) {
pSeries.imageloadedArr.push(obj.instanceId)
}
}
}
if (prefetchInstanceCount >= instanceCount * 100) {
series.prefetchInstanceCount = instanceCount * 100
// 设置当前序列状态为已下载完成
series.loadStatus = true
}
if (prefetchInstanceCount2 !== null && instanceCount2 !== null && prefetchInstanceCount2 >= instanceCount2 * 100) {
pSeries.prefetchInstanceCount = instanceCount2 * 100
// 设置当前序列状态为已下载完成
pSeries.loadStatus = true
}
} catch (e) {
console.log('error')
}
},
setImageloadedInfo({ state }, obj) {
console.log('setImageloadedInfo', obj)
// if(obj.instance === '20dd8fc9-51b0-ec63-942b-cb3006c72650')
// var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
// // const prefetchInstanceCount = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount
// const instanceList = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].instanceList
// const idx = state.visitTaskList[index].StudyList.findIndex(i => i.IsCriticalSequence)
// if (!state.visitTaskList[index].StudyList[obj.studyIndex].IsCriticalSequence) {
// // 当前下载的非关键序列
// console.log('当前下载的非关键序列')
// if (idx > -1) {
// const keyInstance = state.visitTaskList[index].StudyList[idx].SeriesList[0].instanceList
// obj.markedImages = getKeySeriesInfo(keyInstance, state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex])
// instanceList.map(i => {
// if (obj.markedImages.hasOwnProperty(i) && state.visitTaskList[index].StudyList[idx].SeriesList[0].imageloadedArr.indexOf(i) < 0) {
// state.visitTaskList[index].StudyList[idx].SeriesList[0].imageloadedArr.push(i)
// state.visitTaskList[index].StudyList[idx].SeriesList[0].prefetchInstanceCount = state.visitTaskList[index].StudyList[idx].SeriesList[0].prefetchInstanceCount + 100
// }
// })
// if (state.visitTaskList[index].StudyList[idx].SeriesList[0].imageloadedArr >= state.visitTaskList[index].StudyList[idx].SeriesList[0].instanceCount) {
// state.visitTaskList[index].StudyList[idx].SeriesList[0].loadStatus = true
// }
// }
// }
// state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].instanceCount * 100
// state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].imageloadedArr = instanceList
// state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].loadStatus = true
// const imageloadedArr = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].imageloadedArr
// if (imageloadedArr.indexOf())
// if (state.visitTaskList[index].StudyList[0].IsCriticalSequence){
// state.visitTaskList[index].StudyList[0].SeriesList[0].prefetchInstanceCount = prefetchInstanceCount + 100
// state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].imageloadedArr.push(obj.imageId)
// }
},
setStatus({ state }, obj) { setStatus({ state }, obj) {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId) var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
state.visitTaskList[index].IsInit = true state.visitTaskList[index].IsInit = true
@ -861,7 +1082,15 @@ const actions = {
}, },
setLastCanvasTaskId({ state }, taskId) { setLastCanvasTaskId({ state }, taskId) {
return new Promise(resolve => { return new Promise(resolve => {
state.lastCanvasTaskId = taskId var isReadingTaskViewInOrder = localStorage.getItem('isReadingTaskViewInOrder')
if (parseInt(isReadingTaskViewInOrder) === 2) {
if (!state.lastCanvasTaskId) {
console.log('setLastCanvasTaskId')
state.lastCanvasTaskId = taskId
}
} else {
state.lastCanvasTaskId = taskId
}
resolve() resolve()
}) })
}, },

View File

@ -0,0 +1,103 @@
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
function parseImageId(imageId) {
// build a url by parsing out the url scheme and frame index from the imageId
const firstColonIndex = imageId.indexOf(':');
let url = imageId.substring(firstColonIndex + 1);
const frameIndex = url.indexOf('frame=');
let frame;
if (frameIndex !== -1) {
const frameStr = url.substr(frameIndex + 6);
frame = parseInt(frameStr, 10);
url = url.substr(0, frameIndex - 1);
}
return {
scheme: imageId.substr(0, firstColonIndex),
url,
frame,
};
}
function getNumberValues(dataSet, tag, minimumLength) {
const values = [];
const valueAsString = dataSet.string(tag);
if (!valueAsString) {
return;
}
const split = valueAsString.split('\\');
if (minimumLength && split.length < minimumLength) {
return;
}
for (let i = 0; i < split.length; i++) {
values.push(parseFloat(split[i]));
}
return values;
}
function metaDataProvider(type, imageId) {
const parsedImageId = parseImageId(imageId);
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
if (!dataSet) {
return;
}
if (type === 'imagePlaneModule') {
const imageOrientationPatient = getNumberValues(dataSet, 'x00200037', 6);
const imagePositionPatient = getNumberValues(dataSet, 'x00200032', 3);
const pixelSpacing = getNumberValues(dataSet, 'x00280030', 2);
const imagePixelSpacing = getNumberValues(dataSet, 'x00181164', 2);
const estimatedRadiographicMagnificationFactor = getNumberValues(dataSet, 'x00181114', 2);
let columnPixelSpacing = null;
let rowPixelSpacing = null;
if (pixelSpacing) {
rowPixelSpacing = pixelSpacing[0];
columnPixelSpacing = pixelSpacing[1];
} else if (imagePixelSpacing && estimatedRadiographicMagnificationFactor) {
rowPixelSpacing = imagePixelSpacing[0] / estimatedRadiographicMagnificationFactor[0];
columnPixelSpacing = imagePixelSpacing[1] / estimatedRadiographicMagnificationFactor[1];
} else if (imagePixelSpacing && !estimatedRadiographicMagnificationFactor) {
rowPixelSpacing = imagePixelSpacing[0];
columnPixelSpacing = imagePixelSpacing[1];
}
let rowCosines = null;
let columnCosines = null;
if (imageOrientationPatient) {
rowCosines = [
parseFloat(imageOrientationPatient[0]),
parseFloat(imageOrientationPatient[1]),
parseFloat(imageOrientationPatient[2]),
];
columnCosines = [
parseFloat(imageOrientationPatient[3]),
parseFloat(imageOrientationPatient[4]),
parseFloat(imageOrientationPatient[5]),
];
}
return {
frameOfReferenceUID: dataSet.string('x00200052'),
rows: dataSet.uint16('x00280010'),
columns: dataSet.uint16('x00280011'),
imageOrientationPatient,
rowCosines,
columnCosines,
imagePositionPatient,
sliceThickness: dataSet.floatString('x00180050'),
sliceLocation: dataSet.floatString('x00201041'),
pixelSpacing,
rowPixelSpacing,
columnPixelSpacing,
};
}
}
export default metaDataProvider;

View File

@ -8,10 +8,10 @@
<!-- <div class="studyDesc" style="border-bottom:1px solid #9e9e9e;" @click="closeDialog()"> <!-- <div class="studyDesc" style="border-bottom:1px solid #9e9e9e;" @click="closeDialog()">
<span style="font-size:14px;color:#d0d0d0;margin:5px 0px;line-height: 25px;">返回列表</span> <span style="font-size:14px;color:#d0d0d0;margin:5px 0px;line-height: 25px;">返回列表</span>
</div> --> </div> -->
<div class="studyDesc" style="line-height: 10px;"> <div class="studyDesc">
{{ studyTitle }} {{ studyTitle }}
</div> </div>
<div class="studyDesc" style="line-height: 10px"> <div class="studyDesc">
{{ seriesCount }} Series {{ seriesCount }} Series
</div> </div>
<div class="viewerSidethumbs ps" style="position: relative;"> <div class="viewerSidethumbs ps" style="position: relative;">
@ -38,11 +38,12 @@
</span> </span>
</span>--> </span>-->
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div style="padding: 1px;">#{{ item.seriesTitle }}</div> <div style="padding: 1px;">#{{ item.seriesNumber }}</div>
<div style="padding: 1px;">{{ item.description }}</div>
<div <div
v-show="item.instanceCount" v-show="item.instanceCount"
style="padding: 1px;" style="padding: 1px;"
>{{ item.instanceCount }} image >{{ item.modality }} : {{ item.instanceCount }} image
</div> </div>
</div> </div>
</div> </div>
@ -63,20 +64,24 @@
import * as dicomParser from 'dicom-parser' import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core' import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomStore from '@/utils/dicom-store.js' // import dicomStore from '@/utils/dicom-store'
import dicomViewer from '@/components/Dicom/DicomViewer' import dicomViewer from '@/components/Dicom/DicomViewer'
import dicomPreview from '@/components/Dicom/DicomPreview' import dicomPreview from '@/components/Dicom/DicomPreview'
import metaDataProvider from '@/utils/metaDataProvider'
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
var config = {
maxWebWorkers: 4,
startWebWorkersOnDemand: true,
taskConfiguration: {
decodeTask: {
initializeCodecsOnStartup: false
}
}
}
cornerstoneWADOImageLoader.webWorkerManager.initialize(config)
cornerstoneWADOImageLoader.external.dicomParser = dicomParser cornerstoneWADOImageLoader.external.dicomParser = dicomParser
cornerstoneWADOImageLoader.external.cornerstone = cornerstone cornerstoneWADOImageLoader.external.cornerstone = cornerstone
// cornerstoneWADOImageLoader.webWorkerManager.initialize({
// webWorkerPath: './webWorker.js',
// taskConfiguration: {
// decodeTask: {
// codecsPath: './dicomCodecs.js'
// }
// }
// })
export default { export default {
components: { components: {
dicomViewer, dicomViewer,
@ -86,6 +91,11 @@ export default {
uid: { uid: {
type: String, type: String,
default: '' default: ''
},
studyList: {
type: Array,
// eslint-disable-next-line vue/require-valid-default-prop
default: []
} }
}, },
@ -102,7 +112,7 @@ export default {
var totalHeight = window.innerHeight || document.body.clientHeight var totalHeight = window.innerHeight || document.body.clientHeight
var wrapper = this.$refs['preview-wrapper'] var wrapper = this.$refs['preview-wrapper']
wrapper.style.height = (totalHeight - 70) + 'px' wrapper.style.height = (totalHeight - 70) + 'px'
if (!dicomStore.studyList || !this.uid) return if (!this.studyList || !this.uid) return
this.loadStudy() this.loadStudy()
}, },
@ -120,15 +130,14 @@ export default {
return newObj return newObj
}, },
loadStudy() { loadStudy() {
var studyList = dicomStore.studyList var studyList = this.studyList
var studyUid = this.uid var studyUid = this.uid
var studyItem = studyList.find(function(item) { var studyItem = studyList.find(function(item) {
return item.dicomInfo.studyUid === studyUid return item.dicomInfo.studyUid === studyUid
}) })
if (!studyItem) return if (!studyItem) return
this.studyTitle = this.studyTitle = studyItem.dicomInfo.description
studyItem.dicomInfo.patientName || studyItem.dicomInfo.description
this.seriesCount = studyItem.seriesList.length this.seriesCount = studyItem.seriesList.length
var scope = this var scope = this
@ -151,7 +160,8 @@ export default {
scope.seriesList.push({ scope.seriesList.push({
seriesNumber: series.seriesNumber, seriesNumber: series.seriesNumber,
seriesTitle: series.description || series.modality || '(Anonymous)', description: series.description,
modality: series.modality,
instanceCount: series.instanceList.length, instanceCount: series.instanceList.length,
imageIds: imageIds, imageIds: imageIds,
previewImageId: imageIds[0] previewImageId: imageIds[0]
@ -253,7 +263,7 @@ export default {
text-align: center; text-align: center;
background: rgb(88 84 83); background: rgb(88 84 83);
color: #d0d0d0; color: #d0d0d0;
padding: 2px; padding: 5px;
} }
.ps { .ps {

View File

@ -128,7 +128,7 @@ export default {
// imageIds.push(`wadouri:/api/instance/content/${item}`) // imageIds.push(`wadouri:/api/instance/content/${item}`)
// }) // })
// seriesInfo.InstanceList.forEach((id) => { // seriesInfo.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:http://106.14.89.110:7000/instance/content/${id}`) // imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`)
// }) // })
seriesInfo.InstancePathList.forEach((path) => { seriesInfo.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)

View File

@ -43,45 +43,73 @@
fit="fill" fit="fill"
> >
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div v-if="item.keySeries" style="padding: 1px;color:red"> <div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
Key Images <div v-if="item.keySeries" style="color:red">
</div> Key Images
<div v-else style="padding: 1px;"> </div>
#{{ item.seriesNumber }} <div v-else>
#{{ item.seriesNumber }}
</div>
<div v-if="item.isExistMutiFrames && item.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div class="frame_list">
<div
v-for="(instance, idx) in item.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(item, index, instance)"
>
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
</div> </div>
<div v-show="item.instanceCount" style="padding: 1px;"> <div v-show="item.instanceCount" style="padding: 1px;">
{{ item.modality }}: {{ item.instanceCount }} image {{ item.modality }}: {{ item.instanceCount }} image
</div> </div>
<div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;"> <div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;">
T: {{ item.sliceThickness }} T: {{ parseFloat(item.sliceThickness).toFixed(2) }}
</div> </div>
<div v-show="!item.keySeries &&item.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;"> <div v-show="!item.keySeries &&item.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
{{ item.description }} {{ item.description }}
</div> </div>
<div v-if="!item.keySeries" style="padding: 1px;"> <div v-if="!item.keySeries" style="padding: 1px;">
{{ item.prefetchInstanceCount }}/{{ item.instanceCount }} {{ item.imageloadedArr.length }}/{{ item.instanceCount }}
</div> </div>
</div> </div>
</div> </div>
<div v-if="showDelete" @click.stop=""> <div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span> <div>
<el-switch <span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') }}</span>
v-model="item.isReading" <el-switch
size="mini" v-model="item.isReading"
@change="changeReadingStatus($event, item)" size="mini"
/> @change="changeReadingStatus($event, item)"
/>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span> </div>
<el-switch <div>
v-model="item.isDeleted" <span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isDelete') }}</span>
size="mini" <el-switch
@change="changeDeleteStatus($event, item)" v-model="item.isDeleted"
/> size="mini"
@change="changeDeleteStatus($event, item)"
/>
</div>
</div> </div>
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount"> <div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount * 100">
<el-progress :percentage="parseInt(((item.prefetchInstanceCount/item.instanceCount)*100).toFixed(2))" /> <el-progress :percentage="parseInt((item.prefetchInstanceCount/item.instanceCount).toFixed(2))" />
</div> </div>
</div> </div>
@ -110,13 +138,27 @@ import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomViewer from '@/components/Dicom/DicomViewer' import dicomViewer from '@/components/Dicom/DicomViewer'
import { getStudyInfo, getSeriesList } from '@/api/reading' import { getStudyInfo, getSeriesList } from '@/api/reading'
import { getInstanceList, setSeriesStatus, getPatientSeriesList } from '@/api/trials' import { getInstanceList, getPatientSeriesList, setSeriesStatus } from '@/api/trials'
import requestPoolManager from '@/utils/request-pool' import requestPoolManager from '@/utils/request-pool'
import store from '@/store' import store from '@/store'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import metaDataProvider from '@/utils/metaDataProvider'
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
var config = {
maxWebWorkers: 4,
startWebWorkersOnDemand: true,
taskConfiguration: {
decodeTask: {
initializeCodecsOnStartup: false
}
}
}
cornerstoneWADOImageLoader.webWorkerManager.initialize(config)
cornerstoneWADOImageLoader.external.dicomParser = dicomParser cornerstoneWADOImageLoader.external.dicomParser = dicomParser
cornerstoneWADOImageLoader.external.cornerstone = cornerstone cornerstoneWADOImageLoader.external.cornerstone = cornerstone
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB const maximumSizeInBytes = 1024 * 1024 * 1024 * 6
cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
export default { export default {
components: { components: {
'dicom-viewer': dicomViewer 'dicom-viewer': dicomViewer
@ -151,20 +193,25 @@ export default {
firstInstanceId: '', firstInstanceId: '',
showDelete: false, showDelete: false,
loading: false, loading: false,
imageList: [] imageList: [],
showSeriesList: [],
currentLoadIns: [],
isFromCRCUpload: false
} }
}, },
created: function() { created: function() {
requestPoolManager.resetRequestPool()
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : '' this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
this.visitNum = this.$router.currentRoute.query.visitNum ? parseInt(this.$router.currentRoute.query.visitNum) : 0 this.visitNum = this.$router.currentRoute.query.visitNum ? parseInt(this.$router.currentRoute.query.visitNum) : 0
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded) // cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
// cornerstone.events.addEventListener('datasetscachechanged', this.datasetsCacheChanged) // cornerstone.events.addEventListener('datasetscachechanged', this.datasetsCacheChanged)
if (this.$router.currentRoute.query.TokenKey) { if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey) store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '') changeURLStatic('TokenKey', '')
} }
this.studyId = this.$router.currentRoute.query.studyId this.studyId = this.$router.currentRoute.query.studyId
this.isFromCRCUpload = !!this.$router.currentRoute.query.isFromCRCUpload
if (this.type === 'Series') { if (this.type === 'Series') {
// this.initStudy() // this.initStudy()
this.showDelete = parseInt(this.$router.currentRoute.query.showDelete) this.showDelete = parseInt(this.$router.currentRoute.query.showDelete)
@ -177,49 +224,62 @@ export default {
} else if (this.type === 'Patient') { } else if (this.type === 'Patient') {
this.loadPatientStudy() this.loadPatientStudy()
} }
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
}, },
beforeDestroy() { beforeDestroy() {
requestPoolManager.stopTaskTimer() requestPoolManager.stopTaskTimer()
window.removeEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
}, },
methods: { methods: {
loadStudy() { async loadStudy() {
var scope = this const data = await getStudyInfo(this.studyId)
getStudyInfo(scope.studyId).then(data => { if (data.IsSuccess) {
if (data.IsSuccess) { if (data.Result) {
scope.studyCode = data.Result.StudyCode this.studyCode = data.Result.StudyCode
scope.modality = data.Result.Modalities this.modality = data.Result.Modalities
scope.seriesCount = data.Result.SeriesCount this.seriesCount = data.Result.SeriesCount
scope.description = data.Result.Description this.description = data.Result.Description
var url = `/series/list/${scope.studyId}`
scope.getSeriesList(url)
} }
}) const url = `/series/list/${this.studyId}`
this.getSeriesList(url)
}
}, },
getSeriesList(url) { async loadPatientStudy() {
var scope = this try {
getSeriesList(url).then(data => { const data = await getPatientSeriesList(this.studyId)
if (data.IsSuccess) { if (data.IsSuccess) {
const { Result } = data const { Result } = data
var seriesList = [] var seriesList = []
Result.forEach(function(item) { Result.forEach((item, index) => {
const imageIds = [] const imageIds = []
// item.InstanceList.forEach(function(id) { item.InstanceInfoList.forEach(i => {
// imageIds.push(`wadouri:/api/instance/content/${id}`) if (i.NumberOfFrames && i.NumberOfFrames > 1) {
// }) for (let j = 0; j < i.NumberOfFrames; j++) {
// item.InstanceList.forEach((id) => { imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&seriesIndex=${index}`)
// imageIds.push(`wadouri:http://106.14.89.110:7000/instance/content/${id}`) }
// }) i.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?frame=0&instanceId=${i.Id}&seriesIndex=${index}`
item.InstancePathList.forEach((path) => { } else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`) const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&seriesIndex=${index}`
imageIds.push(imageId)
i.ImageId = imageId
}
}) })
var subjectVisitId = scope.$router.currentRoute.query.subjectVisitId var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
var studyId = scope.$router.currentRoute.query.studyId var studyId = this.$router.currentRoute.query.studyId
var trialId = scope.$router.currentRoute.query.trialId var trialId = this.$router.currentRoute.query.trialId
seriesList.push({ seriesList.push({
trialId, trialId,
subjectVisitId, subjectVisitId,
studyId, studyId,
imageIds: imageIds, imageIds: imageIds,
instanceInfoList: item.InstanceInfoList,
seriesId: item.Id, seriesId: item.Id,
seriesUid: item.SeriesInstanceUid, seriesUid: item.SeriesInstanceUid,
seriesNumber: item.SeriesNumber, seriesNumber: item.SeriesNumber,
@ -228,77 +288,99 @@ export default {
description: item.Description, description: item.Description,
isReading: item.IsReading, isReading: item.IsReading,
isDeleted: item.IsDeleted, isDeleted: item.IsDeleted,
previewImageUrl: item.ImageResizePath ? scope.OSSclientConfig.basePath + item.ImageResizePath : `/api/series/preview/${item.Id}`, previewImageUrl: item.ImageResizePath ? this.OSSclientConfig.basePath + item.ImageResizePath : `/api/series/preview/${item.Id}`,
instanceCount: item.InstanceCount, instanceCount: item.InstanceCount,
prefetchInstanceCount: 0, prefetchInstanceCount: 0,
hasLabel: item.HasLabel, hasLabel: item.HasLabel,
keySeries: item.KeySeries, keySeries: item.KeySeries,
tpCode: scope.tpCode, tpCode: this.tpCode,
loadStatus: false, loadStatus: false,
imageloadedArr: [] imageloadedArr: [],
}) isExistMutiFrames: item.IsExistMutiFrames
})
scope.seriesList = seriesList
if (scope.seriesList.length > 0) {
scope.$refs.dicomViewer.loadImageStack(scope.seriesList[0], scope.labels[scope.tpCode])
scope.firstInstanceId = scope.seriesList[0].imageIds[0]
}
}
})
},
async loadPatientStudy() {
try {
let res = await getPatientSeriesList(this.studyId);
if (res.IsSuccess && res.Result.length > 0) {
console.log(res.Result)
this.modality = res.OtherInfo.Modalities
this.seriesCount = res.Result.length
this.description = res.OtherInfo.Description
this.seriesList = []
res.Result.map(item=>{
var imageIds = []
item.InstancePathList.forEach(instance => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance}`)
})
this.seriesList.push({
imageIds: imageIds,
seriesId: item.SeriesInstanceUid,
seriesUid: item.SeriesInstanceUid,
seriesNumber:item.SeriesNumber,
sliceThickness: item.SliceThickness,
modality: item.Modality,
description: item.Description,
previewImageUrl: item.ImageResizePath ? this.OSSclientConfig.basePath + item.ImageResizePath : item.ImageResizePath,
instanceCount: item.InstanceCount,
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: []
}) })
}) })
this.seriesList = seriesList
if (this.seriesList.length > 0) { if (this.seriesList.length > 0) {
this.$nextTick(() => { this.loadAllImages()
this.loadAllImages() this.$refs.dicomViewer.loadImageStack(this.seriesList[0], this.labels[this.tpCode])
this.$refs.dicomViewer.loadImageStack(this.seriesList[0]) this.firstInstanceId = this.seriesList[0].imageIds[0]
this.firstInstanceId = this.seriesList[0].imageIds[0]
})
} }
} }
} catch (err) { } catch (err) {
console.log(err); console.log(err)
} }
}, },
initSeries() { async getSeriesList(url) {
var scope = this try {
this.studyCode = this.$router.currentRoute.query.studyCode const data = await getSeriesList(url)
this.modality = this.$router.currentRoute.query.modality if (data.IsSuccess) {
this.seriesCount = 1 const { Result } = data
this.description = this.$router.currentRoute.query.description var seriesList = []
var seriesId = this.$router.currentRoute.query.seriesId Result.forEach((item, index) => {
var seriesNumber = this.$router.currentRoute.query.seriesNumber const imageIds = []
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId item.InstanceInfoList.forEach(i => {
var studyId = this.$router.currentRoute.query.studyId if (i.NumberOfFrames && i.NumberOfFrames > 1) {
var trialId = this.$router.currentRoute.query.trialId for (let j = 0; j < i.NumberOfFrames; j++) {
getInstanceList(seriesId).then(res => { imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&seriesIndex=${index}`)
}
i.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?frame=0&instanceId=${i.Id}&seriesIndex=${index}`
} else {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&seriesIndex=${index}`
imageIds.push(imageId)
i.ImageId = imageId
}
})
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
var studyId = this.$router.currentRoute.query.studyId
var trialId = this.$router.currentRoute.query.trialId
seriesList.push({
trialId,
subjectVisitId,
studyId,
imageIds: imageIds,
instanceInfoList: item.InstanceInfoList,
seriesId: item.Id,
seriesUid: item.SeriesInstanceUid,
seriesNumber: item.SeriesNumber,
sliceThickness: item.SliceThickness,
modality: item.Modality,
description: item.Description,
isReading: item.IsReading,
isDeleted: item.IsDeleted,
previewImageUrl: item.ImageResizePath ? this.OSSclientConfig.basePath + item.ImageResizePath : `/api/series/preview/${item.Id}`,
instanceCount: item.InstanceCount,
prefetchInstanceCount: 0,
hasLabel: item.HasLabel,
keySeries: item.KeySeries,
tpCode: this.tpCode,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
})
})
this.seriesList = seriesList
if (this.seriesList.length > 0) {
this.loadAllImages()
this.$refs.dicomViewer.loadImageStack(this.seriesList[0], this.labels[this.tpCode])
this.firstInstanceId = this.seriesList[0].imageIds[0]
}
}
} catch (e) {
console.log(e)
}
},
async initSeries() {
try {
this.studyCode = this.$router.currentRoute.query.studyCode
this.modality = this.$router.currentRoute.query.modality
this.seriesCount = 1
this.description = this.$router.currentRoute.query.description
var seriesId = this.$router.currentRoute.query.seriesId
var seriesNumber = this.$router.currentRoute.query.seriesNumber
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
var studyId = this.$router.currentRoute.query.studyId
var trialId = this.$router.currentRoute.query.trialId
const res = await getInstanceList(seriesId)
if (!res.Result || (res.Result && res.Result.length === 0)) return if (!res.Result || (res.Result && res.Result.length === 0)) return
var seriesInstanceUid = res.Result[0].SeriesInstanceUid var seriesInstanceUid = res.Result[0].SeriesInstanceUid
var sliceThickness = res.Result[0].SliceThickness var sliceThickness = res.Result[0].SliceThickness
@ -306,14 +388,29 @@ export default {
var isDeleted = res.Result[0].IsDeleted var isDeleted = res.Result[0].IsDeleted
var seriesList = [] var seriesList = []
var imageIds = [] var imageIds = []
let isExistMutiFrames = false
const instanceInfoList = []
res.Result.forEach(instance => { res.Result.forEach(instance => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}`) let imageId = ''
if (instance.NumberOfFrames > 1) {
for (let i = 0; i < instance.NumberOfFrames; i++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&seriesIndex=0`)
}
isExistMutiFrames = true
imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?frame=0&instanceId=${instance.Id}&seriesIndex=0`
} else {
const path = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&seriesIndex=0`
imageIds.push(path)
imageId = path
}
instanceInfoList.push({ Id: instance.Id, InstanceNumber: instance.InstanceNumber, NumberOfFrames: instance.NumberOfFrames, Path: instance.Path, ImageId: imageId })
}) })
seriesList.push({ seriesList.push({
trialId, trialId,
subjectVisitId, subjectVisitId,
studyId, studyId,
imageIds: imageIds, imageIds: imageIds,
instanceInfoList,
seriesId: seriesId, seriesId: seriesId,
seriesUid: seriesInstanceUid, seriesUid: seriesInstanceUid,
seriesNumber: seriesNumber, seriesNumber: seriesNumber,
@ -322,11 +419,12 @@ export default {
description: this.description, description: this.description,
isReading, isReading,
isDeleted, isDeleted,
previewImageUrl: res.OtherInfo.ImageResizePath ? scope.OSSclientConfig.basePath + res.OtherInfo.ImageResizePath : res.OtherInfo.ImageResizePath, previewImageUrl: res.OtherInfo.ImageResizePath ? this.OSSclientConfig.basePath + res.OtherInfo.ImageResizePath : res.OtherInfo.ImageResizePath,
instanceCount: res.Result.length, instanceCount: res.Result.length,
prefetchInstanceCount: 0, prefetchInstanceCount: 0,
loadStatus: false, loadStatus: false,
imageloadedArr: [] imageloadedArr: [],
isExistMutiFrames: isExistMutiFrames
}) })
this.seriesList = seriesList this.seriesList = seriesList
if (this.seriesList.length > 0) { if (this.seriesList.length > 0) {
@ -336,7 +434,9 @@ export default {
this.firstInstanceId = this.seriesList[0].imageIds[0] this.firstInstanceId = this.seriesList[0].imageIds[0]
}) })
} }
}) } catch (e) {
console.log(e)
}
}, },
showSeriesImage(e, seriesIndex, series) { showSeriesImage(e, seriesIndex, series) {
// if (seriesIndex === this.currentSeriesIndex) return // if (seriesIndex === this.currentSeriesIndex) return
@ -350,16 +450,101 @@ export default {
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex]) this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
if (!series.loadStatus) { if (!series.loadStatus) {
series.isLoading = true series.isLoading = true
var p = new Date().getTime() var isAddToTakPool = false
series.imageIds.map((imageId, i) => { if (this.showSeriesList.includes(`0_${seriesIndex}`)) {
var priority = '' isAddToTakPool = true
if (i === 0) { } else {
priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime() this.showSeriesList.push(`0_${seriesIndex}`)
}
if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime())
// var images = []
// if (series.isExistMutiFrames) {
// images = series.imageIds.filter(i => i.includes('?frame=0'))
// } else {
// images = series.imageIds
// }
// images.map(imageId => {
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: 0, seriesIndex: seriesIndex, priority })
// })
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, priority })
})
} else { } else {
priority = p - 1 series.imageIds.map(imageId => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
})
} }
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority }) if (this.imageList.length > 0) {
}) this.loopLoad()
}
} else {
requestPoolManager.changePriority(series.seriesId)
}
}
},
showMultiFrames(series, seriesIndex, instanceInfo) {
this.currentSeriesIndex = seriesIndex
const imageIds = []
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}&seriesIndex=${seriesIndex}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}&seriesIndex=${seriesIndex}`)
}
const seriesInfo = {
trialId: series.trialId,
subjectVisitId: series.subjectVisitId,
studyId: series.studyId,
imageIds: imageIds,
seriesId: series.seriesId,
seriesUid: series.seriesUid,
seriesNumber: series.seriesNumber,
sliceThickness: series.sliceThickness,
modality: series.modality,
description: series.description,
isReading: series.isReading,
isDeleted: series.isDeleted,
previewImageUrl: series.previewImageUrl,
instanceCount: series.instanceCount
}
this.$refs.dicomViewer.loadImageStack(seriesInfo)
if (!series.loadStatus) {
var isAddToTakPool = false
if (this.showSeriesList.includes(`0_${seriesIndex}`)) {
isAddToTakPool = true
} else {
this.showSeriesList.push(`0_${seriesIndex}`)
}
if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime())
// if (series.isExistMutiFrames) {
// series.instanceInfoList.map(image => {
// this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: 0, seriesIndex: seriesIndex, priority })
// })
// } else {
// series.imageIds.map((imageId) => {
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: 0, seriesIndex: seriesIndex, priority })
// })
// }
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, priority })
})
} else {
series.imageIds.map(imageId => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
})
}
if (this.imageList.length > 0) {
this.loopLoad()
}
} else {
requestPoolManager.changePriority(series.seriesId)
}
} }
}, },
initStudy() { initStudy() {
@ -371,13 +556,6 @@ export default {
const seriesInfo = JSON.parse(this.$router.currentRoute.query.series) const seriesInfo = JSON.parse(this.$router.currentRoute.query.series)
var seriesList = [] var seriesList = []
const imageIds = [] const imageIds = []
// const scope = this
// seriesInfo.InstanceList.forEach(function(item) {
// imageIds.push(`wadouri:/api/instance/content/${item}`)
// })
// seriesInfo.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:http://106.14.89.110:7000/instance/content/${id}`)
// })
seriesInfo.InstancePathList.forEach((path) => { seriesInfo.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)
}) })
@ -407,22 +585,25 @@ export default {
} }
} }
}, },
deleteSeries() { async deleteSeries() {
this.loading = true this.loading = true
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
var studyId = this.$router.currentRoute.query.studyId var studyId = this.$router.currentRoute.query.studyId
var seriesId = this.$router.currentRoute.query.seriesId var seriesId = this.$router.currentRoute.query.seriesId
// trialId, subjectVisitId, studyId, seriesId, state try {
setSeriesStatus(this.trialId, subjectVisitId, studyId, seriesId, 5).then(res => { const res = await setSeriesStatus(this.trialId, subjectVisitId, studyId, seriesId, 5)
this.loading = false this.loading = false
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location) window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
} }
}).catch(() => { this.loading = false }) } catch (e) {
console.log(e)
this.loading = false
}
}, },
changeReadingStatus(callback, data) { async changeReadingStatus(callback, data) {
let statusStr = '' let statusStr = ''
if (callback) { if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesReading') statusStr = this.$t('trials:audit:label:setSeriesReading')
@ -432,24 +613,31 @@ export default {
data.isReading = true data.isReading = true
} }
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr) var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
this.$confirm(message, { message = message.replace('yyy', this.$fd('YesOrNo', !data.isReading))
distinguishCancelAndClose: true, const confirm = await this.$confirm(
type: 'warning' message,
}).then(() => { {
const state = data.isReading ? 1 : 2 type: 'warning',
this.loading = true distinguishCancelAndClose: true
}
setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state).then(res => { )
this.loading = false if (confirm !== 'confirm') return
if (res.IsSuccess) { const state = data.isReading ? 1 : 2
data.isReading = !data.isReading this.loading = true
this.$message.success(this.$t('common:message:savedSuccessfully')) try {
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location) const res = await setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state)
} this.loading = false
}).catch(() => { this.loading = false }) if (res.IsSuccess) {
}).catch(() => {}) data.isReading = !data.isReading
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
} catch (e) {
console.log(e)
this.loading = false
}
}, },
changeDeleteStatus(callback, data) { async changeDeleteStatus(callback, data) {
let statusStr = '' let statusStr = ''
if (callback) { if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesDeleted') statusStr = this.$t('trials:audit:label:setSeriesDeleted')
@ -459,88 +647,76 @@ export default {
data.isDeleted = true data.isDeleted = true
} }
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr) var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
this.$confirm(message, { message = message.replace('yyy', this.$fd('YesOrNo', !data.isDeleted))
distinguishCancelAndClose: true, const confirm = await this.$confirm(
type: 'warning' message,
}).then(() => { {
const state = data.isDeleted ? 5 : 4 type: 'warning',
this.loading = true distinguishCancelAndClose: true
// var trialId = this.$router.currentRoute.query.trialId }
// var subjectVisitId = this.$router.currentRoute.query.subjectVisitId )
// var studyId = this.$router.currentRoute.query.studyId if (confirm !== 'confirm') return
// var seriesId = this.$router.currentRoute.query.seriesId const state = data.isDeleted ? 5 : 4
setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state).then(res => { this.loading = true
this.loading = false try {
if (res.IsSuccess) { const res = await setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state)
data.isDeleted = !data.isDeleted this.loading = false
this.$message.success(this.$t('common:message:savedSuccessfully')) if (res.IsSuccess) {
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location) data.isDeleted = !data.isDeleted
} this.$message.success(this.$t('common:message:savedSuccessfully'))
}).catch(() => { this.loading = false }) window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}).catch(() => {}) }
} catch (e) {
console.log(e)
this.loading = false
}
}, },
loadAllImages() { loadAllImages() {
const seriesIndex = this.seriesList.findIndex(i => i.loadStatus === false)
if (seriesIndex === -1) return
const series = this.seriesList[seriesIndex]
var priority = new Date().getTime() var priority = new Date().getTime()
this.seriesList.forEach(series => { // var images = []
series.imageIds.forEach(imageId => { // if (series.isExistMutiFrames) {
priority-- // images = series.imageIds.filter(i => i.includes('?frame=0'))
// this.load(imageId, series.seriesId, priority) // } else {
// images = series.imageIds
// }
// images.map(imageId => {
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: 0, seriesIndex: seriesIndex, priority })
// })
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, priority })
})
} else {
series.imageIds.map(imageId => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority }) this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
}) })
}) }
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
this.loopLoad() this.loopLoad()
} }
}, },
getInstanceInfo(imageId) {
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
return params
},
loopLoad() { loopLoad() {
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
requestPoolManager.startTaskTimer() requestPoolManager.startTaskTimer()
console.log('loopLoad')
this.imageList.map(image => { this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => { requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
this.imageLoaded(image, res.data.string('x0020000e'))
})
}) })
requestPoolManager.sortTaskPool()
this.imageList = [] this.imageList = []
} }
}, },
load(imageId, seriesId, priority = 999) {
return new Promise((resolve, reject) => {
requestPoolManager.loadAndCacheImagePlus(imageId, seriesId, priority).then(res => {
if (!res) return
this.imageLoaded(imageId, res.data.string('x0020000e'))
resolve(res)
}).catch(e => {
reject(e)
})
})
},
imageLoaded(imageId, seriesUid) {
var seriesIndex = -1
for (let i = 0; i < this.seriesList.length; ++i) {
if (this.seriesList[i].seriesUid === seriesUid) {
seriesIndex = i
break
}
}
if (seriesIndex < 0) return
const imageIdIndex = this.seriesList[seriesIndex].imageIds.indexOf(imageId)
if (imageIdIndex < 0) return
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
++this.seriesList[seriesIndex].prefetchInstanceCount
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
if (this.seriesList[seriesIndex].prefetchInstanceCount >= this.seriesList[seriesIndex].instanceCount) {
this.seriesList[seriesIndex].prefetchInstanceCount = this.seriesList[seriesIndex].instanceCount
//
this.seriesList[seriesIndex].loadStatus = true
// if (!this.isLoadedAll) {
// this.loadAllImages()
// }
}
}
},
datasetsCacheChanged(e) { datasetsCacheChanged(e) {
// const uri = e.detail.uri // const uri = e.detail.uri
const cacheInfo = e.detail.cacheInfo const cacheInfo = e.detail.cacheInfo
@ -564,48 +740,44 @@ export default {
return 0 return 0
}, },
cornerstoneImageLoaded(e) { cornerstoneimageloadprogress(e) {
if (this.firstInstanceId === e.detail.image.imageId && !this.isStartLoad) { const imageId = e.detail.imageId
// const percentComplete = e.detail.percentComplete
this.loadAllImages() const params = {}
this.isStartLoad = true const searchParams = new URLSearchParams(imageId.split('?')[1])
// requestPoolManager.executeTask() for (const [key, value] of searchParams.entries()) {
params[key] = value
} }
const uri = e.detail.image.sharedCacheKey if (this.visitTaskId === params.visitTaskId) {
const index = this.cachedImages.findIndex(item => item.uri === uri) const seriesIndex = params.seriesIndex
if (index === -1) { var prefetchInstanceCount = this.seriesList[seriesIndex].prefetchInstanceCount
this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() }) var instanceCount = this.seriesList[seriesIndex].instanceCount
} else { if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0 && this.seriesList[seriesIndex].imageloadedArr.length < this.seriesList[seriesIndex].instanceCount) {
this.cachedImages[index].timestamp = new Date().getTime() const i = this.currentLoadIns.findIndex(i => i.imageId === imageId)
} if (i > -1) {
// loadedDataSets[uri].dataSet.byteArray.length prefetchInstanceCount = prefetchInstanceCount - this.currentLoadIns[i].percentComplete + percentComplete
// console.log(this.cachedImages.length) this.currentLoadIns[i].percentComplete = percentComplete
// console.log(cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.getInfo().cacheSizeInBytes) if (percentComplete === 100) {
// const imageId = e.detail.image.imageId this.currentLoadIns.splice(i, 1)
var imageId = e.detail.image.imageId }
var seriesUid = e.detail.image.data.string('x0020000e') } else {
var seriesIndex = -1 if (percentComplete !== 100) {
for (let i = 0; i < this.seriesList.length; ++i) { this.currentLoadIns.push({ imageId, percentComplete })
if (this.seriesList[i].seriesUid === seriesUid) { }
seriesIndex = i prefetchInstanceCount = prefetchInstanceCount + percentComplete
break }
this.seriesList[seriesIndex].prefetchInstanceCount = prefetchInstanceCount
if (percentComplete >= 100) {
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
}
} }
} if (prefetchInstanceCount >= instanceCount * 100) {
if (seriesIndex < 0) return this.seriesList[seriesIndex].prefetchInstanceCount = instanceCount * 100
const imageIdIndex = this.seriesList[seriesIndex].imageIds.indexOf(imageId)
if (imageIdIndex < 0) return
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
++this.seriesList[seriesIndex].prefetchInstanceCount
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
if (this.seriesList[seriesIndex].prefetchInstanceCount >= this.seriesList[seriesIndex].instanceCount) {
this.seriesList[seriesIndex].prefetchInstanceCount = this.seriesList[seriesIndex].instanceCount
// //
this.seriesList[seriesIndex].loadStatus = true this.seriesList[seriesIndex].loadStatus = true
// if (!this.isLoadedAll) { if (!this.isFromCRCUpload) {
// this.loadAllImages() this.loadAllImages()
// } }
} }
} }
} }
@ -710,7 +882,7 @@ export default {
} }
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper { .viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
display: flex; display: flex;
width: 210px; width: 200px;
height: 84px; height: 84px;
padding: 1px 2px 1px 8px; padding: 1px 2px 1px 8px;
margin: 6px 0 6px 1px; margin: 6px 0 6px 1px;
@ -757,6 +929,41 @@ export default {
color: #D0D0D0; color: #D0D0D0;
font-size: 13px; font-size: 13px;
} }
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_list{
max-height: 500px;
overflow-y: auto;
}
.instance_frame_wrapper ::-webkit-scrollbar {
width: 7px;
height: 7px;
}
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
/* .viewerRightSidePanel { /* .viewerRightSidePanel {
width: 300px; width: 300px;
height: 100%; height: 100%;

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,43 @@
<template> <template>
<div class="adReview_wrapper"> <div class="adReview_wrapper">
<el-card v-if="isReadingShowSubjectInfo" shadow="never" :body-style="{ padding: '10px' }" style="margin-bottom:10px"> <el-card
v-if="isReadingShowSubjectInfo"
shadow="never"
:body-style="{ padding: '10px' }"
style="margin-bottom: 10px"
>
<h4> <h4>
<!-- 受试者 --> <!-- 受试者 -->
{{ $t('trials:adReview:title:subject') }} {{ $t("trials:adReview:title:subject") }}
<span style="font-weight:normal">{{ subjectCode }} </span> <span style="font-weight: normal">{{ subjectCode }} </span>
<span style="font-weight:normal">({{ taskBlindName }})</span> <span style="font-weight: normal">({{ taskBlindName }})</span>
</h4> </h4>
</el-card> </el-card>
<el-card :body-style="{ padding: '10px' }" shadow="never"> <el-card :body-style="{ padding: '10px' }" shadow="never">
<!-- <div slot="header" class="clearfix"> <!-- <div slot="header" class="clearfix">
<span style="font-weight: bold;">评估结果</span> <span style="font-weight: bold;">评估结果</span>
</div> --> </div> -->
<div slot="header" style="display: flex;flex-direction: row;justify-content: space-between;"> <div
slot="header"
style="
display: flex;
flex-direction: row;
justify-content: space-between;
"
>
<!-- 评估结果 --> <!-- 评估结果 -->
<div style="font-weight: bold;">{{ $t('trials:adReview:title:result') }}</div> <div style="font-weight: bold">
{{ $t("trials:adReview:title:result") }}
</div>
<div v-if="isExistsClinicalData"> <div v-if="isExistsClinicalData">
<!-- 临床数据 --> <!-- 临床数据 -->
<el-button type="text" @click="previewCD">{{ $t('trials:adReview:title:clinicalData') }}</el-button> <el-button type="text" @click="previewCD">{{
$t("trials:adReview:title:clinicalData")
}}</el-button>
</div> </div>
</div> </div>
<el-table <el-table :data="adInfo.VisitInfoList" style="width: 100%">
:data="adInfo.VisitInfoList"
style="width: 100%"
>
<!-- 访视名称 --> <!-- 访视名称 -->
<el-table-column <el-table-column
prop="VisitName" prop="VisitName"
@ -37,13 +50,19 @@
<el-table-column <el-table-column
v-for="j in judgeQuestion" v-for="j in judgeQuestion"
:key="j.armEnum" :key="j.armEnum"
:label="j.armEnum===1?$t('trials:adReview:table:viewR1'):j.armEnum===2?$t('trials:adReview:table:viewR2'):$fd('ArmEnum', j.armEnum)" :label="
j.armEnum === 1
? $t('trials:adReview:table:viewR1')
: j.armEnum === 2
? $t('trials:adReview:table:viewR2')
: $fd('ArmEnum', j.armEnum)
"
align="center" align="center"
prop="" prop=""
> >
<template> <template>
<el-table-column <el-table-column
v-for="(qs,i) in j.judgeQuestionList" v-for="(qs, i) in j.judgeQuestionList"
:key="i" :key="i"
prop="" prop=""
:label="qs" :label="qs"
@ -51,28 +70,49 @@
width="150" width="150"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType===1"> <div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 1">
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode">{{ $fd(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode, parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer )) }}</span> <span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode">
<span v-else>{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}</span> {{ $fd(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode,parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))
}}
</span>
<span v-else>
{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}
</span>
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit && !isNaN(parseFloat(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))">{{ $fd('ValueUnit', parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit)) }}</span>
</div> </div>
<div v-else-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType===2"> <div v-else-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 2">
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer"> <div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer">
<span>{{ $fd('YesOrNo', scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer ) }}</span> <span>
{{ $fd("YesOrNo",scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer) }}
</span>
<!-- 查看详情 --> <!-- 查看详情 -->
<el-button <el-button
type="text" type="text"
style="margin-left:5px;" style="margin-left: 5px"
@click="handleViewDetail(scope.row.VisitTaskInfoList[j.index].GlobalVisitTaskId)" @click="
handleViewDetail(
scope.row.VisitTaskInfoList[j.index].GlobalVisitTaskId
)
"
> >
{{ $t('trials:adReview:table:view') }} {{ $t("trials:adReview:table:view") }}
</el-button> </el-button>
</div> </div>
<div v-else> <div v-else>
{{ $fd('YesOrNo', scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer ) }} {{
$fd(
"YesOrNo",
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[
i
].Answer
)
}}
</div> </div>
</div> </div>
<div v-else>{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}</div> <div v-else>
{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}
</div>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
@ -80,16 +120,20 @@
<!-- 查看详情 --> <!-- 查看详情 -->
<el-table-column <el-table-column
:label="criterionType === 10?$t('trials:adReview:table:visitInfoview'):$t('trials:adReview:table:view')" :label="
criterionType === 10
? $t('trials:adReview:table:visitInfoview')
: $t('trials:adReview:table:view')
"
width="200" width="200"
:fixed="isFixed ? 'right' : false"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 查看R1详情 --> <!-- 查看R1详情 -->
<el-button <el-button
type="text" type="text"
:title="$t('trials:adReview:table:viewR1')" :title="$t('trials:adReview:table:viewR1')"
@click="handleView(scope.row,1)" @click="handleView(scope.row, 1)"
> >
R1 R1
</el-button> </el-button>
@ -97,7 +141,7 @@
<el-button <el-button
type="text" type="text"
:title="$t('trials:adReview:table:viewR2')" :title="$t('trials:adReview:table:viewR2')"
@click="handleView(scope.row,2)" @click="handleView(scope.row, 2)"
> >
R2 R2
</el-button> </el-button>
@ -115,19 +159,19 @@
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 查看R1详情 --> <!-- 查看R1详情 -->
<el-button <el-button
v-if="scope.$index === adInfo.VisitInfoList.length -1" v-if="scope.$index === adInfo.VisitInfoList.length - 1"
type="text" type="text"
:title="$t('trials:adReview:table:viewR1')" :title="$t('trials:adReview:table:viewR1')"
@click="handleViewGl(scope.row,1)" @click="handleViewGl(scope.row, 1)"
> >
R1 R1
</el-button> </el-button>
<!-- 查看R2详情 --> <!-- 查看R2详情 -->
<el-button <el-button
v-if="scope.$index === adInfo.VisitInfoList.length -1" v-if="scope.$index === adInfo.VisitInfoList.length - 1"
type="text" type="text"
:title="$t('trials:adReview:table:viewR2')" :title="$t('trials:adReview:table:viewR2')"
@click="handleViewGl(scope.row,2)" @click="handleViewGl(scope.row, 2)"
> >
R2 R2
</el-button> </el-button>
@ -138,13 +182,15 @@
<el-card :body-style="{ padding: '10px' }" class="box-mr"> <el-card :body-style="{ padding: '10px' }" class="box-mr">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<!-- 裁判结果 --> <!-- 裁判结果 -->
<span style="font-weight: bold;">{{ $t('trials:adReview:title:adResult') }}</span> <span style="font-weight: bold">{{
$t("trials:adReview:title:adResult")
}}</span>
</div> </div>
<el-form <el-form
ref="adForm" ref="adForm"
v-loading="loading" v-loading="loading"
:model="adForm" :model="adForm"
style="width:800px" style="width: 800px"
label-width="100" label-width="100"
> >
<!-- 选择阅片人 --> <!-- 选择阅片人 -->
@ -152,7 +198,7 @@
:label="$t('trials:adReview:title:choseReader')" :label="$t('trials:adReview:title:choseReader')"
prop="judgeResultTaskId" prop="judgeResultTaskId"
:rules="[ :rules="[
{ required: true, message: this.$t('common:ruleMessage:select')}, { required: true, message: this.$t('common:ruleMessage:select') },
]" ]"
> >
<el-radio-group <el-radio-group
@ -165,7 +211,7 @@
:label="t.VisitTaskId" :label="t.VisitTaskId"
@change="handleVisitTaskArmChange" @change="handleVisitTaskArmChange"
> >
{{ $fd('ArmEnum', t.ArmEnum) }} {{ $fd("ArmEnum", t.ArmEnum) }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
@ -174,87 +220,121 @@
:label="$t('trials:adReview:title:adReason')" :label="$t('trials:adReview:title:adReason')"
prop="judgeResultRemark" prop="judgeResultRemark"
:rules="[ :rules="[
{ required: true, message: this.$t('common:ruleMessage:specify')}, { required: true, message: this.$t('common:ruleMessage:specify') },
{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500`, trigger: ['blur', 'change'] } {
max: 500,
message: `${this.$t('common:ruleMessage:maxLength')} 500`,
trigger: ['blur', 'change'],
},
]" ]"
> >
<el-input <div style="position: relative">
v-model="adForm.judgeResultRemark" <div
type="textarea" style="
:autosize="{ minRows: 4, maxRows: 6}" position: absolute;
:disabled="adInfo.ReadingTaskState >= 2" left: 0;
/> top: 30px;
color: #606266;
font-size: 13px;
"
>
{{ remark }}
</div>
<el-input
v-model="adForm.judgeResultRemark"
type="textarea"
:autosize="{ minRows: 4, maxRows: 6 }"
:disabled="adInfo.ReadingTaskState >= 2"
style="margin-top: 25px"
/>
</div>
</el-form-item> </el-form-item>
<!-- 截图说明 --> <!-- 截图说明 -->
<el-form-item <el-form-item :label="$t('trials:adReview:title:screenShot')">
:label="$t('trials:adReview:title:screenShot')"
>
<el-upload <el-upload
:action="accept" action
:accept="accept"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:http-request="uploadScreenshot" :http-request="uploadScreenshot"
list-type="picture-card" list-type="picture-card"
:on-remove="handleRemove" :on-remove="handleRemove"
:file-list="fileList" :file-list="fileList"
:class="{disabled:adInfo.ReadingTaskState >= 2}" :class="{ disabled: adInfo.ReadingTaskState >= 2 }"
:disabled="adInfo.ReadingTaskState >= 2" :disabled="adInfo.ReadingTaskState >= 2"
> >
<i slot="default" class="el-icon-plus" /> <i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}"> <div
<img slot="file"
class="el-upload-list__item-thumbnail" slot-scope="{ file }"
crossOrigin="Anonymous" style="width: 100%; height: 100%"
:src="OSSclientConfig.basePath + file.url" >
alt="" <viewer
:ref="file.url"
:images="images"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
> >
<span class="el-upload-list__item-actions"> <img
<span class="el-upload-list__item-thumbnail"
class="el-upload-list__item-preview" :src="OSSclientConfig.basePath + file.url"
@click="handlePictureCardPreview(file)" alt=""
crossorigin="anonymous"
style="max-width: 100%; max-height: 100%"
> >
<i class="el-icon-zoom-in" /> <span class="el-upload-list__item-actions">
</span> <span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span <span
v-if="adInfo.ReadingTaskState < 2" v-if="adInfo.ReadingTaskState < 2"
class="el-upload-list__item-delete" class="el-upload-list__item-delete"
@click="handleRemove(file)" @click="handleRemove(file)"
> >
<i class="el-icon-delete" /> <i class="el-icon-delete" />
</span>
</span> </span>
</span> </viewer>
</div> </div>
</el-upload> </el-upload>
<el-dialog
append-to-body
:visible.sync="imgVisible"
width="600px"
>
<!-- <img width="100%" :src="imageUrl" alt="图片未找到"> -->
<el-image :src="imageUrl" width="100%">
<div slot="placeholder" class="image-slot">
{{ $t('trials:adReview:title:loading') }}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
</el-form-item> </el-form-item>
<el-form-item v-if="adInfo.ReadingTaskState < 2"> <el-form-item v-if="adInfo.ReadingTaskState < 2">
<div style="text-align:center;"> <div style="text-align: center">
<el-button type="primary" @click="skipTask">
<!-- 跳过 -->
{{ $t("trials:readingReport:button:skip") }}
</el-button>
<!-- 保存 --> <!-- 保存 -->
<el-button type="primary" @click="handleSave">{{ $t('common:button:save') }}</el-button> <el-button type="primary" @click="handleSave">{{
$t("common:button:save")
}}</el-button>
<!-- 提交 --> <!-- 提交 -->
<el-button type="primary" @click="handleSubmit">{{ $t('common:button:submit') }}</el-button> <el-button type="primary" @click="handleSubmit">{{
$t("common:button:submit")
}}</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card v-if="isReadingShowPreviousResults" :body-style="{ padding: '10px' }"> <el-card
v-if="isReadingShowPreviousResults"
:body-style="{ padding: '10px' }"
>
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<!-- 既往裁判评估 --> <!-- 既往裁判评估 -->
<span style="font-weight: bold;">{{ $t('trials:adReview:title:previousRes') }}</span> <span style="font-weight: bold">{{
$t("trials:adReview:title:previousRes")
}}</span>
</div> </div>
<el-table <el-table
@ -276,13 +356,10 @@
width="200" width="200"
> >
<template slot-scope="scope"> <template slot-scope="scope">
{{ $fd('ArmEnum', scope.row.JudgeResultArm) }} {{ $fd("ArmEnum", scope.row.JudgeResultArm) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column :label="$t('common:action:action')" width="200">
:label="$t('common:action:action')"
width="200"
>
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 查看详情 --> <!-- 查看详情 -->
<el-button <el-button
@ -304,21 +381,34 @@
custom-class="base-dialog-wrapper" custom-class="base-dialog-wrapper"
> >
<div slot="title"> <div slot="title">
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span> <span style="font-size: 18px">{{ $t("common:dialogTitle:sign") }}</span>
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span> <span style="font-size: 12px; margin-left: 5px">{{
`(${$t("common:label:sign")}${currentUser})`
}}</span>
</div> </div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" /> <SignForm
ref="signForm"
:sign-code-enum="signCode"
@closeDialog="closeSignDialog"
/>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { getJudgeReadingInfo, uploadJudgeTaskImage, saveJudgeVisitTaskResult, submitJudgeVisitTaskResult, getReadingPastResultList } from '@/api/trials' import {
getJudgeReadingInfo,
// uploadJudgeTaskImage,
saveJudgeVisitTaskResult,
submitJudgeVisitTaskResult,
getReadingPastResultList
} from '@/api/trials'
import { getAutoCutNextTask } from '@/api/user' import { getAutoCutNextTask } from '@/api/user'
import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent' import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import store from '@/store' // import store from '@/store'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
export default { export default {
name: 'AdReview', name: 'AdReview',
@ -386,7 +476,10 @@ export default {
priorLoading: false, priorLoading: false,
judgeResultArmEnum: '', judgeResultArmEnum: '',
criterionType: null, criterionType: null,
openWindow: null openWindow: null,
isFixed: false,
images: [],
remark: ''
} }
}, },
// watch: { // watch: {
@ -421,51 +514,92 @@ export default {
} }
}, },
methods: { methods: {
getAdInfo() { async getAdInfo() {
this.loading = true this.loading = true
getJudgeReadingInfo({ visitTaskId: this.visitTaskId }).then(res => { try {
var judgeQS = [] const res = await getJudgeReadingInfo({
if (res.Result.VisitInfoList.length > 0) { visitTaskId: this.visitTaskId
res.Result.VisitInfoList[0].VisitTaskInfoList.map((v, index) => { })
var qsObj = { armEnum: v.ArmEnum, judgeQuestionList: [], index: index } if (res.IsSuccess) {
v.JudgeQuestionList.map(q => { var judgeQS = []
if (q.QuestionType === 1) { if (res.Result.VisitInfoList.length > 0) {
qsObj.judgeQuestionList.push(q.QuestionName) res.Result.VisitInfoList[0].VisitTaskInfoList.map((v, index) => {
} else if (q.QuestionType === 3 && this.criterionType === 10) { var qsObj = {
qsObj.judgeQuestionList.push(this.$t('trials:globalReview:table:visitRemark')) armEnum: v.ArmEnum,
} else { judgeQuestionList: [],
qsObj.judgeQuestionList.push(this.$fd('JudgeReadingQuestionType', q.QuestionType)) index: index
}
v.JudgeQuestionList.map((q) => {
if (q.QuestionType === 1) {
qsObj.judgeQuestionList.push(q.QuestionName)
} else if (q.QuestionType === 3 && this.criterionType === 10) {
qsObj.judgeQuestionList.push(
this.$t('trials:globalReview:table:visitRemark')
)
} else {
qsObj.judgeQuestionList.push(
this.$fd('JudgeReadingQuestionType', q.QuestionType)
)
}
})
judgeQS.push(qsObj)
})
}
this.judgeQuestion = judgeQS
this.isFixed =
this.judgeQuestion.length > 0 &&
this.judgeQuestion[0].judgeQuestionList.length > 4
this.adInfo = res.Result
this.adForm.judgeResultTaskId = res.Result.JudgeResultTaskId
this.fileList = []
if (res.Result.JudgeResultImagePathList) {
res.Result.JudgeResultImagePathList.map((url) => {
if (url) {
this.fileList.push({ name: '', url: url })
} }
}) })
judgeQS.push(qsObj) this.adForm.judgeResultImagePathList =
}) res.Result.JudgeResultImagePathList
}
this.visitTaskArmList = res.Result.VisitTaskArmList
var i = this.visitTaskArmList.findIndex(
(i) => i.VisitTaskId === this.adForm.judgeResultTaskId
)
if (i > -1) {
// R1
this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum
var msg = ''
if (this.judgeResultArmEnum === 1) {
msg = this.$t('trials:adReview:title:msg1')
} else if (this.judgeResultArmEnum === 2) {
msg = this.$t('trials:adReview:title:msg3')
}
this.remark = msg
this.adForm.judgeResultRemark = res.Result.JudgeResultRemark
}
} }
this.judgeQuestion = judgeQS
this.adInfo = res.Result
this.adForm.judgeResultTaskId = res.Result.JudgeResultTaskId
this.adForm.judgeResultRemark = res.Result.JudgeResultRemark
this.fileList = []
if (res.Result.JudgeResultImagePathList) {
res.Result.JudgeResultImagePathList.map(url => {
if (url) { this.fileList.push({ name: '', url: url }) }
})
this.adForm.judgeResultImagePathList = res.Result.JudgeResultImagePathList
}
this.visitTaskArmList = res.Result.VisitTaskArmList
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
getPriorAdList() { async getPriorAdList() {
this.priorLoading = true this.priorLoading = true
getReadingPastResultList({ visitTaskId: this.visitTaskId }).then(res => { try {
this.priorADList = res.Result const res = await getReadingPastResultList({
visitTaskId: this.visitTaskId
})
if (res.IsSuccess) {
this.priorADList = res.Result
}
this.priorLoading = false this.priorLoading = false
}).catch(() => { this.priorLoading = false }) } catch (e) {
this.priorLoading = false
}
}, },
handleVisitTaskArmChange(v) { handleVisitTaskArmChange(v) {
var i = this.visitTaskArmList.findIndex(i => i.VisitTaskId === v) var i = this.visitTaskArmList.findIndex((i) => i.VisitTaskId === v)
if (i > -1) { if (i > -1) {
// R1 // R1
this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum
@ -476,9 +610,12 @@ export default {
msg = this.$t('trials:adReview:title:msg3') msg = this.$t('trials:adReview:title:msg3')
} }
// this.adForm.judgeResultRemark = `${this.$fd('ArmEnum', this.judgeResultArmEnum)}` // this.adForm.judgeResultRemark = `${this.$fd('ArmEnum', this.judgeResultArmEnum)}`
this.adForm.judgeResultRemark = msg this.remark = msg
this.adForm.judgeResultRemark = ''
} else { } else {
this.judgeResultArmEnum = '' this.judgeResultArmEnum = ''
this.remark = ''
this.adForm.judgeResultRemark = ''
} }
}, },
previewCD() { previewCD() {
@ -488,33 +625,32 @@ export default {
}) })
window.open(routeData.href, '_blank') window.open(routeData.href, '_blank')
}, },
handleSave() { async handleSave() {
this.$refs['adForm'].validate((valid) => { const valid = await this.$refs['adForm'].validate()
if (!valid) return if (!valid) return
this.loading = true this.loading = true
var paths = [] var paths = []
this.fileList.map(file => { this.fileList.map((file) => {
if (file.url) { if (file.url) {
paths.push(file.url) paths.push(file.url)
} }
})
this.adForm.judgeResultImagePathList = paths
this.adForm.visitTaskId = this.visitTaskId
saveJudgeVisitTaskResult(this.adForm).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.loading = false
}).catch(() => {
this.loading = false
})
}) })
this.adForm.judgeResultImagePathList = paths
this.adForm.visitTaskId = this.visitTaskId
try {
await saveJudgeVisitTaskResult(this.adForm)
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.loading = false
} catch (e) {
this.loading = false
}
}, },
handleSubmit() { async handleSubmit() {
this.$refs['adForm'].validate((valid) => { const valid = await this.$refs['adForm'].validate()
if (!valid) return if (!valid) return
const { ImageAssessmentReportConfirmation } = const_.processSignature const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true this.signVisible = true
})
}, },
// //
closeSignDialog(isSign, signInfo) { closeSignDialog(isSign, signInfo) {
@ -525,10 +661,10 @@ export default {
} }
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
var paths = [] var paths = []
this.fileList.map(file => { this.fileList.map((file) => {
paths.push(file.url) paths.push(file.url)
}) })
var params = { var params = {
@ -540,7 +676,8 @@ export default {
}, },
signInfo: signInfo signInfo: signInfo
} }
submitJudgeVisitTaskResult(params).then(async res => { try {
const res = await submitJudgeVisitTaskResult(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.isEdit = false this.isEdit = false
@ -550,38 +687,35 @@ export default {
// window.opener.postMessage('refreshTaskList', window.location) // window.opener.postMessage('refreshTaskList', window.location)
// //
this.adInfo.ReadingTaskState = 2 this.adInfo.ReadingTaskState = 2
var isAutoTask = await this.getAutoTaskVal() const res = await getAutoCutNextTask()
var isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) { if (isAutoTask) {
store.dispatch('reading/resetVisitTasks') // store.dispatch('reading/resetVisitTasks')
DicomEvent.$emit('getNextTask') window.location.reload()
} else { } else {
// '' // ''
this.$confirm(this.$t('trials:adReview:title:msg2'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:adReview:title:msg2'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(() => { distinguishCancelAndClose: true
store.dispatch('reading/resetVisitTasks') }
DicomEvent.$emit('getNextTask') )
}) if (confirm === 'confirm') {
.catch(action => { // store.dispatch('reading/resetVisitTasks')
changeURLStatic('visitTaskId', this.visitTaskId) // DicomEvent.$emit('getNextTask')
}) window.location.reload()
} else {
changeURLStatic('visitTaskId', this.visitTaskId)
}
} }
window.opener.postMessage('refreshTaskList', window.location) window.opener.postMessage('refreshTaskList', window.location)
} }
this.loading = false this.loading = false
}).catch(_ => { } catch (e) {
this.loading = false this.loading = false
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
}) }
},
getAutoTaskVal() {
return new Promise((resolve, reject) => {
getAutoCutNextTask().then(res => {
resolve(res.Result.AutoCutNextTask)
}).catch(() => { reject() })
})
}, },
handleViewDetail(visitTaskId) { handleViewDetail(visitTaskId) {
if (this.openWindow) { if (this.openWindow) {
@ -591,14 +725,24 @@ export default {
var criterionType = parseInt(localStorage.getItem('CriterionType')) var criterionType = parseInt(localStorage.getItem('CriterionType'))
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder =
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId =
this.$router.currentRoute.query.TrialReadingCriterionId
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
this.trialId
}&subjectCode=${this.subjectCode}&subjectId=${
this.subjectId
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
} else { } else {
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
this.trialId
}&subjectCode=${this.subjectCode}&subjectId=${
this.subjectId
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
} }
var routeData = this.$router.resolve({ path }) var routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, '_blank') this.openWindow = window.open(routeData.href, '_blank')
@ -614,18 +758,32 @@ export default {
// }) // })
// window.open(routeData.href, '_blank') // window.open(routeData.href, '_blank')
var token = getToken() var token = getToken()
var task = row.VisitTaskInfoList.find(item => item.ArmEnum === armEnum) var task = row.VisitTaskInfoList.find((item) => item.ArmEnum === armEnum)
var criterionType = this.$router.currentRoute.query.criterionType var criterionType = this.$router.currentRoute.query.criterionType
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder =
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId =
this.$router.currentRoute.query.TrialReadingCriterionId
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
this.trialId
}&subjectCode=${this.subjectCode}&subjectId=${
this.subjectId
}&visitTaskId=${
task.VisitTaskId
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
} else { } else {
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
this.trialId
}&subjectCode=${this.subjectCode}&subjectId=${
this.subjectId
}&visitTaskId=${
task.VisitTaskId
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
} }
var routeData = this.$router.resolve({ path }) var routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, '_blank') this.openWindow = window.open(routeData.href, '_blank')
@ -635,43 +793,77 @@ export default {
this.openWindow.close() this.openWindow.close()
} }
var token = getToken() var token = getToken()
var task = row.VisitTaskInfoList.find(item => item.ArmEnum === armEnum) var task = row.VisitTaskInfoList.find((item) => item.ArmEnum === armEnum)
var criterionType = this.$router.currentRoute.query.criterionType var criterionType = this.$router.currentRoute.query.criterionType
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder =
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId =
this.$router.currentRoute.query.TrialReadingCriterionId
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${task.GlobalVisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
this.trialId
}&subjectCode=${this.subjectCode}&subjectId=${
this.subjectId
}&visitTaskId=${
task.GlobalVisitTaskId
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
} else { } else {
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${task.GlobalVisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
this.trialId
}&subjectCode=${this.subjectCode}&subjectId=${
this.subjectId
}&visitTaskId=${
task.GlobalVisitTaskId
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
} }
var routeData = this.$router.resolve({ path }) var routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, '_blank') this.openWindow = window.open(routeData.href, '_blank')
}, },
uploadScreenshot(param) { // uploadScreenshot(param) {
// this.loading = true
// this.uploadDisabled = false
// const formData = new FormData()
// formData.append('file', param.file)
// uploadJudgeTaskImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
// this.loading = false
// if (res.IsSuccess) {
// this.fileList.push({ name: res.Result.FileName, url: `${res.Result.Path}` })
// }
// this.uploadDisabled = true
// }).catch(() => {
// this.loading = false
// })
// },
async uploadScreenshot(param) {
this.loading = true this.loading = true
this.uploadDisabled = false this.uploadDisabled = false
const formData = new FormData() var trialId = this.$route.query.trialId
formData.append('file', param.file) var file = await this.fileToBlob(param.file)
uploadJudgeTaskImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => { const res = await this.OSSclient.put(
this.loading = false `/${trialId}/Read/${this.subjectId}/visit/${param.file.name}`,
if (res.IsSuccess) { file
this.fileList.push({ name: res.Result.FileName, url: `${res.Result.Path}` }) )
} console.log(res)
this.uploadDisabled = true this.fileList.push({
}).catch(() => { name: param.file.name,
this.loading = false url: this.$getObjectName(res.url)
}) })
this.loading = false
this.uploadDisabled = true
}, },
handleBeforeUpload(file) { handleBeforeUpload(file) {
// //
if (this.checkFileSuffix(file.name)) { if (this.checkFileSuffix(file.name)) {
return true return true
} else { } else {
const msg = this.$t('trials:adReview:title:msg4').replace('xxx', this.accept) const msg = this.$t('trials:adReview:title:msg4').replace(
'xxx',
this.accept
)
this.$alert(msg) this.$alert(msg)
return false return false
} }
@ -679,7 +871,10 @@ export default {
checkFileSuffix(fileName) { checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.') var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length) var suffix = fileName.substring(index + 1, fileName.length)
if (this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) { if (
this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) ===
-1
) {
return false return false
} else { } else {
return true return true
@ -693,39 +888,66 @@ export default {
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = file.url this.images = this.fileList.map(
this.imgVisible = true (f) => this.OSSclientConfig.basePath + f.url
)
// this.imageUrl = this.OSSclientConfig.basePath + file.url
this.$refs[file.url].$viewer.show()
}, },
// //
handleRemove(file, fileList) { handleRemove(file, fileList) {
var idx = this.fileList.findIndex(i => i.url === file.url) var idx = this.fileList.findIndex((i) => i.url === file.url)
if (idx === -1) return if (idx === -1) return
this.fileList.splice(idx, 1) this.fileList.splice(idx, 1)
},
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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.adReview_wrapper{ .adReview_wrapper {
flex: 1; flex: 1;
padding: 10px; padding: 10px;
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
.box-mr{ .box-mr {
margin:10px 0; margin: 10px 0;
} }
.disabled{ .disabled {
>>>.el-upload--picture-card { /deep/ .el-upload--picture-card {
display: none; display: none;
} }
} }
>>> .el-upload-list__item { /deep/ .el-upload-list__item {
transition: none !important; transition: none !important;
} }
>>> .el-upload-list__item-thumbnail { /deep/ .el-upload-list__item-thumbnail {
/* 图片在方框内显示长边 */ /* 图片在方框内显示长边 */
object-fit: scale-down !important; object-fit: scale-down !important;
} }
} }
</style> </style>

View File

@ -111,10 +111,11 @@ export default {
this.isRender = true this.isRender = true
}, },
methods: { methods: {
handleSave() { async handleSave() {
this.$refs.assessmentForm.validate(async valid => { const valid = await this.$refs.assessmentForm.validate()
if (!valid) return if (!valid) return
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
try {
var answers = [] var answers = []
for (const k in this.form) { for (const k in this.form) {
answers.push({ questionId: k, answer: this.form[k] }) answers.push({ questionId: k, answer: this.form[k] })
@ -123,13 +124,15 @@ export default {
visitTaskId: this.visitTaskId, visitTaskId: this.visitTaskId,
answerList: answers answerList: answers
} }
submitTaskAdditionalQuestion(params).then(res => { const res = await submitTaskAdditionalQuestion(params)
if (res.IsSuccess) {
this.$emit('sign') this.$emit('sign')
loading.close() }
}).catch(() => { loading.close()
loading.close() } catch (e) {
}) console.log(e)
}) loading.close()
}
}, },
handleCancel() { handleCancel() {
this.$emit('close') this.$emit('close')

View File

@ -1,6 +1,6 @@
<template> <template>
<el-form <el-form
ref="subjectForm" ref="customWWWC"
v-loading="loading" v-loading="loading"
:model="form" :model="form"
:rules="rules" :rules="rules"
@ -67,11 +67,10 @@ export default {
} }
}, },
methods: { methods: {
handleSave() { async handleSave() {
this.$refs.subjectForm.validate(valid => { const valid = await this.$refs.customWWWC.validate()
if (!valid) return if (!valid) return
this.$emit('setWwwc', this.form) this.$emit('setWwwc', this.form)
})
}, },
handleCancel() { handleCancel() {
this.$emit('close') this.$emit('close')

View File

@ -19,7 +19,7 @@
</div> </div>
<!-- 切换访视 --> <!-- 切换访视 -->
<div <div
v-if="stack.imageRendered && isReadingTaskViewInOrder" v-if="stack.imageRendered && isReadingTaskViewInOrder === 1"
class="info-visit" class="info-visit"
@dblclick.stop="preventDefault($event)" @dblclick.stop="preventDefault($event)"
> >
@ -181,7 +181,7 @@ export default {
required: true required: true
}, },
isReadingTaskViewInOrder: { isReadingTaskViewInOrder: {
type: Boolean, type: Number,
required: true required: true
}, },
customWwcTpl: { customWwcTpl: {
@ -222,7 +222,8 @@ export default {
taskBlindName: '', taskBlindName: '',
frame: null, frame: null,
imageRendered: false, imageRendered: false,
isExistsClinicalData: false isExistsClinicalData: false,
isExistMutiFrames: false
// preventCache: true // preventCache: true
}, },
dicomInfo: { dicomInfo: {
@ -333,7 +334,8 @@ export default {
mounted() { mounted() {
console.log(cornerstoneTools) console.log(cornerstoneTools)
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
document.addEventListener('mouseup', () => { document.addEventListener('mouseup', () => {
this.sliderMouseup() this.sliderMouseup()
}) })
@ -477,7 +479,7 @@ export default {
}, },
methods: { methods: {
goViewer(e) { goViewer(e) {
console.log(this.$refs['sliderBox'].clientHeight) // console.log(this.$refs['sliderBox'].clientHeight)
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
this.height = height this.height = height
var index = Math.trunc(this.stack.imageIds.length * this.height / 100) var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
@ -546,7 +548,7 @@ export default {
}, },
mouseUp(e) { mouseUp(e) {
console.log('mouseUp') // console.log('mouseUp')
if (this.readingTaskState >= 2) return if (this.readingTaskState >= 2) return
this.image = e.detail.image this.image = e.detail.image
this.getToolStateInfo(e) this.getToolStateInfo(e)
@ -672,7 +674,7 @@ export default {
this.sliderInfo.isMove = false this.sliderInfo.isMove = false
}, },
getMeasureData() { getMeasureData() {
console.log('getMeasureData') // console.log('getMeasureData')
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
@ -757,7 +759,7 @@ export default {
const imageInfo = this.getInstanceInfo(imageId) const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
for (var m = 0; m < this.measuredTools.length; m++) { for (var m = 0; m < this.measuredTools.length; m++) {
var toolType = this.measuredTools[m] var toolType = this.measuredTools[m]
@ -814,7 +816,7 @@ export default {
} }
}, },
stackScrollCallback(e) { stackScrollCallback(e) {
console.log('stackScrollCallback') // console.log('stackScrollCallback')
const { detail } = e const { detail } = e
if (this.isScrollSync && this.currentDicomCanvasIndex === this.canvasIndex) { if (this.isScrollSync && this.currentDicomCanvasIndex === this.canvasIndex) {
this.scrollSyncInfo.canvasIndex = this.canvasIndex this.scrollSyncInfo.canvasIndex = this.canvasIndex
@ -879,7 +881,6 @@ export default {
return seriesList[seriesIdx].loadStatus ? 1 : 0 return seriesList[seriesIdx].loadStatus ? 1 : 0
}, },
renderMeasuredData(e) { renderMeasuredData(e) {
this.stack.frame = !isNaN(parseInt(this.stack.frame)) ? parseInt(this.stack.frame) : 0
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
if (idx === -1) return if (idx === -1) return
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
@ -898,9 +899,7 @@ export default {
} else { } else {
cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 }) cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
} }
// console.log('renderMeasuredData', this.stack.frame) if (this.stack.instanceId.includes(data.InstanceId) && ((this.stack.isExistMutiFrames && data.MeasureData.frame === this.stack.frame && data.MeasureData) || (!this.stack.isExistMutiFrames && data.MeasureData))) {
if (this.stack.instanceId.includes(data.InstanceId) && ((data.NumberOfFrames === this.stack.frame) || !data.NumberOfFrames) && data.MeasureData) {
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type) const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type)
if (toolState && toolState.data.length > 0) { if (toolState && toolState.data.length > 0) {
var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid) var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid)
@ -987,7 +986,7 @@ export default {
const imageInfo = this.getInstanceInfo(imageId) const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
for (let t = 0; t < this.measuredTools.length; t++) { for (let t = 0; t < this.measuredTools.length; t++) {
var toolType = this.measuredTools[t] var toolType = this.measuredTools[t]
@ -998,7 +997,7 @@ export default {
if (i > -1) { if (i > -1) {
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid) var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
if (idx > -1) { if (idx > -1) {
console.log('mouseClick') // console.log('mouseClick')
DicomEvent.$emit('setCollapseActive', this.measureData[idx]) DicomEvent.$emit('setCollapseActive', this.measureData[idx])
if (this.readingTaskState < 2) { if (this.readingTaskState < 2) {
const measureData = {} const measureData = {}
@ -1040,7 +1039,7 @@ export default {
loadImageStack(dicomSeries) { loadImageStack(dicomSeries) {
return new Promise(resolve => { return new Promise(resolve => {
this.isCurrentTask = dicomSeries.isCurrentTask this.isCurrentTask = dicomSeries.isCurrentTask
this.isBaseline = dicomSeries.isBaseline this.isBaseline = dicomSeries.isBaseLineTask
this.readingTaskState = dicomSeries.readingTaskState this.readingTaskState = dicomSeries.readingTaskState
if (this.isCurrentTask && this.readingTaskState < 2) { if (this.isCurrentTask && this.readingTaskState < 2) {
this.activeTool = 1 this.activeTool = 1
@ -1055,7 +1054,7 @@ export default {
this.stack.studyId = dicomSeries.studyId this.stack.studyId = dicomSeries.studyId
this.stack.seriesNumber = dicomSeries.seriesNumber this.stack.seriesNumber = dicomSeries.seriesNumber
this.stack.imageIds = dicomSeries.imageIds this.stack.imageIds = dicomSeries.imageIds
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex ? dicomSeries.imageIdIndex : 0 this.stack.currentImageIdIndex = dicomSeries.imageIdIndex && dicomSeries.imageIdIndex < dicomSeries.imageIds.length ? dicomSeries.imageIdIndex : 0
this.stack.imageIdIndex = dicomSeries.imageIdIndex this.stack.imageIdIndex = dicomSeries.imageIdIndex
this.stack.firstImageLoading = true this.stack.firstImageLoading = true
this.stack.visitTaskId = dicomSeries.visitTaskId this.stack.visitTaskId = dicomSeries.visitTaskId
@ -1066,6 +1065,7 @@ export default {
this.stack.sliceThickness = dicomSeries.sliceThickness this.stack.sliceThickness = dicomSeries.sliceThickness
this.stack.instanceCount = dicomSeries.instanceCount this.stack.instanceCount = dicomSeries.instanceCount
this.stack.isExistsClinicalData = dicomSeries.isExistsClinicalData this.stack.isExistsClinicalData = dicomSeries.isExistsClinicalData
this.stack.isExistMutiFrames = dicomSeries.isExistMutiFrames
// this.measuredData = dicomSeries.measuredData // this.measuredData = dicomSeries.measuredData
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId)
this.stack.visitTaskNum = this.visitTaskList[idx].VisitTaskNum this.stack.visitTaskNum = this.visitTaskList[idx].VisitTaskNum
@ -1086,18 +1086,18 @@ export default {
const imageInfo = this.getInstanceInfo(imageId) const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
this.stack.instanceId = instanceId this.stack.instanceId = instanceId
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
if (this.toolState.clipPlaying) this.toggleClipPlay()
this.toolState.viewportInvert = false
this.toolState.dicomInfoVisible = false
const element = this.$refs.canvas const element = this.$refs.canvas
cornerstone.enable(element) cornerstone.enable(element)
element.tabIndex = 0 element.tabIndex = 0
element.focus() element.focus()
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
this.toggleClipPlay(false)
this.toolState.viewportInvert = false
this.toolState.dicomInfoVisible = false
var scope = this var scope = this
// var p = parseInt(new Date().getTime()) // var p = parseInt(new Date().getTime())
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{ // requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{
@ -1110,22 +1110,27 @@ export default {
// } // }
// resolve() // resolve()
// }) // })
this.loading = true
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex]) cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(async image => { .then(async image => {
await scope.onFirstImageLoaded(image) if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
await scope.onFirstImageLoaded(image)
}
scope.loading = false
resolve() resolve()
}) })
.catch((error) => { .catch((error) => {
if (error.error && error.error.message) { if (error.error && error.error.message) {
this.$alert(error.error.message) this.$alert(error.error.message)
} }
scope.loading = false
resolve() resolve()
}) })
}) })
}, },
onFirstImageLoaded(image) { onFirstImageLoaded(image) {
console.log('onFirstImageLoaded') // console.log('onFirstImageLoaded')
return new Promise(resolve => { return new Promise(async resolve => {
const element = this.$refs.canvas const element = this.$refs.canvas
var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image) var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image)
cornerstone.displayImage(this.canvas, image, viewport) cornerstone.displayImage(this.canvas, image, viewport)
@ -1195,15 +1200,15 @@ export default {
const imageInfo = this.getInstanceInfo(image.imageId) const imageInfo = this.getInstanceInfo(image.imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
this.stack.instanceId = instanceId this.stack.instanceId = instanceId
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1) this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
this.resetWwwc() // this.resetWwwc()
resolve() resolve()
}) })
}, },
onNewImage(e) { onNewImage(e) {
console.log('cornerstonenewimage') // console.log('cornerstonenewimage')
if (this.isCurrentTask && this.readingTaskState < 2) { if (this.isCurrentTask && this.readingTaskState < 2) {
this.resetHideMeasureArr() this.resetHideMeasureArr()
} }
@ -1240,6 +1245,12 @@ export default {
if (this.dicomInfo.thick) { if (this.dicomInfo.thick) {
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2) this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
} }
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === imageId)
if (newImageIdIndex === -1) return
this.stack.currentImageIdIndex = newImageIdIndex
this.stack.imageIdIndex = newImageIdIndex
this.series.imageIdIndex = newImageIdIndex
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
}, },
getScreenshots() { getScreenshots() {
const canvas = this.canvas.querySelector('canvas') const canvas = this.canvas.querySelector('canvas')
@ -1264,7 +1275,7 @@ export default {
const imageInfo = this.getInstanceInfo(imageId) const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
if (this.imageId !== instanceId) { if (this.imageId !== instanceId) {
this.getOrientationMarker(e.detail.element) this.getOrientationMarker(e.detail.element)
// //
@ -1316,20 +1327,20 @@ export default {
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport var viewport = element.viewport
// //
console.log('completed') // console.log('completed')
this.activeTool = 1 this.activeTool = 1
this.activeToolName = '' this.activeToolName = ''
var { imageId } = element.image var { imageId } = element.image
const imageInfo = this.getInstanceInfo(imageId) const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi') { if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi') {
const measureData = {} const measureData = {}
measureData.studyId = this.stack.studyId measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId measureData.seriesId = this.stack.seriesId
measureData.instanceId = instanceId measureData.instanceId = instanceId
measureData.frame = this.stack.frame ? this.stack.frame : 0 measureData.frame = this.stack.frame
measureData.data = e.detail.measurementData measureData.data = e.detail.measurementData
measureData.type = e.detail.toolName measureData.type = e.detail.toolName
measureData.thick = this.dicomInfo.thick measureData.thick = this.dicomInfo.thick
@ -1434,7 +1445,7 @@ export default {
}, },
onMeasurementmodified(e) { onMeasurementmodified(e) {
// //
console.log('modified') // console.log('modified')
if (this.readingTaskState >= 2) return if (this.readingTaskState >= 2) return
const { measurementData, toolType } = e.detail const { measurementData, toolType } = e.detail
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
@ -1443,7 +1454,8 @@ export default {
const imageInfo = this.getInstanceInfo(imageId) const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId var instanceId = imageInfo.instanceId
var frame = imageInfo.frame var frame = imageInfo.frame
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
var uuid = measurementData.uuid var uuid = measurementData.uuid
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid) var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) { if (idx > -1) {
@ -1559,8 +1571,10 @@ export default {
resetViewport() { resetViewport() {
this.toolState.viewportInvert = false this.toolState.viewportInvert = false
this.orientationMarkers = [...this.originalMarkers] if (this.originalMarkers.length > 0) {
this.setMarkers() this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
var image = cornerstone.getImage(this.canvas) var image = cornerstone.getImage(this.canvas)
cornerstone.setViewport( cornerstone.setViewport(
this.canvas, this.canvas,
@ -1619,18 +1633,19 @@ export default {
} }
}, },
toggleClipPlay() { toggleClipPlay(isPlay) {
if (this.toolState.clipPlaying) { if (isPlay) {
this.toolState.clipPlaying = true
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
} else {
cornerstoneTools.stopClip(this.canvas) cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false this.toolState.clipPlaying = false
return return
} }
this.toolState.clipPlaying = true
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
}, },
setFps(fps) { setFps(fps) {
this.dicomInfo.fps = fps this.dicomInfo.fps = fps
@ -1639,7 +1654,7 @@ export default {
resetWwwc() { resetWwwc() {
this.toolState.viewportInvert = false this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = false // viewport.invert = false
var image = cornerstone.getImage(this.canvas) var image = cornerstone.getImage(this.canvas)
viewport.voi.windowWidth = image.windowWidth viewport.voi.windowWidth = image.windowWidth
viewport.voi.windowCenter = image.windowCenter viewport.voi.windowCenter = image.windowCenter
@ -1675,8 +1690,10 @@ export default {
}, },
resetRotate() { resetRotate() {
this.orientationMarkers = [...this.originalMarkers] if (this.originalMarkers.length > 0) {
this.setMarkers() this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
viewport.hflip = false viewport.hflip = false
viewport.vflip = false viewport.vflip = false
@ -1691,23 +1708,25 @@ export default {
} }
}, },
setRotate(hflip, vflip, angle, type) { setRotate(hflip, vflip, angle, type) {
var markers = [...this.orientationMarkers] if (this.orientationMarkers.length > 0) {
if (type === 2) { var markers = [...this.orientationMarkers]
// if (type === 2) {
this.orientationMarkers[0] = markers[2] //
this.orientationMarkers[2] = markers[0] this.orientationMarkers[0] = markers[2]
} else if (type === 3) { this.orientationMarkers[2] = markers[0]
// } else if (type === 3) {
this.orientationMarkers[1] = markers[3] //
this.orientationMarkers[3] = markers[1] this.orientationMarkers[1] = markers[3]
} else if (type === 4) { this.orientationMarkers[3] = markers[1]
// 90 } else if (type === 4) {
this.orientationMarkers = markers.slice(1, 4).concat(markers[0]) // 90
} else if (type === 5) { this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
// 90 } else if (type === 5) {
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3)) // 90
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
} }
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
if (hflip) viewport.hflip = !viewport.hflip if (hflip) viewport.hflip = !viewport.hflip
if (vflip) viewport.vflip = !viewport.vflip if (vflip) viewport.vflip = !viewport.vflip
@ -1716,9 +1735,8 @@ export default {
}, },
saveImage() { saveImage() {
let timestamp = Date.now() var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
// var uid = cornerstone.getImage(this.canvas).data.string('x00080018') cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
cornerstoneTools.SaveAs(this.canvas, `${this.subjectCode}_${this.stack.taskBlindName}_${timestamp}.png`)
}, },
fitToWindow() { fitToWindow() {
if (this.stack.seriesNumber) { if (this.stack.seriesNumber) {
@ -1917,6 +1935,17 @@ export default {
} }
} }
}, },
getInstanceInfo(imageId) {
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
if (isNaN(params.frame)) {
params.frame = 0
}
return params
},
preventDefault(e) { preventDefault(e) {
e.stopImmediatePropagation() e.stopImmediatePropagation()
e.stopPropagation() e.stopPropagation()
@ -1927,15 +1956,6 @@ export default {
e.stopImmediatePropagation() e.stopImmediatePropagation()
e.stopPropagation() e.stopPropagation()
e.preventDefault() e.preventDefault()
},
getInstanceInfo(imageId) {
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
return params
} }
} }

View File

@ -26,7 +26,7 @@
A A
</div> </div>
</li> </li>
<li v-if="isReadingTaskViewInOrder" class="flex_row" @click.stop="changeLayout('A|B')"> <li v-if="isReadingTaskViewInOrder === 1" class="flex_row" @click.stop="changeLayout('A|B')">
<div class="layout_box_1_1"> <div class="layout_box_1_1">
A A
</div> </div>
@ -280,6 +280,54 @@
<div class="text">{{ tool.text }}</div> <div class="text">{{ tool.text }}</div>
</div> --> </div> -->
</div> </div>
<div class="tool-frame">
<!-- 第一帧 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:dicom-show:firstframe')" placement="bottom">
<div class="icon" @click.prevent="scrollPage(-99999)">
<svg-icon icon-class="firstframe" class="svg-icon" />
</div>
</el-tooltip>
<!-- 上一帧 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:dicom-show:previousframe')" placement="bottom">
<div class="icon" @click.prevent="scrollPage(-1)">
<svg-icon icon-class="previousframe" class="svg-icon" />
</div>
</el-tooltip>
<!-- 播放/暂停 -->
<el-tooltip class="item" effect="dark" :content="clipPlaying?$t('trials:dicom-show:stop'):$t('trials:dicom-show:play')" placement="bottom">
<div v-if="clipPlaying" class="icon" @click.prevent="toggleClipPlay(false)">
<svg-icon icon-class="stop" class="svg-icon" />
</div>
<div v-else class="icon" @click.prevent="toggleClipPlay(true)">
<svg-icon icon-class="play" class="svg-icon" />
</div>
</el-tooltip>
<!-- 下一帧 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:dicom-show:nextframe')" placement="bottom">
<div class="icon" @click.prevent="scrollPage(1)">
<svg-icon icon-class="nextframe" class="svg-icon" />
</div>
</el-tooltip>
<!-- 最后一帧 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:dicom-show:lastframe')" placement="bottom">
<div class="icon" @click.prevent="scrollPage(99999)">
<svg-icon icon-class="lastframe" class="svg-icon" />
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="$t('trials:dicom-show:speed')" placement="bottom">
<select v-model="fps" class="select-wrapper" :disabled="clipPlaying" @change="setDicomCanvasfps($event)">
<!-- 默认值 -->
<!-- <option :value="5">{{ $t('trials:dicom-show:default') }}</option> -->
<option :value="5">5</option>
<option :value="10">10</option>
<option :value="15">15</option>
<option :value="20">20</option>
<option :value="25">25</option>
<option :value="30">30</option>
</select>
</el-tooltip>
</div>
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:reset')" placement="bottom"> <el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:reset')" placement="bottom">
<div class="tool-wrapper"> <div class="tool-wrapper">
@ -337,41 +385,63 @@
</div> </div>
</div> </div>
<div ref="form-container" class="form-container"> <div ref="form-container" class="form-container">
<!-- 激活canvas测量数据 --> <div class="form-wrapper">
<RecistBMQuestionList
v-if="CriterionType === 17"
ref="measurementList"
:question-form-change-state="questionFormChangeState"
:question-form-change-num="questionFormChangeNum"
:is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
/>
<IRecistQuestionList
v-else-if="CriterionType === 3"
ref="measurementList"
:question-form-change-state="questionFormChangeState"
:question-form-change-num="questionFormChangeNum"
:is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
/>
<PCWGQuestionList
v-else-if="CriterionType === 10"
ref="measurementList"
:question-form-change-state="questionFormChangeState"
:question-form-change-num="questionFormChangeNum"
:is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
/>
<RecistBMQuestionList <RecistQuestionList
v-if="CriterionType === 17" v-else-if="CriterionType === 1"
ref="measurementList" ref="measurementList"
:question-form-change-state="questionFormChangeState" :question-form-change-state="questionFormChangeState"
:question-form-change-num="questionFormChangeNum" :question-form-change-num="questionFormChangeNum"
:is-show="isShow" :is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :is-reading-show-subject-info="isReadingShowSubjectInfo"
/> />
<IRecistQuestionList <h2 v-else style="color:#ddd">
v-else-if="CriterionType === 3" Developing...
ref="measurementList" </h2>
:question-form-change-state="questionFormChangeState" </div>
:question-form-change-num="questionFormChangeNum" <div v-if="iseCRFShowInDicomReading && currentReadingTaskState < 2" class="form-footer">
:is-show="isShow" <el-button
:is-reading-show-subject-info="isReadingShowSubjectInfo" type="primary"
/> size="small"
<PCWGQuestionList @click="skipTask"
v-else-if="CriterionType === 10" >
ref="measurementList" <!-- 跳过 -->
:question-form-change-state="questionFormChangeState" {{ $t('trials:readingReport:button:skip') }}
:question-form-change-num="questionFormChangeNum" </el-button>
:is-show="isShow" <el-button
:is-reading-show-subject-info="isReadingShowSubjectInfo" type="primary"
/> size="small"
@click="submit"
>
<!-- 提交 -->
{{ $t('common:button:submit') }}
</el-button>
</div>
<RecistQuestionList
v-else-if="CriterionType !== 17"
ref="measurementList"
:question-form-change-state="questionFormChangeState"
:question-form-change-num="questionFormChangeNum"
:is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
/>
</div> </div>
</div> </div>
@ -438,6 +508,21 @@
<Manuals :trial-id="trialId" /> <Manuals :trial-id="trialId" />
</div> </div>
</el-dialog> </el-dialog>
<!-- 签名框 -->
<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;user-select: text !important;">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
</div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
@ -466,6 +551,12 @@ import WL from './WL'
import Others from './Others' import Others from './Others'
import DicomEvent from './DicomEvent' import DicomEvent from './DicomEvent'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import SignForm from '@/views/trials/components/newSignForm'
import { getCriterionReadingInfo, verifyVisitTaskQuestions, submitDicomVisitTask } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import const_ from '@/const/sign-code'
import { changeURLStatic } from '@/utils/history.js'
export default { export default {
name: 'DicomViewer', name: 'DicomViewer',
components: { components: {
@ -479,7 +570,8 @@ export default {
RecistQuestionList, RecistQuestionList,
PCWGQuestionList, PCWGQuestionList,
RecistBMQuestionList, RecistBMQuestionList,
IRecistQuestionList IRecistQuestionList,
SignForm
}, },
props: { props: {
isShow: { isShow: {
@ -499,13 +591,17 @@ export default {
required: true required: true
}, },
isReadingTaskViewInOrder: { isReadingTaskViewInOrder: {
type: Boolean, type: Number,
required: true required: true
}, },
isExistsManual: { isExistsManual: {
type: Boolean, type: Boolean,
required: true required: true
}, },
iseCRFShowInDicomReading: {
type: Boolean,
required: true
},
questionFormChangeState: { questionFormChangeState: {
type: Boolean, type: Boolean,
default() { default() {
@ -603,7 +699,13 @@ export default {
digitPlaces: 2, digitPlaces: 2,
activeCanvasWW: null, activeCanvasWW: null,
activeCanvasWC: null, activeCanvasWC: null,
activeTaskInfo: {} activeTaskInfo: {},
clipPlaying: false,
fps: 15,
taskId: '',
signVisible: false,
signCode: null,
currentUser: zzSessionStorage.getItem('userName')
} }
}, },
@ -642,22 +744,34 @@ export default {
activeSeries: { activeSeries: {
immediate: true, immediate: true,
handler(v) { handler(v) {
if (v && v.isCurrentTask && this.studyList.length === 0) { // console.log('activeSeries', v)
this.activeTaskInfo.taskName = v.taskBlindName // if (v && v.isCurrentTask && this.studyList.length === 0) {
this.activeTaskInfo.visitTaskId = v.visitTaskId // this.activeTaskInfo.taskName = v.taskBlindName
const i = this.visitTaskList.findIndex(i => i.VisitTaskId === v.visitTaskId) // this.activeTaskInfo.visitTaskId = v.visitTaskId
if (i < 0) return // const i = this.visitTaskList.findIndex(i => i.VisitTaskId === v.visitTaskId)
this.activeTaskInfo.visitTaskIndex = i // if (i < 0) return
var studyList = this.visitTaskList[i].StudyList || [] // this.activeTaskInfo.visitTaskIndex = i
studyList = studyList.filter(i => !i.IsCriticalSequence && i.Modalities.indexOf('CT') !== -1 && i.Modalities.indexOf('PT') !== -1) // var studyList = this.visitTaskList[i].StudyList || []
if (studyList.length === 0) return // studyList = studyList.filter(i => !i.IsCriticalSequence && i.Modalities.indexOf('CT') !== -1 && i.Modalities.indexOf('PT') !== -1)
this.studyList = studyList // if (studyList.length === 0) return
} // this.studyList = studyList
// }
} }
}, },
imageQualityIssues: { imageQualityIssues: {
immediate: true, immediate: true,
handler(v) {} handler(v) {}
},
currentDicomCanvasIndex: {
immediate: true,
handler(v) {
if (this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`] && this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0]) {
this.clipPlaying = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toolState.clipPlaying
} else {
this.clipPlaying = false
this.fps = 15
}
}
} }
}, },
@ -675,6 +789,10 @@ export default {
this.measuredTools = [{ toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }] this.measuredTools = [{ toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }]
} else if (this.CriterionType === 17) { } else if (this.CriterionType === 17) {
this.measuredTools = [{ toolName: 'Length', text: this.$t('trials:reading:button:length'), icon: 'length', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }, { toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }] this.measuredTools = [{ toolName: 'Length', text: this.$t('trials:reading:button:length'), icon: 'length', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }, { toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }]
} else if (this.CriterionType === 19) {
this.measuredTools = []
} else if (this.CriterionType === 20) {
this.measuredTools = []
} }
this.rotateList[0] = '1' this.rotateList[0] = '1'
this.colorList[0] = '' this.colorList[0] = ''
@ -717,6 +835,7 @@ export default {
) )
var canvas = await html2canvas(divForDownloadViewport) var canvas = await html2canvas(divForDownloadViewport)
var base64Str = canvas.toDataURL('image/png', 1) var base64Str = canvas.toDataURL('image/png', 1)
console.log('getScreenshots')
callback(base64Str) callback(base64Str)
}, 50) }, 50)
} }
@ -772,6 +891,10 @@ export default {
if (!this.petctWindow) return if (!this.petctWindow) return
this.petctWindow.postMessage({ type: 'readingPageUpdate', data: data }, window.location) this.petctWindow.postMessage({ type: 'readingPageUpdate', data: data }, window.location)
}) })
DicomEvent.$on('resetPage', () => {
if (!this.petctWindow) return
this.petctWindow.postMessage({ type: 'resetPage' }, window.location)
})
DicomEvent.$on('setReadingState', (data) => { DicomEvent.$on('setReadingState', (data) => {
if (!this.petctWindow) return if (!this.petctWindow) return
this.petctWindow.postMessage({ type: 'setReadingState', data: data }, window.location) this.petctWindow.postMessage({ type: 'setReadingState', data: data }, window.location)
@ -809,28 +932,30 @@ export default {
}) })
}, },
methods: { methods: {
getWwcTpl() { async getWwcTpl() {
const loading = this.$loading({ fullscreen: true }) // const loading = this.$loading({ fullscreen: true })
getUserWLTemplateList().then(res => { try {
const res = await getUserWLTemplateList()
this.customWwcTpl = [] this.customWwcTpl = []
res.Result.map(i => { res.Result.map(i => {
this.customWwcTpl.push({ label: i.TemplateName, wc: i.WL, ww: i.WW }) this.customWwcTpl.push({ label: i.TemplateName, wc: i.WL, ww: i.WW })
}) })
this.wwwcArr = [...this.defaultWwwc, ...this.customWwcTpl] this.wwwcArr = [...this.defaultWwwc, ...this.customWwcTpl]
loading.close() } catch (e) {
}).catch(() => { loading.close() }) console.log(e)
}
}, },
getHotKeys() { async getHotKeys() {
const loading = this.$loading({ fullscreen: true }) // const loading = this.$loading({ fullscreen: true })
getDoctorShortcutKey({ imageToolType: 0 }).then(res => { try {
const res = await getDoctorShortcutKey({ imageToolType: 0 })
res.Result.map(item => { res.Result.map(item => {
this.hotKeyList.push({ id: item.Id, altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code, text: item.Text, shortcutKeyEnum: item.ShortcutKeyEnum }) this.hotKeyList.push({ id: item.Id, altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code, text: item.Text, shortcutKeyEnum: item.ShortcutKeyEnum })
}) })
this.bindHotKey() this.bindHotKey()
loading.close() } catch (e) {
}).catch(() => { console.log(e)
loading.close() }
})
}, },
resetHotkeyList(arr) { resetHotkeyList(arr) {
this.hotKeyList = [] this.hotKeyList = []
@ -853,7 +978,7 @@ export default {
var container = this.$refs['container'] var container = this.$refs['container']
// window.addEventListener // window.addEventListener
container.addEventListener('keydown', event => { container.addEventListener('keydown', event => {
console.log(event) // console.log(event)
event.preventDefault() event.preventDefault()
var idx = this.hotKeyList.findIndex(i => i.code === event.code && i.ctrlKey === event.ctrlKey && i.shiftKey === event.shiftKey && i.altKey === event.altKey) var idx = this.hotKeyList.findIndex(i => i.code === event.code && i.ctrlKey === event.ctrlKey && i.shiftKey === event.shiftKey && i.altKey === event.altKey)
@ -992,7 +1117,8 @@ export default {
store.dispatch('reading/setActiveSeries', series) store.dispatch('reading/setActiveSeries', series)
store.dispatch('reading/setLastCanvasTaskId', series.visitTaskId) store.dispatch('reading/setLastCanvasTaskId', series.visitTaskId)
} }
this.$refs[`dicomCanvas${index}`][0].loadImageStack(series) const s = Object.assign({}, series)
this.$refs[`dicomCanvas${index}`][0].loadImageStack(s)
if (this.activeTool) { if (this.activeTool) {
if (series.isCurrentTask && series.readingTaskState < 2) { if (series.isCurrentTask && series.readingTaskState < 2) {
@ -1010,10 +1136,13 @@ export default {
}) })
}, },
loadImageStack(dicomSeries) { loadImageStack(dicomSeries) {
this.clipPlaying = false
this.fps = 15
this.canvasObj[this.currentDicomCanvasIndex] = dicomSeries this.canvasObj[this.currentDicomCanvasIndex] = dicomSeries
this.$nextTick(() => { this.$nextTick(() => {
this.activeSeries = dicomSeries this.activeSeries = dicomSeries
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].loadImageStack(dicomSeries).then(res => { const s = Object.assign({}, dicomSeries)
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].loadImageStack(s).then(res => {
if (this.activeTool) { if (this.activeTool) {
if (dicomSeries.isCurrentTask && dicomSeries.readingTaskState < 2) { if (dicomSeries.isCurrentTask && dicomSeries.readingTaskState < 2) {
this.$nextTick(() => { this.$nextTick(() => {
@ -1074,7 +1203,8 @@ export default {
// } // }
this.$nextTick(() => { this.$nextTick(() => {
this.activeSeries = dicomSeries this.activeSeries = dicomSeries
this.$refs[`dicomCanvas${canvasIndex}`][0].loadImageStack(dicomSeries) const s = Object.assign({}, dicomSeries)
this.$refs[`dicomCanvas${canvasIndex}`][0].loadImageStack(s)
store.dispatch('reading/setActiveSeries', dicomSeries) store.dispatch('reading/setActiveSeries', dicomSeries)
if (this.currentDicomCanvasIndex === this.maxCanvas - 1) { if (this.currentDicomCanvasIndex === this.maxCanvas - 1) {
@ -1149,7 +1279,8 @@ export default {
var promiseArr = [] var promiseArr = []
for (let i = 0; i < this.maxCanvas && i < seriesStack.length; i++) { for (let i = 0; i < this.maxCanvas && i < seriesStack.length; i++) {
this.canvasObj[i] = seriesStack[i] this.canvasObj[i] = seriesStack[i]
promiseArr.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(seriesStack[i])) const s = Object.assign({}, seriesStack[i])
promiseArr.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(s))
} }
Promise.all(promiseArr).then(() => { Promise.all(promiseArr).then(() => {
// this.activateDicomCanvas(this.currentDicomCanvasIndex) // this.activateDicomCanvas(this.currentDicomCanvasIndex)
@ -1181,7 +1312,7 @@ export default {
var firstAddSeries = null var firstAddSeries = null
var currentAddSeries = null var currentAddSeries = null
if (this.isReadingTaskViewInOrder) { if (this.isReadingTaskViewInOrder === 1) {
// //
// 访 // 访
var firstAddVisitTaskId = null var firstAddVisitTaskId = null
@ -1252,12 +1383,14 @@ export default {
for (let i = 0; i < this.maxCanvas; i++) { for (let i = 0; i < this.maxCanvas; i++) {
if (i === this.maxCanvas - 1) { if (i === this.maxCanvas - 1) {
loadImagePromises.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(currentAddSeries)) const s = Object.assign({}, currentAddSeries)
loadImagePromises.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(s))
this.currentDicomCanvasIndex = i this.currentDicomCanvasIndex = i
this.activeSeries = currentAddSeries this.activeSeries = currentAddSeries
store.dispatch('reading/setActiveSeries', currentAddSeries) store.dispatch('reading/setActiveSeries', currentAddSeries)
} else { } else {
loadImagePromises.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(firstAddSeries)) const s = Object.assign({}, firstAddSeries)
loadImagePromises.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(s))
} }
} }
Promise.all(loadImagePromises) Promise.all(loadImagePromises)
@ -1331,7 +1464,9 @@ export default {
var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId) var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId)
if (seriesIdx > -1) { if (seriesIdx > -1) {
var series = studyList[studyIdx].SeriesList[seriesIdx] var series = studyList[studyIdx].SeriesList[seriesIdx]
var instanceIdx = series.instanceList.findIndex(imageId => !!~imageId.indexOf(instanceId)) const frame = this.visitTaskList[index].MeasureData[idx].MeasureData.frame
const filterStr = series.isExistMutiFrames ? `frame=${frame}&instanceId=${instanceId}` : `instanceId=${instanceId}`
var instanceIdx = series.imageIds.findIndex(imageId => imageId.includes(filterStr))
if (instanceIdx > -1) { if (instanceIdx > -1) {
series.imageIdIndex = instanceIdx series.imageIdIndex = instanceIdx
seriesInfo = series seriesInfo = series
@ -1687,6 +1822,31 @@ export default {
} }
this.activeTool = toolName this.activeTool = toolName
}, },
//
scrollPage(i) {
//
const isLoaded = this.getSeriesLoadStatus()
if (!isLoaded) return
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].scrollPage(i)
},
// /
toggleClipPlay(isPlay) {
//
const isLoaded = this.getSeriesLoadStatus()
if (!isLoaded) return
this.clipPlaying = isPlay
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setFps(this.fps)
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleClipPlay(isPlay)
},
getSeriesLoadStatus() {
const index = this.visitTaskList.findIndex(i => i.VisitTaskId === this.activeSeries.visitTaskId)
if (index === -1) return false
const loadStatus = this.visitTaskList[index].StudyList[this.activeSeries.studyIndex].SeriesList[this.activeSeries.seriesIndex].loadStatus
return loadStatus
},
setDicomCanvasfps(event) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setFps(event.target.value)
},
// //
setMeasureData(data) { setMeasureData(data) {
this.$refs['measurementList'].setMeasuredData(data) this.$refs['measurementList'].setMeasuredData(data)
@ -1779,7 +1939,109 @@ export default {
previewManuals() { previewManuals() {
this.isFullscreen = false this.isFullscreen = false
this.manualsDialog.visible = true this.manualsDialog.visible = true
} },
async skipTask() {
//
const confirm = await this.$confirm(
this.$t('trials:readingReport:message:skipConfirm'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
// const loading = this.$loading({ fullscreen: true })
try {
const idx = this.visitTaskList.findIndex(i => i.IsCurrentTask)
if (idx > -1) {
var visitTaskId = this.visitTaskList[idx].VisitTaskId
const res = await setSkipReadingCache({ visitTaskId: visitTaskId })
if (res.IsSuccess) {
window.location.reload()
}
}
// loading.close()
} catch (e) {
// loading.close()
console.log(e)
}
},
async submit() {
const loading = this.$loading({ fullscreen: true })
try {
const idx = this.visitTaskList.findIndex(i => i.IsCurrentTask)
if (idx > -1) {
var visitTaskId = this.visitTaskList[idx].VisitTaskId
this.taskId = visitTaskId
await verifyVisitTaskQuestions({ visitTaskId: visitTaskId })
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}
loading.close()
} catch (e) {
loading.close()
}
},
//
closeSignDialog(isSign, signInfo) {
if (isSign) {
this.signConfirm(signInfo)
} else {
this.signVisible = false
}
},
//
async signConfirm(signInfo) {
this.loading = true
try {
var params = {
data: {
visitTaskId: this.taskId
},
signInfo: signInfo
}
const res = await submitDicomVisitTask(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) {
this.$refs['signForm'].btnLoading = false
}
this.signVisible = false
//
this.readingTaskState = 2
await store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
await store.dispatch('reading/setCurrentReadingTaskState', 2)
const res = await getAutoCutNextTask()
var isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
window.location.reload()
} else {
// ''
this.$confirm(this.$t('trials:readingReport:message:msg4'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
window.location.reload()
})
.catch(action => {
changeURLStatic('visitTaskId', this.visitTaskId)
})
}
window.opener.postMessage('refreshTaskList', window.location)
}
this.loading = false
} catch (e) {
this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false
}
}
},
} }
} }
</script> </script>
@ -1832,7 +2094,7 @@ export default {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-right: 30px; margin-right: 20px;
.icon{ .icon{
padding: 5px; padding: 5px;
border: 1px solid #404040; border: 1px solid #404040;
@ -1851,6 +2113,39 @@ export default {
display: none; display: none;
} }
} }
.tool-frame{
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
margin-right: 20px;
border: 1px solid #404040;
.icon{
padding: 5px;
border-right: 1px solid #404040;
cursor: pointer;
text-align: center;
.svg-icon{
font-size:20px;
color:#ddd;
}
}
.select-wrapper{
width: 60px;
background-color: black;
color: #ddd;
border: none;
font-size: 13px;
outline: none;
}
.text{
position: relative;
font-size: 12px;
margin-top: 5px;
color: #d0d0d0;
display: none;
}
}
.tool_active{ .tool_active{
background-color: #607d8b; background-color: #607d8b;
} }
@ -1963,9 +2258,22 @@ export default {
.form-container{ .form-container{
// box-sizing: border-box; // box-sizing: border-box;
width: 350px; width: 350px;
height: 100%; // height: 100vh;
border: 1px solid #727272; border: 1px solid #727272;
// overflow-y: auto; // position: relative;
display: flex;
flex-direction: column;
}
.form-wrapper{
flex-grow: 1;
height: 0;
overflow: hidden;
}
.form-footer{
background: #000;
padding: 10px 0;
text-align: center;
} }
.viewer-container{ .viewer-container{
box-sizing: border-box; box-sizing: border-box;

View File

@ -56,22 +56,25 @@ export default {
this.getHotkeys() this.getHotkeys()
}, },
methods: { methods: {
getHotkeys(isReset = false) { async getHotkeys(isReset = false) {
this.loading = true this.loading = true
this.hotKeyList = [] this.hotKeyList = []
getDoctorShortcutKey({ imageToolType: this.readingTool }).then(res => { try {
res.Result.map(item => { const res = await getDoctorShortcutKey({ imageToolType: this.readingTool })
this.hotKeyList.push({ id: item.Id, keys: { controlKey: { altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code }, text: item.Text }, label: item.ShortcutKeyEnum }) if (res.IsSuccess) {
}) res.Result.map(item => {
if (isReset) { this.hotKeyList.push({ id: item.Id, keys: { controlKey: { altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code }, text: item.Text }, label: item.ShortcutKeyEnum })
this.$emit('reset', this.hotKeyList) })
if (isReset) {
this.$emit('reset', this.hotKeyList)
}
} }
this.loading = false this.loading = false
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
}) }
}, },
handleSave() { async handleSave() {
var params = { var params = {
imageToolType: this.readingTool, imageToolType: this.readingTool,
shortcutKeyList: [] shortcutKeyList: []
@ -86,17 +89,15 @@ export default {
emptyLabel = item.label emptyLabel = item.label
break break
} else { } else {
shortcutKeyList.push( shortcutKeyList.push({
{ shortcutKeyEnum: item.label,
shortcutKeyEnum: item.label, keyboardkey: item.keys.controlKey.key,
keyboardkey: item.keys.controlKey.key, code: item.keys.controlKey.code,
code: item.keys.controlKey.code, text: item.keys.text,
text: item.keys.text, altKey: item.keys.controlKey.altKey,
altKey: item.keys.controlKey.altKey, ctrlKey: item.keys.controlKey.ctrlKey,
ctrlKey: item.keys.controlKey.ctrlKey, shiftKey: item.keys.controlKey.shiftKey,
shiftKey: item.keys.controlKey.shiftKey, metaKey: item.keys.controlKey.metaKey })
metaKey: item.keys.controlKey.metaKey }
)
} }
} }
if (isExistEmptyText) { if (isExistEmptyText) {
@ -112,43 +113,40 @@ export default {
}) })
} else { } else {
this.loading = true this.loading = true
// this.hotKeyList.map(item => {
// shortcutKeyList.push(
// {
// shortcutKeyEnum: item.label,
// keyboardkey: item.keys.controlKey.key,
// code: item.keys.controlKey.code,
// text: item.keys.text,
// altKey: item.keys.controlKey.altKey,
// ctrlKey: item.keys.controlKey.ctrlKey,
// shiftKey: item.keys.controlKey.shiftKey,
// metaKey: item.keys.controlKey.metaKey }
// )
// })
params.shortcutKeyList = shortcutKeyList params.shortcutKeyList = shortcutKeyList
setShortcutKey(params).then(res => { try {
this.$emit('reset', this.hotKeyList) const res = await setShortcutKey(params)
// this.$emit('close') if (res.IsSuccess) {
this.$emit('reset', this.hotKeyList)
}
this.loading = false this.loading = false
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
}) }
} }
}, },
handleReset() { async handleReset() {
// '' // ''
this.$confirm(this.$t('trials:hotkeys:message:confirmReset'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:hotkeys:message:confirmReset'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(() => { distinguishCancelAndClose: true
this.loading = true }
restoreDefaultShortcutKey({ imageToolType: this.readingTool }).then(res => { )
this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // '' if (confirm !== 'confirm') return
this.getHotkeys(true)
}).catch(() => { this.loading = false }) this.loading = true
}) try {
.catch(action => {}) const res = await restoreDefaultShortcutKey({ imageToolType: this.readingTool })
if (res.IsSuccess) {
this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // ''
this.getHotkeys(true)
}
this.loading = false
} catch (e) {
this.loading = false
}
}, },
handleHotkeyVerify(hotkey) { handleHotkeyVerify(hotkey) {
for (const item of this.hotKeyList) { for (const item of this.hotKeyList) {

View File

@ -1,11 +1,21 @@
<template> <template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}"> <div class="measurement-wrapper">
<div class="container" :style="{'height':height+'px'}"> <div class="container">
<h3 v-if="isReadingShowSubjectInfo" style="color: #ddd;padding: 5px 0px;margin: 0;"> <div class="basic-info">
<span v-if="subjectCode">{{ subjectCode }} </span> <h3 v-if="isReadingShowSubjectInfo">
<span style="margin-left:5px;">{{ taskBlindName }}</span> <span v-if="subjectCode">{{ subjectCode }} </span>
</h3> <span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<div v-if="readingTaskState < 2">
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
<i
class="el-icon-refresh-left"
@click="resetMeasuredData"
/>
</el-tooltip>
</div>
</div>
<!-- 非测量问题 --> <!-- 非测量问题 -->
<div class="lesions"> <div class="lesions">
<Questions <Questions
@ -29,7 +39,7 @@
class="title" class="title"
> >
{{ item.QuestionName }} {{ item.QuestionName }}
<span v-if="isFirstChangeTask && item.TableQuestions.Answers.length > 0" style="color:red;font-size: 12px;">()</span> <span v-if="isFirstChangeTask && item.TableQuestions.Answers.length > 0" style="color:red;font-size: 12px;">{{ $t("trials:reading:dicom:IRecist:reevaluate") }}</span>
</div> </div>
<div v-else class="title"> <div v-else class="title">
{{ item.QuestionName }} {{ item.QuestionName }}
@ -157,6 +167,7 @@
</template> </template>
<script> <script>
import { splitLesion } from '@/api/trials' import { splitLesion } from '@/api/trials'
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent' import DicomEvent from './../DicomEvent'
import store from '@/store' import store from '@/store'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
@ -192,7 +203,6 @@ export default {
}, },
data() { data() {
return { return {
height: window.innerHeight - 140,
questions: [], questions: [],
activeName: '', activeName: '',
activeItem: { activeItem: {
@ -237,7 +247,8 @@ export default {
} }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
window.addEventListener('message', this.receiveMsg) window.addEventListener('message', this.receiveMsg)
this.criterionType = parseInt(localStorage.getItem('CriterionType')) this.criterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => { DicomEvent.$on('setCollapseActive', measureData => {
@ -257,8 +268,6 @@ export default {
DicomEvent.$on('split', measureData => { DicomEvent.$on('split', measureData => {
this.handleSplit(measureData.RowId, measureData.QuestionId) this.handleSplit(measureData.RowId, measureData.QuestionId)
}) })
window.addEventListener('resize', this.setHeight)
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('setCollapseActive') DicomEvent.$off('setCollapseActive')
@ -445,9 +454,6 @@ export default {
} catch (e) { console.log(e) } } catch (e) { console.log(e) }
}) })
}, },
setHeight() {
this.height = window.innerHeight - 140
},
getQuestionAnswer(questions, questionMark, answers) { getQuestionAnswer(questions, questionMark, answers) {
var idx = questions.findIndex(i => i.QuestionMark === questionMark) var idx = questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) { if (idx > -1) {
@ -577,15 +583,15 @@ export default {
} }
} }
}, },
split(rowId, questionId) { async split(rowId, questionId) {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
var params = { try {
visitTaskId: this.visitTaskId, var params = {
questionId: questionId, visitTaskId: this.visitTaskId,
rowId: rowId questionId: questionId,
} rowId: rowId
splitLesion(params).then(async res => { }
loading.close() await splitLesion(params)
await this.getReadingQuestionAndAnswer() await this.getReadingQuestionAndAnswer()
this.$nextTick(() => { this.$nextTick(() => {
this.tableQuestions.forEach(item => { this.tableQuestions.forEach(item => {
@ -595,7 +601,11 @@ export default {
}) })
}) })
}) })
}) loading.close()
} catch (e) {
loading.close()
console.log(e)
}
}, },
isCanActiveTool(toolName) { isCanActiveTool(toolName) {
console.log('isCanActiveTool') console.log('isCanActiveTool')
@ -907,7 +917,6 @@ export default {
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: questionsObj.measureData, questionId: questionsObj.questionId, rowIndex: questionsObj.rowIndex }) await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: questionsObj.measureData, questionId: questionsObj.questionId, rowIndex: questionsObj.rowIndex })
questionsObj.measureData.data.remark = lesionMark questionsObj.measureData.data.remark = lesionMark
lesionObj.MarkTool = questionsObj.measureData.type
lesionObj.MeasureData = JSON.stringify(questionsObj.measureData) lesionObj.MeasureData = JSON.stringify(questionsObj.measureData)
} }
@ -1068,6 +1077,39 @@ export default {
getECRFQuestions(obj) { getECRFQuestions(obj) {
this.$refs['ecrf'].getQuestions(obj.visitTaskId) this.$refs['ecrf'].getQuestions(obj.visitTaskId)
}, },
async resetMeasuredData() {
const confirm = await this.$confirm(
this.$t('trials:dicomReading:message:confirmReset1'),
this.$t('trials:dicomReading:message:confirmReset2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const loading = this.$loading({ fullscreen: true })
try {
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
//
this.activeName = ''
this.activeItem.activeRowIndex = null
this.activeItem.activeCollapseId = null
await this.getReadingQuestionAndAnswer(this.visitTaskId)
const triald = this.$router.currentRoute.query.trialId
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
DicomEvent.$emit('getMeasureData')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('refreshStudyListMeasureData')
}
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
receiveMsg(event) { receiveMsg(event) {
if (event.data.type === 'isCanActiveNoneDicomTool') { if (event.data.type === 'isCanActiveNoneDicomTool') {
this.getUnSaveTarget() this.getUnSaveTarget()
@ -1135,11 +1177,28 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.measurement-wrapper{ .measurement-wrapper{
height: 100%;
overflow-y: auto; overflow-y: auto;
// overflow: hidden; // overflow: hidden;
.container{ .container{
padding: 10px; padding: 10px;
.basic-info{
display: flex;
justify-content: space-between;
align-items: center;
h3{
color: #ddd;
padding: 5px 0px;
margin: 0;
}
i{
color: #fff;
font-size: 22px;
font-weight: bold;
cursor: pointer;
}
}
} }
.title{ .title{
padding: 5px; padding: 5px;

View File

@ -21,7 +21,7 @@
</div> </div>
<div class="right-wrapper"> <div class="right-wrapper">
<div class="right-content"> <div class="right-content">
<iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" /> <iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" />
</div> </div>
</div> </div>
</div> </div>
@ -44,26 +44,31 @@ export default {
}, },
fileList: [], fileList: [],
loading: false, loading: false,
currentUser: zzSessionStorage.getItem('userName') currentUser: zzSessionStorage.getItem('userName'),
COMPANY:process.env.VUE_APP_COMPANY_NAME
} }
}, },
mounted() { mounted() {
this.getList() this.getList()
}, },
methods: { methods: {
getList() { async getList() {
this.loading = true this.loading = true
var param = { try {
trialId: this.trialId var param = {
} trialId: this.trialId
getManualList(param).then(res => { }
this.fileList = res.Result const res = await getManualList(param)
if (res.IsSuccess) {
if (this.fileList.length > 0) { this.fileList = res.Result
this.preview(this.fileList[0]) if (this.fileList.length > 0) {
this.preview(this.fileList[0])
}
} }
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
preview(file) { preview(file) {
this.$set(this.selected, 'filePath', file.Path) this.$set(this.selected, 'filePath', file.Path)

View File

@ -76,9 +76,10 @@
</div> </div>
</template> </template>
<script> <script>
import { getTableAnswerRowInfoList } from '@/api/trials'
import { on, off } from 'element-ui/src/utils/dom' import { on, off } from 'element-ui/src/utils/dom'
import { rafThrottle, isFirefox } from 'element-ui/src/utils/util' import { rafThrottle, isFirefox } from 'element-ui/src/utils/util'
import store from '@/store' // import store from '@/store'
const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel' const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel'
var ctx = '' // var ctx = '' //
export default { export default {
@ -223,15 +224,26 @@ export default {
return new Promise(async resolve => { return new Promise(async resolve => {
this.visitTaskId = this.$router.currentRoute.query.visitTaskId this.visitTaskId = this.$router.currentRoute.query.visitTaskId
this.canvasData = [] this.canvasData = []
await store.dispatch('reading/getMeasuredData', this.visitTaskId) const res = await getTableAnswerRowInfoList(this.visitTaskId)
await store.dispatch('reading/getNoneDicomMeasuredData', this.visitTaskId).then(res => { res.Result.forEach(el => {
res.forEach(item => { if (!el.IsDicomReading) {
if (item && item.MeasureData) { if (el.MeasureData) {
this.canvasData.push(item.MeasureData) el.MeasureData = JSON.parse(el.MeasureData)
el.MeasureData.data.remark = el.OrderMarkName
this.canvasData.push(el.MeasureData)
} }
}) }
sessionStorage.setItem('measureData', this.canvasData)
}) })
sessionStorage.setItem('measureData', this.canvasData)
// await store.dispatch('reading/getMeasuredData', this.visitTaskId)
// await store.dispatch('reading/getNoneDicomMeasuredData', this.visitTaskId).then(res => {
// res.forEach(item => {
// if (item && item.MeasureData) {
// this.canvasData.push(item.MeasureData)
// }
// })
// sessionStorage.setItem('measureData', this.canvasData)
// })
resolve() resolve()
}) })
}, },

View File

@ -31,7 +31,7 @@
/> />
<div ref="imagesWrapper" class="images"> <div ref="imagesWrapper" class="images">
<div v-if="noData" class="empty-text"> <div v-if="noData" class="empty-text">
<slot name="empty">暂无数据</slot> <slot name="empty">{{ $t('trial:reading:noneDicoms:noData') }}</slot>
</div> </div>
<div v-show="!noData" class="items" :style="itemsStyle"> <div v-show="!noData" class="items" :style="itemsStyle">
<div <div

View File

@ -36,27 +36,31 @@ export default {
this.initForm() this.initForm()
}, },
methods: { methods: {
initForm() { async initForm() {
this.loading = true this.loading = true
getAutoCutNextTask().then(async res => { try {
this.form.AutoCutNextTask = res.Result.AutoCutNextTask const res = await getAutoCutNextTask()
this.loading = false if (res.IsSuccess) {
}).catch(() => { this.form.AutoCutNextTask = res.Result.AutoCutNextTask
this.loading = false
})
},
handleSave() {
this.$refs.otherForm.validate((valid) => {
if (valid) {
this.loading = true
setAutoCutNextTask(this.form).then((res) => {
this.loading = false
this.$message.success(this.$t('common:message:savedSuccessfully'))
}).catch(() => {
this.loading = false
})
} }
}) this.loading = false
} catch (e) {
this.loading = false
}
},
async handleSave() {
const valid = await this.$refs.otherForm.validate()
if (!valid) return
this.loading = true
try {
const res = await setAutoCutNextTask(this.form)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
this.loading = false
} catch (e) {
this.loading = false
}
} }
} }
} }

View File

@ -69,7 +69,7 @@
@focus="focusQs = {...qs}" @focus="focusQs = {...qs}"
@change="((val)=>{formItemChange(val, qs)})" @change="((val)=>{formItemChange(val, qs)})"
> >
<template v-if="qs.Unit" slot="append"> <template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(qs.Unit)) }} {{ $fd('ValueUnit', parseInt(qs.Unit)) }}
</template> </template>
</el-input> </el-input>
@ -296,7 +296,7 @@ export default {
} else if (!reg.test(value) || (parseInt(value) > 99 || parseInt(value) <= 0)) { } else if (!reg.test(value) || (parseInt(value) > 99 || parseInt(value) <= 0)) {
callback(new Error(this.$t('trials:readingPGWC:warnning:msg1'))) callback(new Error(this.$t('trials:readingPGWC:warnning:msg1')))
} else if (parseInt(value) > parseInt(this.questionForm.BaseLineLesionNumber)) { } else if (parseInt(value) > parseInt(this.questionForm.BaseLineLesionNumber)) {
callback(new Error(this.$t('trials:reading:pcwg:msg6') + this.questionForm.BaseLineLesionNumber + this.$fd('ValueUnit', 3))) callback(new Error(this.$t('trials:reading:pcwg:msg6') + this.questionForm.BaseLineLesionNumber))
} else { } else {
callback() callback()
} }
@ -484,8 +484,8 @@ export default {
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionState = Number(this.getQuestionVal(7)) const lesionState = this.getQuestionVal(7)
const lesionNum = Number(this.getQuestionVal(11)) const lesionNum = this.getQuestionVal(11)
this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionNum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionNum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
}, },
@ -547,8 +547,8 @@ export default {
this.$set(this.questionForm, 'MeasureData', measureData) this.$set(this.questionForm, 'MeasureData', measureData)
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionState = Number(this.getQuestionVal(7)) const lesionState = this.getQuestionVal(7)
const lesionNum = Number(this.getQuestionVal(11)) const lesionNum = this.getQuestionVal(11)
this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, lesionNum, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, lesionNum, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
this.toolType = measureData.type this.toolType = measureData.type
@ -572,10 +572,15 @@ export default {
} }
}, },
getQuestionVal(questionMark) { getQuestionVal(questionMark) {
var idx = this.questions.findIndex(i => i.QuestionMark === questionMark) const idx = this.questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) { if (idx > -1) {
var questionId = this.questions[idx].Id const questionId = this.questions[idx].Id
return this.questionForm[questionId] const answer = this.questionForm[questionId]
if (isNaN(parseFloat(answer))) {
return answer
} else {
return parseFloat(answer)
}
} else { } else {
return '' return ''
} }
@ -619,82 +624,83 @@ export default {
// Blob // Blob
return new Blob([bytesCode], { type: imgtype }) return new Blob([bytesCode], { type: imgtype })
}, },
handleSave() { async handleSave() {
this.$refs.measurementForm.validate(async valid => { const valid = await this.$refs.measurementForm.validate()
if (!valid) return if (!valid) return
var lesionState = this.getQuestionVal(7) var lesionState = this.getQuestionVal(7)
var measureData = this.questionForm.MeasureData var measureData = this.questionForm.MeasureData
// 线 // 线
if (!this.isBaseLineTask) { if (!this.isBaseLineTask) {
// 2 // 2
// 使2 // 使2
if (this.lesionType === 2 && lesionState === 2) { if (this.lesionType === 2 && lesionState === 2) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) { if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg2'), { this.$confirm(this.$t('trials:readingPGWC:warnning:msg2'), {
type: 'warning', type: 'warning',
showCancelButton: false, showCancelButton: false,
callback: action => {} callback: action => {}
}) })
loading.close() loading.close()
return return
}
}
// 3
// 使2
if (this.lesionType === 3 && lesionState === 2) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg3'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 使3
if (this.lesionType === 3 && lesionState === 3) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg4'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 使1
if (this.lesionType === 3 && lesionState === 1) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg5'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 4
if (this.lesionType === 3 && lesionState === 4) {
if (measureData) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg6'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
} }
} }
const loading = this.$loading({ fullscreen: true }) // 3
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.lesionMark, lesionType: this.lesionType, isMarked: !!measureData }, async val => { // 使2
if (this.lesionType === 3 && lesionState === 2) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg3'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 使3
if (this.lesionType === 3 && lesionState === 3) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg4'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 使1
if (this.lesionType === 3 && lesionState === 1) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg5'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 4
if (this.lesionType === 3 && lesionState === 4) {
if (measureData) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg6'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
}
const loading = this.$loading({ fullscreen: true })
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.lesionMark, lesionType: this.lesionType, isMarked: !!measureData }, async val => {
try {
var picturePath = '' var picturePath = ''
if (val && measureData) { if (val && measureData) {
var pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val) var pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
picturePath = pictureObj.isSuccess ? pictureObj.result.name : '' picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
} }
var answers = [] var answers = []
var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/) var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
@ -724,106 +730,115 @@ export default {
organInfoId: this.questionForm.OrganInfoId, organInfoId: this.questionForm.OrganInfoId,
markTool: measureData ? measureData.type : '' markTool: measureData ? measureData.type : ''
} }
submitTableQuestion(params).then(async res => {
try {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.currentMarkTool = measureData ? measureData.type : ''
this.$set(this.questionForm, 'saveTypeEnum', 2)
this.originalQuestionForm = { ...this.questionForm }
loading.close()
var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
var lesionOrgan = this.getQuestionVal(6)
this.$set(this.questionForm, 'RowId', res.Result.RowId)
const lesionPart = this.getQuestionVal(8)
const lesionState = Number(this.getQuestionVal(7))
const lesionNum = Number(this.getQuestionVal(11))
this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, saveTypeEnum: this.questionForm.saveTypeEnum, lesionState, lesionNum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) const res = await submitTableQuestion(params)
DicomEvent.$emit('getMeasureData') if (res.IsSuccess) {
this.$emit('close') this.$message.success(this.$t('common:message:savedSuccessfully'))
DicomEvent.$emit('getReportInfo', true) this.currentMarkTool = measureData ? measureData.type : ''
DicomEvent.$emit('setMeasuredToolsPassive') this.$set(this.questionForm, 'saveTypeEnum', 2)
} catch (e) { this.originalQuestionForm = { ...this.questionForm }
console.log(e)
}
}).catch(() => { loading.close() })
})
})
},
handleDeleteMeasureData() {
this.$confirm(this.$t('trials:reading:warnning:msg47'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(async() => {
if (this.questionForm.RowId) {
this.$set(this.questionForm, 'saveTypeEnum', 1)
} else {
this.$set(this.questionForm, 'saveTypeEnum', 0)
}
var remark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: remark })
DicomEvent.$emit('getMeasureData')
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionState = Number(this.getQuestionVal(7))
const lesionNum = Number(this.getQuestionVal(11))
this.$set(this.questionForm, 'MeasureData', '') var isLymphLesion = this.getQuestionVal(2)
let anwsers = null isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
if (this.answers.measureObj) { var lesionOrgan = this.getQuestionVal(6)
anwsers = Object.assign({ measureObj: '' }, this.questionForm) this.$set(this.questionForm, 'RowId', res.Result.RowId)
} else { const lesionPart = this.getQuestionVal(8)
anwsers = Object.assign({}, this.questionForm) const lesionState = this.getQuestionVal(7)
} const lesionNum = this.getQuestionVal(11)
this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, lesionNum, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: anwsers })
DicomEvent.$emit('refreshStudyListMeasureData')
})
.catch(() => {})
},
handleDelete() {
this.$confirm(this.$t('trials:reading:warnning:msg48'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(async() => {
if (this.questionForm.RowId) {
const loading = this.$loading({ fullscreen: true })
var param = {
visitTaskId: this.visitTaskId,
questionId: this.parentQsId,
rowId: this.questionForm.RowId
}
deleteReadingRowAnswer(param)
.then(async res => {
loading.close()
if (res.IsSuccess) {
if (this.questionForm.MeasureData) {
var remark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: remark })
}
DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
loading.close()
}
}).catch(() => { loading.close() })
} else {
const loading = this.$loading({ fullscreen: true })
//
if (this.questionForm.MeasureData) {
var remark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: remark })
}
this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, saveTypeEnum: this.questionForm.saveTypeEnum, lesionState, lesionNum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
DicomEvent.$emit('getMeasureData') DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId }) this.$emit('close')
DicomEvent.$emit('refreshStudyListMeasureData') DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('setMeasuredToolsPassive')
loading.close() loading.close()
} }
}) } catch (e) {
console.log(e)
loading.close()
}
})
},
async handleDeleteMeasureData() {
//
const confirm = await this.$confirm(
this.$t('trials:reading:warnning:msg47'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
if (this.questionForm.RowId) {
this.$set(this.questionForm, 'saveTypeEnum', 1)
} else {
this.$set(this.questionForm, 'saveTypeEnum', 0)
}
var remark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: remark })
DicomEvent.$emit('getMeasureData')
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionState = this.getQuestionVal(7)
const lesionNum = this.getQuestionVal(11)
this.$set(this.questionForm, 'MeasureData', '')
let anwsers = null
if (this.answers.measureObj) {
anwsers = Object.assign({ measureObj: '' }, this.questionForm)
} else {
anwsers = Object.assign({}, this.questionForm)
}
this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, lesionNum, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: anwsers })
DicomEvent.$emit('refreshStudyListMeasureData')
},
async handleDelete() {
//
const loading = this.$loading({ fullscreen: true })
try {
const confirm = await this.$confirm(
this.$t('trials:reading:warnning:msg48'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
if (this.questionForm.RowId) {
var param = {
visitTaskId: this.visitTaskId,
questionId: this.parentQsId,
rowId: this.questionForm.RowId
}
const res = await deleteReadingRowAnswer(param)
if (res.IsSuccess) {
if (this.questionForm.MeasureData) {
const remark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: remark })
}
DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
loading.close()
} else {
//
if (this.questionForm.MeasureData) {
const remark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: remark })
}
DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
DicomEvent.$emit('refreshStudyListMeasureData')
loading.close()
}
} catch (e) {
console.log(e)
loading.close()
}
}, },
handleClose() { handleClose() {
if (!this.questionForm.RowId) { if (!this.questionForm.RowId) {
@ -866,7 +881,7 @@ export default {
this.$set(this.questionForm, stateId, 4) this.$set(this.questionForm, stateId, 4)
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' const lesionState = this.getQuestionVal(7)
this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
} }
} }

View File

@ -1,11 +1,21 @@
<template> <template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}"> <div class="measurement-wrapper">
<div class="container" :style="{'height':height+'px'}"> <div class="container">
<h3 v-if="isReadingShowSubjectInfo" style="color: #ddd;padding: 5px 0px;margin: 0;"> <div class="basic-info">
<span v-if="subjectCode">{{ subjectCode }} </span> <h3 v-if="isReadingShowSubjectInfo">
<span style="margin-left:5px;">{{ taskBlindName }}</span> <span v-if="subjectCode">{{ subjectCode }} </span>
</h3> <span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<div v-if="readingTaskState < 2">
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
<i
class="el-icon-refresh-left"
@click="resetMeasuredData"
/>
</el-tooltip>
</div>
</div>
<!-- 非测量问题 --> <!-- 非测量问题 -->
<div class="lesions"> <div class="lesions">
<Questions <Questions
@ -64,7 +74,7 @@
{{ item.TableQuestions.Answers[i].lesionType }} {{ item.TableQuestions.Answers[i].lesionType }}
</div> </div>
<div v-if="!isNaN(parseInt(item.TableQuestions.Answers[i].lesionNum)) && item.LesionType === 4" style="margin-left:10px;"> <div v-if="!isNaN(parseInt(item.TableQuestions.Answers[i].lesionNum)) && item.LesionType === 4" style="margin-left:10px;">
{{ item.TableQuestions.Answers[i].lesionNum }}{{$fd('ValueUnit', 3)}} {{ item.TableQuestions.Answers[i].lesionNum }}
</div> </div>
</div> </div>
</div> </div>
@ -101,6 +111,7 @@
</template> </template>
<script> <script>
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent' import DicomEvent from './../DicomEvent'
import Questions from './../Questions' import Questions from './../Questions'
import QuestionForm from './QuestionForm' import QuestionForm from './QuestionForm'
@ -136,7 +147,6 @@ export default {
}, },
data() { data() {
return { return {
height: window.innerHeight - 140,
questions: [], questions: [],
activeName: '', activeName: '',
activeItem: { activeItem: {
@ -184,7 +194,8 @@ export default {
} }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
window.addEventListener('message', this.receiveMsg) window.addEventListener('message', this.receiveMsg)
this.criterionType = parseInt(localStorage.getItem('CriterionType')) this.criterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => { DicomEvent.$on('setCollapseActive', measureData => {
@ -200,8 +211,6 @@ export default {
callback(list) callback(list)
console.log('getAllUnSaveLesions') console.log('getAllUnSaveLesions')
}) })
window.addEventListener('resize', this.setHeight)
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('setCollapseActive') DicomEvent.$off('setCollapseActive')
@ -687,6 +696,102 @@ export default {
this.activeItem.activeRowIndex = null this.activeItem.activeRowIndex = null
this.activeItem.activeCollapseId = null this.activeItem.activeCollapseId = null
this.activeName = '' this.activeName = ''
},
getECRFQuestions(obj) {
this.$refs['ecrf'].getQuestions(obj.visitTaskId)
},
async resetMeasuredData() {
const confirm = await this.$confirm(
this.$t('trials:dicomReading:message:confirmReset1'),
this.$t('trials:dicomReading:message:confirmReset2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const loading = this.$loading({ fullscreen: true })
try {
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
//
this.activeName = ''
this.activeItem.activeRowIndex = null
this.activeItem.activeCollapseId = null
await this.getReadingQuestionAndAnswer(this.visitTaskId)
const triald = this.$router.currentRoute.query.trialId
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
DicomEvent.$emit('getMeasureData')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('refreshStudyListMeasureData')
}
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
receiveMsg(event) {
if (event.data.type === 'isCanActiveNoneDicomTool') {
this.getUnSaveTarget()
var obj = {}
if (this.unSaveTargets.length > 0) {
var rowIndex = String(this.unSaveTargets[0].rowIndex)
var questionId = this.unSaveTargets[0].questionId
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
if (rowIndex === this.activeItem.activeRowIndex && questionId === this.activeItem.activeCollapseId && !this.$refs[refName][0].questionForm.MeasureData) {
//
// questions.findIndex(i => i.QuestionMark === questionMark)
var lesionType = this.$refs[refName][0].questionForm.LesionType
if (lesionType === 0) {
// ''
obj = { isCanActiveTool: false, lesionName: '', reason: this.$t('trials:reading:warnning:msg18') }
} else {
obj = { isCanActiveTool: true, lesionName: this.$refs[refName][0].lesionMark, reason: '', toolName: event.data.toolName }
}
} else {
let msg = this.$t('trials:reading:warnning:msg5')
msg = msg.replace('xxx', this.unSaveTargets[0].lessionName)
obj = { isCanActiveTool: false, lesionName: '', reason: msg }
}
} else {
if (this.activeItem.activeCollapseId) {
//
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
const lesionType = this.$refs[refName][0].questionForm.LesionType
if (lesionType === 0) {
//
obj = { isCanActiveTool: false, lesionName: '', reason: this.$t('trials:reading:warnning:msg18') }
} else {
obj = { isCanActiveTool: true, lesionName: this.$refs[refName][0].lesionMark, reason: '', toolName: event.data.toolName }
}
} else {
// /
var qsObj = null
var lesionName = ''
if (this.isBaseLineTask) {
const idx = this.tableQuestions.findIndex(item => item.LesionType === 1)
if (idx > -1) {
qsObj = this.tableQuestions[idx]
}
} else {
const idx = this.tableQuestions.findIndex(item => item.LesionType === 2)
if (idx > -1) {
qsObj = this.tableQuestions[idx]
}
}
var maxIndex = this.getMaxRowIndex(qsObj.TableQuestions.Answers)
lesionName = `${qsObj.OrderMark}${String(maxIndex + 1).padStart(2, '0')}`
obj = { isCanActiveTool: true, lesionName: lesionName, reason: '', toolName: event.data.toolName }
}
}
DicomEvent.$emit('isCanActiveNoneDicomTool', obj)
} else if (event.data.type === 'setMeasurement') {
this.setMeasuredData(event.data.data)
}
} }
} }
} }
@ -694,11 +799,28 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.measurement-wrapper{ .measurement-wrapper{
height: 100%;
overflow-y: auto; overflow-y: auto;
// overflow: hidden; // overflow: hidden;
.container{ .container{
padding: 10px; padding: 10px;
.basic-info{
display: flex;
justify-content: space-between;
align-items: center;
h3{
color: #ddd;
padding: 5px 0px;
margin: 0;
}
i{
color: #fff;
font-size: 22px;
font-weight: bold;
cursor: pointer;
}
}
} }
.title{ .title{
padding: 5px; padding: 5px;

View File

@ -13,46 +13,86 @@
{{ language==='en'?question.GroupEnName:question.GroupName }} {{ language==='en'?question.GroupEnName:question.GroupName }}
</h4> </h4>
</div> </div>
<template v-else-if="((question.QuestionType === 56 || question.QuestionType === 57) && question.IsBaseLineTask)" />
<template v-else> <template v-else>
<el-form-item <el-form-item
v-if="(question.ShowQuestion===1 && String(questionForm[question.ParentId]) === String(question.ParentTriggerValue)) || question.ShowQuestion===0" v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
:label="`${question.QuestionName}`" :label="`${question.QuestionName}`"
:prop="question.Id" :prop="question.Id"
:rules="[ :rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary', { required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']}, message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
]" ]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']" :class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
> >
<template v-if="question.QuestionType === 60 || question.QuestionType === 61">
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
<el-input
v-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
disabled
style="width: 130px;"
>
<template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template>
</el-input>
<!-- 测量 -->
<el-button v-if="!questionForm[question.Id] && readingTaskState!== 2" size="mini" type="text" @click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation') }}</el-button>
<!-- 清除标记 -->
<el-button v-if="questionForm[question.Id]&& readingTaskState!== 2" size="mini" type="text" @click="removeAnnotation(question)">{{ $t('trials:lugano:button:clearAnnotation') }}</el-button>
<!-- 定位 -->
<el-button v-if="questionForm[question.Id]" size="mini" type="text" @click="locateAnnotation(question)">{{ $t('trials:lugano:button:locateAnnotation') }}</el-button>
<!-- 保存 -->
<el-button v-if="readingTaskState!== 2 && question.SaveEnum === 1" size="mini" type="text" @click="saveAnnotation(question)">
<!-- 未保存 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<i class="el-icon-warning" style="color:red" />
</el-tooltip>
{{ $t('common:button:save') }}
</el-button>
</div>
</template>
<template v-else-if="question.QuestionType === 48 || question.QuestionType === 51 || question.QuestionType === 52 || question.QuestionType === 53">
<el-input
v-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
disabled
>
<template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template>
</el-input>
</template>
<!-- 输入框 --> <!-- 输入框 -->
<el-input <el-input
v-if="question.Type==='input'" v-else-if="question.Type==='input'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask" :disabled="readingTaskState >= 2 || isFirstChangeTask"
@change="((val)=>{formItemChange(val, question)})"
/> />
<!-- 多行文本输入框 --> <!-- 多行文本输入框 -->
<el-input <el-input
v-if="question.Type==='textarea'" v-else-if="question.Type==='textarea'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
type="textarea" type="textarea"
:autosize="{ minRows: 2, maxRows: 4}" :autosize="{ minRows: 2, maxRows: 4}"
maxlength="500"
:disabled="readingTaskState >= 2 || isFirstChangeTask" :disabled="readingTaskState >= 2 || isFirstChangeTask"
@change="((val)=>{formItemChange(val, question)})"
/> />
<!-- 下拉框 --> <!-- 下拉框 -->
<el-select <el-select
v-if="question.Type==='select'" v-else-if="question.Type==='select'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode) || isFirstChangeTask" :disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode) || isFirstChangeTask || question.QuestionType === 50 || question.QuestionType === 55"
clearable clearable
@change="((val)=>{formItemChange(val, question)})" @change="((val)=>{formItemChange(val, question)})"
> >
<!-- <el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
/> -->
<template v-if="question.TableQuestionType === 1"> <template v-if="question.TableQuestionType === 1">
<el-option <el-option
v-for="item in organList" v-for="item in organList"
@ -61,6 +101,50 @@
:value="item[question.DataTableColumn]" :value="item[question.DataTableColumn]"
/> />
</template> </template>
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 47 && question.IsBaseLineTask">
<el-option
v-for="item of $d[question.DictionaryCode]"
v-show="item.value === 1 ||item.value === 2 || item.value === 5 "
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template>
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 47 && !question.IsBaseLineTask">
<el-option-group
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
>
<el-option
v-for="item of $d[question.DictionaryCode]"
v-show="item.value === 1 ||item.value === 3|| item.value === 4 || item.value === 5"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</el-option-group>
</template>
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 49 && question.IsBaseLineTask">
<el-option
v-for="item of $d[question.DictionaryCode]"
v-show="item.value === 1 ||item.value === 5 || item.value === 6 "
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template>
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 49 && !question.IsBaseLineTask">
<el-option-group
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
>
<el-option
v-for="item of $d[question.DictionaryCode]"
v-show="item.value === 1 ||item.value === 2 || item.value === 3 || item.value === 4 || item.value === 5"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</el-option-group>
</template>
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3"> <template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
<el-option <el-option
v-for="item of $d[question.DictionaryCode]" v-for="item of $d[question.DictionaryCode]"
@ -88,18 +172,11 @@
</el-select> </el-select>
<!-- 单选 --> <!-- 单选 -->
<el-radio-group <el-radio-group
v-if="question.Type==='radio'" v-else-if="question.Type==='radio'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask" :disabled="readingTaskState >= 2 || isFirstChangeTask"
@change="((val)=>{formItemChange(val, question)})" @change="((val)=>{formItemChange(val, question)})"
> >
<!-- <el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }}
</el-radio> -->
<template v-if="question.DictionaryCode"> <template v-if="question.DictionaryCode">
<el-radio <el-radio
v-for="item of $d[question.DictionaryCode]" v-for="item of $d[question.DictionaryCode]"
@ -121,7 +198,7 @@
</el-radio-group> </el-radio-group>
<!-- 复选框 --> <!-- 复选框 -->
<el-checkbox-group <el-checkbox-group
v-if="question.Type==='checkbox'" v-else-if="question.Type==='checkbox'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask" :disabled="readingTaskState >= 2 || isFirstChangeTask"
> >
@ -134,16 +211,45 @@
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<!-- 数值 --> <!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" --> <!-- <el-input-number
<el-input-number v-else-if="question.Type==='number'"
v-if="question.Type==='number'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask" :disabled="readingTaskState >= 2 || isFirstChangeTask"
/> :precision="2"
/> -->
<template v-else-if="question.Type==='number'">
<el-input-number
v-if="question.ValueType === 0"
v-model="questionForm[question.Id]"
:precision="0"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
/>
<el-input-number
v-else-if="question.ValueType === 3"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
/>
<el-input-number
v-else-if="question.ValueType === 1 || question.ValueType === 2"
v-model="questionForm[question.Id]"
:precision="digitPlaces"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
/>
</template>
<el-input
v-else-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
disabled
>
<template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template>
</el-input>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-else-if="question.Type==='upload'"
:action="accept" action
:accept="accept"
:limit="question.ImageCount" :limit="question.ImageCount"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
@ -158,7 +264,6 @@
<div slot="file" slot-scope="{file}"> <div slot="file" slot-scope="{file}">
<img <img
class="el-upload-list__item-thumbnail" class="el-upload-list__item-thumbnail"
crossOrigin="Anonymous"
:src="OSSclientConfig.basePath + file.url" :src="OSSclientConfig.basePath + file.url"
alt="" alt=""
> >
@ -209,7 +314,8 @@
</div> </div>
</template> </template>
<script> <script>
import { uploadReadingAnswerImage } from '@/api/trials' // import { uploadReadingAnswerImage } from '@/api/trials'
import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
export default { export default {
name: 'QuestionItem', name: 'QuestionItem',
@ -245,7 +351,8 @@ export default {
accept: '.png,.jpg,.jpeg', accept: '.png,.jpg,.jpeg',
imgVisible: false, imgVisible: false,
imageUrl: '', imageUrl: '',
urls: [] urls: [],
digitPlaces: 2
} }
}, },
computed: { computed: {
@ -271,11 +378,19 @@ export default {
}) })
} }
} }
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
}, },
methods: { methods: {
formItemChange(v, question) { formItemChange(v, question) {
// if (parseInt(v) !== 5) {
// return
// }
if (question.Childrens.length > 0) { if (question.Childrens.length > 0) {
this.resetChild(question.Childrens) this.resetChild(question.Childrens)
} else {
this.$emit('setFormItemData', { key: question.Id, val: v })
} }
}, },
resetChild(obj) { resetChild(obj) {
@ -292,7 +407,28 @@ export default {
setFormItemData(obj) { setFormItemData(obj) {
this.$emit('setFormItemData', obj) this.$emit('setFormItemData', obj)
}, },
uploadScreenshot(param) { addAnnotation(question) {
DicomEvent.$emit('addAnnotation', question)
},
saveAnnotation(question) {
DicomEvent.$emit('saveAnnotation', question)
},
removeAnnotation(question) {
DicomEvent.$emit('locateAnnotation', question)
//
this.$confirm(this.$t('trials:reading:warnning:msg47'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
DicomEvent.$emit('removeAnnotation', question)
})
.catch(() => {})
},
locateAnnotation(question) {
DicomEvent.$emit('locateAnnotation', question)
},
async uploadScreenshot(param) {
if (!this.visitTaskId) return if (!this.visitTaskId) return
const loading = this.$loading({ const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'), target: document.querySelector('.ecrf-wrapper'),
@ -301,18 +437,12 @@ export default {
text: 'Loading', text: 'Loading',
spinner: 'el-icon-loading' spinner: 'el-icon-loading'
}) })
const formData = new FormData() var file = await this.fileToBlob(param.file)
formData.append('file', param.file) const res = await this.OSSclient.put(`/${this.trialId}/ReadAttachment/${this.subjectId}/${this.visitTaskId}/${param.file.name}`, file)
uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => { this.fileList.push({ name: param.file.name, url: this.$getObjectName(res.url) })
if (res.IsSuccess) { this.urls.push(this.$getObjectName(res.url))
this.fileList.push({ url: `${res.Result.Path}` }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
this.urls.push(res.Result.Path) loading.close()
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
}
loading.close()
}).catch(() => {
loading.close()
})
}, },
handleBeforeUpload(file) { handleBeforeUpload(file) {
// //
@ -335,7 +465,7 @@ export default {
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = file.url this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true this.imgVisible = true
}, },
// //
@ -353,19 +483,25 @@ export default {
margin-bottom: 0px; margin-bottom: 0px;
} }
.disabled{ .disabled{
>>>.el-upload--picture-card { /deep/ .el-upload--picture-card {
display: none; display: none;
} }
} }
.uploadWrapper{ .uploadWrapper{
display: flex; display: flex;
flex-direction: column; flex-direction: column !important;
align-items: flex-start; align-items: flex-start;
} }
>>>.el-input.is-disabled .el-input__inner{ /deep/ .el-input.is-disabled .el-input__inner{
background-color: #646464a1; background-color: #646464a1;
} }
>>>.el-select.is-disabled .el-input__inner{ /deep/ .el-input-group__append, .el-input-group__prepend{
padding: 0 10px;
}
/deep/ .el-form-item__content {
width: 100%;
}
/deep/ .el-select.is-disabled .el-input__inner{
background-color: #646464a1; background-color: #646464a1;
} }
</style> </style>

View File

@ -19,8 +19,9 @@
/> />
<el-form-item v-if="readingTaskState < 2 && !isFirstChangeTask"> <el-form-item v-if="readingTaskState < 2 && !isFirstChangeTask">
<div style="text-align:right"> <div class="ecrf-footer">
<el-button size="mini" :disabled="!questionFormChangeState" :type="questionFormChangeState ? 'primary' : null" @click="handleSave">{{ $t('common:button:save') }}</el-button> <!-- <i v-if="groupClassify === null || groupClassify === 1" class="el-icon-question feedback-icon" @click="openFeedBackTable" /> -->
<el-button size="mini" :disabled="!questionFormChangeState || (!formChanged && groupClassify > 0)" :type="questionFormChangeState || (!formChanged && groupClassify > 0) ? 'primary' : null" @click="handleSave">{{ $t('common:button:save') }}</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -29,8 +30,9 @@
</template> </template>
<script> <script>
// import { uploadPrintscreen } from '@/api/reading'
import { saveImageQuality } from '@/api/trials' import { saveTaskQuestion, getSplenicState, getSplenicVerify, getCanChooseNotMerge, getDicomReadingQuestionAnswer } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import QuestionItem from './QuestionItem' import QuestionItem from './QuestionItem'
import DicomEvent from './DicomEvent' import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
@ -52,6 +54,18 @@ export default {
isFirstChangeTask: { isFirstChangeTask: {
type: Boolean, type: Boolean,
default: false default: false
},
groupClassify: {
type: Number,
default: null
},
isQulityIssues: {
type: Boolean,
default: true
},
questionType: {
type: Number,
default: 0
} }
}, },
data() { data() {
@ -61,7 +75,20 @@ export default {
questionForm: {}, questionForm: {},
readingTaskState: 2, readingTaskState: 2,
visitTaskId: '', visitTaskId: '',
imageQualityId: '' imageQualityId: '',
imageQualityIssuesId: '',
measurements: [],
spleenStatusId: '',
spleenLengthId: '',
spleenCommentsId: '',
spleenTopId: '',
spleenBottomId: '',
isBaseLineTask: false,
criterionType: null,
spleenInfo: null,
calculateSpleenStatus: '',
formChanged: false,
digitPlaces: 2
} }
}, },
computed: { computed: {
@ -72,7 +99,9 @@ export default {
deep: true, deep: true,
immediate: false, immediate: false,
handler(v) { handler(v) {
DicomEvent.$emit('questionFormChange', true) if (this.isQulityIssues) {
DicomEvent.$emit('questionFormChange', true)
}
} }
}, },
currentReadingTaskState: { currentReadingTaskState: {
@ -85,45 +114,120 @@ export default {
} }
}, },
mounted() { mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.criterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setReadingState', readingTaskState => { DicomEvent.$on('setReadingState', readingTaskState => {
this.readingTaskState = readingTaskState this.readingTaskState = readingTaskState
}) })
DicomEvent.$on('handleSaveQuestions', readingTaskState => { if (this.groupClassify === 3) {
this.handleSave() DicomEvent.$on('addAnnotation', obj => {
}) this.$set(obj, 'SaveEnum', 1)
this.addAnnotation(obj)
})
DicomEvent.$on('removeAnnotation', obj => {
this.$set(obj, 'SaveEnum', 0)
this.removeAnnotation(obj)
})
DicomEvent.$on('saveAnnotation', obj => {
this.saveAnnotation(obj)
})
DicomEvent.$on('locateAnnotation', obj => {
this.locateAnnotation(obj)
})
}
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('setReadingState') DicomEvent.$off('setReadingState')
if (this.groupClassify === 3) {
DicomEvent.$off('addAnnotation')
DicomEvent.$off('removeAnnotation')
DicomEvent.$off('saveAnnotation')
DicomEvent.$off('locateAnnotation')
}
}, },
methods: { methods: {
async getQuestions(visitTaskId) { async getQuestions(visitTaskId, isRefresh = false) {
var isChangeVisitTask = this.visitTaskId !== visitTaskId
this.visitTaskId = visitTaskId this.visitTaskId = visitTaskId
// const loading = this.$loading({ fullscreen: true }) // const loading = this.$loading({ fullscreen: true })
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
var qs = []
if (idx > -1) { if (idx > -1) {
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
var questions = this.visitTaskList[idx].Questions var questions = this.visitTaskList[idx].Questions
questions.map((v) => { if (this.groupClassify === 3) {
if (v.Type === 'group' && v.Childrens.length === 0) return this.measurements = []
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') { this.visitTaskList[idx].QuestionMarkInfoList.forEach(i => {
if (this.isJSONString(i.MeasureData)) {
i.MeasureData = JSON.parse(i.MeasureData)
}
this.measurements.push(i)
})
if (isChangeVisitTask || isRefresh) {
const { Result } = await getSplenicVerify(visitTaskId)
this.spleenInfo = Result
}
}
for (var i = 0; i < questions.length; i++) {
var v = questions[i]
v.IsBaseLineTask = this.isBaseLineTask
if (v.Type === 'group' && v.GroupClassify !== this.groupClassify) continue
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null) this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
if (v.QuestionType === 44) { if (v.QuestionType === 44) {
// //
this.imageQualityId = v.Id this.imageQualityId = v.Id
// store.dispatch('reading/setImageQuality', v.Answer ? v.Answer : null) // store.dispatch('reading/setImageQuality', v.Answer ? v.Answer : null)
} }
if (v.QuestionType === 67) {
//
this.imageQualityIssuesId = v.Id
}
if (v.QuestionType === 49) {
//
this.spleenStatusId = v.Id
}
if (v.QuestionType === 48) {
//
this.spleenLengthId = v.Id
}
if (v.QuestionType === 58) {
//
this.spleenCommentsId = v.Id
}
if (v.QuestionType === 60) {
//
this.spleenTopId = v.Id
}
if (v.QuestionType === 61) {
//
this.spleenBottomId = v.Id
}
} }
if (v.Childrens.length > 0) { if (v.Childrens.length > 0) {
this.setChild(v.Childrens) this.setChild(v.Childrens)
} }
}) qs.push(v)
this.questions = questions }
this.questions = Object.assign([], qs)
}
if (this.imageQualityIssuesId) {
store.dispatch('reading/setImageQualityIssues', this.questionForm[this.imageQualityIssuesId])
}
if (this.spleenLengthId && this.spleenInfo && this.readingTaskState < 2) {
this.calculateSpleenStatus = this.spleenInfo.SplenicStatus
this.setSpleenCommentDisplay()
} }
// loading.close() // loading.close()
}, },
setChild(obj) { setChild(obj) {
obj.forEach(i => { obj.forEach(i => {
i.IsBaseLineTask = this.isBaseLineTask
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) { if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null) this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
if (i.QuestionType === 44) { if (i.QuestionType === 44) {
@ -131,95 +235,673 @@ export default {
this.imageQualityId = i.Id this.imageQualityId = i.Id
// store.dispatch('reading/setImageQuality', i.Answer ? i.Answer : null) // store.dispatch('reading/setImageQuality', i.Answer ? i.Answer : null)
} }
if (i.QuestionType === 67) {
//
this.imageQualityIssuesId = i.Id
}
if (i.QuestionType === 49) {
//
this.spleenStatusId = i.Id
}
if (i.QuestionType === 48) {
//
this.spleenLengthId = i.Id
}
if (i.QuestionType === 58) {
//
this.spleenCommentsId = i.Id
}
if (i.QuestionType === 60) {
//
this.spleenTopId = i.Id
this.$set(i, 'SaveEnum', 0)
}
if (i.QuestionType === 61) {
//
this.spleenBottomId = i.Id
this.$set(i, 'SaveEnum', 0)
}
} }
if (i.Childrens && i.Childrens.length > 0) { if (i.Childrens && i.Childrens.length > 0) {
this.setChild(i.Childrens) this.setChild(i.Childrens)
} }
}) })
}, },
handleSave() { handleSave() {
this.$refs['questions'].validate((valid) => { this.$refs['questions'].validate(async(valid) => {
if (!valid) return if (!valid) return
// lugano
if (this.criterionType === 2 && this.groupClassify === 3) {
//
var existUnSave = this.checkAnnotationStatus(this.questions)
if (existUnSave) {
this.$alert(this.$t('trials:lugano:message:saveWarning'), this.$t('trials:lugano:fusionDialog:warning'))
return
}
var currentSpleenStatus = this.questionForm[this.spleenStatusId]
var currentSpleenLength = this.questionForm[this.spleenLengthId]
currentSpleenStatus = isNaN(parseInt(currentSpleenStatus)) ? null : parseInt(currentSpleenStatus)
var stIdx = this.measurements.findIndex(i => i.QuestionType === 60)
var slIdx = this.measurements.findIndex(i => i.QuestionType === 61)
if (currentSpleenLength && currentSpleenStatus === 5) {
// '!'
this.$alert(this.$t('trials:lugano:message:validSpleen1'), this.$t('trials:lugano:fusionDialog:warning'), {
callback: _ => {}
})
} else if (currentSpleenStatus === 5 && ((stIdx > -1 && this.measurements[stIdx].MeasureData) || (slIdx > -1 && this.measurements[slIdx].MeasureData))) {
//
this.$alert(this.$t('trials:lugano:message:validSpleen1'), this.$t('trials:lugano:fusionDialog:warning'), {
callback: _ => {}
})
} else if (((stIdx > -1 && this.measurements[stIdx].MeasureData) || (slIdx > -1 && this.measurements[slIdx].MeasureData)) && !currentSpleenLength) {
this.$alert(this.$t('trials:lugano:message:validSpleen2'), this.$t('trials:lugano:fusionDialog:warning'), {
callback: _ => {}
})
} else {
this.saveQuestionsList()
}
} else if (this.criterionType === 2 && this.groupClassify === 1 && this.questionForm[this.imageQualityIssuesId] && parseInt(this.questionForm[this.imageQualityIssuesId]) === 6) {
// PET-CT
const res = await getCanChooseNotMerge({ visitTaskId: this.visitTaskId })
if (res.IsSuccess && !res.Result.IsCanChooseNotMerge) {
// this.$alert(this.$t('trials:lugano:saveQuestions:warning1'), this.$t('trials:lugano:fusionDialog:warning'), {showCancelButton: false})
this.$alert(this.$t('trials:lugano:saveQuestions:warning1'), this.$t('trials:lugano:fusionDialog:warning'), {
showCancelButton: false,
callback: action => {}
})
return
} else {
// PET-CTFDG-PETNE
this.$confirm(this.$t('trials:lugano:saveQuestions:warning2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
this.saveQuestionsList()
})
}
} else {
this.saveQuestionsList()
}
// this.saveQuestionsList()
})
},
async saveQuestionsList() {
this.loading = true
var answers = []
var imageQuality = null
for (const k in this.questionForm) {
answers.push({ id: k, answer: this.questionForm[k] })
if (k === this.imageQualityId) {
imageQuality = this.questionForm[k]
}
}
var params = {
visitTaskId: this.visitTaskId,
answers: answers
}
// if (this.groupClassify === 3) {
// var questionMarkInfoList = []
// this.measurements.forEach(item => {
// var i = Object.assign({}, item)
// if (i.MeasureData) {
// i.MeasureData = JSON.stringify(i.MeasureData)
// }
// questionMarkInfoList.push(i)
// })
// params.questionMarkInfoList = questionMarkInfoList
// }
saveTaskQuestion(this.questionType, params).then(async res => {
if (this.imageQualityIssuesId) {
store.dispatch('reading/setImageQualityIssues', this.questionForm[this.imageQualityIssuesId])
if (this.questionForm[this.imageQualityIssuesId] && parseInt(this.questionForm[this.imageQualityIssuesId]) === 6) {
DicomEvent.$emit('closePetct')
}
}
this.$message.success(this.$t('common:message:savedSuccessfully'))
var trialId = this.$route.query.trialId
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: trialId, visitTaskId: this.visitTaskId })
this.getQuestions(this.visitTaskId, true)
this.loading = false
if (this.isQulityIssues) {
DicomEvent.$emit('questionFormChange', false)
}
DicomEvent.$emit('getReportInfo', true)
// DicomEvent.$emit('readingPageUpdate', {})
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
const criterionType = parseInt(localStorage.getItem('CriterionType'))
if (idx > -1 && !this.visitTaskList[idx].IsBaseLineTask && (criterionType === 1 || criterionType === 2 || criterionType === 3 || criterionType === 17)) {
if (parseInt(imageQuality) === 2) {
this.$confirm(this.$t('trials:reading:warnning:unableEvaluate'), '', {
type: 'warning'
}).then(() => {
store.dispatch('reading/setImageQuality', imageQuality)
DicomEvent.$emit('handleImageQualityAbnormal')
DicomEvent.$emit('readingPageUpdate', {})
}).catch(() => {
})
}
}
this.formChanged = false
}).catch(() => {
this.loading = false
})
},
checkAnnotationStatus(obj) {
for (let i = 0; i < obj.length; i++) {
if (obj[i].SaveEnum === 1) {
return true
}
if (obj[i].Childrens && obj[i].Childrens.length > 0) {
if (this.checkAnnotationStatus(obj[i].Childrens)) {
return true
}
}
}
},
checkAnnotationValid(stIdx, slIdx) {
var isValid = true
if (stIdx > -1 && slIdx > -1 && this.measurements[stIdx].MeasureData && this.measurements[slIdx].MeasureData) {
var stSeriesId = this.measurements[stIdx].SeriesId
var stInstanceId = this.measurements[stIdx].InstanceId
var slSeriesId = this.measurements[slIdx].SeriesId
var slInstanceId = this.measurements[slIdx].InstanceId
if (!(stSeriesId && stInstanceId && slSeriesId && slInstanceId && stSeriesId === slSeriesId && stInstanceId !== slInstanceId)) {
isValid = false
}
}
return isValid
},
setSpleenCommentDisplay() {
if (this.spleenCommentsId && this.spleenStatusId) {
for (let i = 0; i < this.questions[0].Childrens.length; i++) {
if (this.questions[0].Childrens[i].QuestionType === 58) {
if (this.calculateSpleenStatus && this.calculateSpleenStatus !== this.questionForm[this.spleenStatusId]) {
this.questions[0].Childrens[i].ShowQuestion = 0
this.questions[0].Childrens[i].IsRequired = 0
} else {
this.questions[0].Childrens[i].ShowQuestion = 2
this.questions[0].Childrens[i].IsRequired = 3
this.questionForm[this.spleenCommentsId] = ''
}
break
}
}
}
},
async getSplenicState() {
try {
var spleenLength = this.questionForm[this.spleenLengthId]
spleenLength = isNaN(parseFloat(spleenLength)) ? -1 : parseFloat(spleenLength)
const result = await getSplenicState(this.visitTaskId, spleenLength)
return { isSuccess: true, result: result.Result }
} catch (e) {
return { isSuccess: false, result: e }
}
},
async uploadScreenshots(fileName, file) {
try {
file = this.convertBase64ToBlob(file)
var trialId = this.$route.query.trialId
var subjectId = this.$route.query.trialId
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
return { isSuccess: true, result: result }
} catch (e) {
console.log(e)
return { isSuccess: false, result: e }
}
},
convertBase64ToBlob(imageEditorBase64) {
var base64Arr = imageEditorBase64.split(',')
var imgtype = ''
var base64String = ''
if (base64Arr.length > 1) {
// base64
base64String = base64Arr[1]
imgtype = base64Arr[0].substring(
base64Arr[0].indexOf(':') + 1,
base64Arr[0].indexOf(';')
)
}
// base64
var bytes = atob(base64String)
// var bytes = base64;
var bytesCode = new ArrayBuffer(bytes.length)
//
var byteArray = new Uint8Array(bytesCode)
// base64ascii
for (var i = 0; i < bytes.length; i++) {
byteArray[i] = bytes.charCodeAt(i)
}
// Blob
return new Blob([bytesCode], { type: imgtype })
},
addAnnotation(obj) {
const { Id, QuestionType } = obj
this.currentQsId = Id
var idx = this.measurements.findIndex(i => i.QuestionId === Id)
var orderMarkName = QuestionType === 60 ? 'Spleen Top' : QuestionType === 61 ? 'Spleen Bottom' : ''
if (idx === -1) {
this.measurements.push({ QuestionId: Id, QuestionType: QuestionType, StudyId: '', SeriesId: '', InstanceId: '', MarkTool: '', PicturePath: '', NumberOfFrames: '', MeasureData: '', OrderMarkName: orderMarkName })
}
//
this.$emit('setNonTargetMeasurementStatus', { status: true })
DicomEvent.$emit('imageLocation', { questionId: Id, visitTaskId: this.visitTaskId, lesionName: orderMarkName, markTool: 'ArrowAnnotate', readingTaskState: this.readingTaskState, isMarked: false })
},
async removeAnnotation(obj) {
const { Id } = obj
var idx = this.measurements.findIndex(i => i.QuestionId === Id)
if (idx === -1) return
this.$set(this.questionForm, Id, '')
if (!this.questionForm[this.spleenTopId] && !this.questionForm[this.spleenBottomId]) {
this.clearSpleenStatus()
}
// if (obj.QuestionType === 60 || obj.QuestionType === 61) {
// this.$set(this.questionForm, this.spleenStatusId, '')
// this.$set(this.questionForm, this.spleenLengthId, '')
// }
await store.dispatch('reading/removeNonTargetMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.measurements[idx].MeasureData, questionId: Id })
this.setQuestionStatus(this.questions, this.measurements[idx].QuestionType)
this.measurements.splice(idx, 1)
DicomEvent.$emit('getMeasureData')
// this.calculateSpleenStatus = ''
// this.setSpleenCommentDisplay()
this.formChanged = true
},
clearSpleenStatus() {
this.$set(this.questionForm, this.spleenStatusId, '')
this.$set(this.questionForm, this.spleenLengthId, '')
for (let i = 0; i < this.questions[0].Childrens.length; i++) {
if (this.questions[0].Childrens[i].QuestionType === 58) {
this.questions[0].Childrens[i].ShowQuestion = 2
this.questions[0].Childrens[i].IsRequired = 3
this.questionForm[this.spleenCommentsId] = ''
break
}
}
},
saveAnnotation(question) {
var stIdx = this.measurements.findIndex(i => i.QuestionType === 60)
var slIdx = this.measurements.findIndex(i => i.QuestionType === 61)
var chenckVaild = this.checkAnnotationValid(stIdx, slIdx)
if (!chenckVaild) {
//
this.$alert(this.$t('trials:lugano:message:validSpleen3'), this.$t('trials:lugano:fusionDialog:warning'), {
callback: _ => {}
})
return
}
this.loading = true
//
var annotationObj = this.measurements.find(i => i.QuestionType === question.QuestionType)
if (!annotationObj) {
this.saveQuestions(question)
} else {
var obj = Object.assign({}, annotationObj)
DicomEvent.$emit('getScreenshots', { questionId: obj.Id, visitTaskId: this.visitTaskId, lesionName: obj.OrderMarkName, markTool: obj.MarkTool, readingTaskState: this.readingTaskState, isMarked: !!obj.MeasureData }, async val => {
try {
var pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
var picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
this.saveQuestions(question, obj, picturePath)
} catch (e) {
console.log(e)
this.loading = false
}
})
}
},
async saveQuestions(question, obj, picturePath) {
try {
this.loading = true this.loading = true
var answers = [] var answers = []
var imageQuality = null var questionMarkInfoList = []
if (obj && obj.MeasureData) {
var annotation = Object.assign({}, obj.MeasureData)
obj.MeasureData = JSON.stringify(annotation)
obj.PicturePath = picturePath
questionMarkInfoList.push(obj)
}
for (const k in this.questionForm) { for (const k in this.questionForm) {
answers.push({ id: k, answer: this.questionForm[k] }) if (k === question.Id) {
if (k === this.imageQualityId) { answers.push({ id: k, answer: this.questionForm[k] })
imageQuality = this.questionForm[k] break
} }
} }
var params = { var params = {
visitTaskId: this.visitTaskId, visitTaskId: this.visitTaskId,
answers: answers answers,
questionMarkInfoList
} }
saveImageQuality(params).then(async res => { const qsType = question.QuestionType === 60 ? 4 : question.QuestionType === 61 ? 5 : null
this.$message.success(this.$t('common:message:savedSuccessfully')) await saveTaskQuestion(qsType, params)
var trialId = this.$route.query.trialId this.$message.success(this.$t('common:message:savedSuccessfully'))
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: trialId, visitTaskId: this.visitTaskId }) await this.setQuestions()
this.getQuestions(this.visitTaskId) for (let i = 0; i < this.questions[0].Childrens.length; i++) {
if (this.questions[0].Childrens[i].QuestionType === 58) {
this.loading = false this.questions[0].Childrens[i].ShowQuestion = 2
this.questions[0].Childrens[i].IsRequired = 3
DicomEvent.$emit('questionFormChange', false) this.questionForm[this.spleenCommentsId] = ''
DicomEvent.$emit('getReportInfo', true) break
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1 && !this.visitTaskList[idx].IsBaseLineTask) {
if (parseInt(imageQuality) === 2) {
this.$confirm(this.$t('trials:reading:warnning:unableEvaluate'), '', {
type: 'warning'
}).then(() => {
store.dispatch('reading/setImageQuality', imageQuality)
DicomEvent.$emit('handleImageQualityAbnormal')
}).catch(() => {
})
}
} }
}).catch(() => { }
this.loading = false this.loading = false
}) this.$set(question, 'SaveEnum', 0)
}) DicomEvent.$emit('getReportInfo', true)
} catch (e) {
console.log(e)
this.loading = false
}
},
locateAnnotation(obj) {
const { Id } = obj
var idx = this.measurements.findIndex(i => i.QuestionId === Id)
if (idx === -1) return
const measureObj = this.measurements[idx]
DicomEvent.$emit('imageLocation', { questionId: Id, visitTaskId: this.visitTaskId, lesionName: measureObj.OrderMarkName, markTool: measureObj.MarkTool, readingTaskState: this.readingTaskState, isMarked: !!measureObj.MeasureData })
},
setMeasuredData(measurement) {
var idx = -1
if (this.currentQsId) {
//
idx = this.measurements.findIndex(i => i.QuestionId === this.currentQsId)
this.currentQsId = ''
} else {
//
idx = this.measurements.findIndex(i => i.OrderMarkName === measurement.data.remark)
}
if (idx === -1) return
var remark = this.measurements[idx].QuestionType === 60 ? 'Spleen Top' : this.measurements[idx].QuestionType === 61 ? 'Spleen Bottom' : ''
measurement.data.remark = remark
this.measurements[idx].StudyId = measurement.studyId
this.measurements[idx].SeriesId = measurement.seriesId
this.measurements[idx].InstanceId = measurement.instanceId
this.measurements[idx].MarkTool = measurement.type
this.measurements[idx].NumberOfFrames = isNaN(parseInt(measurement.frame)) ? 0 : measurement.frame
this.measurements[idx].MeasureData = measurement
this.measurements[idx].pictureBaseStr = measurement.pictureBaseStr
measurement.pictureBaseStr = ''
//
var data = {
Id: '',
IsDicomReading: true,
StudyId: measurement.studyId,
InstanceId: measurement.instanceId,
SeriesId: measurement.seriesId,
MeasureData: measurement,
QuestionId: this.measurements[idx].QuestionId,
RowIndex: null,
RowId: null,
VisitTaskId: this.visitTaskId,
OrderMarkName: measurement.data.remark,
frame: isNaN(parseInt(measurement.frame)) ? 0 : measurement.frame
}
if (measurement.type === 'ArrowAnnotate') {
const location = measurement.location ? Number(measurement.location).toFixed(this.digitPlaces) : null
this.$set(this.questionForm, this.measurements[idx].QuestionId, location || null)
// if (this.measurements[idx].QuestionType === 60 || this.measurements[idx].QuestionType === 61) {
// var length = this.getSpleenL()
// this.$set(this.questionForm, this.spleenLengthId, length)
// var status = this.setSpleenStatus(length)
// this.$set(this.questionForm, this.spleenStatusId, status)
// this.calculateSpleenStatus = status
// }
// if (this.measurements[idx].QuestionType === 48 && length <= 130 && this.isBaseLineTask) {
// //
// this.$set(this.questionForm, this.spleenStatusId, '1')
// }
// if (this.measurements[idx].QuestionType === 48 && length > 130 && this.isBaseLineTask) {
// //
// this.$set(this.questionForm, this.spleenStatusId, '6')
// }
}
store.dispatch('reading/addOrUpdateNonTargetMeasuredData', { visitTaskId: this.visitTaskId, data: data })
if (this.isQulityIssues) {
DicomEvent.$emit('questionFormChange', true)
}
this.formChanged = true
this.setQuestionStatus(this.questions, this.measurements[idx].QuestionType)
},
setQuestionStatus(obj, questionType) {
console.log(obj, questionType)
for (let i = 0; i < obj.length; i++) {
if (obj[i].QuestionType === questionType) {
this.$set(obj[i], 'SaveEnum', 1)
return true
}
if (obj[i].Childrens && obj[i].Childrens.length > 0) {
if (this.setQuestionStatus(obj[i].Childrens, questionType)) {
return true
}
}
}
},
getSpleenL() {
var length = null
//
var st = this.questionForm[this.spleenTopId]
st = isNaN(parseFloat(st)) ? null : parseFloat(st)
//
var sb = this.questionForm[this.spleenBottomId]
sb = isNaN(parseFloat(sb)) ? null : parseFloat(sb)
if (st && sb) {
length = Math.abs(st - sb).toFixed(this.digitPlaces)
}
return length
},
setSpleenStatus(length) {
console.log('setSpleenStatus')
var status = ''
if (length) {
if (this.isBaseLineTask) {
// 130mm
if (length <= 130) {
status = '1'
}
// >130mm
if (length > 130) {
status = '6'
}
} else {
// 线
var diffFromBaseline = length - this.spleenInfo.BaseLineSpleenLength
var percentFormBaseline = 0
if (this.spleenInfo.BaseLineSpleenLength) {
percentFormBaseline = diffFromBaseline * 100 / (this.spleenInfo.BaseLineSpleenLength - 130)
}
if (length <= 130) {
// 访130mm
//
status = '1'
} else if (this.spleenInfo.BaseLineSpleenLength > 130 && diffFromBaseline >= 10 && percentFormBaseline > 50 && length > 130) {
// 1线 >130 mm
// 2线10 mm
// 3线>50
// 4>130 mm
//
status = '4'
} else if (this.spleenInfo.BaseLineSpleenLength <= 130 && diffFromBaseline >= 20 && length > 130) {
// 1线130mm
// 2线20 mm
// 3>130 mm
//
status = '4'
} else if (this.spleenInfo.BaseLineSpleenLength > 130 && this.spleenInfo.LowSpleenLength <= 130 && length - this.spleenInfo.LowSpleenLength >= 20 && length > 130) {
// 1线 >130 mm
// 2访访 130mm
// 320 mm
// 4>130 mm
//
status = '4'
} else if (this.spleenInfo.BaseLineState === '6' && percentFormBaseline < -50 && length > 130) {
// 1线
// 2线-50
// 3>130 mm
//
status = '2'
} else {
//
status = '3'
}
}
}
return status
}, },
resetFormItemData(v) { resetFormItemData(v) {
this.questionForm[v] = null this.questionForm[v] = null
// if (v === this.spleenLengthId) {
// var spleenStatus = this.questionForm[this.spleenStatusId]
// spleenStatus = isNaN(parseInt(spleenStatus)) ? null : parseInt(spleenStatus)
// if (spleenStatus === 5) {
// this.removeAnnotation({ Id: this.spleenLengthId })
// }
// }
this.formChanged = true
}, },
setFormItemData(obj) { setFormItemData(obj) {
this.questionForm[obj.key] = obj.val this.questionForm[obj.key] = obj.val
if (obj.key === this.spleenStatusId) {
this.setSpleenCommentDisplay()
}
this.formChanged = true
},
setQuestions() {
return new Promise(resolve => {
var params = {
trialId: this.$route.query.trialId,
visitTaskId: this.visitTaskId
}
getDicomReadingQuestionAnswer(params).then(res => {
var questions = []
for (var i = 0; i < res.Result.length; i++) {
var v = res.Result[i]
if (v.Type === 'group' && v.GroupClassify !== this.groupClassify) continue
questions.push(v)
}
questions.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return
if (v.Childrens.length > 0) {
this.setQSChild(v.Childrens)
}
})
resolve()
})
})
},
setQSChild(obj) {
obj.forEach(i => {
if (i.QuestionType === 49) {
// ;
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
this.calculateSpleenStatus = i.Answer
}
if (i.QuestionType === 48) {
// ;
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
}
if (i.Childrens && i.Childrens.length > 0) {
this.setQSChild(i.Childrens)
}
})
},
openFeedBackTable() {
this.$FB({
type: 'imgfail',
trialId: this.$route.query.trialId,
visitTaskId: this.visitTaskId,
callBack: async() => {
console.log('callBack')
const confirm = await this.$confirm(
this.$t('trials:reading:confirm:feedbackmsg'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
try {
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
}
})
},
isJSONString(str) {
try {
JSON.stringify(JSON.parse(str))
return true
} catch (e) {
return false
}
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.ecrf-wrapper{ .ecrf-wrapper{
>>>.el-form-item__label{ /deep/ .el-form-item__label{
color: #c3c3c3; color: #c3c3c3;
text-align: left;
} }
>>>.el-input__inner{ /deep/ .el-input__inner{
background-color: transparent; background-color: transparent;
color: #ddd; color: #ddd;
border: 1px solid #5e5e5e; border: 1px solid #5e5e5e;
} }
>>>.el-textarea__inner{ /deep/ .el-textarea__inner{
background-color: transparent; background-color: transparent;
color: #ddd; color: #ddd;
border: 1px solid #5e5e5e; border: 1px solid #5e5e5e;
} }
>>>.el-form-item{
/deep/ .el-form-item{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap;
} }
>>>.el-form-item__content{ /deep/ .el-form-item__content{
flex: 1; flex: 1;
} }
>>>.el-button--mini, .el-button--mini.is-round { /deep/ .el-button--mini, .el-button--mini.is-round {
padding: 7px 10px; padding: 7px 10px;
} }
.el-form-item__content /deep/ .el-form-item__content
.el-select{ .el-select{
width: 100%; width: 100%;
} }
.ecrf-footer{
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
.feedback-icon{
padding: 0 10px;
color: #fff;
font-weight: 400;
font-size: 22px;
cursor: pointer;
&:hover{
color: #68a2d5;
}
}
}
} }
</style> </style>

View File

@ -57,6 +57,7 @@
:is-reading-show-subject-info="isReadingShowSubjectInfo" :is-reading-show-subject-info="isReadingShowSubjectInfo"
:is-reading-task-view-in-order="isReadingTaskViewInOrder" :is-reading-task-view-in-order="isReadingTaskViewInOrder"
:is-exists-manual="isExistsManual" :is-exists-manual="isExistsManual"
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
@previewCD="previewCD" @previewCD="previewCD"
/> />
</div> </div>
@ -72,6 +73,25 @@ import DicomEvent from './DicomEvent'
import store from '@/store' import store from '@/store'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import metaDataProvider from '@/utils/metaDataProvider'
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
var config = {
maxWebWorkers: 4,
startWebWorkersOnDemand: true,
taskConfiguration: {
decodeTask: {
initializeCodecsOnStartup: false
}
}
}
cornerstoneWADOImageLoader.webWorkerManager.initialize(config)
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
const maximumSizeInBytes = 1024 * 1024 * 1024 * 6
cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
export default { export default {
name: 'ReadPage', name: 'ReadPage',
components: { components: {
@ -112,13 +132,17 @@ export default {
required: true required: true
}, },
isReadingTaskViewInOrder: { isReadingTaskViewInOrder: {
type: Boolean, type: Number,
required: true required: true
}, },
isExistsManual: { isExistsManual: {
type: Boolean, type: Boolean,
required: true required: true
}, },
iseCRFShowInDicomReading: {
type: Boolean,
required: true
},
questionFormChangeState: { questionFormChangeState: {
type: Boolean, type: Boolean,
default() { default() {
@ -210,14 +234,20 @@ export default {
this.$refs[this.activeTaskVisitId][0].selectSeries(data) this.$refs[this.activeTaskVisitId][0].selectSeries(data)
}) })
}) })
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
})
}, },
beforeDestroy() { beforeDestroy() {
cornerstone.imageCache.purgeCache()
DicomEvent.$off('getNextVisitInfo') DicomEvent.$off('getNextVisitInfo')
DicomEvent.$off('toggleSeries') DicomEvent.$off('toggleSeries')
DicomEvent.$off('isCanActiveNoneDicomTool') DicomEvent.$off('isCanActiveNoneDicomTool')
DicomEvent.$off('removeNoneDicomMeasureData') DicomEvent.$off('removeNoneDicomMeasureData')
DicomEvent.$off('addNoneDicomMeasureData') DicomEvent.$off('addNoneDicomMeasureData')
DicomEvent.$off('selectSeries') DicomEvent.$off('selectSeries')
window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() })
}, },
methods: { methods: {
async getVisitInfo() { async getVisitInfo() {
@ -400,7 +430,7 @@ export default {
idx > -1 ? obj = seriesList[idx] : '' idx > -1 ? obj = seriesList[idx] : ''
} }
if (obj) { if (obj) {
const index = Math.floor(obj.imageIds.length * ((baseSeries.imageIdIndex + 1) / baseSeries.instanceCount)) const index = Math.floor(obj.imageIds.length * ((baseSeries.imageIdIndex + 1) / baseSeries.imageIds))
obj.imageIdIndex = index > 0 ? index - 1 : 0 obj.imageIdIndex = index > 0 ? index - 1 : 0
} }
return obj return obj
@ -464,7 +494,10 @@ export default {
var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId) var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId)
if (seriesIdx > -1) { if (seriesIdx > -1) {
var series = studyList[studyIdx].SeriesList[seriesIdx] var series = studyList[studyIdx].SeriesList[seriesIdx]
var instanceIdx = series.instanceList.findIndex(imageId => !!~imageId.indexOf(instanceId)) // var instanceIdx = series.instanceList.findIndex(imageId => !!~imageId.indexOf(instanceId))
const frame = this.visitTaskList[index].MeasureData[idx].MeasureData.frame
const filterStr = series.isExistMutiFrames ? `frame=${frame}&instanceId=${instanceId}` : `instanceId=${instanceId}`
var instanceIdx = series.imageIds.findIndex(imageId => imageId.includes(filterStr))
if (instanceIdx > -1) { if (instanceIdx > -1) {
series.imageIdIndex = instanceIdx series.imageIdIndex = instanceIdx
// series.studyIndex = studyIdx // series.studyIndex = studyIdx
@ -485,6 +518,16 @@ export default {
seriesInfo = this.getLinkedSeries(baseSeries, visitTaskId, visitTaskIdx) seriesInfo = this.getLinkedSeries(baseSeries, visitTaskId, visitTaskIdx)
} }
return seriesInfo return seriesInfo
},
cornerstoneimageloadprogress(e) {
const imageId = e.detail.imageId
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
params.percentComplete = e.detail.percentComplete
store.dispatch('reading/setImageLoadedProgress', params)
} }
} }
} }

View File

@ -1,11 +1,22 @@
<template> <template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}"> <div class="measurement-wrapper">
<div class="container">
<div class="basic-info">
<h3 v-if="isReadingShowSubjectInfo">
<span v-if="subjectCode">{{ subjectCode }} </span>
<span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<div v-if="readingTaskState < 2">
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
<i
class="el-icon-refresh-left"
@click="resetMeasuredData"
/>
</el-tooltip>
</div>
</div>
<div class="container" :style="{'height':height+'px'}">
<h3 v-if="isReadingShowSubjectInfo" style="color: #ddd;padding: 5px 0px;margin: 0;">
<span v-if="subjectCode">{{ subjectCode }} </span>
<span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<!-- 非测量问题 --> <!-- 非测量问题 -->
<div class="lesions"> <div class="lesions">
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" /> <Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" />
@ -122,6 +133,7 @@
</template> </template>
<script> <script>
import { splitLesion } from '@/api/trials' import { splitLesion } from '@/api/trials'
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent' import DicomEvent from './../DicomEvent'
import store from '@/store' import store from '@/store'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
@ -157,7 +169,6 @@ export default {
}, },
data() { data() {
return { return {
height: window.innerHeight - 140,
questions: [], questions: [],
activeName: '', activeName: '',
activeItem: { activeItem: {
@ -201,7 +212,8 @@ export default {
} }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
window.addEventListener('message', this.receiveMsg) window.addEventListener('message', this.receiveMsg)
this.CriterionType = parseInt(localStorage.getItem('CriterionType')) this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => { DicomEvent.$on('setCollapseActive', measureData => {
@ -221,8 +233,6 @@ export default {
DicomEvent.$on('split', measureData => { DicomEvent.$on('split', measureData => {
this.handleSplit(measureData.RowId, measureData.QuestionId) this.handleSplit(measureData.RowId, measureData.QuestionId)
}) })
window.addEventListener('resize', this.setHeight)
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('setCollapseActive') DicomEvent.$off('setCollapseActive')
@ -403,9 +413,6 @@ export default {
} catch (e) { console.log(e) } } catch (e) { console.log(e) }
}) })
}, },
setHeight() {
this.height = window.innerHeight - 140
},
getQuestionAnswer(questions, questionMark, answers) { getQuestionAnswer(questions, questionMark, answers) {
var idx = questions.findIndex(i => i.QuestionMark === questionMark) var idx = questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) { if (idx > -1) {
@ -503,15 +510,15 @@ export default {
} }
} }
}, },
split(rowId, questionId) { async split(rowId, questionId) {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
var params = { try {
visitTaskId: this.visitTaskId, var params = {
questionId: questionId, visitTaskId: this.visitTaskId,
rowId: rowId questionId: questionId,
} rowId: rowId
splitLesion(params).then(async res => { }
loading.close() await splitLesion(params)
await this.getReadingQuestionAndAnswer() await this.getReadingQuestionAndAnswer()
this.$nextTick(() => { this.$nextTick(() => {
this.tableQuestions.forEach(item => { this.tableQuestions.forEach(item => {
@ -521,7 +528,11 @@ export default {
}) })
}) })
}) })
}) loading.close()
} catch (e) {
loading.close()
console.log(e)
}
}, },
isCanActiveTool(toolName) { isCanActiveTool(toolName) {
this.getUnSaveTarget() this.getUnSaveTarget()
@ -942,6 +953,39 @@ export default {
getECRFQuestions(obj) { getECRFQuestions(obj) {
this.$refs['ecrf'].getQuestions(obj.visitTaskId) this.$refs['ecrf'].getQuestions(obj.visitTaskId)
}, },
async resetMeasuredData() {
const confirm = await this.$confirm(
this.$t('trials:dicomReading:message:confirmReset1'),
this.$t('trials:dicomReading:message:confirmReset2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const loading = this.$loading({ fullscreen: true })
try {
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
//
this.activeName = ''
this.activeItem.activeRowIndex = null
this.activeItem.activeCollapseId = null
await this.getReadingQuestionAndAnswer(this.visitTaskId)
const triald = this.$router.currentRoute.query.trialId
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
DicomEvent.$emit('getMeasureData')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('refreshStudyListMeasureData')
}
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
receiveMsg(event) { receiveMsg(event) {
if (event.data.type === 'isCanActiveNoneDicomTool') { if (event.data.type === 'isCanActiveNoneDicomTool') {
this.getUnSaveTarget() this.getUnSaveTarget()
@ -1015,11 +1059,28 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.measurement-wrapper{ .measurement-wrapper{
height: 100%;
overflow-y: auto; overflow-y: auto;
// overflow: hidden; // overflow: hidden;
.container{ .container{
padding: 10px; padding: 10px;
.basic-info{
display: flex;
justify-content: space-between;
align-items: center;
h3{
color: #ddd;
padding: 5px 0px;
margin: 0;
}
i{
color: #fff;
font-size: 22px;
font-weight: bold;
cursor: pointer;
}
}
} }
.title{ .title{
padding: 5px; padding: 5px;

View File

@ -110,34 +110,38 @@
/> />
</template> </template>
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask"> <template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask">
<!-- 首次分裂的病灶只能选择存在 --> <el-option-group
<template v-if="answers.IsFristAdd=== 'True' && answers.SplitOrMergeType === '0'"> :label="!isNaN(parseFloat(answers.LastTaskState)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(qs.DictionaryCode,parseFloat(answers.LastTaskState))}` : ''"
<el-option >
v-for="item of $d[qs.DictionaryCode]" <!-- 首次分裂的病灶只能选择存在 -->
v-show="item.value === 0" <template v-if="answers.IsFristAdd=== 'True' && answers.SplitOrMergeType === '0'">
:key="item.id" <el-option
:value="item.value" v-for="item of $d[qs.DictionaryCode]"
:label="item.label" v-show="item.value === 0"
/> :key="item.id"
</template> :value="item.value"
<!-- 首次添加的新病灶不能为无法评估和消失 --> :label="item.label"
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2"> />
<el-option </template>
v-for="item of $d[qs.DictionaryCode]" <!-- 首次添加的新病灶不能为无法评估和消失 -->
v-show="item.value === 0 || item.value === 1" <template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
:key="item.id" <el-option
:value="item.value" v-for="item of $d[qs.DictionaryCode]"
:label="item.label" v-show="item.value === 0 || item.value === 1"
/> :key="item.id"
</template> :value="item.value"
<template v-else> :label="item.label"
<el-option />
v-for="item of filterState($d[qs.DictionaryCode])" </template>
:key="item.id" <template v-else>
:value="item.value" <el-option
:label="item.label" v-for="item of filterState($d[qs.DictionaryCode])"
/> :key="item.id"
</template> :value="item.value"
:label="item.label"
/>
</template>
</el-option-group>
</template> </template>
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7"> <template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
<el-option <el-option
@ -340,16 +344,15 @@ export default {
await this.getOrganInfoList() await this.getOrganInfoList()
// //
if (this.answers.IsFristAdd === 'True' && this.answers.SplitOrMergeType === '0' && isNaN(parseInt(this.getQuestionVal(7)))) { if (this.answers.IsFristAdd === 'True' && this.answers.SplitOrMergeType === '0' && lesionState === '') {
const stateId = this.getQuestionId(7) const stateId = this.getQuestionId(7)
this.$set(this.questionForm, stateId, 0) this.$set(this.questionForm, stateId, 0)
var isLymphLesion = this.getQuestionVal(2) var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : '' const lesionLength = this.getQuestionVal(0)
const lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : '' const lesionShort = this.getQuestionVal(1)
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' const lesionState = this.getQuestionVal(7)
this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, lesionShort, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, lesionShort, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
} }
this.isRender = true this.isRender = true
@ -515,8 +518,8 @@ export default {
} }
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : '' const lesionLength = this.getQuestionVal(0)
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' const lesionState = this.getQuestionVal(7)
this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
if (question.QuestionMark === 7) { if (question.QuestionMark === 7) {
@ -575,9 +578,8 @@ export default {
} }
var isLymphLesion = this.getQuestionVal(2) var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null var lesionLength = this.getQuestionVal(0)
var lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : '' var lesionShort = this.getQuestionVal(1)
var lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : ''
// //
if (!(this.isCurrentTaskAdd === 'True')) { if (!(this.isCurrentTaskAdd === 'True')) {
@ -597,7 +599,7 @@ export default {
} }
} }
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' const lesionState = this.getQuestionVal(7)
var status = '' var status = ''
if (lesionState) { if (lesionState) {
if (this.lesionType === 0 && lesionState === 1) { if (this.lesionType === 0 && lesionState === 1) {
@ -646,8 +648,8 @@ export default {
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionL = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : '' const lesionL = this.getQuestionVal(0)
var lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' var lesionState = this.getQuestionVal(7)
this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionLength: lesionL, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionLength: lesionL, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
this.toolType = measureData.type this.toolType = measureData.type
DicomEvent.$emit('refreshStudyListMeasureData') DicomEvent.$emit('refreshStudyListMeasureData')
@ -670,27 +672,31 @@ export default {
} }
}, },
getQuestionVal(questionMark) { getQuestionVal(questionMark) {
var idx = this.questions.findIndex(i => i.QuestionMark === questionMark) const idx = this.questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) { if (idx > -1) {
var questionId = this.questions[idx].Id const questionId = this.questions[idx].Id
return this.questionForm[questionId] const answer = this.questionForm[questionId]
if (isNaN(parseFloat(answer))) {
return answer
} else {
return parseFloat(answer)
}
} else { } else {
return '' return ''
} }
}, },
filterState(arr) { filterState(arr) {
if (!this.isBaseLineTask) { if (!this.isBaseLineTask) {
var isLymphLesion = this.getQuestionVal(2) const isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null const lesionLength = this.getQuestionVal(0)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : 0 const lesionShort = this.getQuestionVal(1)
const lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : 0 const bLesionL = !isNaN(parseInt(this.answers.LastTaskMajorAxis)) ? parseInt(this.answers.LastTaskMajorAxis) : 0
const lastLesionL = !isNaN(parseInt(this.answers.LastTaskMajorAxis)) ? parseInt(this.answers.LastTaskMajorAxis) : 0 const bLesionS = !isNaN(parseInt(this.answers.LastTaskShortAxis)) ? parseInt(this.answers.LastTaskShortAxis) : 0
const lastLesionS = !isNaN(parseInt(this.answers.LastTaskShortAxis)) ? parseInt(this.answers.LastTaskShortAxis) : 0 if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.type === 'Bidirectional' && lesionShort < bLesionS) {
if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && (this.questionForm.MeasureData.type === 'Length' || this.questionForm.MeasureData.type === 'Bidirectional') && lesionShort < lastLesionS) {
arr = arr.filter(i => i.value !== 1) arr = arr.filter(i => i.value !== 1)
} else if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && (this.questionForm.MeasureData.type === 'Length' || this.questionForm.MeasureData.type === 'Bidirectional') && lesionShort >= 10 && lesionShort > lastLesionS) { } else if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.type === 'Bidirectional' && lesionShort >= 10 && lesionShort > bLesionS) {
arr = arr.filter(i => i.value === 0 || i.value === 1) arr = arr.filter(i => i.value === 0 || i.value === 1)
} else if (this.lesionType === 1 && isLymphLesion === 0 && this.questionForm.MeasureData && (this.questionForm.MeasureData.type === 'Length' || this.questionForm.MeasureData.type === 'Bidirectional') && lesionLength < lastLesionL) { } else if (this.lesionType === 1 && isLymphLesion === 0 && this.questionForm.MeasureData && (this.questionForm.MeasureData.type === 'Length' || this.questionForm.MeasureData.type === 'Bidirectional') && lesionLength < bLesionL) {
arr = arr.filter(i => i.value !== 1) arr = arr.filter(i => i.value !== 1)
} }
return arr return arr
@ -754,227 +760,228 @@ export default {
// Blob // Blob
return new Blob([bytesCode], { type: imgtype }) return new Blob([bytesCode], { type: imgtype })
}, },
handleSave() { async handleSave() {
this.$refs.measurementForm.validate(async valid => { const valid = await this.$refs.measurementForm.validate()
if (!valid) return if (!valid) return
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
var measureData = this.questionForm.MeasureData var measureData = this.questionForm.MeasureData
var lesionState = this.getQuestionVal(7) var lesionState = this.getQuestionVal(7)
var lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : '' var lesionLength = this.getQuestionVal(0)
if (this.isBaseLineTask) { if (this.isBaseLineTask) {
// 线 // 线
// 0 // 0
if (this.lesionType === 0 && lesionState === 0) { if (this.lesionType === 0 && lesionState === 0) {
// 10mm2 // 10mm2
if (!(measureData && measureData.type === 'Length' && lesionLength >= 10 && (measureData.thick && lesionLength >= 2 * measureData.thick || !measureData.thick))) { if (!(measureData && measureData.type === 'Length' && lesionLength >= 10 && (measureData.thick && lesionLength >= 2 * measureData.thick || !measureData.thick))) {
// 10mm2使 // 10mm2使
this.$confirm(this.$t('trials:readingBM:warnning:msg06'), { this.$confirm(this.$t('trials:readingBM:warnning:msg06'), {
type: 'warning', type: 'warning',
showCancelButton: false, showCancelButton: false,
callback: action => {} callback: action => {}
}) })
loading.close() loading.close()
return return
}
}
// 0
if (this.lesionType === 1 && lesionState === 0) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'RectangleRoi'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg07'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
} else {
// 线
// 0
if (this.lesionType === 0 && lesionState === 0) {
if (!(measureData && measureData.type === 'Length')) {
// `使`
this.$confirm(this.$t('trials:readingBM:warnning:msg08'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 1
if (this.lesionType === 0 && lesionState === 1) {
if (!(measureData && (measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg09'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
} else if (measureData && measureData.type === 'ArrowAnnotate') {
const lengthId = this.getQuestionId(0)
this.$set(this.questionForm, lengthId, 5)
lesionLength = 5
}
}
// 2
if (this.lesionType === 0 && lesionState === 2) {
if (measureData) {
//
this.$confirm(this.$t('trials:readingBM:warnning:msg10'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 3
if (this.lesionType === 0 && lesionState === 3) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg11'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
} else if (measureData && measureData.type === 'ArrowAnnotate') {
const lId = this.getQuestionId(0)
this.$set(this.questionForm, lId, 0)
lesionLength = 0
}
}
// 0
if (this.lesionType === 1 && lesionState === 0) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'RectangleRoi'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg12'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 1
if (this.lesionType === 1 && lesionState === 1) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'RectangleRoi'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg13'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 2
if (this.lesionType === 1 && lesionState === 2) {
if (measureData) {
//
this.$confirm(this.$t('trials:readingBM:warnning:msg14'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 3
if (this.lesionType === 1 && lesionState === 3) {
if (!(measureData && (measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg15'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 0
if (this.lesionType === 2 && lesionState === 0) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg16'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 1
if (this.lesionType === 2 && lesionState === 1) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg17'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 2
if (this.lesionType === 2 && lesionState === 2) {
if (measureData) {
//
this.$confirm(this.$t('trials:readingBM:warnning:msg18'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 3
if (this.lesionType === 2 && lesionState === 3) {
if (!(measureData && (measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg19'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
} }
} }
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.lesionMark, lesionType: this.lesionType, isMarked: !!measureData }, async val => { // 0
if (this.lesionType === 1 && lesionState === 0) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'RectangleRoi'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg07'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
} else {
// 线
// 0
if (this.lesionType === 0 && lesionState === 0) {
if (!(measureData && measureData.type === 'Length')) {
// `使`
this.$confirm(this.$t('trials:readingBM:warnning:msg08'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 1
if (this.lesionType === 0 && lesionState === 1) {
if (!(measureData && (measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg09'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
} else if (measureData && measureData.type === 'ArrowAnnotate') {
const lengthId = this.getQuestionId(0)
this.$set(this.questionForm, lengthId, 5)
lesionLength = 5
}
}
// 2
if (this.lesionType === 0 && lesionState === 2) {
if (measureData) {
//
this.$confirm(this.$t('trials:readingBM:warnning:msg10'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 3
if (this.lesionType === 0 && lesionState === 3) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg11'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
} else if (measureData && measureData.type === 'ArrowAnnotate') {
const lId = this.getQuestionId(0)
this.$set(this.questionForm, lId, 0)
lesionLength = 0
}
}
// 0
if (this.lesionType === 1 && lesionState === 0) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'RectangleRoi'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg12'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 1
if (this.lesionType === 1 && lesionState === 1) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'RectangleRoi'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg13'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 2
if (this.lesionType === 1 && lesionState === 2) {
if (measureData) {
//
this.$confirm(this.$t('trials:readingBM:warnning:msg14'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 3
if (this.lesionType === 1 && lesionState === 3) {
if (!(measureData && (measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg15'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 0
if (this.lesionType === 2 && lesionState === 0) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg16'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 1
if (this.lesionType === 2 && lesionState === 1) {
if (!(measureData && (measureData.type === 'Length' || measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg17'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 2
if (this.lesionType === 2 && lesionState === 2) {
if (measureData) {
//
this.$confirm(this.$t('trials:readingBM:warnning:msg18'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
// 3
if (this.lesionType === 2 && lesionState === 3) {
if (!(measureData && (measureData.type === 'ArrowAnnotate'))) {
// 使
this.$confirm(this.$t('trials:readingBM:warnning:msg19'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
return
}
}
}
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.lesionMark, lesionType: this.lesionType, isMarked: !!measureData }, async val => {
try {
var picturePath = '' var picturePath = ''
if (val && measureData && this.questionForm.IsDicomReading) { if (val && measureData && this.questionForm.IsDicomReading) {
var pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val) var pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
picturePath = pictureObj.isSuccess ? pictureObj.result.name : '' picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
} }
var answers = [] var answers = []
var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/) var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
@ -1010,7 +1017,8 @@ export default {
await this.deleteOldLesion(this.deleteInfo.questionId, this.deleteInfo.rowId) await this.deleteOldLesion(this.deleteInfo.questionId, this.deleteInfo.rowId)
this.deleteInfo = null this.deleteInfo = null
} }
submitTableQuestion(params).then(async res => { const res = await submitTableQuestion(params)
if (res.IsSuccess) {
// //
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.currentMarkTool = measureData ? measureData.type : '' this.currentMarkTool = measureData ? measureData.type : ''
@ -1018,94 +1026,87 @@ export default {
this.$set(this.questionForm, 'saveTypeEnum', 2) this.$set(this.questionForm, 'saveTypeEnum', 2)
this.originalQuestionForm = { ...this.questionForm } this.originalQuestionForm = { ...this.questionForm }
loading.close()
var lesionOrgan = this.getQuestionVal(6) var lesionOrgan = this.getQuestionVal(6)
this.$set(this.questionForm, 'RowId', res.Result.RowId) this.$set(this.questionForm, 'RowId', res.Result.RowId)
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionState = Number(this.getQuestionVal(7)) const lesionState = this.getQuestionVal(7)
this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, lesionState, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, lesionState, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
this.$emit('close') this.$emit('close')
DicomEvent.$emit('getReportInfo', true) DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('setMeasuredToolsPassive') DicomEvent.$emit('setMeasuredToolsPassive')
}).catch(() => { loading.close() }) }
}) loading.close()
} catch (e) {
console.log(e)
loading.close()
}
}) })
}, },
handleDeleteMeasureData() { async handleDeleteMeasureData() {
// //
this.$confirm(this.$t('trials:reading:warnning:msg47'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:reading:warnning:msg47'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(async() => { distinguishCancelAndClose: true
// }
var lengId = this.getQuestionId(0) )
this.$set(this.questionForm, lengId, '') if (confirm !== 'confirm') return
//
var lengId = this.getQuestionId(0)
this.$set(this.questionForm, lengId, '')
var stateId = this.getQuestionId(7) var stateId = this.getQuestionId(7)
this.$set(this.questionForm, stateId, '') this.$set(this.questionForm, stateId, '')
// saveTypeEnum 01访/ // saveTypeEnum 01访/
if (this.questionForm.RowId) { if (this.questionForm.RowId) {
this.$set(this.questionForm, 'saveTypeEnum', 1) this.$set(this.questionForm, 'saveTypeEnum', 1)
} else { } else {
this.$set(this.questionForm, 'saveTypeEnum', 0) this.$set(this.questionForm, 'saveTypeEnum', 0)
} }
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex }) await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex })
DicomEvent.$emit('getMeasureData') DicomEvent.$emit('getMeasureData')
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionLength = '' const lesionLength = ''
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' const lesionState = this.getQuestionVal(7)
if (!this.questionForm.IsDicomReading) { if (!this.questionForm.IsDicomReading) {
DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData) DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData)
} }
this.$set(this.questionForm, 'IsDicomReading', true) this.$set(this.questionForm, 'IsDicomReading', true)
this.$set(this.questionForm, 'MeasureData', '') this.$set(this.questionForm, 'MeasureData', '')
let anwsers = null let anwsers = null
if (this.answers.measureObj) { if (this.answers.measureObj) {
anwsers = Object.assign({ measureObj: '' }, this.questionForm) anwsers = Object.assign({ measureObj: '' }, this.questionForm)
} else { } else {
anwsers = Object.assign({}, this.questionForm) anwsers = Object.assign({}, this.questionForm)
} }
this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: anwsers }) this.$emit('resetQuestions', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: anwsers })
DicomEvent.$emit('refreshStudyListMeasureData') DicomEvent.$emit('refreshStudyListMeasureData')
})
.catch(() => {})
}, },
handleDelete() { async handleDelete() {
// //
this.$confirm(this.$t('trials:reading:warnning:msg48'), { const loading = this.$loading({ fullscreen: true })
type: 'warning', try {
distinguishCancelAndClose: true const confirm = await this.$confirm(
}) this.$t('trials:reading:warnning:msg48'),
.then(async() => { {
if (this.questionForm.RowId) { type: 'warning',
const loading = this.$loading({ fullscreen: true }) distinguishCancelAndClose: true
var param = { }
visitTaskId: this.visitTaskId, )
questionId: this.parentQsId, if (confirm !== 'confirm') return
rowId: this.questionForm.RowId if (this.questionForm.RowId) {
} var param = {
deleteReadingRowAnswer(param) visitTaskId: this.visitTaskId,
.then(async res => { questionId: this.parentQsId,
loading.close() rowId: this.questionForm.RowId
if (res.IsSuccess) { }
if (this.questionForm.IsDicomReading && this.questionForm.MeasureData) { const res = await deleteReadingRowAnswer(param)
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex }) if (res.IsSuccess) {
}
if (!this.questionForm.IsDicomReading && this.questionForm.MeasureData) {
DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData)
}
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
loading.close()
}
}).catch(() => { loading.close() })
} else {
if (this.questionForm.IsDicomReading && this.questionForm.MeasureData) { if (this.questionForm.IsDicomReading && this.questionForm.MeasureData) {
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex }) await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex })
} }
@ -1113,26 +1114,41 @@ export default {
DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData) DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData)
} }
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId }) this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
} }
DicomEvent.$emit('refreshStudyListMeasureData') } else {
}) if (this.questionForm.IsDicomReading && this.questionForm.MeasureData) {
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex })
}
if (!this.questionForm.IsDicomReading && this.questionForm.MeasureData) {
DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData)
}
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
}
DicomEvent.$emit('refreshStudyListMeasureData')
loading.close()
} catch (e) {
console.log(e)
loading.close()
}
}, },
handleClose() { async handleClose() {
if (!this.questionForm.RowId) { if (!this.questionForm.RowId) {
// '' // ''
this.$confirm(this.$t('trials:reading:warnning:msg49'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:reading:warnning:msg49'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(async() => { distinguishCancelAndClose: true
// }
if (this.questionForm.MeasureData) { )
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex }) if (confirm !== 'confirm') return
} if (this.questionForm.MeasureData) {
DicomEvent.$emit('getMeasureData') await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex })
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId }) }
}) DicomEvent.$emit('getMeasureData')
.catch(() => {}) this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
} else { } else {
// saveTypeEnum 01访/ // saveTypeEnum 01访/
@ -1150,13 +1166,12 @@ export default {
if (isNaN(parseInt(lesionState)) && this.answers.IsFristAdd === 'False') { if (isNaN(parseInt(lesionState)) && this.answers.IsFristAdd === 'False') {
const stateId = this.getQuestionId(7) const stateId = this.getQuestionId(7)
this.$set(this.questionForm, stateId, 2) this.$set(this.questionForm, stateId, 2)
var isLymphLesion = this.getQuestionVal(2) const isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null
const lesionPart = this.getQuestionVal(8) const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6) const lesionOrgan = this.getQuestionVal(6)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : '' const lesionLength = this.getQuestionVal(0)
const lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : '' const lesionShort = this.getQuestionVal(1)
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : '' const lesionState = this.getQuestionVal(7)
this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, lesionShort, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm }) this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, lesionShort, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
} }
} }

View File

@ -1,11 +1,21 @@
<template> <template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}"> <div class="measurement-wrapper">
<div class="container" :style="{'height':height+'px'}"> <div class="container">
<h3 v-if="isReadingShowSubjectInfo" style="color: #ddd;padding: 5px 0px;margin: 0;"> <div class="basic-info">
<span v-if="subjectCode">{{ subjectCode }} </span> <h3 v-if="isReadingShowSubjectInfo">
<span style="margin-left:5px;">{{ taskBlindName }}</span> <span v-if="subjectCode">{{ subjectCode }} </span>
</h3> <span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<div v-if="readingTaskState < 2">
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
<i
class="el-icon-refresh-left"
@click="resetMeasuredData"
/>
</el-tooltip>
</div>
</div>
<!-- 非测量问题 --> <!-- 非测量问题 -->
<div class="lesions"> <div class="lesions">
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" /> <Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" />
@ -118,6 +128,7 @@
</template> </template>
<script> <script>
import { splitLesion } from '@/api/trials' import { splitLesion } from '@/api/trials'
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent' import DicomEvent from './../DicomEvent'
import store from '@/store' import store from '@/store'
@ -154,7 +165,6 @@ export default {
}, },
data() { data() {
return { return {
height: window.innerHeight - 140,
questions: [], questions: [],
activeName: '', activeName: '',
activeItem: { activeItem: {
@ -197,7 +207,8 @@ export default {
} }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
window.addEventListener('message', this.receiveMsg) window.addEventListener('message', this.receiveMsg)
this.CriterionType = parseInt(localStorage.getItem('CriterionType')) this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => { DicomEvent.$on('setCollapseActive', measureData => {
@ -217,8 +228,6 @@ export default {
DicomEvent.$on('split', measureData => { DicomEvent.$on('split', measureData => {
this.handleSplit(measureData.RowId, measureData.QuestionId) this.handleSplit(measureData.RowId, measureData.QuestionId)
}) })
window.addEventListener('resize', this.setHeight)
}, },
beforeDestroy() { beforeDestroy() {
DicomEvent.$off('loadMeasurementList') DicomEvent.$off('loadMeasurementList')
@ -397,9 +406,6 @@ export default {
} catch (e) { console.log(e) } } catch (e) { console.log(e) }
}) })
}, },
setHeight() {
this.height = window.innerHeight - 140
},
getQuestionAnswer(questions, questionMark, answers) { getQuestionAnswer(questions, questionMark, answers) {
var idx = questions.findIndex(i => i.QuestionMark === questionMark) var idx = questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) { if (idx > -1) {
@ -497,15 +503,15 @@ export default {
} }
} }
}, },
split(rowId, questionId) { async split(rowId, questionId) {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
var params = { try {
visitTaskId: this.visitTaskId, var params = {
questionId: questionId, visitTaskId: this.visitTaskId,
rowId: rowId questionId: questionId,
} rowId: rowId
splitLesion(params).then(async res => { }
loading.close() await splitLesion(params)
await this.getReadingQuestionAndAnswer() await this.getReadingQuestionAndAnswer()
this.$nextTick(() => { this.$nextTick(() => {
this.tableQuestions.forEach(item => { this.tableQuestions.forEach(item => {
@ -515,7 +521,11 @@ export default {
}) })
}) })
}) })
}) loading.close()
} catch (e) {
loading.close()
console.log(e)
}
}, },
isCanActiveTool(toolName) { isCanActiveTool(toolName) {
this.getUnSaveTarget() this.getUnSaveTarget()
@ -879,6 +889,39 @@ export default {
getECRFQuestions(obj) { getECRFQuestions(obj) {
this.$refs['ecrf'].getQuestions(obj.visitTaskId) this.$refs['ecrf'].getQuestions(obj.visitTaskId)
}, },
async resetMeasuredData() {
const confirm = await this.$confirm(
this.$t('trials:dicomReading:message:confirmReset1'),
this.$t('trials:dicomReading:message:confirmReset2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const loading = this.$loading({ fullscreen: true })
try {
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
//
this.activeName = ''
this.activeItem.activeRowIndex = null
this.activeItem.activeCollapseId = null
await this.getReadingQuestionAndAnswer(this.visitTaskId)
const triald = this.$router.currentRoute.query.trialId
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
DicomEvent.$emit('getMeasureData')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('refreshStudyListMeasureData')
}
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
receiveMsg(event) { receiveMsg(event) {
if (event.data.type === 'isCanActiveNoneDicomTool') { if (event.data.type === 'isCanActiveNoneDicomTool') {
this.getUnSaveTarget() this.getUnSaveTarget()
@ -945,11 +988,28 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.measurement-wrapper{ .measurement-wrapper{
height: 100%;
overflow-y: auto; overflow-y: auto;
// overflow: hidden; // overflow: hidden;
.container{ .container{
padding: 10px; padding: 10px;
.basic-info{
display: flex;
justify-content: space-between;
align-items: center;
h3{
color: #ddd;
padding: 5px 0px;
margin: 0;
}
i{
color: #fff;
font-size: 22px;
font-weight: bold;
cursor: pointer;
}
}
} }
.title{ .title{
padding: 5px; padding: 5px;

View File

@ -12,8 +12,15 @@
style="margin-right:5px;" style="margin-right:5px;"
@change="handleShowDetail" @change="handleShowDetail"
/> />
<!--评估报告--> <el-button
<el-button :loading="reportBtnLoading" v-if="readingTaskState>=2" type="primary" size="small" @click="showReport">{{$t('trials:dicoms:button:evaluationReport')}}</el-button> v-if="readingTaskState<2"
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button <el-button
v-if="readingTaskState<2" v-if="readingTaskState<2"
type="primary" type="primary"
@ -24,7 +31,7 @@
{{ $t('trials:readingReport:button:refresh') }} {{ $t('trials:readingReport:button:refresh') }}
</el-button> </el-button>
<el-button <el-button
v-if="readingTaskState<2" v-if="readingTaskState<2 && CriterionType !== 10"
type="primary" type="primary"
size="small" size="small"
@click="handleSave(true)" @click="handleSave(true)"
@ -95,8 +102,8 @@
</div> </div>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
<span :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) || (scope.row.QuestionMark === 12) ? '#f66' : '#fff'}"> <span :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) || (scope.row.QuestionMark === 12) || scope.row.HighlightAnswerList.includes(`${scope.row.Answers[task.VisitTaskId]}`) ? '#f66' : '#fff'}">
<template v-if="task.VisitTaskId === visitTaskId && readingTaskState < 2 && [13,14,15,21,22,42].includes(scope.row.QuestionType)"> <template v-if="task.VisitTaskId === visitTaskId && readingTaskState < 2 && [13,14,15,42].includes(scope.row.QuestionType)">
<!-- 是否存在疾病基线时可修改 --> <!-- 是否存在疾病基线时可修改 -->
<template v-if="task.IsBaseLine && scope.row.QuestionType=== 15"> <template v-if="task.IsBaseLine && scope.row.QuestionType=== 15">
<el-select <el-select
@ -150,32 +157,6 @@
</template> </template>
</el-select> </el-select>
</template> </template>
<!-- 访视点肿瘤评估 -->
<template v-else-if="!task.IsBaseLine && scope.row.QuestionType=== 21">
<el-select
v-if="scope.row.Type==='select' && scope.row.DictionaryCode"
v-model="currentEvaluateResult"
size="mini"
@change="handleEvaluateResultChange"
>
<template>
<el-option
v-for="item of $d[ scope.row.DictionaryCode]"
v-show="task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
</el-select>
</template>
<template v-else-if="!task.IsBaseLine && scope.row.QuestionType=== 22">
<el-input v-model="intervalDays" size="mini" @change="handleIntervalDaysChange"
@input="handleNumberInput" maxlength="3"></el-input>
</template>
<template v-else-if="task.IsBaseLine && scope.row.QuestionType=== 22">
{{ scope.row.Answers[task.VisitTaskId] }}
</template>
<!-- <template v-else-if="task.IsBaseLine && scope.row.QuestionType=== 13"> <!-- <template v-else-if="task.IsBaseLine && scope.row.QuestionType=== 13">
{{ $fd(scope.row.DictionaryCode, currentEvaluateResult) }} {{ $fd(scope.row.DictionaryCode, currentEvaluateResult) }}
</template> --> </template> -->
@ -200,8 +181,9 @@
@change="evaluateReasonChange" @change="evaluateReasonChange"
/> />
<!-- 系统评估结果为xxx,与当前调整的结果不一致请填写调整原因 --> <!-- 系统评估结果为xxx,与当前调整的结果不一致请填写调整原因 -->
<p v-if="tumorEvaluate && currentEvaluateResult && parseInt(currentEvaluateResult) !== parseInt(tumorEvaluate)" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;">{{ $t('trials:readingReport:message:msg6').replace('***', $fd('CriterionType', CriterionType)) }}<span v-if="CriterionType === 2" style="color:red">{{ $fd('ImagingOverallAssessment_Lugano',tumorEvaluate) }}</span><span v-else-if="CriterionType === 10" style="color:red">{{ $fd('VisitTumorEvaluation',tumorEvaluate) }}</span><span v-else style="color:red">{{ $fd('OverallAssessment',tumorEvaluate) }}</span>{{ $t('trials:readingReport:message:msg7') }}<span v-if="CriterionType === 2" style="color:red">{{ $fd('ImagingOverallAssessment_Lugano',currentEvaluateResult) }}</span><span v-else-if="CriterionType === 10" style="color:red">{{ $fd('VisitTumorEvaluation',currentEvaluateResult) }}</span><span v-else style="color:red">{{ $fd('OverallAssessment',currentEvaluateResult) }}</span>{{ $t('trials:readingReport:message:msg8') }}</p> <p v-if="currentEvaluateResult !== tumorEvaluate" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;" v-html="getWarningText()" />
<p v-else-if="currentExistDisease !== isExistDisease" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;">{{ $t('trials:readingReport:title:sysEvaluationRes') }}<span style="color:red">{{ $fd('ExistDisease',isExistDisease) }}</span>{{ $t('trials:readingReport:message:msg1') }}</p> <p v-else-if="currentExistDisease !== isExistDisease" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;">{{ $t('trials:readingReport:title:sysEvaluationRes') }}<span style="color:red">{{ $fd('ExistDisease',isExistDisease) }}</span>{{ $t('trials:readingReport:message:msg1') }}
</p>
</template> </template>
<!-- <template v-else> <!-- <template v-else>
<span>{{ currentTaskReason }}</span> <span>{{ currentTaskReason }}</span>
@ -284,15 +266,11 @@
</div> </div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" /> <SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog> </el-dialog>
<!--评估报告-->
<PreviewFileDialog
:visible.sync="previewFileVisible"
:fileData="fileData"
/>
</div> </div>
</template> </template>
<script> <script>
import { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getTaskAdditionalQuestion } from '@/api/trials' import { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getTaskAdditionalQuestion } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user' import { getAutoCutNextTask } from '@/api/user'
import DicomEvent from './DicomEvent' import DicomEvent from './DicomEvent'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
@ -302,11 +280,9 @@ import store from '@/store'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import AdditionalAssessment from './AdditionalAssessment' import AdditionalAssessment from './AdditionalAssessment'
import { showReadReport } from "@/api/export";
import PreviewFileDialog from "@/components/PreviewFileDialog/PreviewFileDialog.vue";
export default { export default {
name: 'ReportPage', name: 'ReportPage',
components: { SignForm, AdditionalAssessment,PreviewFileDialog }, components: { SignForm, AdditionalAssessment },
props: { props: {
visitTaskId: { visitTaskId: {
type: String, type: String,
@ -343,13 +319,7 @@ export default {
assessmentQuestions: [], assessmentQuestions: [],
tLesionCount: null, tLesionCount: null,
ntLesionCount: null, ntLesionCount: null,
openWindow: null, openWindow: null
//
previewFileVisible: false,
fileData: {},
reportBtnLoading:false,
intervalDays: null
} }
}, },
computed: { computed: {
@ -390,35 +360,6 @@ export default {
} }
}, },
methods: { methods: {
//
async showReport(){
if(this.reportBtnLoading) return;
let data = {
VisitTaskId: this.visitTaskId,
};
try {
this.reportBtnLoading = true;
let res = await showReadReport(data);
// let urlPdf = window.URL.createObjectURL(new Blob([res]))
if(res.IsSuccess){
this.viewVisible = true;
let href = this.OSSclientConfig.basePath + res.Result;
// let fileName =
// res.Result.split("/")[res.Result.split("/").length - 1];
let fileName = '评估报告.pdf';
this.fileData = {
path:href,
name:fileName
};
}
this.reportBtnLoading = false;
this.previewFileVisible = true;
} catch (err) {
this.reportBtnLoading = false;
console.log(err);
}
},
myConfirm(msg) { myConfirm(msg) {
return new Promise(resolve => { return new Promise(resolve => {
this.$confirm(msg, { this.$confirm(msg, {
@ -470,32 +411,38 @@ export default {
getTableHeight() { getTableHeight() {
this.height = window.innerHeight - 170 this.height = window.innerHeight - 170
}, },
getReportInfo(IsCalculate) { async getReportInfo(IsCalculate) {
this.loading = true this.loading = true
var params = { try {
visitTaskId: this.visitTaskId, var params = {
trialId: this.$router.currentRoute.query.trialId, visitTaskId: this.visitTaskId,
IsCalculate: IsCalculate !== false trialId: this.$router.currentRoute.query.trialId,
} IsCalculate: IsCalculate !== false
getReadingReportEvaluation(params).then(res => { }
this.readingTaskState = res.Result.ReadingTaskState const res = await getReadingReportEvaluation(params)
this.tumorEvaluate = res.Result.CalculateResult.TumorEvaluate ? parseInt(res.Result.CalculateResult.TumorEvaluate) : null if (res.IsSuccess) {
this.isExistDisease = res.Result.CalculateResult.IsExistDisease ? parseInt(res.Result.CalculateResult.IsExistDisease) : null this.readingTaskState = res.Result.ReadingTaskState
this.answerArr = [] this.tumorEvaluate = res.Result.CalculateResult.TumorEvaluate ? parseInt(res.Result.CalculateResult.TumorEvaluate) : null
this.questions = res.Result.TaskQuestions.concat() this.isExistDisease = res.Result.CalculateResult.IsExistDisease ? parseInt(res.Result.CalculateResult.IsExistDisease) : null
this.visitTaskList = res.Result.VisitTaskList this.answerArr = []
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null) this.questions = res.Result.TaskQuestions.concat()
this.taskQuestions = [] this.visitTaskList = res.Result.VisitTaskList
taskQuestions.forEach(item => { var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
this.$set(this.taskQuestions, this.taskQuestions.length, item) this.taskQuestions = []
}) taskQuestions.forEach(item => {
const tLesion = res.Result.LesionCountList.find(i => i.LesionType === 0) this.$set(this.taskQuestions, this.taskQuestions.length, item)
this.tLesionCount = tLesion ? tLesion.Count : 0 })
const ntLesion = res.Result.LesionCountList.find(i => i.LesionType === 1) const tLesion = res.Result.LesionCountList.find(i => i.LesionType === 0)
this.ntLesionCount = ntLesion ? ntLesion.Count : 0 this.tLesionCount = tLesion ? tLesion.Count : 0
this.setScrollTop() const ntLesion = res.Result.LesionCountList.find(i => i.LesionType === 1)
this.ntLesionCount = ntLesion ? ntLesion.Count : 0
this.setScrollTop()
}
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
console.log(e)
}
}, },
setScrollTop(a) { setScrollTop(a) {
setTimeout(() => { setTimeout(() => {
@ -503,7 +450,6 @@ export default {
if (this.$refs.reportList) { if (this.$refs.reportList) {
this.getTableHeight() this.getTableHeight()
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
} }
}) })
}, 50) }, 50)
@ -611,7 +557,7 @@ export default {
this.currentExistDisease = obj.Answers[this.visitTaskId] this.currentExistDisease = obj.Answers[this.visitTaskId]
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 15 }) this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 15 })
} }
if (item.QuestionType === 13 || item.QuestionType === 42 || item.QuestionType === 21) { if (item.QuestionType === 13 || item.QuestionType === 42) {
this.currentEvaluateResult = obj.Answers[this.visitTaskId] this.currentEvaluateResult = obj.Answers[this.visitTaskId]
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: item.QuestionType }) this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: item.QuestionType })
} }
@ -619,10 +565,6 @@ export default {
this.currentTaskReason = obj.Answers[this.visitTaskId] this.currentTaskReason = obj.Answers[this.visitTaskId]
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 }) this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 })
} }
if (item.QuestionType === 22) {
this.intervalDays = obj.Answers[this.visitTaskId]
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId]?obj.Answers[this.visitTaskId]:null, questionType: 22 })
}
if (item.Childrens.length >= 1) { if (item.Childrens.length >= 1) {
obj.Childrens = this.getQuestions(item.Childrens, isNTFilterLength, lesionType, isLymphNodes) obj.Childrens = this.getQuestions(item.Childrens, isNTFilterLength, lesionType, isLymphNodes)
} }
@ -657,7 +599,7 @@ export default {
} }
this.currentTaskReason = '' this.currentTaskReason = ''
this.evaluateReasonChange('') this.evaluateReasonChange('')
var idx = this.answerArr.findIndex(i => i.questionType === 13 || i.questionType === 42 || i.questionType === 21) var idx = this.answerArr.findIndex(i => i.questionType === 13 || i.questionType === 42)
if (idx > -1) { if (idx > -1) {
this.answerArr[idx].answer = val this.answerArr[idx].answer = val
} }
@ -670,39 +612,32 @@ export default {
this.answerArr[idx].answer = val this.answerArr[idx].answer = val
} }
}, },
handleIntervalDaysChange(v) {
var idx = this.answerArr.findIndex(i => i.questionType === 22)
if (idx > -1) {
this.answerArr[idx].answer = v
}
},
handleNumberInput(value) {
var reg = /^(?!0)\d{1,3}$/
if(reg.test(value)==false){
this.intervalDays = ""
}else{
this.intervalDays = value
}
},
async handleConfirm() { async handleConfirm() {
await this.handleSave(false) this.loading = true
await this.verifyVisitTaskQuestions() try {
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) await this.handleSave(false)
var isBaseline = this.visitTaskList[i].IsBaseLine await verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId })
if (isBaseline) { var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.assessmentQuestions = await this.getAdditionalAssessments() var isBaseline = this.visitTaskList[i].IsBaseLine
if (this.assessmentQuestions.length > 0) { if (isBaseline) {
const res = await getTaskAdditionalQuestion({ visitTaskId: this.visitTaskId })
this.assessmentQuestions = res.Result
if (this.assessmentQuestions.length > 0) {
// //
this.additionalAssessmentsDig.visible = true this.additionalAssessmentsDig.visible = true
} else {
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}
} else { } else {
const { ImageAssessmentReportConfirmation } = const_.processSignature const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true this.signVisible = true
} }
} else { this.loading = false
const { ImageAssessmentReportConfirmation } = const_.processSignature } catch (e) {
this.signCode = ImageAssessmentReportConfirmation this.loading = false
this.signVisible = true
} }
}, },
sign() { sign() {
@ -713,31 +648,6 @@ export default {
this.signVisible = true this.signVisible = true
}) })
}, },
//
getAdditionalAssessments() {
return new Promise((resolve) => {
this.loading = true
getTaskAdditionalQuestion({ visitTaskId: this.visitTaskId }).then(res => {
this.loading = false
resolve(res.Result)
}).catch(() => {
this.loading = false
resolve()
})
})
},
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() { handleResize() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.reportList && this.$refs.reportList.doLayout() this.$refs.reportList && this.$refs.reportList.doLayout()
@ -752,15 +662,16 @@ export default {
} }
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
var params = { try {
data: { var params = {
visitTaskId: this.visitTaskId data: {
}, visitTaskId: this.visitTaskId
signInfo: signInfo },
} signInfo: signInfo
submitDicomVisitTask(params).then(async res => { }
const res = await submitDicomVisitTask(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) { if (this.$refs['signForm']) {
@ -776,7 +687,8 @@ export default {
await store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 }) await store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
// DicomEvent.$emit('setReadingState', 2) // DicomEvent.$emit('setReadingState', 2)
await store.dispatch('reading/setCurrentReadingTaskState', 2) await store.dispatch('reading/setCurrentReadingTaskState', 2)
var isAutoTask = await this.getAutoTaskVal() const res = await getAutoCutNextTask()
var isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) { if (isAutoTask) {
// DicomEvent.$emit('reload') // DicomEvent.$emit('reload')
// DicomEvent.$emit('getNextTask') // DicomEvent.$emit('getNextTask')
@ -800,19 +712,12 @@ export default {
// DicomEvent.$emit('readingPageStateUpdate', { readingTaskState: 2 }) // DicomEvent.$emit('readingPageStateUpdate', { readingTaskState: 2 })
} }
this.loading = false this.loading = false
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) { if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
} }
}) }
},
getAutoTaskVal() {
return new Promise((resolve, reject) => {
getAutoCutNextTask().then(res => {
resolve(res.Result.AutoCutNextTask)
}).catch(() => { reject() })
})
}, },
previewDicoms(task) { previewDicoms(task) {
if (this.openWindow) { if (this.openWindow) {
@ -820,7 +725,8 @@ export default {
} }
var token = getToken() var token = getToken()
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var subjectCode = this.$router.currentRoute.query.subjectCode // var subjectCode = this.$router.currentRoute.query.subjectCode
var subjectCode = localStorage.getItem('subjectCode')
var subjectId = this.$router.currentRoute.query.subjectId var subjectId = this.$router.currentRoute.query.subjectId
var trialId = this.$router.currentRoute.query.trialId var trialId = this.$router.currentRoute.query.trialId
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
@ -831,14 +737,14 @@ export default {
this.openWindow = window.open(routeData.href, '_blank') this.openWindow = window.open(routeData.href, '_blank')
}, },
handleSave(isPrompt) { handleSave(isPrompt) {
return new Promise((resolve, reject) => { return new Promise(async(resolve, reject) => {
var isBeill var isBeill
var evaluateResult = '' var evaluateResult = ''
var evaluateAjustReason = '' var evaluateAjustReason = ''
this.answers = [] this.answers = []
var isExistEvaluateResult = false var isExistEvaluateResult = false
this.answerArr.map(item => { this.answerArr.map(item => {
if (item.questionType === 13 || item.questionType === 42 || item.questionType === 21) { if (item.questionType === 13 || item.questionType === 42) {
evaluateResult = item.answer evaluateResult = item.answer
isExistEvaluateResult = true isExistEvaluateResult = true
} }
@ -870,7 +776,7 @@ export default {
reject() reject()
return return
} }
if (this.tumorEvaluate !== null && isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) { if (isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) {
// //
this.$confirm(this.$t('trials:readingReport:message:msg3'), { this.$confirm(this.$t('trials:readingReport:message:msg3'), {
type: 'warning', type: 'warning',
@ -881,21 +787,57 @@ export default {
return return
} }
this.loading = true this.loading = true
var params = { try {
visitTaskId: this.visitTaskId, var params = {
answers: this.answers visitTaskId: this.visitTaskId,
} answers: this.answers
changeDicomReadingQuestionAnswer(params).then(res => { }
if (isPrompt) { const res = await changeDicomReadingQuestionAnswer(params)
if (res.IsSuccess && isPrompt) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
} }
this.loading = false this.loading = false
resolve() resolve()
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
reject() reject()
}) }
}) })
},
getWarningText() {
var sysRes = ''
var curRes = ''
if (this.CriterionType === 2) {
sysRes = this.$fd('ImagingOverallAssessment_Lugano', this.tumorEvaluate)
curRes = this.$fd('ImagingOverallAssessment_Lugano', this.currentEvaluateResult)
} else {
sysRes = this.$fd('OverallAssessment', this.tumorEvaluate)
curRes = this.$fd('OverallAssessment', this.currentEvaluateResult)
}
const msg = this.$t('trials:readingReport:message:msg9').replace('xxx', '<font color="red">' + sysRes + '</font>').replace('yyy', '<font color="red">' + curRes + '</font>')
return msg
},
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)
}
} }
} }
} }
@ -976,4 +918,7 @@ export default {
/deep/ .el-switch__label.is-active{ /deep/ .el-switch__label.is-active{
color: #428bca; color: #428bca;
} }
.colorOfRed{
color: #f66;
}
</style> </style>

View File

@ -49,20 +49,42 @@
/> />
<div class="image-desc"> <div class="image-desc">
<div class="flex-div"> <div class="flex-div">
<div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }} </div> <div style="width: 40px;display: flex;flex-direction: row;justify-content: space-between;">
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount && series.modality!== 'SR'"> <div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }}</div>
<!-- 下载 --> <div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount * 100 && series.modality!== 'SR'">
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom"> <!-- 下载 -->
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
</el-tooltip>
</div>
<el-tooltip v-else-if="series.isDicom && series.prefetchInstanceCount === 0 &&series.modality!== 'SR'" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" /> <i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
</el-tooltip> </el-tooltip>
<!-- 暂停 -->
<!-- <el-tooltip v-else class="item" effect="dark" :content="$t('trials:reading:button:pause')" placement="bottom">
<i class="el-icon-video-pause" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="stopLoadSeries(series,index,i)" />
</el-tooltip> -->
</div> </div>
<el-tooltip v-else-if="series.isDicom && series.prefetchInstanceCount === 0 &&series.modality!== 'SR'" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom"> <div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" /> <el-popover
</el-tooltip> placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div class="frame_list">
<div
v-for="(instance, idx) in series.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.instanceInfoList.length-1? '5px':'0px'}"
@click.stop="showMultiFrames(index,series, i, instance)"
>
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;color: #ffeb3b;" />
</el-popover>
</div>
</div> </div>
<p v-show="series.description"> <p v-show="series.description">
<el-tooltip class="item" effect="dark" :content="series.description" placement="right"> <el-tooltip class="item" effect="dark" :content="series.description" placement="right">
@ -73,7 +95,10 @@
<p v-show="series.sliceThickness && !study.IsCriticalSequence"> <p v-show="series.sliceThickness && !study.IsCriticalSequence">
T: {{ parseFloat(series.sliceThickness).toFixed(digitPlaces) }} T: {{ parseFloat(series.sliceThickness).toFixed(digitPlaces) }}
</p> </p>
<p v-show="series.instanceCount"> <p v-show="series.instanceCount && series.imageloadedArr.length < series.instanceCount">
{{ series.modality }}: {{ series.imageloadedArr.length }}/{{ series.instanceCount }} image
</p>
<p v-show="series.instanceCount && series.imageloadedArr.length >= series.instanceCount">
{{ series.modality }}: {{ series.instanceCount }} image {{ series.modality }}: {{ series.instanceCount }} image
</p> </p>
@ -88,9 +113,9 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" style="width: 100%;"> <div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount * 100" style="width: 100%;">
<el-progress <el-progress
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))" :percentage="parseInt((series.prefetchInstanceCount / series.instanceCount).toFixed(2))"
/> />
</div> </div>
@ -125,18 +150,13 @@
</div> </div>
</template> </template>
<script> <script>
import * as dicomParser from 'dicom-parser' // import * as cornerstone from 'cornerstone-core'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import requestPoolManager from '@/utils/request-pool' import requestPoolManager from '@/utils/request-pool'
import DicomEvent from './DicomEvent' import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import store from '@/store' import store from '@/store'
import SrList from './SrList' import SrList from './SrList'
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
export default { export default {
name: 'StudyList', name: 'StudyList',
components: { SrList }, components: { SrList },
@ -219,7 +239,8 @@ export default {
// } // }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
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
DicomEvent.$on('refreshStudyListMeasureData', () => { DicomEvent.$on('refreshStudyListMeasureData', () => {
@ -233,99 +254,72 @@ export default {
// this.studyList = this.visitTaskList[idx].StudyList // this.studyList = this.visitTaskList[idx].StudyList
// } // }
// }) // })
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded) // const debouncedInputHandler = this.debounce(this.cornerstoneimageloadprogress, 100)
// cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
// cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
// cornerstone.events.addEventListener('cornerstoneimagecachefull', this.cornerstoneimagecachefull) // cornerstone.events.addEventListener('cornerstoneimagecachefull', this.cornerstoneimagecachefull)
// cornerstone.events.addEventListener('cornerstoneimagecachechanged', this.cornerstoneimagecachechanged) // cornerstone.events.addEventListener('cornerstoneimagecachechanged', this.cornerstoneimagecachechanged)
window.addEventListener('beforeunload', e => { // window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache() // cornerstone.imageCache.purgeCache()
}) // })
}, },
beforeDestroy() { beforeDestroy() {
cornerstone.imageCache.purgeCache() // cornerstone.imageCache.purgeCache()
DicomEvent.$off('refreshStudyListMeasureData') DicomEvent.$off('refreshStudyListMeasureData')
window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() }) // window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() })
}, },
methods: { methods: {
debounce(fn, delay) {
let timer = null
return function() {
const context = this
const args = arguments
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
},
initStudyInfo() { initStudyInfo() {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
// //
this.getInitSeries().then((res) => { this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer() requestPoolManager.startTaskTimer()
res.map((item) => { res.map(async(item) => {
this.loadInitialImage(item) // this.loadInitialImage(item)
const imageId = item.imageIds[item.imageIdIndex]
const p = parseInt(new Date().getTime())
await requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
if (!item.isCurrentTask) {
store.dispatch('reading/setImageloadedInfo', item)
}
}) })
var i = res.findIndex(s => s.isCurrentTask) var i = -1
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
if (isReadingTaskViewInOrder === 2) {
//
i = res.length === 2 ? 1 : -1
} else {
i = res.findIndex(s => s.isCurrentTask)
}
if (i > -1) { if (i > -1) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1) { if (idx > -1) {
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
this.studyList = this.visitTaskList[idx].StudyList this.studyList = this.visitTaskList[idx].StudyList
var priority = parseInt(new Date().getTime()) var priority = parseInt(new Date().getTime())
res[i].imageIds.map(image => { if (res[i].isExistMutiFrames) {
priority-- res[i].instanceInfoList.map(image => {
this.imageList.push({ imageId: image, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].visitTaskId, priority }) priority--
}) this.imageList.push({ imageId: image.ImageId, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].visitTaskId, priority })
// this.studyList.map((study, studyIndex) => {
// study.SeriesList.map((series, seriesIndex) => {
// if (series.modality !== 'SR') {
// series.imageIds.map(image => {
// var p = priority - seriesIndex
// if (series.seriesId === res[i].seriesId) {
// p = priority
// } else {
// --p
// }
// this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority: p })
// })
// }
// })
// })
this.loopLoad()
}
}
DicomEvent.$emit('loadImageStacks', res)
loading.close()
this.isRender = true
}).catch(() => {
loading.close()
})
},
initStudyInfo2() {
console.log('initStudyInfo')
const loading = this.$loading({ fullscreen: true })
//
this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer()
res.map((item) => {
this.loadInitialImage(item)
})
var i = res.findIndex(s => s.isCurrentTask)
if (i > -1) {
var p = parseInt(new Date().getTime())
// var p = this.visitTaskId === this.currentTaskId ? parseInt(new Date().getTime()) : 999 //
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1) {
this.measureData = this.visitTaskList[idx].MeasureData
this.studyList = this.visitTaskList[idx].StudyList
this.studyList.map((study, studyIndex) => {
study.SeriesList.map((series, seriesIndex) => {
if (series.modality !== 'SR') {
// var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
// if (sliceThickness === 5 || series.instanceCount <= 100) {
series.imageIds.map(image => {
let priority = 0
if (series.seriesId === res[i].seriesId) {
priority = parseInt(new Date().getTime()) * 10
} else {
priority = --p
}
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
}) })
}) } else {
res[i].imageIds.map(image => {
priority--
this.imageList.push({ imageId: image, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].visitTaskId, priority })
})
}
this.loopLoad() this.loopLoad()
} }
} }
@ -341,9 +335,9 @@ export default {
var p = parseInt(new Date().getTime()) var p = parseInt(new Date().getTime())
var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex] var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex]
requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100).then(res => { requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100).then(res => {
if (seriesInfo.isCurrentTask) { // if (seriesInfo.isCurrentTask) {
this.imageLoaded({ studyIndex: seriesInfo.studyIndex, seriesIndex: seriesInfo.seriesIndex, imageId: res.imageId }, res.data.string('x0020000e')) // this.imageLoaded({ studyIndex: seriesInfo.studyIndex, seriesIndex: seriesInfo.seriesIndex, imageId: res.imageId }, res.data.string('x0020000e'))
} // }
}) })
}, },
getStudyList() { getStudyList() {
@ -355,11 +349,31 @@ export default {
this.studyList = this.visitTaskList[idx].StudyList this.studyList = this.visitTaskList[idx].StudyList
var sIdx = this.studyList.findIndex(s => s.IsDicom) var sIdx = this.studyList.findIndex(s => s.IsDicom)
if (sIdx > -1) { if (sIdx > -1) {
this.studyIndex = sIdx console.log(this.studyIndex, this.studyIndex)
this.seriesIndex = 0 // this.studyIndex = sIdx
// c = 0
this.activeNames = [`${this.studyList[sIdx].StudyId}`] this.activeNames = [`${this.studyList[sIdx].StudyId}`]
//
this.loadImages(this.visitTaskList[idx]) const i = this.studyList.findIndex(i => i.IsCriticalSequence)
if (i > -1 && this.studyList[i].SeriesList[0].length > 0) {
const series = this.studyList[i].SeriesList[0]
if (!series.loadStatus) {
let priority = parseInt(new Date().getTime())
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
priority = priority - 1
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: i, seriesIndex: 0, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map(imageId => {
priority = priority - 1
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: i, seriesIndex: 0, visitTaskId: series.visitTaskId, priority })
})
}
}
}
this.loopLoad()
// this.loadImages(this.visitTaskList[idx])
} }
} }
this.isRender = true this.isRender = true
@ -368,11 +382,26 @@ export default {
async getInitSeries() { async getInitSeries() {
var seriesList = [] var seriesList = []
var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder) var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.studyList = this.visitTaskList[idx].StudyList this.studyList = this.visitTaskList[idx].StudyList
if (this.visitTaskList[idx].IsBaseLineTask || !isReadingTaskViewInOrder) { const studyList = this.visitTaskList[idx].StudyList.filter(i => i.IsDicom)
// 线 const seriesArr = studyList.map(s => s.SeriesList).flat()
if (isReadingTaskViewInOrder === 2) {
//
if (seriesArr.length === 1) {
seriesList.push(seriesArr[0], seriesArr[0])
this.studyIndex = seriesArr[0].studyIndex
this.seriesIndex = seriesArr[0].seriesIndex
this.activeNames = [`${seriesArr[0].studyId}`]
} else if (seriesArr.length > 1) {
seriesList.push(seriesArr[0], seriesArr[1])
this.studyIndex = seriesArr[1].studyIndex
this.seriesIndex = seriesArr[1].seriesIndex
this.activeNames = [`${seriesArr[1].studyId}`]
}
} else if (this.visitTaskList[idx].IsBaseLineTask || isReadingTaskViewInOrder === 0) {
// 线
const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList]) const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList])
if (Object.keys(obj).length !== 0) { if (Object.keys(obj).length !== 0) {
this.studyIndex = obj.studyIndex this.studyIndex = obj.studyIndex
@ -381,9 +410,13 @@ export default {
this.activeNames = [`${this.studyList[ this.studyIndex].StudyId}`] this.activeNames = [`${this.studyList[ this.studyIndex].StudyId}`]
this.studyList[ obj.studyIndex].SeriesList[obj.seriesIndex].isFirstRender = true this.studyList[ obj.studyIndex].SeriesList[obj.seriesIndex].isFirstRender = true
} else { } else {
//
if (this.studyList.length > 0) { if (this.studyList.length > 0) {
this.activeNames = [`${this.studyList[0].StudyId}`] //
this.studyIndex = seriesArr[0].studyIndex
this.seriesIndex = seriesArr[0].seriesIndex
this.activeNames = [`${seriesArr[0].studyId}`]
seriesList.push(seriesArr[0])
// this.activeNames = [`${this.studyList[0].StudyId}`]
} }
// DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskList[idx].VisitTaskId, taskBlindName: this.visitTaskList[idx].TaskBlindName }) // DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskList[idx].VisitTaskId, taskBlindName: this.visitTaskList[idx].TaskBlindName })
@ -407,6 +440,7 @@ export default {
const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList]) const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList])
seriesList.push(firstObj.series) seriesList.push(firstObj.series)
const secondObj = this.getSecondMarkedSeries(firstObj, { ...this.visitTaskList[idx] }) const secondObj = this.getSecondMarkedSeries(firstObj, { ...this.visitTaskList[idx] })
this.studyIndex = secondObj.studyIndex this.studyIndex = secondObj.studyIndex
this.seriesIndex = secondObj.seriesIndex this.seriesIndex = secondObj.seriesIndex
@ -441,9 +475,10 @@ export default {
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId) const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId)
const seriesList = studyList[sdIndx].SeriesList const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId) const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId)
// const instanceList = seriesList[srIdx].imageIds // const instanceList = seriesList[srIdx].instanceList
const instanceList = seriesList[srIdx].instanceList const imageIds = seriesList[srIdx].imageIds
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId)) const filterStr = seriesList[srIdx].isExistMutiFrames ? `frame=${measureDatas[i].MeasureData.frame}&instanceId=${measureDatas[i].InstanceId}` : `instanceId=${measureDatas[i].InstanceId}`
const isIdx = imageIds.findIndex(is => is.includes(filterStr))
const series = seriesList[srIdx] const series = seriesList[srIdx]
series.imageIdIndex = isIdx series.imageIdIndex = isIdx
@ -514,8 +549,9 @@ export default {
const seriesList = studyList[sdIndx].SeriesList const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId) const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId)
// const instanceList = seriesList[srIdx].imageIds // const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList const imageIds = seriesList[srIdx].imageIds
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId)) const filterStr = seriesList[srIdx].isExistMutiFrames ? `frame=${measureDatas[mIdx].MeasureData.frame}&instanceId=${measureDatas[mIdx].InstanceId}` : `instanceId=${measureDatas[mIdx].InstanceId}`
const isIdx = imageIds.findIndex(is => is.includes(filterStr))
const series = seriesList[srIdx] const series = seriesList[srIdx]
series.imageIdIndex = isIdx series.imageIdIndex = isIdx
@ -544,22 +580,20 @@ export default {
obj.series = seriesObj.series obj.series = seriesObj.series
obj.seriesId = seriesObj.series.seriesId obj.seriesId = seriesObj.series.seriesId
obj.isMarked = false obj.isMarked = false
} else {
const sIdx = studyList.findIndex(s => s.IsDicom)
if (sIdx > -1) {
// 5
const series = studyList[sIdx].SeriesList[0]
var imageIdIndex = series.imageIds.length > 1 ? Math.floor(series.imageIds.length / 2) - 1 : 0
obj.studyIndex = sIdx
obj.seriesIndex = 0
obj.series = series
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
obj.seriesId = series.seriesId
obj.isMarked = false
}
} }
} }
if (Object.keys(obj).length === 0) {
const sIdx = studyList.findIndex(s => s.IsDicom)
if (sIdx > -1) {
obj.studyIndex = sIdx
obj.seriesIndex = 0
obj.series = studyList[obj.studyIndex].SeriesList[obj.seriesIndex]
const imageIdIndex = Math.floor(obj.series.imageIds.length / 2)
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
// obj.seriesId = series.seriesId
obj.isMarked = false
}
}
return obj return obj
}, },
strSimilarity2Number(s, t) { strSimilarity2Number(s, t) {
@ -613,7 +647,10 @@ export default {
this.studyIndex = studyIndex this.studyIndex = studyIndex
this.seriesIndex = seriesIndex this.seriesIndex = seriesIndex
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
var dicomStatck = this.studyList[studyIndex].SeriesList[seriesIndex] // var dicomStatck = this.studyList[studyIndex].SeriesList[seriesIndex]
var dicomStatck = Object.assign({}, this.studyList[studyIndex].SeriesList[seriesIndex])
dicomStatck.imageIdIndex = 0
this.$emit('loadImageStack', dicomStatck) this.$emit('loadImageStack', dicomStatck)
if (!series.loadStatus && series.modality !== 'SR') { if (!series.loadStatus && series.modality !== 'SR') {
this.loopLoadStatus = -1 this.loopLoadStatus = -1
@ -626,9 +663,15 @@ export default {
} }
if (!isAddToTakPool) { if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime()) var priority = parseInt(new Date().getTime())
series.imageIds.map((imageId) => { if (series.isExistMutiFrames) {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) series.instanceInfoList.map(image => {
}) this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map(imageId => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
this.loopLoadStatus = 0 this.loopLoadStatus = 0
this.loopLoad() this.loopLoad()
@ -647,6 +690,59 @@ export default {
store.dispatch('reading/setActiveSeries', series) store.dispatch('reading/setActiveSeries', series)
}, },
showMultiFrames(studyIndex, series, seriesIndex, instanceInfo) {
this.currentSeriesIndex = seriesIndex
var idx = this.visitTaskIdx
const imageIds = []
if (instanceInfo.KeyFramesList.length > 0) {
instanceInfo.KeyFramesList.map(i => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${i}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
})
} else if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
}
this.studyIndex = studyIndex
this.seriesIndex = seriesIndex
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
// var dicomStatck = this.studyList[studyIndex].SeriesList[seriesIndex]
var dicomStatck = Object.assign({}, this.studyList[studyIndex].SeriesList[seriesIndex])
dicomStatck.imageIds = imageIds
dicomStatck.imageIdIndex = 0
this.$emit('loadImageStack', dicomStatck)
this.loopLoadStatus = -1
series.isLoading = true
var isAddToTakPool = false
if (this.showSeriesList.includes(`${studyIndex}_${seriesIndex}`)) {
isAddToTakPool = true
} else {
this.showSeriesList.push(`${studyIndex}_${seriesIndex}`)
}
if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime())
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map((imageId) => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
if (this.imageList.length > 0) {
this.loopLoadStatus = 0
this.loopLoad()
}
} else {
requestPoolManager.changePriority(series.seriesId)
}
DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskId, taskBlindName: this.taskBlindName })
},
setSeriesActive(obj) { setSeriesActive(obj) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx === -1) return if (idx === -1) return
@ -656,7 +752,8 @@ export default {
var activeNames = `${this.studyList[obj.studyIndex].StudyId}` var activeNames = `${this.studyList[obj.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames) this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx]) // console.log('setSeriesActive', obj)
this.loadImages(obj)
}, },
selectSeries(obj) { selectSeries(obj) {
var seriseList = this.studyList.map(s => s.SeriesList).flat() var seriseList = this.studyList.map(s => s.SeriesList).flat()
@ -681,10 +778,27 @@ export default {
var activeNames = `${this.studyList[series.studyIndex].StudyId}` var activeNames = `${this.studyList[series.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames) this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx]) this.loadImages(series)
store.dispatch('reading/setActiveSeries', series) store.dispatch('reading/setActiveSeries', series)
}, },
loadImages(taskInfo) { loadImages(series) {
var priority = parseInt(new Date().getTime())
if (!series.loadStatus && series.isDicom && series.modality !== 'SR') {
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
priority = priority - 1
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: series.studyIndex, seriesIndex: series.seriesIndex, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map(imageId => {
priority = priority - 1
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: series.studyIndex, seriesIndex: series.seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
}
this.loopLoad()
},
loadImages1(taskInfo) {
// const isBaseLineTask = taskInfo.IsBaseLineTask // const isBaseLineTask = taskInfo.IsBaseLineTask
const isCurrentTask = taskInfo.IsCurrentTask const isCurrentTask = taskInfo.IsCurrentTask
// var priority = isCurrentTask ? parseInt(new Date().getTime()) : 999 // var priority = isCurrentTask ? parseInt(new Date().getTime()) : 999
@ -705,10 +819,17 @@ export default {
// } // }
// //
if (!isCurrentTask && study.IsCriticalSequence) { if (!isCurrentTask && study.IsCriticalSequence) {
series.imageIds.map(image => { if (series.isExistMutiFrames) {
priority = priority - 1 series.instanceInfoList.map(image => {
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) priority = priority - 1
}) this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map(imageId => {
priority = priority - 1
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
} }
} }
}) })
@ -720,11 +841,7 @@ export default {
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
// requestPoolManager.startTaskTimer() // requestPoolManager.startTaskTimer()
this.imageList.map(image => { this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => { requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
if (res) {
this.imageLoaded(image, res.data.string('x0020000e'))
}
})
}) })
requestPoolManager.sortTaskPool() requestPoolManager.sortTaskPool()
@ -744,12 +861,22 @@ export default {
} }
if (!isAddToTakPool) { if (!isAddToTakPool) {
const priority = parseInt(new Date().getTime()) const priority = parseInt(new Date().getTime())
series.imageIds.map(image => { if (series.isExistMutiFrames) {
const index = this.cachedImages.findIndex(item => item.uri === image) series.instanceInfoList.map(image => {
if (index === -1) { const index = this.cachedImages.findIndex(item => item.uri === image)
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) if (index === -1) {
} this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
}) }
})
} else {
series.imageIds.map(image => {
const index = this.cachedImages.findIndex(item => item.uri === image)
if (index === -1) {
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
}
})
}
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
this.loopLoadStatus = 0 this.loopLoadStatus = 0
this.loopLoad() this.loopLoad()
@ -763,83 +890,6 @@ export default {
console.log('stopLoadSeries') console.log('stopLoadSeries')
requestPoolManager.removeTask(series.seriesId) requestPoolManager.removeTask(series.seriesId)
this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', false) this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', false)
},
async imageLoaded(image, seriesUid) {
// await store.dispatch('reading/updateStudyList', { visitTaskId: image.visitTaskId, imageId: image.imageId, seriesUid })
// console.log(this.studyList[image.studyIndex].SeriesList[image.seriesIndex])
if (image.studyIndex > -1 && image.seriesIndex > -1) {
var prefetchInstanceCount = this.studyList[image.studyIndex].SeriesList[image.seriesIndex].prefetchInstanceCount
var instanceCount = this.studyList[image.studyIndex].SeriesList[image.seriesIndex].instanceCount
if (this.studyList[image.studyIndex].SeriesList[image.seriesIndex].imageloadedArr.indexOf(image.imageId) < 0) {
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].imageloadedArr.push(image.imageId)
prefetchInstanceCount = prefetchInstanceCount + 1
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].prefetchInstanceCount = prefetchInstanceCount
}
if (prefetchInstanceCount >= instanceCount) {
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].prefetchInstanceCount = this.studyList[image.studyIndex].SeriesList[image.seriesIndex].instanceCount
//
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].loadStatus = true
}
}
// store.dispatch('reading/updateSeriesList', { visitTaskindex: this.visitTaskIdx, studyIndex: image.studyIndex, seriesIndex: image.seriesIndex, imageId: image.imageId })
},
// instance
async cornerstoneImageLoaded(e) {
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
// if (idx === -1) return
// this.studyList = this.visitTaskList[idx].StudyList
// if (!this.studyList || this.studyList.length === 0) {
// return
// }
// if (!this.visitTaskList[idx].IsInit) {
// const loading = this.$loading({ fullscreen: true })
// await store.dispatch('reading/getMeasuredData', this.visitTaskList[idx].VisitTaskId)
// await store.dispatch('reading/getStudyInfo', { trialId: this.trialId, subjectVisitId: this.visitTaskList[idx].VisitId, visitTaskId: this.visitTaskList[idx].VisitTaskId, taskBlindName: this.visitTaskList[idx].TaskBlindName })
// await store.dispatch('reading/getReadingQuestionAndAnswer', { trialId: this.trialId, visitTaskId: this.visitTaskList[idx].VisitTaskId })
// await store.dispatch('reading/getDicomReadingQuestionAnswer', { trialId: this.trialId, visitTaskId: this.visitTaskList[idx].VisitTaskId })
// await store.dispatch('reading/setStatus', { visitTaskId: this.visitTaskList[idx].VisitTaskId })
// loading.close()
// }
// await store.dispatch('reading/updateStudyList', { visitTaskId: this.visitTaskId, imageId: e.detail.image.imageId, seriesUid: e.detail.image.data.string('x0020000e') })
// const uri = e.detail.image.sharedCacheKey
// const index = this.cachedImages.findIndex(item => item.uri === uri)
// if (index === -1) {
// this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
// } else {
// this.cachedImages[index].timestamp = new Date().getTime()
// }
// var imageId = e.detail.image.imageId
// var seriesUid = e.detail.image.data.string('x0020000e')
// var studyIndex = -1
// var seriesIndex = -1
// for (let i = 0; i < this.studyList.length; ++i) {
// for (let j = 0; j < this.studyList[i].SeriesList.length; ++j) {
// if (this.studyList[i].SeriesList[j].seriesUid === seriesUid) {
// studyIndex = i
// seriesIndex = j
// break
// }
// }
// if (studyIndex > 0) break
// }
// if (seriesIndex < 0) return
// const imageIdIndex = this.studyList[studyIndex].SeriesList[seriesIndex].imageIds.indexOf(imageId)
// if (imageIdIndex < 0) return
// if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
// if (this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount >= this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount) {
// //
// this.studyList[studyIndex].SeriesList[seriesIndex].loadStatus = true
// }
// }
},
cornerstoneimagecachechanged(e) {
const cacheInfo = cornerstone.imageCache.getCacheInfo()
console.log(cacheInfo)
},
cornerstoneimagecachefull(e) {
console.log('超过内存了')
} }
} }
} }
@ -936,6 +986,7 @@ export default {
padding: 1px; padding: 1px;
margin: 0px; margin: 0px;
} }
} }
} }
/deep/.el-collapse{ /deep/.el-collapse{
@ -986,5 +1037,41 @@ export default {
} }
} }
} }
</style>
<style>
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_list{
max-height: 500px;
overflow-y: auto;
}
.instance_frame_wrapper ::-webkit-scrollbar {
width: 7px;
height: 7px;
}
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
</style> </style>

View File

@ -83,13 +83,16 @@ export default {
this.getWL() this.getWL()
}, },
methods: { methods: {
getWL() { async getWL() {
this.loading = true this.loading = true
getUserWLTemplateList().then(res => { try {
const res = await getUserWLTemplateList()
this.tableData = res.Result this.tableData = res.Result
this.loading = false this.loading = false
this.$emit('getWwcTpl') this.$emit('getWwcTpl')
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
handleAdd() { handleAdd() {
this.customWwc.title = this.$t('common:button:new') this.customWwc.title = this.$t('common:button:new')
@ -101,22 +104,27 @@ export default {
this.row = Object.assign({}, row) this.row = Object.assign({}, row)
this.customWwc.visible = true this.customWwc.visible = true
}, },
handleDelete(row) { async handleDelete(row) {
// '' // ''
var msg = this.$t('trials:reading:wlTemplate:delete') var msg = this.$t('trials:reading:wlTemplate:delete')
const confirm = await this.$confirm(
this.$confirm(msg, { msg,
type: 'warning', {
distinguishCancelAndClose: true type: 'warning',
}).then(() => { distinguishCancelAndClose: true
this.loading = true }
deleteUserWLTemplate(row.Id).then(res => { )
this.loading = false if (confirm !== 'confirm') return
// this.loading = true
this.$message.success(this.$t('common:message:deletedSuccessfully')) try {
this.getWL() await deleteUserWLTemplate(row.Id)
}).catch(() => { this.loading = false }) this.loading = false
}) //
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.getWL()
} catch (e) {
this.loading = false
}
} }
} }
} }

View File

@ -83,24 +83,23 @@ export default {
} }
}, },
methods: { methods: {
handleSave() { async handleSave() {
this.$refs.wlForm.validate((valid) => { const valid = await this.$refs.wlForm.validate()
if (valid) { if (!valid) return
this.loading = true this.loading = true
addOrUpdateUserWLTemplate(this.form).then((res) => { try {
this.loading = false await addOrUpdateUserWLTemplate(this.form)
this.$emit('getWL') this.loading = false
this.$emit('close') this.$emit('getWL')
if (this.form.Id) { this.$emit('close')
this.$message.success(this.$t('common:message:savedSuccessfully')) if (this.form.Id) {
} else { this.$message.success(this.$t('common:message:savedSuccessfully'))
this.$message.success(this.$t('common:message:addedSuccessfully')) } else {
} this.$message.success(this.$t('common:message:addedSuccessfully'))
}).catch(() => {
this.loading = false
})
} }
}) } catch (e) {
this.loading = false
}
}, },
handleCancel() { handleCancel() {
this.$emit('close') this.$emit('close')

View File

@ -19,7 +19,7 @@
</div> </div>
<!-- 切换访视 --> <!-- 切换访视 -->
<div <div
v-if="stack.imageRendered && isReadingTaskViewInOrder" v-if="stack.imageRendered && isReadingTaskViewInOrder === 1"
class="info-visit" class="info-visit"
@dblclick.stop="preventDefault($event)" @dblclick.stop="preventDefault($event)"
> >
@ -43,7 +43,7 @@
<i class="el-icon-caret-right" /> <i class="el-icon-caret-right" />
</div> </div>
</div> </div>
<div class="info-series"> <div class="info-series">
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{ stack.taskBlindName }}</h2> <h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{ stack.taskBlindName }}</h2>
<div v-show="dicomInfo.series">Series: #{{ dicomInfo.series }}</div> <div v-show="dicomInfo.series">Series: #{{ dicomInfo.series }}</div>
<div>Image: #{{ dicomInfo.frame }}</div> <div>Image: #{{ dicomInfo.frame }}</div>
@ -99,8 +99,8 @@
</div> </div>
<div class="info-instance"> <div class="info-instance">
<div v-show="dicomInfo.location">Location: {{ dicomInfo.location }}</div> <div v-if="dicomInfo.location">Location: {{ `${Number(dicomInfo.location).toFixed(digitPlaces)} mm` }}</div>
<div v-show="dicomInfo.thick">Slice Thickness: {{ dicomInfo.thick }}mm</div> <div v-show="dicomInfo.thick">Slice Thickness: {{ `${dicomInfo.thick} mm` }}</div>
<div v-show="dicomInfo.wwwc">WW/WL: {{ dicomInfo.wwwc }}</div> <div v-show="dicomInfo.wwwc">WW/WL: {{ dicomInfo.wwwc }}</div>
</div> </div>
@ -146,6 +146,7 @@ import LengthTool from '@/views/trials/trials-panel/reading/dicoms/tools/Length/
import BidirectionalTool from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/BidirectionalTool' import BidirectionalTool from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/BidirectionalTool'
import ArrowAnnotateTool from '@/views/trials/trials-panel/reading/dicoms/tools/ArrowAnnotate/ArrowAnnotateTool' import ArrowAnnotateTool from '@/views/trials/trials-panel/reading/dicoms/tools/ArrowAnnotate/ArrowAnnotateTool'
import RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/RectangleRoiTool' import RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/RectangleRoiTool'
import CircleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/CircleRoi/CircleRoiTool'
// import OrientationMarkersTool from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/OrientationMarkersTool' // import OrientationMarkersTool from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/OrientationMarkersTool'
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool' import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString' import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
@ -180,7 +181,7 @@ export default {
required: true required: true
}, },
isReadingTaskViewInOrder: { isReadingTaskViewInOrder: {
type: Boolean, type: Number,
required: true required: true
}, },
customWwcTpl: { customWwcTpl: {
@ -220,7 +221,9 @@ export default {
visitTaskId: '', visitTaskId: '',
taskBlindName: '', taskBlindName: '',
frame: null, frame: null,
imageRendered: false imageRendered: false,
isExistsClinicalData: false,
isExistMutiFrames: false
// preventCache: true // preventCache: true
}, },
dicomInfo: { dicomInfo: {
@ -256,7 +259,7 @@ export default {
series: '', series: '',
ToolStateManager: null, ToolStateManager: null,
renderedMeasured: [], renderedMeasured: [],
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate', 'RectangleRoi'], measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate', 'RectangleRoi', 'CircleRoi'],
measureData: [], measureData: [],
selectedLesion: null, selectedLesion: null,
activeTool: 0, // 0:enable 1:passive 2:active activeTool: 0, // 0:enable 1:passive 2:active
@ -296,8 +299,8 @@ export default {
], ],
scrollSyncInfo: { offset: 0 }, scrollSyncInfo: { offset: 0 },
hideMeasureArr: [] hideMeasureArr: [],
enabledElement: null
} }
}, },
computed: { computed: {
@ -330,7 +333,9 @@ export default {
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode console.log(cornerstoneTools)
// this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
document.addEventListener('mouseup', () => { document.addEventListener('mouseup', () => {
this.sliderMouseup() this.sliderMouseup()
}) })
@ -373,10 +378,10 @@ export default {
} }
) )
// this.canvas.addEventListener( this.canvas.addEventListener(
// 'cornerstonetoolsmeasurementremoved', 'cornerstonetoolsmeasurementremoved',
// this.onMeasurementremoved this.onMeasurementremoved
// ) )
// EVENTS.MOUSE_UP // EVENTS.MOUSE_UP
this.canvas.addEventListener('cornerstonetoolsmouseup', this.mouseUp) this.canvas.addEventListener('cornerstonetoolsmouseup', this.mouseUp)
this.canvas.addEventListener('cornerstonetoolsmousedown', this.mouseDown) this.canvas.addEventListener('cornerstonetoolsmousedown', this.mouseDown)
@ -395,7 +400,8 @@ export default {
cornerstone.updateImage(this.canvas, true) cornerstone.updateImage(this.canvas, true)
}) })
DicomEvent.$on('updateImage', () => { DicomEvent.$on('updateImage', () => {
cornerstone.updateImage(this.canvas) if (!this.canvas) return
this.updateImage()
}) })
// this.canvas.addEventListener('keydown', event => { // this.canvas.addEventListener('keydown', event => {
// event.preventDefault() // event.preventDefault()
@ -477,7 +483,6 @@ export default {
}, },
methods: { methods: {
goViewer(e) { goViewer(e) {
console.log('goViewer')
console.log(this.$refs['sliderBox'].clientHeight) console.log(this.$refs['sliderBox'].clientHeight)
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
this.height = height this.height = height
@ -539,7 +544,7 @@ export default {
this.mousePosition.y = currentPoints.image.y + 1 this.mousePosition.y = currentPoints.image.y + 1
this.mousePosition.mo = stats.mo this.mousePosition.mo = stats.mo
this.mousePosition.suv = stats.suv this.mousePosition.suv = stats.suv
if (this.isFirstChangeTask && this.pointNearTool(e)) { if (this.pointNearTool(e)) {
e.stopImmediatePropagation() e.stopImmediatePropagation()
e.stopPropagation() e.stopPropagation()
e.preventDefault() e.preventDefault()
@ -548,24 +553,25 @@ export default {
mouseUp(e) { mouseUp(e) {
console.log('mouseUp') console.log('mouseUp')
if (this.readingTaskState >= 2) return // if (this.readingTaskState >= 2) return
this.image = e.detail.image this.image = e.detail.image
this.getToolStateInfo(e) this.getToolStateInfo(e)
}, },
mouseDown(e) { mouseDown(e) {
this.image = e.detail.image this.image = e.detail.image
var pointNearTool = this.pointNearTool(e) var pointNearTool = this.pointNearTool(e)
if (this.isFirstChangeTask && pointNearTool) { if (pointNearTool) {
e.stopImmediatePropagation() e.stopImmediatePropagation()
e.stopPropagation() e.stopPropagation()
e.preventDefault() e.preventDefault()
} else if (this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional' && this.readingTaskState < 2) { } else if (this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional') {
if (!e.detail.image.columnPixelSpacing || !e.detail.image.rowPixelSpacing) { if (!e.detail.image.columnPixelSpacing || !e.detail.image.rowPixelSpacing) {
// '' // ''
this.$confirm(this.$t('trials:reading:warnning:msg56'), '', { this.$confirm(this.$t('trials:reading:warnning:msg56'), '', {
showCancelButton: false, showCancelButton: false,
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
}).catch(() => {}) }).catch(() => {})
e.stopImmediatePropagation() e.stopImmediatePropagation()
e.stopPropagation() e.stopPropagation()
@ -597,10 +603,11 @@ export default {
getDisabledMarks(measureDatas) { getDisabledMarks(measureDatas) {
var arr = [] var arr = []
measureDatas.map(i => { measureDatas.map(i => {
if ((i.LesionType === 0 || i.LesionType === 1 || i.LesionType === 7) && i.IsFirstChangeTask) { if (i.Id && this.readingTaskState >= 2) {
arr.push(i.OrderMarkName) arr.push(i.MeasureData.data.remark)
} }
}) })
console.log(arr)
return arr return arr
}, },
getRGBPixels(element, x, y, width, height) { getRGBPixels(element, x, y, width, height) {
@ -651,7 +658,7 @@ export default {
if (PX < 0) return if (PX < 0) return
if (PX > boxHeight) return if (PX > boxHeight) return
var height = PX * 100 / boxHeight var height = PX * 100 / boxHeight
var index = Math.trunc(this.stack.imageIds.length * this.height / 100) var index = Math.trunc(this.stack.imageIds.length * height / 100)
index = index > this.stack.imageIds.length ? this.stack.imageIds.length : index < 0 ? 0 : index index = index > this.stack.imageIds.length ? this.stack.imageIds.length : index < 0 ? 0 : index
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return // if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
this.height = height this.height = height
@ -663,6 +670,7 @@ export default {
this.sliderInfo.isMove = false this.sliderInfo.isMove = false
}, },
getMeasureData() { getMeasureData() {
console.log('getMeasureData')
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
@ -736,14 +744,10 @@ export default {
getToolStateInfo(e) { getToolStateInfo(e) {
const { element, currentPoints, image, viewport } = e.detail const { element, currentPoints, image, viewport } = e.detail
var imageId = image.imageId var imageId = image.imageId
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1] this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
instanceId = instanceId.split('?frame=')[0]
}
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
instanceId = instanceId.split('.')[0]
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
for (var m = 0; m < this.measuredTools.length; m++) { for (var m = 0; m < this.measuredTools.length; m++) {
var toolType = this.measuredTools[m] var toolType = this.measuredTools[m]
@ -771,10 +775,11 @@ export default {
measureData.data = toolState.data[i] measureData.data = toolState.data[i]
measureData.type = toolType measureData.type = toolType
measureData.thick = this.dicomInfo.thick measureData.thick = this.dicomInfo.thick
measureData.location = this.dicomInfo.location
var uuid = toolState.data[i].uuid var uuid = toolState.data[i].uuid
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid) var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) { if (idx > -1) {
var markName = this.measureData[idx].OrderMarkName var markName = this.measureData[idx].MeasureData.data.remark
if (this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) { if (this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) {
measureData.ww = Math.round(viewport.voi.windowWidth) measureData.ww = Math.round(viewport.voi.windowWidth)
measureData.wc = Math.round(viewport.voi.windowCenter) measureData.wc = Math.round(viewport.voi.windowCenter)
@ -799,7 +804,7 @@ export default {
} }
}, },
stackScrollCallback(e) { stackScrollCallback(e) {
console.log('stackScrollCallback') // console.log('stackScrollCallback')
const { detail } = e const { detail } = e
if (this.isScrollSync && this.currentDicomCanvasIndex === this.canvasIndex) { if (this.isScrollSync && this.currentDicomCanvasIndex === this.canvasIndex) {
this.scrollSyncInfo.canvasIndex = this.canvasIndex this.scrollSyncInfo.canvasIndex = this.canvasIndex
@ -864,8 +869,8 @@ export default {
return seriesList[seriesIdx].loadStatus ? 1 : 0 return seriesList[seriesIdx].loadStatus ? 1 : 0
}, },
renderMeasuredData(e) { renderMeasuredData(e) {
this.stack.frame = !isNaN(parseInt(this.stack.frame)) ? parseInt(this.stack.frame) : 0
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
if (idx === -1) return
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
const { element } = e.detail const { element } = e.detail
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
@ -880,11 +885,12 @@ export default {
} else if (this.activeTool === 1 && this.readingTaskState < 2) { } else if (this.activeTool === 1 && this.readingTaskState < 2) {
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 }) cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
} else { } else {
cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 }) // cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
} cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
// console.log('renderMeasuredData', this.stack.frame)
if (this.stack.instanceId.includes(data.InstanceId) && ((data.NumberOfFrames === this.stack.frame) || !data.NumberOfFrames) && data.MeasureData) { }
if (this.stack.instanceId.includes(data.InstanceId) && ((this.stack.isExistMutiFrames && (data.MeasureData.frame === this.stack.frame) && data.MeasureData) || (!this.stack.isExistMutiFrames && data.MeasureData))) {
// console.log('renderMeasuredData', this.stack.frame,data.MeasureData.frame,this.stack.isExistMutiFrames)
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type) const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type)
if (toolState && toolState.data.length > 0) { if (toolState && toolState.data.length > 0) {
var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid) var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid)
@ -904,11 +910,8 @@ export default {
if (this.readingTaskState >= 2) return if (this.readingTaskState >= 2) return
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
var { imageId } = element.image var { imageId } = element.image
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
if (instanceId.includes('?frame=')) { var instanceId = imageInfo.instanceId
instanceId = instanceId.split('?frame=')[0]
}
instanceId = instanceId.split('.')[0]
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId && i.IsCurrentTask && i.ReadingTaskState < 2) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId && i.IsCurrentTask && i.ReadingTaskState < 2)
if (idx === -1) return if (idx === -1) return
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
@ -968,18 +971,13 @@ export default {
} }
} }
}, },
async mouseClick(e) { mouseClick(e) {
const { element, currentPoints, image, viewport } = e.detail const { element, currentPoints, image, viewport } = e.detail
var imageId = image.imageId var imageId = image.imageId
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1] this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
instanceId = instanceId.split('?frame=')[0]
}
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
instanceId = instanceId.split('.')[0]
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
for (let t = 0; t < this.measuredTools.length; t++) { for (let t = 0; t < this.measuredTools.length; t++) {
var toolType = this.measuredTools[t] var toolType = this.measuredTools[t]
@ -990,17 +988,17 @@ export default {
if (i > -1) { if (i > -1) {
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid) var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
if (idx > -1) { if (idx > -1) {
console.log('mouseClick')
DicomEvent.$emit('setCollapseActive', this.measureData[idx]) DicomEvent.$emit('setCollapseActive', this.measureData[idx])
if (this.readingTaskState < 2) {
const measureData = {} const measureData = {}
var markName = this.measureData[idx].OrderMarkName // var markName = this.measureData[idx].OrderMarkName
if (this.activeToolName === 'Eraser') { var markName = this.measureData[idx].MeasureData.data.remark
var questionInfo = this.measureData[idx] if (this.activeToolName === 'Eraser' && this.disabledMarks.indexOf(markName) === -1) {
this.$emit('moveMeasureData', { measureData, questionInfo }) const questionInfo = this.measureData[idx]
measureData.orderMarkName = markName
this.$emit('moveMeasureData', { measureData, questionInfo, orderMarkName: markName})
} }
if ((this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) && this.activeToolName !== 'Eraser') { if ((this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) && this.activeToolName !== 'Eraser') {
var questionInfo = this.measureData[idx] const questionInfo = this.measureData[idx]
const canvas = this.canvas.querySelector('canvas') const canvas = this.canvas.querySelector('canvas')
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1) measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
measureData.studyId = this.stack.studyId measureData.studyId = this.stack.studyId
@ -1010,12 +1008,13 @@ export default {
measureData.data = toolState.data[i] measureData.data = toolState.data[i]
measureData.type = toolType measureData.type = toolType
measureData.thick = this.dicomInfo.thick measureData.thick = this.dicomInfo.thick
measureData.location = this.dicomInfo.location
measureData.ww = Math.round(viewport.voi.windowWidth) measureData.ww = Math.round(viewport.voi.windowWidth)
measureData.wc = Math.round(viewport.voi.windowCenter) measureData.wc = Math.round(viewport.voi.windowCenter)
measureData.data.active = false measureData.data.active = false
this.$emit('modifyMeasureData', { measureData, questionInfo }) this.$emit('modifyMeasureData', { measureData, questionInfo })
} }
}
break break
} }
} }
@ -1039,7 +1038,7 @@ export default {
this.stack.studyId = dicomSeries.studyId this.stack.studyId = dicomSeries.studyId
this.stack.seriesNumber = dicomSeries.seriesNumber this.stack.seriesNumber = dicomSeries.seriesNumber
this.stack.imageIds = dicomSeries.imageIds this.stack.imageIds = dicomSeries.imageIds
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex ? dicomSeries.imageIdIndex : 0 this.stack.currentImageIdIndex = dicomSeries.imageIdIndex && dicomSeries.imageIdIndex < dicomSeries.imageIds.length ? dicomSeries.imageIdIndex : 0
this.stack.imageIdIndex = dicomSeries.imageIdIndex this.stack.imageIdIndex = dicomSeries.imageIdIndex
this.stack.firstImageLoading = true this.stack.firstImageLoading = true
this.stack.visitTaskId = dicomSeries.visitTaskId this.stack.visitTaskId = dicomSeries.visitTaskId
@ -1049,38 +1048,31 @@ export default {
this.stack.seriesIndex = dicomSeries.seriesIndex this.stack.seriesIndex = dicomSeries.seriesIndex
this.stack.sliceThickness = dicomSeries.sliceThickness this.stack.sliceThickness = dicomSeries.sliceThickness
this.stack.instanceCount = dicomSeries.instanceCount this.stack.instanceCount = dicomSeries.instanceCount
this.stack.isExistsClinicalData = dicomSeries.isExistsClinicalData
// this.measuredData = dicomSeries.measuredData // this.measuredData = dicomSeries.measuredData
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId)
this.stack.visitTaskNum = this.visitTaskList[idx].VisitTaskNum this.stack.visitTaskNum = this.visitTaskList[idx].VisitTaskNum
this.isFirstChangeTask = this.visitTaskList[idx].IsFirstChangeTask this.isFirstChangeTask = this.visitTaskList[idx].IsFirstChangeTask
if (this.isFirstChangeTask) { this.disabledMarks = this.getDisabledMarks(this.visitTaskList[idx].MeasureData)
this.disabledMarks = this.getDisabledMarks(this.visitTaskList[idx].MeasureData)
} else {
this.disabledMarks = []
}
this.maxVistNum = this.visitTaskList[this.visitTaskList.length - 1].VisitTaskNum this.maxVistNum = this.visitTaskList[this.visitTaskList.length - 1].VisitTaskNum
this.minVistNum = this.visitTaskList[0].VisitTaskNum this.minVistNum = this.visitTaskList[0].VisitTaskNum
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
const imageId = this.stack.imageIds[this.stack.currentImageIdIndex] const imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1] this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
instanceId = instanceId.split('?frame=')[0]
}
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId this.stack.instanceId = instanceId
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
if (this.toolState.clipPlaying) this.toggleClipPlay()
this.toolState.viewportInvert = false
this.toolState.dicomInfoVisible = false
const element = this.$refs.canvas const element = this.$refs.canvas
cornerstone.enable(element) cornerstone.enable(element)
element.tabIndex = 0 element.tabIndex = 0
element.focus() element.focus()
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
this.toggleClipPlay(false)
this.toolState.viewportInvert = false
this.toolState.dicomInfoVisible = false
var scope = this var scope = this
// var p = parseInt(new Date().getTime()) // var p = parseInt(new Date().getTime())
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{ // requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{
@ -1093,102 +1085,106 @@ export default {
// } // }
// resolve() // resolve()
// }) // })
this.loading = true
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex]) cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(image => { .then(async image => {
scope.onFirstImageLoaded(image) if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
await scope.onFirstImageLoaded(image)
}
scope.loading = false
resolve() resolve()
}) })
.catch((error) => { .catch((error) => {
if (error.error && error.error.message) { if (error.error && error.error.message) {
this.$alert(error.error.message) this.$alert(error.error.message)
} }
scope.loading = false
resolve() resolve()
}) })
}) })
}, },
onFirstImageLoaded(image) { onFirstImageLoaded(image) {
console.log('onFirstImageLoaded') console.log('onFirstImageLoaded')
return new Promise(async resolve => {
const element = this.$refs.canvas
var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image)
cornerstone.displayImage(this.canvas, image, viewport)
const element = this.$refs.canvas if (!this.toolState.initialized) {
var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image) this.toolState.initialized = true
cornerstone.displayImage(this.canvas, image, viewport) const toolButtons = document.querySelectorAll('[data-tool]')
// const scope = this
if (!this.toolState.initialized) { Array.from(toolButtons).forEach((toolBtn) => {
this.toolState.initialized = true
const toolButtons = document.querySelectorAll('[data-tool]')
// const scope = this
Array.from(toolButtons).forEach((toolBtn) => {
// Add the tool // Add the tool
const toolName = toolBtn.getAttribute('data-tool') const toolName = toolBtn.getAttribute('data-tool')
const apiTool = cornerstoneTools[`${toolName}Tool`] const apiTool = cornerstoneTools[`${toolName}Tool`]
if (apiTool) { if (apiTool) {
const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(element, apiTool) const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(element, apiTool)
if (!toolAlreadyAddedToElement) { if (!toolAlreadyAddedToElement) {
if (toolName === 'Length') { if (toolName === 'Length') {
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true }}) cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true }})
} else if (toolName === 'Bidirectional') { } else if (toolName === 'Bidirectional') {
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces }) // cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true // , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true }}) cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true }})
} else if (toolName === 'ArrowAnnotate') { } else if (toolName === 'ArrowAnnotate') {
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }}) cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
} else if (toolName === 'RectangleRoi') { } else if (toolName === 'RectangleRoi') {
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }}) cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
} else { } else if (toolName === 'CircleRoi') {
cornerstoneTools.addToolForElement(element, apiTool) cornerstoneTools.addToolForElement(element, CircleRoiTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true, showMinMax: true }})
} else {
cornerstoneTools.addToolForElement(element, apiTool)
}
} }
} }
})
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.WwwcRegionTool)) {
cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool)
} }
}) if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)) {
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.WwwcRegionTool)) { cornerstoneTools.addToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)
cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool) }
} cornerstoneTools.setToolActiveForElement(element, 'StackScrollMouseWheel', {})
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)) {
cornerstoneTools.addToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)
}
cornerstoneTools.setToolActiveForElement(element, 'StackScrollMouseWheel', {})
if (!cornerstoneTools.getToolForElement(element, ScaleOverlayTool)) { if (!cornerstoneTools.getToolForElement(element, ScaleOverlayTool)) {
cornerstoneTools.addToolForElement(element, ScaleOverlayTool) cornerstoneTools.addToolForElement(element, ScaleOverlayTool)
} }
cornerstoneTools.setToolActiveForElement(element, 'ScaleOverlay', {}) cornerstoneTools.setToolActiveForElement(element, 'ScaleOverlay', {})
cornerstoneTools.setToolActiveForElement(this.canvas, 'Zoom', { cornerstoneTools.setToolActiveForElement(this.canvas, 'Zoom', {
mouseButtonMask: 2 mouseButtonMask: 2
}) })
cornerstoneTools.setToolActiveForElement(this.canvas, 'Pan', { cornerstoneTools.setToolActiveForElement(this.canvas, 'Pan', {
mouseButtonMask: 4 mouseButtonMask: 4
}) })
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) { // if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool) // cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
// } // }
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { }) // cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
} }
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip']) // cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'playClip']) cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'playClip'])
cornerstoneTools.addToolState(this.canvas, 'stack', this.stack) cornerstoneTools.addToolState(this.canvas, 'stack', this.stack)
// cornerstoneTools.stackPrefetch.enable(this.canvas) // cornerstoneTools.stackPrefetch.enable(this.canvas)
cornerstone.updateImage(element, true) cornerstone.updateImage(element, true)
this.stack.firstImageLoading = false this.stack.firstImageLoading = false
this.toolState.dicomInfoVisible = true this.toolState.dicomInfoVisible = true
var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(image.imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1] this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
instanceId = instanceId.split('?frame=')[0] this.stack.instanceId = instanceId
} this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 // this.resetWwwc()
instanceId = instanceId.split('.')[0] resolve()
this.stack.instanceId = instanceId })
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
this.resetWwwc()
}, },
onNewImage(e) { onNewImage(e) {
console.log('cornerstonenewimage') // console.log('cornerstonenewimage')
if (this.isCurrentTask && this.readingTaskState < 2) { if (this.isCurrentTask && this.readingTaskState < 2) {
this.resetHideMeasureArr() this.resetHideMeasureArr()
} }
@ -1225,6 +1221,12 @@ export default {
if (this.dicomInfo.thick) { if (this.dicomInfo.thick) {
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2) this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
} }
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === imageId)
if (newImageIdIndex === -1) return
this.stack.currentImageIdIndex = newImageIdIndex
this.stack.imageIdIndex = newImageIdIndex
this.series.imageIdIndex = newImageIdIndex
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
}, },
getScreenshots() { getScreenshots() {
const canvas = this.canvas.querySelector('canvas') const canvas = this.canvas.querySelector('canvas')
@ -1242,18 +1244,13 @@ export default {
// console.log('onImageLoaded') // console.log('onImageLoaded')
}, },
onImageRendered(e) { onImageRendered(e) {
// console.log('onImageRendered')
this.stack.imageRendered = true this.stack.imageRendered = true
// const { element } = e.detail // const { element } = e.detail
var imageId = e.detail.image.imageId var imageId = e.detail.image.imageId
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1] this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
instanceId = instanceId.split('?frame=')[0]
}
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
instanceId = instanceId.split('.')[0]
if (this.imageId !== instanceId) { if (this.imageId !== instanceId) {
this.getOrientationMarker(e.detail.element) this.getOrientationMarker(e.detail.element)
// //
@ -1290,26 +1287,17 @@ export default {
if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) { if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) {
return return
} }
const row = getOrientationString(imagePlane.rowCosines) const row = getOrientationString(imagePlane.rowCosines)
const column = getOrientationString(imagePlane.columnCosines) const column = getOrientationString(imagePlane.columnCosines)
const oppositeRow = invertOrientationString(row) const oppositeRow = invertOrientationString(row)
const oppositeColumn = invertOrientationString(column) const oppositeColumn = invertOrientationString(column)
const markers = {
top: oppositeColumn,
bottom: column,
left: oppositeRow,
right: row
}
if (!markers) {
return
}
this.orientationMarkers = [oppositeColumn, row, column, oppositeRow] this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
this.originalMarkers = [oppositeColumn, row, column, oppositeRow] this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
this.setMarkers() this.setMarkers()
}, },
onMeasurementcompleted(e) { onMeasurementcompleted(e) {
if (this.readingTaskState >= 2) return // if (this.readingTaskState >= 2) return
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport var viewport = element.viewport
@ -1318,15 +1306,11 @@ export default {
this.activeTool = 1 this.activeTool = 1
this.activeToolName = '' this.activeToolName = ''
var { imageId } = element.image var { imageId } = element.image
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1]
instanceId = instanceId.split('?frame=')[0]
}
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0 this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
instanceId = instanceId.split('.')[0] if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi' || e.detail.toolName === 'CircleRoi') {
if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi') {
const measureData = {} const measureData = {}
measureData.studyId = this.stack.studyId measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId measureData.seriesId = this.stack.seriesId
@ -1335,11 +1319,13 @@ export default {
measureData.data = e.detail.measurementData measureData.data = e.detail.measurementData
measureData.type = e.detail.toolName measureData.type = e.detail.toolName
measureData.thick = this.dicomInfo.thick measureData.thick = this.dicomInfo.thick
measureData.location = this.dicomInfo.location
measureData.ww = Math.round(viewport.voi.windowWidth) measureData.ww = Math.round(viewport.voi.windowWidth)
measureData.wc = Math.round(viewport.voi.windowCenter) measureData.wc = Math.round(viewport.voi.windowCenter)
const canvas = this.canvas.querySelector('canvas') const canvas = this.canvas.querySelector('canvas')
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1) measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
measureData.temporary = this.readingTaskState >= 2
this.$emit('setMeasureData', measureData) this.$emit('setMeasureData', measureData)
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName) cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
} else if (e.detail.toolName === 'Bidirectional') { } else if (e.detail.toolName === 'Bidirectional') {
@ -1351,10 +1337,12 @@ export default {
measureData.data = e.detail.measurementData measureData.data = e.detail.measurementData
measureData.type = e.detail.toolName measureData.type = e.detail.toolName
measureData.thick = this.dicomInfo.thick measureData.thick = this.dicomInfo.thick
measureData.location = this.dicomInfo.location
measureData.ww = Math.round(viewport.voi.windowWidth) measureData.ww = Math.round(viewport.voi.windowWidth)
measureData.wc = Math.round(viewport.voi.windowCenter) measureData.wc = Math.round(viewport.voi.windowCenter)
const canvas = this.canvas.querySelector('canvas') const canvas = this.canvas.querySelector('canvas')
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1) measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
measureData.temporary = this.readingTaskState >= 2
this.$emit('setMeasureData', measureData) this.$emit('setMeasureData', measureData)
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName) cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
} else if (!e.detail.toolName) { } else if (!e.detail.toolName) {
@ -1402,9 +1390,9 @@ export default {
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
const { rowPixelSpacing, colPixelSpacing } = this.getPixelSpacing(element.image) const { rowPixelSpacing, colPixelSpacing } = this.getPixelSpacing(element.image)
const dx = const dx =
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1) (data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
const dy = const dy =
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1) (data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
const length = Math.sqrt(dx * dx + dy * dy) const length = Math.sqrt(dx * dx + dy * dy)
return length.toFixed(this.digitPlaces) return length.toFixed(this.digitPlaces)
@ -1418,9 +1406,9 @@ export default {
if (imagePlane) { if (imagePlane) {
return { return {
rowPixelSpacing: rowPixelSpacing:
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing, imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
colPixelSpacing: colPixelSpacing:
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
} }
} }
@ -1430,30 +1418,27 @@ export default {
} }
}, },
onMeasurementremoved(e) { onMeasurementremoved(e) {
console.log('================移除病灶=================', e)
}, },
onMeasurementmodified(e) { onMeasurementmodified(e) {
// //
console.log('modified') console.log('modified')
if (this.readingTaskState >= 2) return // if (this.readingTaskState >= 2) return
const { measurementData, toolType } = e.detail const { measurementData, toolType } = e.detail
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport var viewport = element.viewport
var { imageId } = element.image var { imageId } = element.image
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
var frame = null var instanceId = imageInfo.instanceId
if (instanceId.includes('?frame=')) { var frame = imageInfo.frame
frame = instanceId.split('?frame=')[1] this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
instanceId = instanceId.split('?frame=')[0]
}
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
instanceId = instanceId.split('.')[0]
var uuid = measurementData.uuid var uuid = measurementData.uuid
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid) var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) { if (idx > -1) {
const measureData = {} const measureData = {}
var markName = this.measureData[idx].OrderMarkName // var markName = this.measureData[idx].OrderMarkName
var markName = this.measureData[idx].MeasureData.data.remark
if (this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) { if (this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) {
var questionInfo = this.measureData[idx] var questionInfo = this.measureData[idx]
const canvas = this.canvas.querySelector('canvas') const canvas = this.canvas.querySelector('canvas')
@ -1465,6 +1450,7 @@ export default {
measureData.data = measurementData measureData.data = measurementData
measureData.type = toolType measureData.type = toolType
measureData.thick = this.dicomInfo.thick measureData.thick = this.dicomInfo.thick
measureData.location = this.dicomInfo.location
measureData.ww = Math.round(viewport.voi.windowWidth) measureData.ww = Math.round(viewport.voi.windowWidth)
measureData.wc = Math.round(viewport.voi.windowCenter) measureData.wc = Math.round(viewport.voi.windowCenter)
measureData.data.active = false measureData.data.active = false
@ -1482,15 +1468,21 @@ export default {
} }
}, },
updateImage(instanceId) { updateImage(instanceId) {
if (!this.canvas) return
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId) var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[i].MeasureData this.measureData = this.visitTaskList[i].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
if (!element) return
var { imageId } = element.image var { imageId } = element.image
ToolStateManager.clearImageIdToolState(imageId) if (imageId) {
cornerstone.updateImage(element, true) ToolStateManager.clearImageIdToolState(imageId)
let elements = cornerstone.getEnabledElementsByImageId(imageId)
elements.map(el=>{
cornerstone.updateImage(el.element)
})
}
// cornerstone.updateImage(element)
}, },
toggleSeries(evt, type) { toggleSeries(evt, type) {
evt.stopImmediatePropagation() evt.stopImmediatePropagation()
@ -1504,11 +1496,8 @@ export default {
// //
var element = cornerstone.getEnabledElement(this.canvas) var element = cornerstone.getEnabledElement(this.canvas)
var { imageId } = element.image var { imageId } = element.image
var instanceId = imageId.split('/')[imageId.split('/').length - 1] const imageInfo = this.getInstanceInfo(imageId)
if (instanceId.includes('?frame=')) { var instanceId = imageInfo.instanceId
instanceId = instanceId.split('?frame=')[0]
}
instanceId = instanceId.split('.')[0]
var idx = this.measureData.findIndex(item => item.InstanceId === instanceId) var idx = this.measureData.findIndex(item => item.InstanceId === instanceId)
var measureData = null var measureData = null
if (idx > -1) { if (idx > -1) {
@ -1626,18 +1615,19 @@ export default {
} }
}, },
toggleClipPlay() { toggleClipPlay(isPlay) {
if (this.toolState.clipPlaying) { if (isPlay) {
this.toolState.clipPlaying = true
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
} else {
cornerstoneTools.stopClip(this.canvas) cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false this.toolState.clipPlaying = false
return return
} }
this.toolState.clipPlaying = true
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
}, },
setFps(fps) { setFps(fps) {
this.dicomInfo.fps = fps this.dicomInfo.fps = fps
@ -1646,7 +1636,7 @@ export default {
resetWwwc() { resetWwwc() {
this.toolState.viewportInvert = false this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = false // viewport.invert = false
var image = cornerstone.getImage(this.canvas) var image = cornerstone.getImage(this.canvas)
viewport.voi.windowWidth = image.windowWidth viewport.voi.windowWidth = image.windowWidth
viewport.voi.windowCenter = image.windowCenter viewport.voi.windowCenter = image.windowCenter
@ -1774,20 +1764,19 @@ export default {
this.activeToolName = toolName this.activeToolName = toolName
this.$nextTick(() => { this.$nextTick(() => {
// console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional')) // console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional'))
if (!cornerstoneTools.isToolActiveForElement(this.canvas, toolName)) {
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
mouseButtonMask: 1
})
}
if (toolName === 'Zoom') { if (toolName === 'Zoom') {
cornerstoneTools.setToolActiveForElement(this.canvas, 'Zoom', { cornerstoneTools.setToolActiveForElement(this.canvas, 'Zoom', {
mouseButtonMask: [1, 2] mouseButtonMask: [1, 2]
}) })
} } else if (toolName === 'Pan') {
if (toolName === 'Pan') {
cornerstoneTools.setToolActiveForElement(this.canvas, 'Pan', { cornerstoneTools.setToolActiveForElement(this.canvas, 'Pan', {
mouseButtonMask: [1, 4] mouseButtonMask: [1, 4]
}) })
} else {
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
mouseButtonMask: 1
})
} }
}) })
}, },
@ -1923,6 +1912,17 @@ export default {
} }
} }
}, },
getInstanceInfo(imageId) {
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
if (isNaN(params.frame)){
params.frame = 0
}
return params
},
preventDefault(e) { preventDefault(e) {
e.stopImmediatePropagation() e.stopImmediatePropagation()
e.stopPropagation() e.stopPropagation()
@ -1940,87 +1940,87 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.context-menu-wrapper{ .context-menu-wrapper{
position: absolute; position: absolute;
ul{ ul{
list-style: none; list-style: none;
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
background: #343333;
color: #fff;
margin: 0;
border: 1px solid #2a2a2a;
border-radius: 3px;
height: auto;
min-height: 50px;
line-height: 1.5em;
width:80px;
box-sizing: border-box;
}
.menu{
li {
padding: 2px 5px;
position: relative;
border-bottom: 1px solid #666;
div{
padding: 5px;
}
}
.submenu{
position: absolute;
left: 77px;
top: -1px;
background: #343333; background: #343333;
color: #fff; color: #fff;
display: none; margin: 0;
border: 1px solid #2a2a2a;
border-radius: 3px;
height: auto;
min-height: 50px;
line-height: 1.5em;
width:80px;
box-sizing: border-box;
}
.menu{
li { li {
padding: 2px 5px; padding: 2px 5px;
position: relative;
border-bottom: 1px solid #666; border-bottom: 1px solid #666;
div{ div{
padding: 5px; padding: 5px;
} }
} }
.submenu{
position: absolute;
left: 77px;
top: -1px;
background: #343333;
color: #fff;
display: none;
li {
padding: 2px 5px;
border-bottom: 1px solid #666;
div{
padding: 5px;
}
}
}
}
.menu li:hover{
background-color: #ff5722;
.submenu{
display:block;
}
}
.menu_active{
cursor: pointer;
}
.menu_disabled{
cursor: not-allowed;
} }
} }
.menu li:hover{ .info-visit{
background-color: #ff5722; position: absolute;
.submenu{ left:50%;
display:block; top: 5px;
transform: translateX(-50%);
display: flex;
flex-direction: row;
.arrw_div_wrapper{
width: 20px;
height: 20px;
background-color: #3f3f3f;
text-align: center;
line-height: 20px;
border-radius: 10%;
}
.blind_name_wrapper{
height: 20px;
line-height: 20px;
background-color: #00000057;
color: #fff;
padding:0 10px;
font-size: 14px;
} }
} }
.menu_active{
cursor: pointer;
}
.menu_disabled{
cursor: not-allowed;
}
}
.info-visit{
position: absolute;
left:50%;
top: 5px;
transform: translateX(-50%);
display: flex;
flex-direction: row;
.arrw_div_wrapper{
width: 20px;
height: 20px;
background-color: #3f3f3f;
text-align: center;
line-height: 20px;
border-radius: 10%;
}
.blind_name_wrapper{
height: 20px;
line-height: 20px;
background-color: #00000057;
color: #fff;
padding:0 10px;
font-size: 14px;
}
}
.info-cd{ .info-cd{
position: absolute; position: absolute;
left: 10px; left: 10px;
@ -2110,10 +2110,10 @@ li:hover {
color: white; color: white;
} }
.msg-div { .msg-div {
position: absolute; position: absolute;
z-index: 10; z-index: 10;
background-color: rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.5);
color: #000; color: #000;
padding: 5px 20px; padding: 5px 20px;
} }
</style> </style>

View File

@ -2,22 +2,37 @@
<div class="measurement-wrapper" :style="{'height':height+10+'px'}" style="position: relative"> <div class="measurement-wrapper" :style="{'height':height+10+'px'}" style="position: relative">
<div class="container" :style="{'height':height+'px'}" style="padding-bottom: 50px;overflow-y: auto;"> <div class="container" :style="{'height':height+'px'}" style="padding-bottom: 50px;overflow-y: auto;">
<h3 style="color: #ddd;padding: 5px 0px;margin: 0;" v-if="isReadingShowSubjectInfo"> <div class="basic-info">
<span v-if="subjectCode">{{ subjectCode }} </span> <div v-if="readingTaskState < 2">
<span style="margin-left:5px;">{{ taskBlindName }}</span> <el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
</h3> <i
class="el-icon-refresh-left"
@click="resetMeasuredData"
/>
</el-tooltip>
</div>
<h3 v-if="isReadingShowSubjectInfo">
<span v-if="subjectCode">{{ subjectCode }} </span>
<span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
</div>
<QuestionsPreview <QuestionsPreview
ref="QuestionsPreview" ref="QuestionsPreview"
v-if="ecrfShow" v-if="ecrfShow && TrialReadingCriterionId"
:visitTaskId="visitTaskId" :visitTaskId="visitTaskId"
:criterionId="TrialReadingCriterionId"> :criterionId="TrialReadingCriterionId">
</QuestionsPreview> </QuestionsPreview>
</div> </div>
<div style="position: absolute;bottom:0;left: 0;z-index: 10;background: #000;width: 100%;display: flex;justify-content: right;align-items: center;height: 50px"> <div class="questions-footer">
<el-button size="mini" v-if="readingTaskState<2" style="margin-right: 10px" @click="handleSave(true)"> <!-- <i class="el-icon-question feedback-icon" @click="openFeedBackTable" /> -->
<el-button v-if="readingTaskState<2" style="margin-right: 10px" type="primary" size="small" @click="handleSave(true)">
{{$t('common:button:save')}} {{$t('common:button:save')}}
</el-button> </el-button>
<el-button size="mini" style="margin-right: 10px" v-if="readingTaskState<2 && IseCRFShowInDicomReading" @click="handleConfirm"> <el-button v-if="readingTaskState<2 && IseCRFShowInDicomReading" type="primary" style="margin-right: 10px" size="small" @click="skipTask">
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button style="margin-right: 10px" type="primary" size="small" v-if="readingTaskState<2 && IseCRFShowInDicomReading" @click="handleConfirm">
{{ $t('common:button:submit') }}</el-button> {{ $t('common:button:submit') }}</el-button>
</div> </div>
<!-- 签名框 --> <!-- 签名框 -->
@ -77,7 +92,8 @@
</template> </template>
<script> <script>
import { submitDicomVisitTask } from '@/api/trials' import { submitDicomVisitTask } from '@/api/trials'
import { getCustomTag, submitCustomTag, deleteCustomTag } from '@/api/reading' import { getCustomTag, submitCustomTag, resetReadingTask } from '@/api/reading'
import { setSkipReadingCache } from '@/api/reading'
import DicomEvent from './../components/DicomEvent' import DicomEvent from './../components/DicomEvent'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
import QuestionsPreview from './CustomizeQuestionsPreview' import QuestionsPreview from './CustomizeQuestionsPreview'
@ -144,7 +160,8 @@ export default {
} }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
this.CriterionType = parseInt(localStorage.getItem('CriterionType')) this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
DicomEvent.$on('getCustomTableQuestionAnswer', (visitTaskId) => { DicomEvent.$on('getCustomTableQuestionAnswer', (visitTaskId) => {
@ -168,7 +185,6 @@ export default {
methods: { methods: {
async initList(){ async initList(){
if (this.visitTaskId !== this.lastCanvasTaskId) { if (this.visitTaskId !== this.lastCanvasTaskId) {
this.activeName = ''
this.ecrfShow = true this.ecrfShow = true
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId) var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId)
console.log(i) console.log(i)
@ -216,19 +232,26 @@ export default {
this.measureData = measureData this.measureData = measureData
}, },
modifyMeasuredData(measureData) { modifyMeasuredData(measureData) {
console.log(measureData)
measureData.visitTaskId = this.visitTaskId measureData.visitTaskId = this.visitTaskId
measureData.measureData.pictureBaseStr = '' measureData.measureData.pictureBaseStr = ''
let params = JSON.parse(JSON.stringify(measureData)) if (this.readingTaskState >=2) {
params.measureData = JSON.stringify(measureData.measureData)
params.Id = params.questionInfo.Id
params.StudyId = params.questionInfo.StudyId
params.SeriesId = params.questionInfo.SeriesId
params.InstanceId = params.questionInfo.InstanceId
submitCustomTag(params).then(() => {
this.measuredDataVisible = false this.measuredDataVisible = false
DicomEvent.$emit('updateImage') store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: measureData.measureData })
}) }else{
let params = JSON.parse(JSON.stringify(measureData))
params.measureData = JSON.stringify(measureData.measureData)
params.Id = params.questionInfo.Id
params.StudyId = params.questionInfo.StudyId
params.SeriesId = params.questionInfo.SeriesId
params.InstanceId = params.questionInfo.InstanceId
params.NumberOfFrames = measureData.frame
submitCustomTag(params).then(() => {
this.measuredDataVisible = false
DicomEvent.$emit('updateImage')
// this.$message.success(this.$t('common:message:savedSuccessfully'))
})
}
}, },
async moveMeasureData(measureData) { async moveMeasureData(measureData) {
console.log('measureData', measureData) console.log('measureData', measureData)
@ -237,24 +260,47 @@ export default {
}, },
handleMeasuredDataCancel() { handleMeasuredDataCancel() {
this.measuredDataVisible = false this.measuredDataVisible = false
// DicomEvent.$emit('updateImage')
}, },
handleMeasuredDataSave() { handleMeasuredDataSave() {
this.$refs.measuredDataForm.validate(valid => { this.$refs.measuredDataForm.validate(valid => {
if (!valid) return if (!valid) return
//
let isValid = this.validateRemarkName(this.form.measuredDataName)
if (!isValid) {
// ''
this.$message.error(this.$t('trials:customReading:error:validMarkName'))
return
}
this.measureData.data.remark = this.form.measuredDataName this.measureData.data.remark = this.form.measuredDataName
this.measureData.pictureBaseStr = '' this.measureData.pictureBaseStr = ''
let params = JSON.parse(JSON.stringify(this.measureData)) if (this.readingTaskState >=2) {
params.measureData = JSON.stringify(this.measureData) this.measuredDataVisible = false
submitCustomTag(params).then(async (res) => { this.form.measuredDataName = ''
this.measuredDataVisible = false store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.measureData })
this.form.measuredDataName = '' DicomEvent.$emit('updateImage')
this.measureData.Id = res.Result this.$message.success(this.$t('common:message:savedSuccessfully'))
await store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, ...this.measureData }) } else {
await store.dispatch('reading/getCustomizeMeasuredData', this.visitTaskId) let params = JSON.parse(JSON.stringify(this.measureData))
DicomEvent.$emit('updateImage') params.measureData = JSON.stringify(this.measureData)
}) params.NumberOfFrames = this.measureData.frame
submitCustomTag(params).then(async (res) => {
this.measuredDataVisible = false
this.form.measuredDataName = ''
await store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.measureData, id: res.Result })
await store.dispatch('reading/getCustomizeMeasuredData', this.visitTaskId)
DicomEvent.$emit('updateImage')
this.$message.success(this.$t('common:message:savedSuccessfully'))
})
}
}) })
}, },
validateRemarkName(remark) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
var measureData = this.visitTaskList[idx].MeasureData
let i = measureData.findIndex(i=>i.MeasureData.data.remark === remark)
return i === -1
},
// //
closeSignDialog(isSign, signInfo) { closeSignDialog(isSign, signInfo) {
if (isSign) { if (isSign) {
@ -291,7 +337,7 @@ export default {
distinguishCancelAndClose: true distinguishCancelAndClose: true
}) })
.then(() => { .then(() => {
try {DicomEvent.$emit('getNextTask')} catch (e) {console.log(e)} window.location.reload()
}) })
.catch(action => { .catch(action => {
}) })
@ -325,9 +371,87 @@ export default {
if (this.visitTaskId !== obj.visitTaskId) { if (this.visitTaskId !== obj.visitTaskId) {
this.visitTaskId = obj.visitTaskId this.visitTaskId = obj.visitTaskId
this.taskBlindName = obj.taskBlindName this.taskBlindName = obj.taskBlindName
this.activeName = ''
this.ecrfShow = true this.ecrfShow = true
} }
},
async resetMeasuredData() {
const confirm = await this.$confirm(
this.$t('trials:dicomReading:message:confirmReset1'),
this.$t('trials:dicomReading:message:confirmReset2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const loading = this.$loading({ fullscreen: true })
try {
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
//
this.$refs['QuestionsPreview'].getCustomTableQuestionAnswer(this.visitTaskId )
await store.dispatch('reading/refreshCustomizeMeasuredData', this.visitTaskId)
DicomEvent.$emit('getMeasureData')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('refreshStudyListMeasureData')
}
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
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)
}
},
openFeedBackTable() {
this.$FB({
type: 'imgfail',
trialId: this.$route.query.trialId,
visitTaskId: this.visitTaskId,
callBack: async() => {
console.log('callBack')
const confirm = await this.$confirm(
this.$t('trials:reading:confirm:feedbackmsg'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
try {
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = false
if (res.IsSuccess) {
window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
}
})
} }
} }
} }
@ -339,6 +463,23 @@ export default {
.container{ .container{
padding: 10px; padding: 10px;
.basic-info{
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row-reverse;
h3{
color: #ddd;
padding: 5px 0px;
margin: 0;
}
i{
color: #fff;
font-size: 22px;
font-weight: bold;
cursor: pointer;
}
}
} }
.title{ .title{
padding: 5px; padding: 5px;
@ -403,5 +544,27 @@ export default {
} }
} }
.questions-footer{
position: absolute;
bottom:0;
left: 0;
z-index: 10;
background: #000;
width: 100%;
display: flex;
justify-content: right;
align-items: center;
height: 50px;
.feedback-icon{
padding: 0 10px;
color: #fff;
font-weight: 400;
font-size: 24px;
cursor: pointer;
&:hover{
color: #68a2d5;
}
}
}
} }
</style> </style>

View File

@ -7,7 +7,7 @@
{{ question.GroupName }} {{ question.GroupName }}
</div> </div>
<div <div
v-if=" question.Type==='table'" v-if="question.Type==='table' || question.Type==='basicTable'"
style="font-weight: bold;font-size: 14px;margin: 5px 0px;" style="font-weight: bold;font-size: 14px;margin: 5px 0px;"
> >
<div style="display: flex;justify-content: space-between;align-items: center;color:#fff;margin: 10px 0 5px"> <div style="display: flex;justify-content: space-between;align-items: center;color:#fff;margin: 10px 0 5px">
@ -33,7 +33,7 @@
> >
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="item.Type === 'upload'"> <span v-if="item.Type === 'upload'">
{{scope.row[item.Id] === '' ? '' : scope.row[item.Id].split('|').length}} {{scope.row[item.Id] === '' ? '' : scope.row[item.Id] ? scope.row[item.Id].split('|').length : ''}}
</span> </span>
<span v-else-if="item.Type === 'number'"> <span v-else-if="item.Type === 'number'">
{{scope.row[item.Id] ? parseFloat(scope.row[item.Id]).toFixed(digitPlaces) : null}} {{scope.row[item.Id] ? parseFloat(scope.row[item.Id]).toFixed(digitPlaces) : null}}
@ -67,7 +67,7 @@
:label="`${question.QuestionName}`" :label="`${question.QuestionName}`"
:prop="question.Id" :prop="question.Id"
:rules="[ :rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (question.RelevanceValueList.includes(questionForm[question.RelevanceId])))) && question.Type!=='group' && question.Type!=='summary', { required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (question.RelevanceValueList.includes(isNaN(parseFloat(questionForm[question.RelevanceId])) ? questionForm[question.RelevanceId] : questionForm[question.RelevanceId].toString())))) && question.Type!=='group' && question.Type!=='summary',
message: $t('common:ruleMessage:specify'), trigger: ['blur', 'change']}, message: $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
]" ]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']" :class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
@ -120,9 +120,9 @@
<template v-else> <template v-else>
<el-option <el-option
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
:key="val" :key="val.trim()"
:label="val" :label="val.trim()"
:value="val" :value="val.trim()"
/> />
</template> </template>
@ -135,10 +135,10 @@
> >
<el-radio <el-radio
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
:key="val" :key="val.trim()"
:label="val" :label="val.trim()"
> >
{{ val }} {{ val.trim() }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<!-- 复选框 --> <!-- 复选框 -->
@ -149,16 +149,50 @@
<el-checkbox <el-checkbox
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
:key="val" :key="val"
:label="val" :label="val.trim()"
> >
{{ val }} {{ val.trim() }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<!-- 自动分类 --> <!-- 自动分类 -->
<el-input <el-input
v-if="question.Type === 'class'" v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
disabled :disabled="!question.ClassifyEditType"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
/>
</el-select>
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
v-for="item of question.TypeValue.split('|')"
:key="item.trim()"
:label="item.trim()"
>
{{ item.trim() }}
</el-radio>
</el-radio-group>
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 4"
type="number"
:disabled="!question.ClassifyEditType"
v-model="questionForm[question.Id]"
@change="(val) => { formItemNumberChange(val, question) }"
/> />
<!-- 自动计算 --> <!-- 自动计算 -->
<!-- :precision="2" :step="0.1" :max="10" --> <!-- :precision="2" :step="0.1" :max="10" -->
@ -176,12 +210,24 @@
/> />
<!-- 数值 --> <!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" --> <!-- :precision="2" :step="0.1" :max="10" -->
<el-select
v-if="question.Type === 'number' && question.TypeValue"
v-model="questionForm[question.Id]"
clearable
@change="(val) => { formItemNumberChange(val, question) }"
>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
/>
</el-select>
<el-input <el-input
type="number" type="number"
v-if="question.Type === 'number' && question.DataSource !== 1" v-if="question.Type === 'number' && question.DataSource !== 1"
@change="((val)=>{formItemNumberChange(val, question)})" @change="(val) => { formItemNumberChange(val, question) }"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));console.log(localStorage.getItem('digitPlaces'))" onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));"
@input="limitInput($event, questionForm, question.Id)" @input="limitInput($event, questionForm, question.Id)"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
> >
@ -191,7 +237,7 @@
<el-input <el-input
type="number" type="number"
v-if="question.Type === 'number' && question.DataSource === 1" v-if="question.Type === 'number' && question.DataSource === 1"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));console.log(localStorage.getItem('digitPlaces'))" onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));"
@input="limitInput($event, questionForm, question.Id)" @input="limitInput($event, questionForm, question.Id)"
:disabled="question.DataSource === 1" :disabled="question.DataSource === 1"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
@ -202,59 +248,37 @@
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-if="question.Type==='upload'"
:action="question.FileType" action
:limit="question.ImageCount" :accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="(file) => {return handleBeforeUpload(file, question.FileType)}" :before-upload="(file) => {return handleBeforeUpload(file, question.FileType)}"
:http-request="uploadScreenshot" :http-request="uploadScreenshot"
:on-remove="handleRemove" :on-remove="handleRemove"
:file-list="fileList" :file-list="fileList"
:class="{disabled:fileList.length >= question.ImageCount}" :class="{disabled:question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}"
> >
<el-button slot="default" class="el-icon-plus"> <el-button slot="default" class="el-icon-plus">
{{this.$t('common:button:upload')}} {{this.$t('common:button:upload')}}
</el-button> </el-button>
<!-- <div slot="file" slot-scope="{file}">-->
<!-- <div class="el-upload-list__item-name"></div>-->
<!--&lt;!&ndash; <img&ndash;&gt;-->
<!--&lt;!&ndash; class="el-upload-list__item-thumbnail"&ndash;&gt;-->
<!--&lt;!&ndash; :src="OSSclientConfig.basePath + file.url"&ndash;&gt;-->
<!--&lt;!&ndash; alt=""&ndash;&gt;-->
<!--&lt;!&ndash; >&ndash;&gt;-->
<!-- <span class="el-upload-list__item-actions">-->
<!-- <span-->
<!-- class="el-upload-list__item-preview"-->
<!-- @click="handlePictureCardPreview(file)"-->
<!-- >-->
<!-- <i class="el-icon-zoom-in" />-->
<!-- </span>-->
<!-- <span-->
<!-- v-if="readingTaskState < 2"-->
<!-- class="el-upload-list__item-delete"-->
<!-- @click="handleRemove(file)"-->
<!-- >-->
<!-- <i class="el-icon-delete" />-->
<!-- </span>-->
<!-- </span>-->
<!-- </div>-->
</el-upload> </el-upload>
<el-dialog <viewer
v-if="question.Type==='upload'" v-if="question.Type==='upload' && imgVisible"
append-to-body :ref="imageUrl"
:visible.sync="imgVisible" style="margin:0 10px;"
width="600px" :images="[imageUrl]"
> >
<el-image :src="imageUrl" width="100%"> <img
<div slot="placeholder" class="image-slot"> v-show="false"
加载中<span class="dot">...</span> crossorigin="anonymous"
</div> :src="imageUrl"
</el-image> alt="Image"
</el-dialog> >
</viewer>
</el-form-item> </el-form-item>
</template> </template>
<template v-if="question.Childrens && question.Childrens.length>0 && question.Type !== 'table'"> <template v-if="question.Childrens && question.Childrens.length>0 && question.Type !== 'table' && question.Type !== 'basicTable'">
<CustomizeQuestionFormItem <CustomizeQuestionFormItem
v-for="(item) in question.Childrens" v-for="(item) in question.Childrens"
:key="item.Id" :key="item.Id"
@ -295,9 +319,8 @@
:type="addOrEdit.type" :type="addOrEdit.type"
:CalculationList="CalculationTabelList" :CalculationList="CalculationTabelList"
@formItemTableNumberChange="formItemTableNumberChange" @formItemTableNumberChange="formItemTableNumberChange"
@setFormItemData="setFormItemData" @resetFormItemData="resetTableFormItemData"
@resetFormItemData="resetFormItemData" @setFormItemData="setFormTableItemData"
@setFormTableItemData="setFormTableItemData"
/> />
</el-form> </el-form>
</template> </template>
@ -374,7 +397,8 @@ export default {
RowIndex: 0, RowIndex: 0,
RowId: null, RowId: null,
digitPlaces: 0, digitPlaces: 0,
CalculationTabelList: [] CalculationTabelList: [],
classArr: []
} }
}, },
watch: { watch: {
@ -382,9 +406,18 @@ export default {
deep: true, deep: true,
immediate: true, immediate: true,
handler(v, oldv) { handler(v, oldv) {
// try {
// if (!v[this.question.Id] || !oldv[this.question.Id]) return
// } catch (e) {
// }
try { try {
if (!v[this.question.Id] || !oldv[this.question.Id]) return if (!v || !v[this.question.Id] || !oldv || !oldv[this.question.Id])
return
} catch (e) { } catch (e) {
console.log(e, v)
}
if (this.question.Type === 'class') {
this.$emit("setFormItemData", { key: this.question.Id, val: v[this.question.Id], question: v })
} }
this.formItemNumberChange(this.question.Id, false) this.formItemNumberChange(this.question.Id, false)
} }
@ -392,21 +425,21 @@ export default {
}, },
mounted() { mounted() {
this.digitPlaces = localStorage.getItem('digitPlaces') ? parseInt(localStorage.getItem('digitPlaces')) : 0 this.digitPlaces = localStorage.getItem('digitPlaces') ? parseInt(localStorage.getItem('digitPlaces')) : 0
if (this.question.Type === 'class') { // if (this.question.Type === 'class') {
this.ClassifyAlgorithmsList = JSON.parse(this.question.ClassifyAlgorithms) // this.ClassifyAlgorithmsList = JSON.parse(this.question.ClassifyAlgorithms)
} // }
setInterval(()=> { // setInterval(()=> {
if (this.question.Type === 'class') { // if (this.question.Type === 'class') {
let o = this.ClassifyAlgorithmsList.find(v => { // let o = this.ClassifyAlgorithmsList.find(v => {
return this.questionForm[this.question.ClassifyQuestionId] >= v.gt && this.questionForm[this.question.ClassifyQuestionId] < v.lt // return this.questionForm[this.question.ClassifyQuestionId] >= v.gt && this.questionForm[this.question.ClassifyQuestionId] < v.lt
}) // })
if (this.questionForm[this.question.ClassifyQuestionId]) { // if (this.questionForm[this.question.ClassifyQuestionId]) {
this.questionForm[this.question.Id] = o ? o.label : null // this.questionForm[this.question.Id] = o ? o.label : null
} else { // } else {
this.questionForm[this.question.Id] = null // this.questionForm[this.question.Id] = null
} // }
} // }
}, 300) // }, 300)
if (this.question.Type === 'upload') { if (this.question.Type === 'upload') {
if (this.questionForm[this.question.Id]) { if (this.questionForm[this.question.Id]) {
this.urls = this.questionForm[this.question.Id].split('|') this.urls = this.questionForm[this.question.Id].split('|')
@ -416,7 +449,7 @@ export default {
}) })
} }
} }
if (this.question.Type === 'table') { if (this.question.Type === 'table' || this.question.Type === 'baiscTable') {
this.getQuestionCalculateRelation() this.getQuestionCalculateRelation()
if (this.questionForm[this.question.Id]) { if (this.questionForm[this.question.Id]) {
this.QuestionsForm = {} this.QuestionsForm = {}
@ -436,11 +469,9 @@ export default {
if (value.split('.')[1].length >= this.digitPlaces) { if (value.split('.')[1].length >= this.digitPlaces) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces)) this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
} }
} else {
} }
}, },
deleteTableCol(row, index) { deleteTableCol(row, index) {
console.log(row)
this.$confirm(this.$t('trials:uploadNonDicoms:message:msg1')).then(() => { this.$confirm(this.$t('trials:uploadNonDicoms:message:msg1')).then(() => {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
var param = { var param = {
@ -451,7 +482,7 @@ export default {
deleteReadingRowAnswer(param) deleteReadingRowAnswer(param)
.then(async res => { .then(async res => {
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success('删除成功') this.$message.success(this.$t('common:message:deletedSuccessfully'))
DicomEvent.$emit('reGetQuestionAnswer') DicomEvent.$emit('reGetQuestionAnswer')
} }
loading.close() loading.close()
@ -461,11 +492,57 @@ export default {
}) })
}, },
setFormTableItemData(id, url) { setFormTableItemData(obj) {
this.$set(this.QuestionsForm, id, url) this.$set(this.QuestionsForm, obj.key, obj.val)
this.classArr.map(i=>{
if (i.triggerId === obj.key) {
let answer = null
let list = JSON.parse(i.classifyAlgorithms)
if (i.classifyType === 0) {
let o = list.find(v => {
return (
parseFloat(obj.val) >= parseFloat(v.gt) &&
parseFloat(obj.val) < parseFloat(v.lt)
)
})
answer = o ? o.label : null
} else if (i.classifyType === 1) {
let o = list.find(v => {
return v.val.includes(obj.val)
})
answer = o ? o.label : null
}
this.$set(this.QuestionsForm, i.classId, answer)
}
})
// if (this.classArr.length > 0) {
// let qs = this.classArr.find(i=>i.triggerId === obj.key)
// if (!qs) return
// let answer = null
// let list = JSON.parse(qs.classifyAlgorithms)
// if (qs.classifyType === 0) {
// let o = list.find(v => {
// return (
// parseFloat(obj.val) >= parseFloat(v.gt) &&
// parseFloat(obj.val) < parseFloat(v.lt)
// )
// })
// answer = o ? o.label : null
// } else if (qs.classifyType === 1) {
// let o = list.find(v => {
// return v.val.includes(obj.val)
// })
// answer = o ? o.label : null
// }
// if (answer !== null) {
// this.$set(this.QuestionsForm, qs.classId, answer)
// }
// }
},
resetTableFormItemData(obj) {
this.$set(this.QuestionsForm, obj.key, null)
}, },
handleSave() { handleSave() {
console.log(this.QuestionsForm)
this.$refs.tableQsForm.validate(valid => { this.$refs.tableQsForm.validate(valid => {
if (!valid) return if (!valid) return
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
@ -474,7 +551,6 @@ export default {
for (const k in this.QuestionsForm) { for (const k in this.QuestionsForm) {
if (reg.test(k)) { if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) { if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
console.log(this.QuestionsForm)
answers.push({ tableQuestionId: k, answer: this.QuestionsForm[k] }) answers.push({ tableQuestionId: k, answer: this.QuestionsForm[k] })
} }
} }
@ -501,6 +577,7 @@ export default {
submitTableQuestion(params).then(async res => { submitTableQuestion(params).then(async res => {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.QuestionsForm.RowId = res.Result.RowId this.QuestionsForm.RowId = res.Result.RowId
// DicomEvent.$emit('reGetQuestionAnswer')
this.save() this.save()
loading.close() loading.close()
}).catch(() => { loading.close() }) }).catch(() => { loading.close() })
@ -523,9 +600,7 @@ export default {
}) })
}, },
save() { save() {
console.log(this.$refs.tableQsForm, this.QuestionsForm)
this.$refs['tableQsForm'].validate((valid) => { this.$refs['tableQsForm'].validate((valid) => {
console.log(valid)
if (!valid) return if (!valid) return
if (this.addOrEdit.type === 'add') { if (this.addOrEdit.type === 'add') {
this.AnswersList.push(this.QuestionsForm) this.AnswersList.push(this.QuestionsForm)
@ -533,7 +608,7 @@ export default {
var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId) var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId)
this.AnswersList.splice(index, 1, this.QuestionsForm) this.AnswersList.splice(index, 1, this.QuestionsForm)
} }
this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList}) this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question})
this.formItemNumberChange(this.question.Id, true) this.formItemNumberChange(this.question.Id, true)
this.addOrEdit.visible = false this.addOrEdit.visible = false
}) })
@ -543,9 +618,10 @@ export default {
if (rules.CalculateQuestionList.length === 0) { if (rules.CalculateQuestionList.length === 0) {
return false return false
} }
let dataArr = []
rules.CalculateQuestionList.forEach((o, i) => { rules.CalculateQuestionList.forEach((o, i) => {
if (i === 0) { if (i === 0) {
if (rules.CustomCalculateMark > 4) { if (rules.CustomCalculateMark > 4 && rules.CustomCalculateMark < 10) {
switch (rules.CustomCalculateMark) { switch (rules.CustomCalculateMark) {
case 5: case 5:
this.questionForm[o.QuestionId].forEach((q, qi) => { this.questionForm[o.QuestionId].forEach((q, qi) => {
@ -592,6 +668,9 @@ export default {
} }
} else { } else {
num = parseFloat(this.questionForm[o.TableQuestionId]) num = parseFloat(this.questionForm[o.TableQuestionId])
if (!isNaN(num)) {
dataArr.push(num)
}
} }
} else { } else {
switch (rules.CustomCalculateMark) { switch (rules.CustomCalculateMark) {
@ -611,6 +690,38 @@ export default {
num /= parseFloat(this.questionForm[o.TableQuestionId]) num /= parseFloat(this.questionForm[o.TableQuestionId])
} }
break; break;
case 10:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => {
return acc + (typeof curr === "number" ? curr : 0);
}, 0) / dataArr.length;
break;
case 11:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = Math.max(...dataArr);
break;
case 12:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = Math.min(...dataArr);
break;
case 13:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => acc && curr) ? 1 : 0
break;
case 14:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => acc || curr, 0) ? 1 : 0;
break;
} }
} }
}) })
@ -621,7 +732,12 @@ export default {
if (rules.ValueType === 2) { if (rules.ValueType === 2) {
num = num * 100 num = num * 100
} }
return num.toFixed(digitPlaces) if (rules.CustomCalculateMark === 13 || rules.CustomCalculateMark === 14) {
return num
} else {
return num.toFixed(digitPlaces)
}
}, },
formItemNumberChange(questionId, isTable) { formItemNumberChange(questionId, isTable) {
if (isTable) { if (isTable) {
@ -633,7 +749,7 @@ export default {
if (find) { if (find) {
var num = this.logic(v) var num = this.logic(v)
if (num !== false) { if (num !== false) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num }) this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
} }
} }
}) })
@ -646,54 +762,107 @@ export default {
if (find) { if (find) {
var num = this.logic(v) var num = this.logic(v)
if (num !== false) { if (num !== false) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num }) this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
} }
} }
}) })
} }
// this.$emit('formItemNumberChange') // this.$emit('formItemNumberChange')
}, },
// formItemTableNumberChange() {
// this.question.TableQuestions.Questions.forEach(v => {
// if (v.Type === 'number' && v.DataSource === 1) {
// var CalculateQuestions = JSON.parse(v.CalculateQuestions)
// var num
// CalculateQuestions.forEach((o, i) => {
// if (i === 0) {
// num = this.QuestionsForm[o.TableQuestionId]
// } else {
// switch (v.CustomCalculateMark) {
// case 1:
// num += this.QuestionsForm[o.TableQuestionId]
// break;
// case 2:
// num -= this.QuestionsForm[o.TableQuestionId]
// break;
// case 3:
// num *= this.QuestionsForm[o.TableQuestionId]
// break;
// case 4:
// num /= this.QuestionsForm[o.TableQuestionId]
// break;
// }
// }
// })
// this.$set(this.QuestionsForm, v.Id, num.toString())
// }
// })
// },
formItemTableNumberChange() { formItemTableNumberChange() {
this.question.TableQuestions.Questions.forEach(v => { this.question.TableQuestions.Questions.forEach((v) => {
if (v.Type === 'number' && v.DataSource === 1) { if (v.Type === "number" && v.DataSource === 1) {
var CalculateQuestions = JSON.parse(v.CalculateQuestions) var CalculateQuestions = JSON.parse(v.CalculateQuestions);
var num var num,
arr = [];
CalculateQuestions.forEach((o, i) => { CalculateQuestions.forEach((o, i) => {
if (i === 0) { if (i === 0) {
num = this.QuestionsForm[o.TableQuestionId] num = parseFloat(this.QuestionsForm[o.TableQuestionId]);
arr = [num];
} else { } else {
switch (v.CustomCalculateMark) { switch (v.CustomCalculateMark) {
case 1: case 1:
num += this.QuestionsForm[o.TableQuestionId] num += parseFloat(this.QuestionsForm[o.TableQuestionId]);
break; break;
case 2: case 2:
num -= this.QuestionsForm[o.TableQuestionId] num -= parseFloat(this.QuestionsForm[o.TableQuestionId]);
break; break;
case 3: case 3:
num *= this.QuestionsForm[o.TableQuestionId] num *= parseFloat(this.QuestionsForm[o.TableQuestionId]);
break; break;
case 4: case 4:
num /= this.QuestionsForm[o.TableQuestionId] num /= parseFloat(this.QuestionsForm[o.TableQuestionId]);
break;
case 7:
arr.push(parseFloat(this.QuestionsForm[o.TableQuestionId]));
num =
arr.length === 0
? 0
: arr.reduce((acc, curr) => {
return acc + (typeof curr === "number" ? curr : 0);
}, 0) / arr.length;
break;
case 8:
arr.push(parseFloat(this.QuestionsForm[o.TableQuestionId]));
num = arr.length === 0 ? 0 : Math.max(...arr);
break;
case 9:
arr.push(parseFloat(this.QuestionsForm[o.TableQuestionId]));
num = arr.length === 0 ? 0 : Math.min(...arr);
// console.log('min', this.questionForm[o.QuestionId], arr, num)
break; break;
} }
} }
}) });
this.$set(this.QuestionsForm, v.Id, num.toString()) this.$set(this.QuestionsForm, v.Id, num.toString());
} }
}) });
}, },
openAddTableCol(row, index) { openAddTableCol(row, index) {
this.addOrEdit.visible = true this.addOrEdit.visible = true
this.addOrEdit.title = row.QuestionName + this.$t('trials:readingUnit:qsList:title:tableQs') this.addOrEdit.title = row.QuestionName + this.$t('trials:readingUnit:qsList:title:tableQs')
this.QuestionsList = row.TableQuestions.Questions this.QuestionsList = row.TableQuestions.Questions
row.TableQuestions.Questions.map(v=>{
if (v.Type === 'class') {
this.classArr.push({triggerId: v.ClassifyTableQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType})
}
})
this.AnswersList = row.TableQuestions.Answers this.AnswersList = row.TableQuestions.Answers
if (!index && index !== 0) { if (!index && index !== 0) {
this.addOrEdit.type = 'add' this.addOrEdit.type = 'add'
this.QuestionsForm = {} this.QuestionsForm = {}
} else { } else {
this.addOrEdit.type = 'edit' this.addOrEdit.type = 'edit'
console.log(this.questionForm)
this.QuestionsForm = Object.assign({}, this.questionForm[row.Id][index]) this.QuestionsForm = Object.assign({}, this.questionForm[row.Id][index])
} }
}, },
@ -709,7 +878,7 @@ export default {
}) })
}, },
formNumberItemChange(v) { formNumberItemChange(v) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num }) this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
}, },
formItemChange(v, question) { formItemChange(v, question) {
if (question.Childrens.length > 0) { if (question.Childrens.length > 0) {
@ -724,8 +893,10 @@ export default {
// if (typeof val === 'boolean') { // if (typeof val === 'boolean') {
// // val = String(val) // // val = String(val)
// } // }
this.$emit('setFormItemData', { key: qs.Id, val: val }) this.$emit('setFormItemData', { key: qs.Id, val: val, question: qs })
}) })
} else {
this.$emit('setFormItemData', { key: question.Id, val: v, question: question })
} }
}, },
resetChild(obj) { resetChild(obj) {
@ -741,9 +912,9 @@ export default {
}, },
setFormItemData(obj) { setFormItemData(obj) {
this.$emit('setFormItemData', obj) this.$emit('setFormItemData', obj)
}, },
async uploadScreenshot(param) { async uploadScreenshot(param) {
console.log('uploadScreenshot')
if (!this.visitTaskId) return if (!this.visitTaskId) return
const loading = this.$loading({ const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'), target: document.querySelector('.ecrf-wrapper'),
@ -756,9 +927,8 @@ export default {
let file = await this.fileToBlob(param.file) let file = await this.fileToBlob(param.file)
let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file) let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file)
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}`, url: this.$getObjectName(res.url) }) this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}`, url: this.$getObjectName(res.url) })
console.log('fileList', this.fileList)
this.urls.push(this.$getObjectName(res.url)) this.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
loading.close() loading.close()
// uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => { // uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
// if (res.IsSuccess) { // if (res.IsSuccess) {
@ -773,7 +943,6 @@ export default {
}, },
handleBeforeUpload(file, accept) { handleBeforeUpload(file, accept) {
// //
console.log('handleBeforeUpload', file)
if (this.checkFileSuffix(file.name, accept) || accept === '-1') { if (this.checkFileSuffix(file.name, accept) || accept === '-1') {
return true return true
} else { } else {
@ -781,7 +950,6 @@ export default {
this.$alert(msg) this.$alert(msg)
return false return false
} }
console.log(file)
}, },
checkFileSuffix(fileName, accept) { checkFileSuffix(fileName, accept) {
var index = fileName.lastIndexOf('.') var index = fileName.lastIndexOf('.')
@ -794,17 +962,25 @@ export default {
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
this.imgVisible = true suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
this.$nextTick(()=>{
this.$refs[this.imageUrl].$viewer.show()
})
}
}, },
// //
handleRemove(file, fileList) { handleRemove(file, fileList) {
console.log('handleRemove')
if (file && file.status === "success") { if (file && file.status === "success") {
this.imageUrl = '' this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1) this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1) this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
} }
} }
} }

View File

@ -125,7 +125,8 @@
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-if="question.Type==='upload'"
:action="accept" action
:accept="accept"
:limit="question.ImageCount" :limit="question.ImageCount"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
@ -138,27 +139,41 @@
> >
<i slot="default" class="el-icon-plus" /> <i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}"> <div slot="file" slot-scope="{file}">
<img <viewer
class="el-upload-list__item-thumbnail" :ref="file.url"
:src="OSSclientConfig.basePath + file.url" :images="[imageUrl]"
alt="" style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
> >
<span class="el-upload-list__item-actions"> <img
<span class="el-upload-list__item-thumbnail"
class="el-upload-list__item-preview" :src="OSSclientConfig.basePath + file.url"
@click="handlePictureCardPreview(file)" crossOrigin="anonymous"
> alt=""
<i class="el-icon-zoom-in" /> style="max-width: 100%; max-height: 100%"
</span> />
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span <span
v-if="readingTaskState < 2" v-if="readingTaskState < 2"
class="el-upload-list__item-delete" class="el-upload-list__item-delete"
@click="handleRemove(file)" @click="handleRemove(file)"
> >
<i class="el-icon-delete" /> <i class="el-icon-delete" />
</span>
</span> </span>
</span> </viewer>
</div> </div>
</el-upload> </el-upload>
<el-dialog <el-dialog
@ -276,7 +291,7 @@ export default {
const res = await this.OSSclient.put(`/${this.trialId}/ReadAttachment/${this.subjectId}/${this.visitTaskId}/${param.file.name}`, file) const res = await this.OSSclient.put(`/${this.trialId}/ReadAttachment/${this.subjectId}/${this.visitTaskId}/${param.file.name}`, file)
this.fileList.push({ name: param.file.name, url: this.$getObjectName(res.url) }) this.fileList.push({ name: param.file.name, url: this.$getObjectName(res.url) })
this.urls.push(this.$getObjectName(res.url)) this.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
loading.close() loading.close()
}, },
handleBeforeUpload(file) { handleBeforeUpload(file) {
@ -302,15 +317,21 @@ export default {
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
this.imgVisible = true suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.$refs[file.url].$viewer.show();
}
}, },
// //
handleRemove(file, fileList) { handleRemove(file, fileList) {
this.imageUrl = '' this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1) this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1) this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
} }
} }
} }

View File

@ -95,7 +95,38 @@
{{ val }} {{ val }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<!-- 自动分类 -->
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
/>
</el-select>
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
v-for="item of question.TypeValue.split('|')"
:key="item.trim()"
:label="item.trim()"
>
{{ item.trim() }}
</el-radio>
</el-radio-group>
<!-- 自动计算 --> <!-- 自动计算 -->
<!-- :precision="2" :step="0.1" :max="10" --> <!-- :precision="2" :step="0.1" :max="10" -->
<el-input <el-input
@ -136,39 +167,54 @@
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-if="question.Type==='upload'"
:action="accept" action
:limit="question.ImageCount" :accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:http-request="uploadScreenshot" :http-request="uploadScreenshot"
list-type="picture-card" list-type="picture-card"
:on-remove="handleRemove" :on-remove="handleRemove"
:file-list="fileList" :file-list="fileList"
:class="{disabled:fileList.length >= question.ImageCount}" :class="{disabled: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}"
> >
<i slot="default" class="el-icon-plus" /> <i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}"> <div slot="file" slot-scope="{file}">
<img <viewer
class="el-upload-list__item-thumbnail" :ref="file.url"
:src="OSSclientConfig.basePath + file.url" :images="[imageUrl]"
alt="" style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
> >
<span class="el-upload-list__item-actions"> <img
<span class="el-upload-list__item-thumbnail"
class="el-upload-list__item-preview" :src="OSSclientConfig.basePath + file.url"
@click="handlePictureCardPreview(file)" crossOrigin="anonymous"
> alt=""
<i class="el-icon-zoom-in" /> style="max-width: 100%; max-height: 100%"
</span> />
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span <span
v-if="readingTaskState < 2" v-if="readingTaskState < 2"
class="el-upload-list__item-delete" class="el-upload-list__item-delete"
@click="handleRemove(file)" @click="handleRemove(file)"
> >
<i class="el-icon-delete" /> <i class="el-icon-delete" />
</span>
</span> </span>
</span> </viewer>
</div> </div>
</el-upload> </el-upload>
<el-dialog <el-dialog
@ -268,11 +314,11 @@ export default {
deep: true, deep: true,
immediate: true, immediate: true,
handler(v, oldv) { handler(v, oldv) {
try { // try {
if (!v[this.question.Id] || !oldv[this.question.Id]) return // if (!v[this.question.Id] || !oldv[this.question.Id]) return
} catch (e) { // } catch (e) {
} // }
this.formItemNumberChange(this.question.Id, false) // this.formItemNumberChange(this.question.Id, false)
} }
}, },
}, },
@ -286,14 +332,15 @@ export default {
this.fileList.push({ name: '', url: `${url}` }) this.fileList.push({ name: '', url: `${url}` })
}) })
} }
console.log('11')
} }
if (this.type === 'edit') return if (this.type === 'edit') return
if (this.question.Type === 'number') { // if (this.question.Type === 'number') {
console.log(this.questionForm) // console.log(this.questionForm)
this.$set(this.questionForm, this.question.Id, null) // this.$set(this.questionForm, this.question.Id, null)
} else { // } else {
this.$set(this.questionForm, this.question.Id, '') // this.$set(this.questionForm, this.question.Id, '')
} // }
}, },
methods: { methods: {
save() { save() {
@ -329,8 +376,10 @@ export default {
// if (typeof val === 'boolean') { // if (typeof val === 'boolean') {
// // val = String(val) // // val = String(val)
// } // }
this.$emit('setFormItemData', { key: qs.Id, val: val }) this.$emit('setFormItemData', { key: qs.Id, val: val, question: qs })
}) })
} else {
this.$emit('setFormItemData', { key: question.Id, val: v, question: question })
} }
}, },
limitInput(value, q) { limitInput(value, q) {
@ -347,10 +396,11 @@ export default {
if (rules.CalculateQuestionList.length === 0) { if (rules.CalculateQuestionList.length === 0) {
return false return false
} }
let dataArr = []
var count = 0 var count = 0
var maxList = [], minList = [] var maxList = [], minList = []
rules.CalculateQuestionList.forEach((o, i) => { rules.CalculateQuestionList.forEach((o, i) => {
if (rules.CustomCalculateMark > 4) { if (rules.CustomCalculateMark > 4 && rules.CustomCalculateMark < 10) {
if (i !== 0) { if (i !== 0) {
switch (rules.CustomCalculateMark) { switch (rules.CustomCalculateMark) {
case 7: case 7:
@ -377,6 +427,7 @@ export default {
minList.push(this.questionForm[o.TableQuestionId]) minList.push(this.questionForm[o.TableQuestionId])
count = parseFloat(this.questionForm[o.TableQuestionId]) count = parseFloat(this.questionForm[o.TableQuestionId])
num = parseFloat(this.questionForm[o.TableQuestionId]) num = parseFloat(this.questionForm[o.TableQuestionId])
dataArr.push(num)
} }
} else { } else {
if (i !== 0) { if (i !== 0) {
@ -397,6 +448,26 @@ export default {
num /= parseFloat(this.questionForm[o.TableQuestionId]) num /= parseFloat(this.questionForm[o.TableQuestionId])
} }
break; break;
case 10:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => {
return acc + (typeof curr === "number" ? curr : 0);
}, 0) / dataArr.length;
break;
case 11:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = Math.max(...dataArr);
break;
case 12:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = Math.min(...dataArr);
break;
} }
} else { } else {
num = parseFloat(this.questionForm[o.TableQuestionId]) num = parseFloat(this.questionForm[o.TableQuestionId])
@ -413,23 +484,7 @@ export default {
return num.toFixed(digitPlaces) return num.toFixed(digitPlaces)
}, },
formItemNumberChange(v, question) { formItemNumberChange(v, question) {
console.log(this.CalculationList) this.$emit('formItemTableNumberChange', v, question)
this.CalculationList.forEach((v, i) => {
console.log('v', v)
var find = v.CalculateQuestionList.filter(o => {
return o.QuestionId === question.Id
})
console.log('find', find)
// findnumber
if (find) {
var num = this.logic(v)
console.log(num)
if (num !== false) {
this.$set(this.questionForm, v.QuestionId, num)
// this.$emit('setFormItemData', { key: v.QuestionId, val: num })
}
}
})
// this.$emit('formItemTableNumberChange', v, question) // this.$emit('formItemTableNumberChange', v, question)
}, },
resetChild(obj) { resetChild(obj) {
@ -462,7 +517,7 @@ export default {
console.log(res) console.log(res)
this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url)}) this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url)})
this.urls.push(this.$getObjectName(res.url)) this.urls.push(this.$getObjectName(res.url))
this.$emit('setFormTableItemData', this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '') this.$emit('setFormItemData', { key:this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
loading.close() loading.close()
}, },
handleBeforeUpload(file) { handleBeforeUpload(file) {
@ -471,14 +526,17 @@ export default {
// this.fileList = [] // this.fileList = []
return true return true
} else { } else {
this.$alert(`必须是 ${this.accept} 格式`) let msg = this.$t(
"trials:readingUnit:qsList:message:imageFormat"
).replace("xxx", this.question.FileType)
this.$alert(msg)
return false return false
} }
}, },
checkFileSuffix(fileName) { checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.') var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length) var suffix = fileName.substring(index + 1, fileName.length)
if (this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) { if (this.question.FileType.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false return false
} else { } else {
return true return true
@ -486,15 +544,23 @@ export default {
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
this.imgVisible = true suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
// this.imgVisible = true
this.$refs[file.url].$viewer.show()
}
}, },
// //
handleRemove(file, fileList) { handleRemove(file, fileList) {
this.imageUrl = '' this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1) this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1) this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormTableItemData', this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '') this.$emit('setFormItemData', { key:this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
} }
} }
} }

View File

@ -57,7 +57,8 @@ export default {
readingTaskState: 0, readingTaskState: 0,
activeName: 0, activeName: 0,
CalculationList: [], CalculationList: [],
IsBaseline: true IsBaseline: true,
classArr: []
} }
}, },
mounted() { mounted() {
@ -82,7 +83,7 @@ export default {
var answers = [] var answers = []
for (const k in this.questionForm) { for (const k in this.questionForm) {
if (this.questionForm[k] instanceof Array) {} else { if (this.questionForm[k] instanceof Array) {} else {
answers.push({ id: k, answer: this.questionForm[k].toString() }) answers.push({ id: k, answer: this.questionForm[k] })
} }
} }
var params = { var params = {
@ -122,12 +123,15 @@ export default {
DicomEvent.$emit('setReadingState', res.OtherInfo.ReadingTaskState) DicomEvent.$emit('setReadingState', res.OtherInfo.ReadingTaskState)
res.Result.SinglePage.map((v) => { res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.Id, v.Answer) this.$set(this.questionForm, v.Id, v.Answer)
} }
if (v.Type === 'table') { if (v.Type === 'table' || v.Type === 'basicTable') {
this.$set(this.questionForm, v.Id, v.TableQuestions.Answers) this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
} }
if (v.Type === 'class') {
this.classArr.push({triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType})
}
if (v.Type === 'number') { if (v.Type === 'number') {
this.$set(this.questionForm, v.Id, v.Answer === '' ? '' : parseFloat(v.Answer).toFixed(localStorage.getItem('digitPlaces'))) this.$set(this.questionForm, v.Id, v.Answer === '' ? '' : parseFloat(v.Answer).toFixed(localStorage.getItem('digitPlaces')))
} }
@ -136,7 +140,6 @@ export default {
} }
}) })
this.questions = res.Result.SinglePage this.questions = res.Result.SinglePage
console.log(this.questions)
this.isRender = true this.isRender = true
this.loading = false this.loading = false
}) })
@ -151,8 +154,8 @@ export default {
if (res.OtherInfo.FormType === 2) { if (res.OtherInfo.FormType === 2) {
if (res.Result.MultiPage.length > 0) { if (res.Result.MultiPage.length > 0) {
res.Result.MultiPage.map((v) => { res.Result.MultiPage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0 && i.Type !== 'table') return if (v.Type === 'group' && v.Childrens.length === 0 && i.Type !== 'table' && i.Type !== 'basicTable') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Type !== 'table') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, v.Id, '') this.$set(this.questionForm, v.Id, '')
} }
if (v.Childrens.length > 0) { if (v.Childrens.length > 0) {
@ -164,8 +167,8 @@ export default {
} }
if (res.Result.PublicPage.length > 0) { if (res.Result.PublicPage.length > 0) {
res.Result.PublicPage.map((v) => { res.Result.PublicPage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0 && i.Type !== 'table') return if (v.Type === 'group' && v.Childrens.length === 0 && i.Type !== 'table' && i.Type !== 'basicTable') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Type !== 'table') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, v.Id, '') this.$set(this.questionForm, v.Id, '')
} }
if (v.Childrens.length > 0) { if (v.Childrens.length > 0) {
@ -176,11 +179,11 @@ export default {
} }
} else { } else {
res.Result.SinglePage.map((v) => { res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table' && v.Type !== 'basicTable') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.Id, v.Answer) this.$set(this.questionForm, v.Id, v.Answer)
} }
if (v.Type === 'table') { if (v.Type === 'table' || v.Type === 'basicTable') {
this.$set(this.questionForm, v.Id, v.TableQuestions.Answers) this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
} }
if (v.Type === 'number') { if (v.Type === 'number') {
@ -198,10 +201,10 @@ export default {
}, },
setChild(obj) { setChild(obj) {
obj.forEach(i => { obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table') { if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, i.Id, i.Answer) this.$set(this.questionForm, i.Id, i.Answer)
} }
if (i.Type === 'table') { if (i.Type === 'table' || i.Type === 'basicTable') {
i.TableQuestions.Questions.forEach(o => { i.TableQuestions.Questions.forEach(o => {
if (o.Type === 'number') { if (o.Type === 'number') {
i.TableQuestions.Answers.forEach((ite, index) => { i.TableQuestions.Answers.forEach((ite, index) => {
@ -211,6 +214,9 @@ export default {
}) })
this.$set(this.questionForm, i.Id, i.TableQuestions.Answers) this.$set(this.questionForm, i.Id, i.TableQuestions.Answers)
} }
if (i.Type === 'class') {
this.classArr.push({triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType})
}
if (i.Type === 'number') { if (i.Type === 'number') {
this.$set(this.questionForm, i.Id, i.Answer === '' ? '' : parseFloat(i.Answer).toFixed(localStorage.getItem('digitPlaces'))) this.$set(this.questionForm, i.Id, i.Answer === '' ? '' : parseFloat(i.Answer).toFixed(localStorage.getItem('digitPlaces')))
} }
@ -224,6 +230,50 @@ export default {
}, },
setFormItemData(obj) { setFormItemData(obj) {
this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val))) this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
this.classArr.map(i=>{
if (i.triggerId === obj.key) {
let answer = null
let list = JSON.parse(i.classifyAlgorithms)
if (i.classifyType === 0) {
let o = list.find(v => {
return (
parseFloat(obj.val) >= parseFloat(v.gt) &&
parseFloat(obj.val) < parseFloat(v.lt)
)
})
answer = o ? o.label : null
} else if (i.classifyType === 1) {
let o = list.find(v => {
return v.val.includes(obj.val)
})
answer = o ? o.label.trim() : null
}
this.$set(this.questionForm, i.classId, answer)
}
})
// if (this.classArr.length > 0) {
// let qs = this.classArr.find(i=>i.triggerId === obj.key)
// if (!qs) return
// let answer = null
// let list = JSON.parse(qs.classifyAlgorithms)
// if (qs.classifyType === 0) {
// let o = list.find(v => {
// return (
// parseFloat(obj.val) >= parseFloat(v.gt) &&
// parseFloat(obj.val) < parseFloat(v.lt)
// )
// })
// answer = o ? o.label : null
// } else if (qs.classifyType === 1) {
// let o = list.find(v => {
// return v.val.includes(obj.val)
// })
// answer = o ? o.label.trim() : null
// }
// if (answer !== null) {
// this.$set(this.questionForm, qs.classId, answer)
// }
// }
} }
} }
} }

View File

@ -11,6 +11,15 @@
style="margin-right:5px" style="margin-right:5px"
@change="handleShowDetail" @change="handleShowDetail"
/> />
<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="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="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> <el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleConfirm">{{$t('common:button:submit')}}</el-button>
@ -71,7 +80,7 @@
</div> </div>
</template> </template>
<template slot-scope="scope"> <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')"> <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' || scope.row.Type === 'class')">
<template> <template>
<!-- 输入框 --> <!-- 输入框 -->
<div> <div>
@ -103,12 +112,12 @@
<el-option <el-option
v-for="val in scope.row.TypeValue.split('|')" v-for="val in scope.row.TypeValue.split('|')"
:key="val" :key="val"
:label="val" :label="val.trim()"
:value="val" :value="val.trim()"
/> />
</template> </template>
</el-select> </el-select>
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='select'"> <span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='select' || scope.row.Type==='radio'">
{{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}} {{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}}
</span> </span>
<el-select <el-select
@ -121,14 +130,20 @@
<el-option <el-option
v-for="val in scope.row.TypeValue.split('|')" v-for="val in scope.row.TypeValue.split('|')"
:key="val" :key="val"
:label="val" :label="val.trim()"
:value="val" :value="val.trim()"
/> />
</template> </template>
</el-select> </el-select>
<span v-else-if="scope.row.Type==='select' || scope.row.Type==='radio'"> <span v-else-if="scope.row.Type==='select' || scope.row.Type==='radio'">
{{questionForm[scope.row.QuestionId]}} {{questionForm[scope.row.QuestionId]}}
</span> </span>
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='class'">
{{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}}
</span>
<span v-else-if="scope.row.Type==='class'">
{{questionForm[scope.row.QuestionId]}}
</span>
<el-input <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-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]" v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
@ -260,6 +275,7 @@
</template> </template>
<script> <script>
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials' import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import DicomEvent from './../components/DicomEvent' import DicomEvent from './../components/DicomEvent'
import CustomizeReportPageUpload from './CustomizeReportPageUpload' import CustomizeReportPageUpload from './CustomizeReportPageUpload'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
@ -415,11 +431,11 @@ export default {
}, },
InitVisitTaskQuestionForm() { InitVisitTaskQuestionForm() {
this.taskQuestions.map((v, i) => { this.taskQuestions.map((v, i) => {
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table' && v.Type !== 'basicTable') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') { if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId]) this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId])
} }
if (v.Type === 'table') { if (v.Type === 'table' || v.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i) var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i)
this.$set(this.questionForm, v.QuestionId, tableAnswers) this.$set(this.questionForm, v.QuestionId, tableAnswers)
// this.$set(v, 'xfIndex', i) // this.$set(v, 'xfIndex', i)
@ -435,17 +451,17 @@ export default {
}, },
setChild(obj) { setChild(obj) {
obj.forEach((i, index) => { obj.forEach((i, index) => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table') { if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId]) this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId])
} }
if (i.Type === 'table') { if (i.Type === 'table' || i.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index) var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
this.$set(this.questionForm, i.QuestionId, tableAnswers) this.$set(this.questionForm, i.QuestionId, tableAnswers)
} }
if (i.Type === 'number') { if (i.Type === 'number') {
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : i.Answers[this.visitTaskId]) this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : i.Answers[this.visitTaskId])
} }
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table') { if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table' && i.Type !== 'basicTable') {
this.setChild(i.Childrens) this.setChild(i.Childrens)
} }
}) })
@ -775,13 +791,15 @@ export default {
}, },
previewDicoms(task) { previewDicoms(task) {
var token = getToken() var token = getToken()
var subjectCode = this.$router.currentRoute.query.subjectCode // var subjectCode = this.$router.currentRoute.query.subjectCode
var subjectCode = localStorage.getItem('subjectCode')
var subjectId = this.$router.currentRoute.query.subjectId var subjectId = this.$router.currentRoute.query.subjectId
var trialId = this.$router.currentRoute.query.trialId var trialId = this.$router.currentRoute.query.trialId
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var criterionType = this.$router.currentRoute.query.criterionType var criterionType = this.$router.currentRoute.query.criterionType
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
var path = `/readingDicoms?trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var path = `/readingDicoms?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 }) const routeData = this.$router.resolve({ path })
window.open(routeData.href, '_blank') window.open(routeData.href, '_blank')
}, },
@ -826,6 +844,28 @@ export default {
reject() 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)
}
} }
} }
} }

View File

@ -1,54 +1,57 @@
<template> <template>
<div> <div>
<el-upload <el-upload
:action="accept" action
:limit="question.ImageCount" :accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:http-request="uploadScreenshot" :http-request="uploadScreenshot"
list-type="picture-card" list-type="picture-card"
:on-remove="handleRemove" :on-remove="handleRemove"
:file-list="fileList" :file-list="fileList"
:class="{disabled:readingTaskState >= 2 || (fileList.length >= question.ImageCount) || (task.VisitTaskId !== visitTaskId) || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))}" :class="{disabled:readingTaskState >= 2 || (question.ImageCount === 0 ? false : fileList.length >= question.ImageCount) || (task.VisitTaskId !== visitTaskId) || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))}"
:disabled="readingTaskState >= 2 || task.VisitTaskId !== visitTaskId || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))" :disabled="readingTaskState >= 2 || task.VisitTaskId !== visitTaskId || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))"
> >
<i slot="default" class="el-icon-plus" /> <i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}"> <div slot="file" slot-scope="{file}">
<img <viewer
class="el-upload-list__item-thumbnail" :ref="file.url"
crossOrigin="Anonymous" :images="[imageUrl]"
:src="OSSclientConfig.basePath + file.url" style="
alt="" display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
> >
<span class="el-upload-list__item-actions"> <img
<span class="el-upload-list__item-thumbnail"
class="el-upload-list__item-preview" :src="OSSclientConfig.basePath + file.url"
@click="handlePictureCardPreview(file)" crossOrigin="anonymous"
> alt=""
<i class="el-icon-zoom-in" /> style="max-width: 100%; max-height: 100%"
</span> />
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span <span
v-if="readingTaskState < 2" v-if="readingTaskState < 2"
class="el-upload-list__item-delete" class="el-upload-list__item-delete"
@click="handleRemove(file)" @click="handleRemove(file)"
> >
<i class="el-icon-delete" /> <i class="el-icon-delete" />
</span> </span>
</span> </span>
</viewer>
</div> </div>
</el-upload> </el-upload>
<el-dialog
append-to-body
:visible.sync="imgVisible"
width="600px"
>
<el-image :src="imageUrl" width="100%" crossOrigin="Anonymous">
<div slot="placeholder" class="image-slot">
加载中<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
</div> </div>
</template> </template>
@ -93,13 +96,13 @@ name: "CustomizeReportPageUpload",
this.urls.map(url => { this.urls.map(url => {
this.fileList.push({ name: '', url: `${url}` }) this.fileList.push({ name: '', url: `${url}` })
}) })
console.log(this.fileList) // console.log(this.fileList)
}, },
methods: { methods: {
checkFileSuffix(fileName) { checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.') var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length) var suffix = fileName.substring(index + 1, fileName.length)
if (this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) { if (this.question.FileType.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false return false
} else { } else {
return true return true
@ -130,14 +133,25 @@ name: "CustomizeReportPageUpload",
// this.fileList = [] // this.fileList = []
return true return true
} else { } else {
this.$alert(`必须是 ${this.accept} 格式`) // this.$alert(` ${this.accept} `)
let msg = this.$t(
"trials:readingUnit:qsList:message:imageFormat"
).replace("xxx", this.question.FileType)
this.$alert(msg)
return false return false
} }
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
this.imgVisible = true suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
// this.imgVisible = true
this.$refs[file.url].$viewer.show()
}
}, },
// //
handleRemove(file, fileList) { handleRemove(file, fileList) {

View File

@ -49,20 +49,52 @@
/> />
<div class="image-desc"> <div class="image-desc">
<div class="flex-div"> <div class="flex-div">
<div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }} </div> <div style="width: 40px;display: flex;flex-direction: row;justify-content: space-between;">
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount && series.modality!== 'SR'"> <div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }}</div>
<!-- 下载 --> <div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount * 100 && series.modality!== 'SR'">
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom"> <!-- 下载 -->
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
</el-tooltip>
</div>
<el-tooltip v-else-if="series.isDicom && series.prefetchInstanceCount === 0 &&series.modality!== 'SR'" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" /> <i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
</el-tooltip> </el-tooltip>
<!-- 暂停 -->
<!-- <el-tooltip v-else class="item" effect="dark" :content="$t('trials:reading:button:pause')" placement="bottom">
<i class="el-icon-video-pause" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="stopLoadSeries(series,index,i)" />
</el-tooltip> -->
</div> </div>
<el-tooltip v-else-if="series.isDicom && series.prefetchInstanceCount === 0 &&series.modality!== 'SR'" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom"> <div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" /> <el-popover
</el-tooltip> placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div class="frame_list">
<div
v-for="(instance, idx) in series.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.instanceInfoList.length-1? '5px':'0px'}"
@click.stop="showMultiFrames(index,series, i, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;color: #ffeb3b;" />
</el-popover>
</div>
</div> </div>
<p v-show="series.description"> <p v-show="series.description">
<el-tooltip class="item" effect="dark" :content="series.description" placement="right"> <el-tooltip class="item" effect="dark" :content="series.description" placement="right">
@ -73,10 +105,12 @@
<p v-show="series.sliceThickness && !study.IsCriticalSequence"> <p v-show="series.sliceThickness && !study.IsCriticalSequence">
T: {{ parseFloat(series.sliceThickness).toFixed(digitPlaces) }} T: {{ parseFloat(series.sliceThickness).toFixed(digitPlaces) }}
</p> </p>
<p v-show="series.instanceCount"> <p v-show="series.instanceCount && series.imageloadedArr.length < series.instanceCount">
{{ series.modality }}: {{ series.imageloadedArr.length }}/{{ series.instanceCount }} image
</p>
<p v-show="series.instanceCount && series.imageloadedArr.length >= series.instanceCount">
{{ series.modality }}: {{ series.instanceCount }} image {{ series.modality }}: {{ series.instanceCount }} image
</p> </p>
<div class="flex-div"> <div class="flex-div">
<div v-if="measureData && measureData.findIndex(v=>v.SeriesId === series.seriesId && v.MeasureData) > -1"> <div v-if="measureData && measureData.findIndex(v=>v.SeriesId === series.seriesId && v.MeasureData) > -1">
<!-- 有标注 --> <!-- 有标注 -->
@ -88,9 +122,9 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" style="width: 100%;"> <div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount * 100" style="width: 100%;">
<el-progress <el-progress
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))" :percentage="parseInt((series.prefetchInstanceCount / series.instanceCount).toFixed(2))"
/> />
</div> </div>
@ -125,18 +159,11 @@
</div> </div>
</template> </template>
<script> <script>
import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import requestPoolManager from '@/utils/request-pool' import requestPoolManager from '@/utils/request-pool'
import DicomEvent from './../components/DicomEvent' import DicomEvent from './../components/DicomEvent'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import store from '@/store' import store from '@/store'
import SrList from './../components/SrList' import SrList from './../components/SrList'
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
export default { export default {
name: 'StudyList', name: 'StudyList',
components: { SrList }, components: { SrList },
@ -219,22 +246,23 @@ export default {
// } // }
}, },
mounted() { mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode // this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectCode = localStorage.getItem('subjectCode')
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
DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
})
// DicomEvent.$on('setReadingState', readingTaskState => { // DicomEvent.$on('setReadingState', readingTaskState => {
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) // var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
// if (idx > -1) { // if (idx > -1) {
// this.studyList = this.visitTaskList[idx].StudyList // this.studyList = this.visitTaskList[idx].StudyList
// } // }
// }) // })
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
// cornerstone.events.addEventListener('cornerstoneimagecachefull', this.cornerstoneimagecachefull)
// cornerstone.events.addEventListener('cornerstoneimagecachechanged', this.cornerstoneimagecachechanged)
}, },
beforeDestroy() { beforeDestroy() {
cornerstone.imageCache.purgeCache()
}, },
methods: { methods: {
initStudyInfo() { initStudyInfo() {
@ -242,81 +270,40 @@ export default {
// //
this.getInitSeries().then((res) => { this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer() requestPoolManager.startTaskTimer()
res.map((item) => { res.map(async(item) => {
this.loadInitialImage(item) let imageId = item.imageIds[item.imageIdIndex]
const p = parseInt(new Date().getTime())
// requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
await requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
if (!item.isCurrentTask) {
store.dispatch('reading/setImageloadedInfo', item)
}
}) })
var i = res.findIndex(s => s.isCurrentTask) var i = -1
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
if (isReadingTaskViewInOrder === 2) {
//
i = res.length === 2 ? 1 : -1
} else {
i = res.findIndex(s => s.isCurrentTask)
}
if (i > -1) { if (i > -1) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1) { if (idx > -1) {
this.measureData = this.visitTaskList[idx].MeasureData this.measureData = this.visitTaskList[idx].MeasureData
this.studyList = this.visitTaskList[idx].StudyList this.studyList = this.visitTaskList[idx].StudyList
var priority = parseInt(new Date().getTime()) var priority = parseInt(new Date().getTime())
res[i].imageIds.map(image => { if (res[i].isExistMutiFrames) {
priority-- res[i].instanceInfoList.map(image => {
this.imageList.push({ imageId: image, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].visitTaskId, priority }) priority--
}) this.imageList.push({ imageId: image.ImageId, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].visitTaskId, priority })
// this.studyList.map((study, studyIndex) => {
// study.SeriesList.map((series, seriesIndex) => {
// if (series.modality !== 'SR') {
// series.imageIds.map(image => {
// var p = priority - seriesIndex
// if (series.seriesId === res[i].seriesId) {
// p = priority
// } else {
// --p
// }
// this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority: p })
// })
// }
// })
// })
this.loopLoad()
}
}
DicomEvent.$emit('loadImageStacks', res)
loading.close()
this.isRender = true
}).catch(() => {
loading.close()
})
},
initStudyInfo2() {
console.log('initStudyInfo')
const loading = this.$loading({ fullscreen: true })
//
this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer()
res.map((item) => {
this.loadInitialImage(item)
})
var i = res.findIndex(s => s.isCurrentTask)
if (i > -1) {
var p = parseInt(new Date().getTime())
// var p = this.visitTaskId === this.currentTaskId ? parseInt(new Date().getTime()) : 999 //
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1) {
this.measureData = this.visitTaskList[idx].MeasureData
this.studyList = this.visitTaskList[idx].StudyList
this.studyList.map((study, studyIndex) => {
study.SeriesList.map((series, seriesIndex) => {
if (series.modality !== 'SR') {
// var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
// if (sliceThickness === 5 || series.instanceCount <= 100) {
series.imageIds.map(image => {
let priority = 0
if (series.seriesId === res[i].seriesId) {
priority = parseInt(new Date().getTime()) * 10
} else {
priority = --p
}
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
}) })
}) } else {
res[i].imageIds.map(image => {
priority--
this.imageList.push({ imageId: image, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].visitTaskId, priority })
})
}
this.loopLoad() this.loopLoad()
} }
} }
@ -331,14 +318,9 @@ export default {
loadInitialImage(seriesInfo) { loadInitialImage(seriesInfo) {
var p = parseInt(new Date().getTime()) var p = parseInt(new Date().getTime())
var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex] var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex]
requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100).then(res => { requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100)
if (seriesInfo.isCurrentTask) {
this.imageLoaded({ studyIndex: seriesInfo.studyIndex, seriesIndex: seriesInfo.seriesIndex, imageId: res.imageId }, res.data.string('x0020000e'))
}
})
}, },
getStudyList() { getStudyList() {
console.log('getStudyList')
if (!this.isRender) { if (!this.isRender) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) { if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) {
@ -349,8 +331,27 @@ export default {
this.studyIndex = sIdx this.studyIndex = sIdx
this.seriesIndex = 0 this.seriesIndex = 0
this.activeNames = [`${this.studyList[sIdx].StudyId}`] this.activeNames = [`${this.studyList[sIdx].StudyId}`]
//
this.loadImages(this.visitTaskList[idx]) const i = this.studyList.findIndex(i => i.IsCriticalSequence)
if (i > -1 && this.studyList[i].SeriesList[0].length > 0) {
const series = this.studyList[i].SeriesList[0]
if (!series.loadStatus) {
let priority = parseInt(new Date().getTime())
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
priority = priority - 1
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: i, seriesIndex: 0, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map(imageId => {
priority = priority - 1
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: i, seriesIndex: 0, visitTaskId: series.visitTaskId, priority })
})
}
}
}
this.loopLoad()
// this.loadImages(this.visitTaskList[idx])
} }
} }
this.isRender = true this.isRender = true
@ -362,7 +363,22 @@ export default {
var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder) var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.studyList = this.visitTaskList[idx].StudyList this.studyList = this.visitTaskList[idx].StudyList
if (this.visitTaskList[idx].IsBaseLineTask || !isReadingTaskViewInOrder) { if (isReadingTaskViewInOrder === 2) {
//
const studyList = this.visitTaskList[idx].StudyList.filter(i => i.IsDicom)
const seriesArr = studyList.map(s => s.SeriesList).flat()
if (seriesArr.length === 1) {
seriesList.push(seriesArr[0], seriesArr[0])
this.studyIndex = seriesArr[0].studyIndex
this.seriesIndex = seriesArr[0].seriesIndex
this.activeNames = [`${seriesArr[0].studyId}`]
} else if (seriesArr.length > 1) {
seriesList.push(seriesArr[0], seriesArr[1])
this.studyIndex = seriesArr[1].studyIndex
this.seriesIndex = seriesArr[1].seriesIndex
this.activeNames = [`${seriesArr[1].studyId}`]
}
} else if (this.visitTaskList[idx].IsBaseLineTask || isReadingTaskViewInOrder === 0){
// 线 // 线
const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList]) const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList])
if (Object.keys(obj).length !== 0) { if (Object.keys(obj).length !== 0) {
@ -393,7 +409,7 @@ export default {
if (bsIdx > -1) { if (bsIdx > -1) {
var trialId = this.$router.currentRoute.query.trialId var trialId = this.$router.currentRoute.query.trialId
await store.dispatch('reading/getMeasuredData', this.visitTaskList[bsIdx].VisitTaskId) await store.dispatch('reading/getCustomizeMeasuredData', this.visitTaskList[bsIdx].VisitTaskId)
await store.dispatch('reading/getStudyInfo', { trialId: trialId, subjectVisitId: this.visitTaskList[bsIdx].VisitId, visitTaskId: this.visitTaskList[bsIdx].VisitTaskId, taskBlindName: this.visitTaskList[bsIdx].TaskBlindName }) await store.dispatch('reading/getStudyInfo', { trialId: trialId, subjectVisitId: this.visitTaskList[bsIdx].VisitId, visitTaskId: this.visitTaskList[bsIdx].VisitTaskId, taskBlindName: this.visitTaskList[bsIdx].TaskBlindName })
const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList]) const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList])
@ -432,9 +448,11 @@ export default {
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId) const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId)
const seriesList = studyList[sdIndx].SeriesList const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId) const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId)
// const instanceList = seriesList[srIdx].imageIds // const instanceList = seriesList[srIdx].instanceList
const instanceList = seriesList[srIdx].instanceList // const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId))
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId)) const imageIds = seriesList[srIdx].imageIds
let filterStr = seriesList[srIdx].isExistMutiFrames ? `frame=${measureDatas[i].MeasureData.frame}&instanceId=${measureDatas[i].InstanceId}` : `instanceId=${measureDatas[i].InstanceId}`
const isIdx = imageIds.findIndex(is => is.includes(filterStr))
const series = seriesList[srIdx] const series = seriesList[srIdx]
series.imageIdIndex = isIdx series.imageIdIndex = isIdx
@ -504,9 +522,11 @@ export default {
if (sdIndx > -1) { if (sdIndx > -1) {
const seriesList = studyList[sdIndx].SeriesList const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId) const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId)
// const instanceList = seriesList[srIdx].imageIds // const instanceList = seriesList[srIdx].instanceList
const instanceList = seriesList[srIdx].instanceList // const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId))
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId)) const imageIds = seriesList[srIdx].imageIds
let filterStr = seriesList[srIdx].isExistMutiFrames ? `frame=${measureDatas[mIdx].MeasureData.frame}&instanceId=${measureDatas[mIdx].InstanceId}` : `instanceId=${measureDatas[mIdx].InstanceId}`
const isIdx = imageIds.findIndex(is => is.includes(filterStr))
const series = seriesList[srIdx] const series = seriesList[srIdx]
series.imageIdIndex = isIdx series.imageIdIndex = isIdx
@ -535,19 +555,18 @@ export default {
obj.series = seriesObj.series obj.series = seriesObj.series
obj.seriesId = seriesObj.series.seriesId obj.seriesId = seriesObj.series.seriesId
obj.isMarked = false obj.isMarked = false
} else { }
const sIdx = studyList.findIndex(s => s.IsDicom) }
if (sIdx > -1) { if (Object.keys(obj).length === 0) {
// 5 const sIdx = studyList.findIndex(s => s.IsDicom)
const series = studyList[sIdx].SeriesList[0] if (sIdx > -1) {
var imageIdIndex = series.imageIds.length > 1 ? Math.floor(series.imageIds.length / 2) - 1 : 0 obj.studyIndex = sIdx
obj.studyIndex = sIdx obj.seriesIndex = 0
obj.seriesIndex = 0 obj.series = studyList[obj.studyIndex].SeriesList[obj.seriesIndex]
obj.series = series const imageIdIndex = Math.floor(obj.series.imageIds.length / 2)
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0 obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
obj.seriesId = series.seriesId // obj.seriesId = series.seriesId
obj.isMarked = false obj.isMarked = false
}
} }
} }
@ -604,7 +623,9 @@ export default {
this.studyIndex = studyIndex this.studyIndex = studyIndex
this.seriesIndex = seriesIndex this.seriesIndex = seriesIndex
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
var dicomStatck = this.studyList[studyIndex].SeriesList[seriesIndex] var dicomStatck = Object.assign({},this.studyList[studyIndex].SeriesList[seriesIndex])
dicomStatck.imageIdIndex = 0
this.$emit('loadImageStack', dicomStatck) this.$emit('loadImageStack', dicomStatck)
if (!series.loadStatus && series.modality !== 'SR') { if (!series.loadStatus && series.modality !== 'SR') {
this.loopLoadStatus = -1 this.loopLoadStatus = -1
@ -617,9 +638,15 @@ export default {
} }
if (!isAddToTakPool) { if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime()) var priority = parseInt(new Date().getTime())
series.imageIds.map((imageId) => { if (series.isExistMutiFrames) {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) series.instanceInfoList.map(image => {
}) this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map(imageId => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
this.loopLoadStatus = 0 this.loopLoadStatus = 0
this.loopLoad() this.loopLoad()
@ -638,6 +665,58 @@ export default {
store.dispatch('reading/setActiveSeries', series) store.dispatch('reading/setActiveSeries', series)
}, },
showMultiFrames(studyIndex, series, seriesIndex, instanceInfo) {
this.currentSeriesIndex = seriesIndex
var idx = this.visitTaskIdx
this.studyIndex = studyIndex
this.seriesIndex = seriesIndex
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
var dicomStatck = Object.assign({},this.studyList[studyIndex].SeriesList[seriesIndex])
const imageIds = []
if (instanceInfo.KeyFramesList.length > 0) {
instanceInfo.KeyFramesList.map(i => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${i}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
})
} else if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
}
dicomStatck.imageIds = imageIds
dicomStatck.imageIdIndex = 0
this.$emit('loadImageStack', dicomStatck)
this.loopLoadStatus = -1
series.isLoading = true
var isAddToTakPool = false
if (this.showSeriesList.includes(`${studyIndex}_${seriesIndex}`)) {
isAddToTakPool = true
} else {
this.showSeriesList.push(`${studyIndex}_${seriesIndex}`)
}
if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime())
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
} else {
series.imageIds.map((imageId) => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
if (this.imageList.length > 0) {
this.loopLoadStatus = 0
this.loopLoad()
}
} else {
requestPoolManager.changePriority(series.seriesId)
}
DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskId, taskBlindName: this.taskBlindName })
},
setSeriesActive(obj) { setSeriesActive(obj) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx === -1) return if (idx === -1) return
@ -647,7 +726,8 @@ export default {
var activeNames = `${this.studyList[obj.studyIndex].StudyId}` var activeNames = `${this.studyList[obj.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames) this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx]) // this.loadImages(this.visitTaskList[idx])
this.loadImages(obj)
}, },
selectSeries(obj) { selectSeries(obj) {
var seriseList = this.studyList.map(s => s.SeriesList).flat() var seriseList = this.studyList.map(s => s.SeriesList).flat()
@ -672,38 +752,25 @@ export default {
var activeNames = `${this.studyList[series.studyIndex].StudyId}` var activeNames = `${this.studyList[series.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames) this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx]) this.loadImages(series)
// this.loadImages(this.visitTaskList[idx])
store.dispatch('reading/setActiveSeries', series) store.dispatch('reading/setActiveSeries', series)
}, },
loadImages(taskInfo) { loadImages(series) {
// const isBaseLineTask = taskInfo.IsBaseLineTask
const isCurrentTask = taskInfo.IsCurrentTask
// var priority = isCurrentTask ? parseInt(new Date().getTime()) : 999
var priority = parseInt(new Date().getTime()) var priority = parseInt(new Date().getTime())
this.studyList.map((study, studyIndex) => { if (!series.loadStatus && series.isDicom && series.modality !== 'SR') {
study.SeriesList.map((series, seriesIndex) => { if (series.isExistMutiFrames) {
if (!series.loadStatus && series.isDicom && series.modality !== 'SR') { series.instanceInfoList.map(image => {
// if (isCurrentTask || isBaseLineTask) { priority = priority - 1
// // /线 this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: series.studyIndex, seriesIndex: series.seriesIndex, visitTaskId: series.visitTaskId, priority })
// series.imageIds.map(image => { })
// this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) } else {
// }) series.imageIds.map(imageId => {
// } else if (!isBaseLineTask && !isCurrentTask && study.IsCriticalSequence) { priority = priority - 1
// // 访 this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: series.studyIndex, seriesIndex: series.seriesIndex, visitTaskId: series.visitTaskId, priority })
// series.imageIds.map(image => { })
// this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) }
// }) }
// }
//
if (!isCurrentTask && study.IsCriticalSequence) {
series.imageIds.map(image => {
priority = priority - 1
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
}
}
})
})
this.loopLoad() this.loopLoad()
}, },
@ -711,9 +778,7 @@ export default {
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
// requestPoolManager.startTaskTimer() // requestPoolManager.startTaskTimer()
this.imageList.map(image => { this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => { requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
this.imageLoaded(image, res.data.string('x0020000e'))
})
}) })
requestPoolManager.sortTaskPool() requestPoolManager.sortTaskPool()
@ -733,12 +798,21 @@ export default {
} }
if (!isAddToTakPool) { if (!isAddToTakPool) {
const priority = parseInt(new Date().getTime()) const priority = parseInt(new Date().getTime())
series.imageIds.map(image => { if (series.isExistMutiFrames) {
const index = this.cachedImages.findIndex(item => item.uri === image) series.instanceInfoList.map(image => {
if (index === -1) { const index = this.cachedImages.findIndex(item => item.uri === image)
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority }) if (index === -1) {
} this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
}) }
})
} else {
series.imageIds.map(image => {
const index = this.cachedImages.findIndex(item => item.uri === image)
if (index === -1) {
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
}
})
}
if (this.imageList.length > 0) { if (this.imageList.length > 0) {
this.loopLoadStatus = 0 this.loopLoadStatus = 0
this.loopLoad() this.loopLoad()
@ -753,83 +827,6 @@ export default {
requestPoolManager.removeTask(series.seriesId) requestPoolManager.removeTask(series.seriesId)
this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', false) this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', false)
}, },
async imageLoaded(image, seriesUid) {
// await store.dispatch('reading/updateStudyList', { visitTaskId: image.visitTaskId, imageId: image.imageId, seriesUid })
// console.log(this.studyList[image.studyIndex].SeriesList[image.seriesIndex])
if (image.studyIndex > -1 && image.seriesIndex > -1) {
var prefetchInstanceCount = this.studyList[image.studyIndex].SeriesList[image.seriesIndex].prefetchInstanceCount
var instanceCount = this.studyList[image.studyIndex].SeriesList[image.seriesIndex].instanceCount
if (this.studyList[image.studyIndex].SeriesList[image.seriesIndex].imageloadedArr.indexOf(image.imageId) < 0) {
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].imageloadedArr.push(image.imageId)
prefetchInstanceCount = prefetchInstanceCount + 1
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].prefetchInstanceCount = prefetchInstanceCount
}
if (prefetchInstanceCount >= instanceCount) {
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].prefetchInstanceCount = this.studyList[image.studyIndex].SeriesList[image.seriesIndex].instanceCount
//
this.studyList[image.studyIndex].SeriesList[image.seriesIndex].loadStatus = true
}
}
// store.dispatch('reading/updateSeriesList', { visitTaskindex: this.visitTaskIdx, studyIndex: image.studyIndex, seriesIndex: image.seriesIndex, imageId: image.imageId })
},
// instance
async cornerstoneImageLoaded(e) {
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
// if (idx === -1) return
// this.studyList = this.visitTaskList[idx].StudyList
// if (!this.studyList || this.studyList.length === 0) {
// return
// }
// if (!this.visitTaskList[idx].IsInit) {
// const loading = this.$loading({ fullscreen: true })
// await store.dispatch('reading/getMeasuredData', this.visitTaskList[idx].VisitTaskId)
// await store.dispatch('reading/getStudyInfo', { trialId: this.trialId, subjectVisitId: this.visitTaskList[idx].VisitId, visitTaskId: this.visitTaskList[idx].VisitTaskId, taskBlindName: this.visitTaskList[idx].TaskBlindName })
// await store.dispatch('reading/getReadingQuestionAndAnswer', { trialId: this.trialId, visitTaskId: this.visitTaskList[idx].VisitTaskId })
// await store.dispatch('reading/getDicomReadingQuestionAnswer', { trialId: this.trialId, visitTaskId: this.visitTaskList[idx].VisitTaskId })
// await store.dispatch('reading/setStatus', { visitTaskId: this.visitTaskList[idx].VisitTaskId })
// loading.close()
// }
// await store.dispatch('reading/updateStudyList', { visitTaskId: this.visitTaskId, imageId: e.detail.image.imageId, seriesUid: e.detail.image.data.string('x0020000e') })
// const uri = e.detail.image.sharedCacheKey
// const index = this.cachedImages.findIndex(item => item.uri === uri)
// if (index === -1) {
// this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
// } else {
// this.cachedImages[index].timestamp = new Date().getTime()
// }
// var imageId = e.detail.image.imageId
// var seriesUid = e.detail.image.data.string('x0020000e')
// var studyIndex = -1
// var seriesIndex = -1
// for (let i = 0; i < this.studyList.length; ++i) {
// for (let j = 0; j < this.studyList[i].SeriesList.length; ++j) {
// if (this.studyList[i].SeriesList[j].seriesUid === seriesUid) {
// studyIndex = i
// seriesIndex = j
// break
// }
// }
// if (studyIndex > 0) break
// }
// if (seriesIndex < 0) return
// const imageIdIndex = this.studyList[studyIndex].SeriesList[seriesIndex].imageIds.indexOf(imageId)
// if (imageIdIndex < 0) return
// if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
// if (this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount >= this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount) {
// //
// this.studyList[studyIndex].SeriesList[seriesIndex].loadStatus = true
// }
// }
},
cornerstoneimagecachechanged(e) {
const cacheInfo = cornerstone.imageCache.getCacheInfo()
console.log(cacheInfo)
},
cornerstoneimagecachefull(e) {
console.log('超过内存了')
}
} }
} }
</script> </script>
@ -977,3 +974,40 @@ export default {
} }
</style> </style>
<style>
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_list{
max-height: 500px;
overflow-y: auto;
}
.instance_frame_wrapper ::-webkit-scrollbar {
width: 7px;
height: 7px;
}
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
</style>

View File

@ -57,10 +57,11 @@ export default {
this.getHotkeys() this.getHotkeys()
}, },
methods: { methods: {
getHotkeys(isReset = false) { async getHotkeys(isReset = false) {
this.loading = true this.loading = true
this.hotKeyList = [] this.hotKeyList = []
getDoctorShortcutKey({ imageToolType: this.readingTool }).then(res => { try{
let res = await getDoctorShortcutKey({ imageToolType: this.readingTool })
res.Result.map(item => { res.Result.map(item => {
this.hotKeyList.push({ id: item.Id, keys: { controlKey: { altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code }, text: item.Text }, label: item.ShortcutKeyEnum }) this.hotKeyList.push({ id: item.Id, keys: { controlKey: { altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code }, text: item.Text }, label: item.ShortcutKeyEnum })
}) })
@ -68,11 +69,12 @@ export default {
this.$emit('reset', this.hotKeyList) this.$emit('reset', this.hotKeyList)
} }
this.loading = false this.loading = false
}).catch(() => { }catch(e){
this.loading = false this.loading = false
}) }
}, },
handleSave() { async handleSave() {
this.loading = true this.loading = true
var params = { var params = {
imageToolType: this.readingTool, imageToolType: this.readingTool,
@ -93,28 +95,34 @@ export default {
) )
}) })
params.shortcutKeyList = shortcutKeyList params.shortcutKeyList = shortcutKeyList
setShortcutKey(params).then(res => { try {
await setShortcutKey(params)
this.$emit('reset', this.hotKeyList) this.$emit('reset', this.hotKeyList)
this.$emit('close') this.$emit('close')
this.loading = false this.loading = false
}).catch(() => { }catch(e){
this.loading = false this.loading = false
}) }
}, },
handleReset() { async handleReset() {
// '' // ''
this.$confirm(this.$t('trials:hotkeys:message:confirmReset'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:hotkeys:message:confirmReset'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(() => { distinguishCancelAndClose: true
this.loading = true }
restoreDefaultShortcutKey({ imageToolType: this.readingTool }).then(res => { )
this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // '' if (confirm !== 'confirm') return
this.getHotkeys(true) this.loading = true
}).catch(() => { this.loading = false }) try{
}) await restoreDefaultShortcutKey({ imageToolType: this.readingTool })
.catch(action => {}) this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // ''
this.getHotkeys(true)
this.loading = false
}catch(e){
this.loading = false
}
}, },
handleHotkeyVerify(hotkey) { handleHotkeyVerify(hotkey) {
for (const item of this.hotKeyList) { for (const item of this.hotKeyList) {

View File

@ -21,7 +21,7 @@
</div> </div>
<div class="right-wrapper"> <div class="right-wrapper">
<div class="right-content"> <div class="right-content">
<iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" /> <iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" />
</div> </div>
</div> </div>
</div> </div>
@ -44,26 +44,30 @@ export default {
}, },
fileList: [], fileList: [],
loading: false, loading: false,
currentUser: zzSessionStorage.getItem('userName') currentUser: zzSessionStorage.getItem('userName'),
COMPANY:process.env.VUE_APP_COMPANY_NAME
} }
}, },
mounted() { mounted() {
this.getList() this.getList()
}, },
methods: { methods: {
getList() { async getList() {
this.loading = true this.loading = true
var param = { var param = {
trialId: this.trialId trialId: this.trialId
} }
getManualList(param).then(res => { try{
let res = await getManualList(param)
this.fileList = res.Result this.fileList = res.Result
if (this.fileList.length > 0) { if (this.fileList.length > 0) {
this.preview(this.fileList[0]) this.preview(this.fileList[0])
} }
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) }catch(e){
this.loading = false
}
}, },
preview(file) { preview(file) {
this.$set(this.selected, 'filePath', file.Path) this.$set(this.selected, 'filePath', file.Path)

View File

@ -3,7 +3,7 @@
<div class="base-dialog-body" style="height:380px;overflow-y: auto;"> <div class="base-dialog-body" style="height:380px;overflow-y: auto;">
<el-form ref="otherForm" :model="form"> <el-form ref="otherForm" :model="form">
<el-form-item <el-form-item
label="是否自动切换到下一任务" :label="$t('trials:reading:label:autoSwitch')"
prop="AutoCutNextTask" prop="AutoCutNextTask"
:rules="[ :rules="[
{ required: true, message: $t('common:ruleMessage:select')} { required: true, message: $t('common:ruleMessage:select')}
@ -35,27 +35,27 @@ export default {
this.initForm() this.initForm()
}, },
methods: { methods: {
initForm() { async initForm() {
this.loading = true this.loading = true
getAutoCutNextTask().then(async res => { try{
await getAutoCutNextTask()
this.form.AutoCutNextTask = res.Result.AutoCutNextTask this.form.AutoCutNextTask = res.Result.AutoCutNextTask
this.loading = false this.loading = false
}).catch(() => { }catch(e){
this.loading = false this.loading = false
}) }
}, },
handleSave() { async handleSave() {
this.$refs.otherForm.validate((valid) => { let valid = await this.$refs.otherForm.validate()
if (valid) { if (!valid) return
this.loading = true this.loading = true
setAutoCutNextTask(this.form).then((res) => { try{
this.loading = false await setAutoCutNextTask(this.form)
this.$message.success(this.$t('common:message:savedSuccessfully')) this.loading = false
}).catch(() => { this.$message.success(this.$t('common:message:savedSuccessfully'))
this.loading = false }catch(e){
}) this.loading = false
} }
})
} }
} }
} }

View File

@ -7,16 +7,19 @@
style="width: 100%" style="width: 100%"
class="wl-table" class="wl-table"
> >
<!-- 名称 -->
<el-table-column <el-table-column
label="名称" :label="$t('trials:reading:label:wlTplName')"
prop="TemplateName" prop="TemplateName"
/> />
<!-- 窗宽 -->
<el-table-column <el-table-column
label="窗宽" :label="$t('trials:reading:label:wlTplWW')"
prop="WW" prop="WW"
/> />
<!-- 窗位 -->
<el-table-column <el-table-column
label="窗位" :label="$t('trials:reading:label:wlTplWL')"
prop="WL" prop="WL"
/> />
<el-table-column <el-table-column
@ -24,22 +27,25 @@
width="200" width="200"
> >
<template slot="header"> <template slot="header">
<!-- 新增 -->
<el-button <el-button
size="mini" size="mini"
@click="handleAdd" @click="handleAdd"
>Add</el-button> >{{ $t('common:button:new') }}</el-button>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 编辑 -->
<el-button <el-button
type="text" type="text"
size="mini" size="mini"
@click="handleEdit(scope.row)" @click="handleEdit(scope.row)"
>Edit</el-button> >{{ $t('common:button:edit') }}</el-button>
<!-- 删除 -->
<el-button <el-button
type="text" type="text"
size="mini" size="mini"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
>Delete</el-button> >{{ $t('common:button:delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -77,16 +83,19 @@ export default {
this.getWL() this.getWL()
}, },
methods: { methods: {
getWL() { async getWL() {
this.loading = true this.loading = true
getUserWLTemplateList().then(res => { try {
const res = await getUserWLTemplateList()
this.tableData = res.Result this.tableData = res.Result
this.loading = false this.loading = false
this.$emit('getWwcTpl') this.$emit('getWwcTpl')
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
handleAdd() { handleAdd() {
this.customWwc.title = this.$t('common:button:add') this.customWwc.title = this.$t('common:button:new')
this.row = {} this.row = {}
this.customWwc.visible = true this.customWwc.visible = true
}, },
@ -95,20 +104,27 @@ export default {
this.row = Object.assign({}, row) this.row = Object.assign({}, row)
this.customWwc.visible = true this.customWwc.visible = true
}, },
handleDelete(row) { async handleDelete(row) {
var msg = this.$t('trials:staffResearch:message:confirmDel') // ''
this.$confirm(msg, { var msg = this.$t('trials:reading:wlTemplate:delete')
type: 'warning', const confirm = await this.$confirm(
distinguishCancelAndClose: true msg,
}).then(() => { {
this.loading = true type: 'warning',
deleteUserWLTemplate(row.Id).then(res => { distinguishCancelAndClose: true
this.loading = false }
// )
this.$message.success(this.$t('common:message:deletedSuccessfully')) if (confirm !== 'confirm') return
this.getWL() this.loading = true
}).catch(() => { this.loading = false }) try {
}) await deleteUserWLTemplate(row.Id)
this.loading = false
//
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.getWL()
} catch (e) {
this.loading = false
}
} }
} }
} }

View File

@ -8,14 +8,16 @@
size="small" size="small"
> >
<!-- 名称 --> <!-- 名称 -->
<el-form-item label="名称" prop="TemplateName"> <el-form-item :label="$t('trials:reading:label:wlTplName')" prop="TemplateName">
<el-input v-model="form.TemplateName" /> <el-input v-model="form.TemplateName" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('CustomWwwcForm:form:label:ww')" prop="WW"> <!-- 窗宽 -->
<el-input-number v-model="form.WW" controls-position="right" :min="1" :precision="0" :step="1" /> <el-form-item :label="$t('trials:reading:label:wlTplWW')" prop="WW">
<el-input-number v-model="form.WW" controls-position="right" :min="1" :max="100000" :precision="0" :step="1" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('CustomWwwcForm:form:label:wl')" prop="WL"> <!-- 窗位 -->
<el-input-number v-model="form.WL" controls-position="right" :precision="0" :step="1" /> <el-form-item :label="$t('trials:reading:label:wlTplWL')" prop="WL">
<el-input-number v-model="form.WL" controls-position="right" :min="-100000" :max="100000" :precision="0" :step="1" />
</el-form-item> </el-form-item>
<el-form-item style="text-align:right;"> <el-form-item style="text-align:right;">
<!-- Cancel --> <!-- Cancel -->
@ -81,24 +83,23 @@ export default {
} }
}, },
methods: { methods: {
handleSave() { async handleSave() {
this.$refs.wlForm.validate((valid) => { const valid = await this.$refs.wlForm.validate()
if (valid) { if (!valid) return
this.loading = true this.loading = true
addOrUpdateUserWLTemplate(this.form).then((res) => { try {
this.loading = false await addOrUpdateUserWLTemplate(this.form)
this.$emit('getWL') this.loading = false
this.$emit('close') this.$emit('getWL')
if (this.form.Id) { this.$emit('close')
this.$message.success(this.$t('common:message:savedSuccessfully')) if (this.form.Id) {
} else { this.$message.success(this.$t('common:message:savedSuccessfully'))
this.$message.success(this.$t('common:message:addedSuccessfully')) } else {
} this.$message.success(this.$t('common:message:addedSuccessfully'))
}).catch(() => {
this.loading = false
})
} }
}) } catch (e) {
this.loading = false
}
}, },
handleCancel() { handleCancel() {
this.$emit('close') this.$emit('close')

View File

@ -1,7 +1,7 @@
<template> <template>
<div ref="container" style="width:100%;height:100%" class="dicom-container"> <div ref="container" style="width:100%;height:100%" class="dicom-container">
<!-- 访视阅片 --> <!-- 访视阅片 -->
<div v-if="(isReadingTaskViewInOrder || (!isReadingTaskViewInOrder && isShow)) && readingCategory=== 1 && CriterionType !== 0" class="reading-wrapper"> <div v-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType !== 0" class="reading-wrapper">
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeave"> <el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeave">
<!-- 阅片 --> <!-- 阅片 -->
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read"> <el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
@ -19,22 +19,24 @@
:is-exists-clinical-data="isExistsClinicalData" :is-exists-clinical-data="isExistsClinicalData"
:is-exists-no-dicom-file="isExistsNoDicomFile" :is-exists-no-dicom-file="isExistsNoDicomFile"
:is-exists-manual="isExistsManual" :is-exists-manual="isExistsManual"
:ise-c-r-f-show-in-dicom-reading="IseCRFShowInDicomReading"
@previewCD="previewCD" @previewCD="previewCD"
/> />
</el-tab-pane> </el-tab-pane>
<!-- 报告 --> <!-- 报告 -->
<el-tab-pane :label="$t('trials:reading:tabTitle:report')" name="report"> <el-tab-pane v-if="!IseCRFShowInDicomReading" :label="$t('trials:reading:tabTitle:report')" name="report">
<ReportPage v-if="tabs.includes('report') && isShow" ref="reportPage" :question-form-change-state="questionFormChangeState" :visit-task-id="visitTaskId" /> <ReportPage v-if="tabs.includes('report') && isShow" ref="reportPage" :question-form-change-state="questionFormChangeState" :visit-task-id="visitTaskId" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
<div v-if="(isReadingTaskViewInOrder || (!isReadingTaskViewInOrder && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper"> <div v-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper">
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeaveCustomize"> <el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeaveCustomize">
<!-- 阅片 --> <!-- 阅片 -->
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read"> <el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
<CustomizeReadPage <CustomizeReadPage
v-if="tabs.includes('read')" v-if="tabs.includes('read')"
:trial-id="trialId" :trial-id="trialId"
:trial-reading-criterion-id="TrialReadingCriterionId"
:visit-task-id="visitTaskId" :visit-task-id="visitTaskId"
:subject-id="subjectId" :subject-id="subjectId"
:subject-code="subjectCode" :subject-code="subjectCode"
@ -116,6 +118,7 @@
:trial-id="trialId" :trial-id="trialId"
:subject-id="subjectId" :subject-id="subjectId"
:visit-task-id="cdVisitTaskId" :visit-task-id="cdVisitTaskId"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
/> />
</div> </div>
<span v-if="!closeCDVisible" slot="footer" class="dialog-footer"> <span v-if="!closeCDVisible" slot="footer" class="dialog-footer">
@ -134,24 +137,24 @@
<!-- 提示 --> <!-- 提示 -->
{{ $t('trials:iRecist:warnning:msg44') }} {{ $t('trials:iRecist:warnning:msg44') }}
</span> </span>
<div style="line-height: 24px;"> <div>
<div style="font-size: 14px;font-weight: bold;"> <div>
<!-- 您确定当前访视的整体评估结果为PD根据独立影像评估章程该访视进入iRECIST阅片环节请对新病灶进行重新评估 --> <!-- 您确定当前访视的整体评估结果为PD根据独立影像评估章程该访视进入iRECIST阅片环节请对新病灶进行重新评估 -->
{{ $t('trials:iRecist:warnning:msg45') }} {{ $t('trials:iRecist:warnning:msg45') }}
</div> </div>
<div style="color: #f44336;font-size: 13px;margin: 5px;"> <div style="color: #f44336;font-size: 12px;margin: 5px;">
<!-- 1新病灶可转为新靶病灶新非靶病灶其它既往新病灶 --> <!-- 1新病灶可转为新靶病灶新非靶病灶其它既往新病灶 -->
{{ $t('trials:iRecist:warnning:msg46') }} {{ $t('trials:iRecist:warnning:msg46') }}
</div> </div>
<div style="color: #f44336;font-size: 13px;margin: 5px;"> <div style="color: #f44336;font-size: 12px;margin: 5px;">
<!-- 2新靶病灶状态为明确的新病灶才能转换为新靶病灶新靶病灶的选择规则与RECIST1.1相同如果当前病灶已有标记但不符合新靶病灶的要求请清除标记重新标注 --> <!-- 2新靶病灶状态为明确的新病灶才能转换为新靶病灶新靶病灶的选择规则与RECIST1.1相同如果当前病灶已有标记但不符合新靶病灶的要求请清除标记重新标注 -->
{{ $t('trials:iRecist:warnning:msg47') }} {{ $t('trials:iRecist:warnning:msg47') }}
</div> </div>
<div style="color: #f44336;font-size: 13px;margin: 5px;"> <div style="color: #f44336;font-size: 12px;margin: 5px;">
<!-- 3新非靶病灶状态为明确的新病灶才能转换为新非靶病灶新靶病灶的选择规则与RECIST1.1相同 --> <!-- 3新非靶病灶状态为明确的新病灶才能转换为新非靶病灶新靶病灶的选择规则与RECIST1.1相同 -->
{{ $t('trials:iRecist:warnning:msg48') }} {{ $t('trials:iRecist:warnning:msg48') }}
</div> </div>
<div style="color: #f44336;font-size: 13px;margin: 5px;"> <div style="color: #f44336;font-size: 12px;margin: 5px;">
<!-- 4其它既往新病灶系统会自动将状态为疑似消失的新病灶转换为其它既往新病灶无需修改 --> <!-- 4其它既往新病灶系统会自动将状态为疑似消失的新病灶转换为其它既往新病灶无需修改 -->
{{ $t('trials:iRecist:warnning:msg49') }} {{ $t('trials:iRecist:warnning:msg49') }}
</div> </div>
@ -163,12 +166,10 @@
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { getNextTask, readClinicalData, verifyDefaultQuestionBeAnswer } from '@/api/trials' import { getNextTask, readClinicalData, verifyDefaultQuestionBeAnswer } from '@/api/trials'
import { confirmTaskReminder } from '@/api/reading'
import ReadPage from './components/ReadPage' import ReadPage from './components/ReadPage'
import CustomizeReadPage from './customize/CustomizeReadPage' import CustomizeReadPage from './customize/CustomizeReadPage'
import ReportPage from './components/ReportPage' import ReportPage from './components/ReportPage'
@ -179,7 +180,7 @@ import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data' import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
import DicomEvent from './components/DicomEvent' import DicomEvent from './components/DicomEvent'
import store from '@/store' import store from '@/store'
import { getToken } from '@/utils/auth' // import { getToken } from '@/utils/auth'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import requestPoolManager from '@/utils/request-pool' import requestPoolManager from '@/utils/request-pool'
export default { export default {
@ -212,7 +213,7 @@ export default {
isNeedReadClinicalData: false, isNeedReadClinicalData: false,
isReadClinicalData: false, isReadClinicalData: false,
digitPlaces: 2, digitPlaces: 2,
isReadingTaskViewInOrder: false, isReadingTaskViewInOrder: null,
firstTaskReadingCategory: null, firstTaskReadingCategory: null,
criterionType: null, criterionType: null,
readingTool: null, readingTool: null,
@ -227,8 +228,7 @@ export default {
isFullscreen: false, isFullscreen: false,
tipVisible: false, tipVisible: false,
closeCDVisible: false, closeCDVisible: false,
cdVisitTaskId: '', cdVisitTaskId: ''
isConfirmTaskReminder: false
} }
}, },
mounted() { mounted() {
@ -245,7 +245,7 @@ export default {
store.dispatch('reading/setLastCanvasTaskId', '') store.dispatch('reading/setLastCanvasTaskId', '')
this.isQualityIssueSaved = false this.isQualityIssueSaved = false
this.firstTaskReadingCategory = this.readingCategory this.firstTaskReadingCategory = this.readingCategory
if (!this.isReadingTaskViewInOrder) { if (this.isReadingTaskViewInOrder !== 1) {
// visitTaskList // visitTaskList
store.dispatch('reading/resetVisitTasks') store.dispatch('reading/resetVisitTasks')
} }
@ -263,18 +263,19 @@ export default {
this.subjectCode = this.$router.currentRoute.query.subjectCode this.subjectCode = this.$router.currentRoute.query.subjectCode
this.subjectId = this.$router.currentRoute.query.subjectId this.subjectId = this.$router.currentRoute.query.subjectId
this.visitTaskId = this.$router.currentRoute.query.visitTaskId this.visitTaskId = this.$router.currentRoute.query.visitTaskId
this.isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder) // this.isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
this.criterionType = this.$router.currentRoute.query.criterionType // this.criterionType = this.$router.currentRoute.query.criterionType
this.readingTool = this.$router.currentRoute.query.readingTool // this.readingTool = this.$router.currentRoute.query.readingTool
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
this.isNewSubject = this.$router.currentRoute.query.isNewSubject // this.isNewSubject = this.$router.currentRoute.query.isNewSubject
if (this.isNewSubject && this.isReadingTaskViewInOrder) {
// ${this.subjectCode} // if (this.isNewSubject && this.isReadingTaskViewInOrder !== 0) {
var msg = this.$t('trials:reading:warnning:msg1') // // ${this.subjectCode}
msg = msg.replace('xxx', this.subjectCode) // var msg = this.$t('trials:reading:warnning:msg1')
this.$message.success(msg) // msg = msg.replace('xxx', this.subjectCode)
changeURLStatic('isNewSubject', '') // this.$message.success(msg)
} // changeURLStatic('isNewSubject', '')
// }
if (this.$router.currentRoute.query.TokenKey) { if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey) store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '') changeURLStatic('TokenKey', '')
@ -318,7 +319,9 @@ export default {
// } // }
// } // }
this.subjectId = res.Result.SubjectId this.subjectId = res.Result.SubjectId
localStorage.setItem('subjectId', res.Result.SubjectId)
this.subjectCode = res.Result.SubjectCode this.subjectCode = res.Result.SubjectCode
localStorage.setItem('subjectCode', res.Result.SubjectCode)
this.taskBlindName = res.Result.TaskBlindName this.taskBlindName = res.Result.TaskBlindName
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
@ -330,7 +333,8 @@ export default {
this.CriterionType = res.Result.CriterionType this.CriterionType = res.Result.CriterionType
this.digitPlaces = res.Result.DigitPlaces this.digitPlaces = res.Result.DigitPlaces
this.IseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading this.IseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
this.isConfirmTaskReminder = res.Result.IsConfirmReminder this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
localStorage.setItem('isReadingTaskViewInOrder', this.isReadingTaskViewInOrder)
localStorage.setItem('CriterionType', res.Result.CriterionType) localStorage.setItem('CriterionType', res.Result.CriterionType)
localStorage.setItem('digitPlaces', res.Result.DigitPlaces) localStorage.setItem('digitPlaces', res.Result.DigitPlaces)
this.readingCategory = res.Result.ReadingCategory this.readingCategory = res.Result.ReadingCategory
@ -345,10 +349,7 @@ export default {
this.activeName = 'read' this.activeName = 'read'
this.tabs = [this.activeName] this.tabs = [this.activeName]
} }
if (!this.isConfirmTaskReminder && res.Result.IsBaseLineTask && parseInt(this.criterionType) !== 10) { if (this.firstTaskReadingCategory === 1 && res.Result.ReadingCategory === 1 && this.isReadingTaskViewInOrder !== 0 && flag) {
this.handleConfirmReminder()
}
if (this.firstTaskReadingCategory === 1 && res.Result.ReadingCategory === 1 && this.isReadingTaskViewInOrder && flag) {
this.activeName = 'read' this.activeName = 'read'
this.tabs = [this.activeName] this.tabs = [this.activeName]
this.$nextTick(() => { this.$nextTick(() => {
@ -377,7 +378,7 @@ export default {
this.$refs.reportPage.setScrollTop(1) this.$refs.reportPage.setScrollTop(1)
}) })
} else { } else {
this.isShow = false // this.isShow = false
} }
return Promise.resolve(true) return Promise.resolve(true)
}, },
@ -477,38 +478,17 @@ export default {
}) })
}) })
}, },
async handleConfirmReminder() { async handleConfirmCD() {
let criterionType = parseInt(this.criterionType)
criterionType = criterionType === 17 ? 1 : criterionType
let i = this.$d.CriterionType.findIndex(i=>i.value === criterionType)
if (i === -1) return
let criterionName = this.$d.CriterionType[i].label
let msg = this.$t('trials:reading:criterion:message').replace('xxx', criterionName)
this.$alert(msg, this.$t('common:message:prompt'), {
callback: action => {
let params = {
visitTaskId: this.visitTaskId,
}
const loading = this.$loading({ fullscreen: true })
confirmTaskReminder(params).then(res=>{
loading.close()
this.isConfirmTaskReminder = true
this.$message.success(this.$t("common:message:confirmSuccessfully"))
}).catch(e=>{
console.log(e)
loading.close()
})
}
})
},
handleConfirmCD() {
this.loading = true this.loading = true
var visitTaskId = this.visitTaskId var visitTaskId = this.visitTaskId
readClinicalData({ visitTaskId }).then(res => { try {
await readClinicalData({ visitTaskId })
this.loading = false this.loading = false
this.dialogVisible = false this.dialogVisible = false
this.isReadClinicalData = true this.isReadClinicalData = true
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
previewCD() { previewCD() {
this.closeCDVisible = true this.closeCDVisible = true

View File

@ -15,7 +15,7 @@
</div> </div>
<!-- 文件层级 --> <!-- 文件层级 -->
<div v-if="study.NoneDicomStudyFileList.length === 0" class="empty-text"> <div v-if="study.NoneDicomStudyFileList.length === 0" class="empty-text">
<slot name="empty">暂无数据</slot> <slot name="empty">{{ $t('trials:audit:message:noData') }}</slot>
</div> </div>
<div v-else id="imgList" style="height:100%;"> <div v-else id="imgList" style="height:100%;">
<div <div
@ -28,7 +28,14 @@
class="img-box" class="img-box"
@click="selected(item,i,j,true)" @click="selected(item,i,j,true)"
> >
{{ `${j+1}. ${item.FileName}` }} <div v-if="item.FileName.length < 15" class="img-text">
{{ `${j+1}. ${item.FileName}` }}
</div>
<el-tooltip v-else :content="item.FileName" placement="bottom">
<div class="img-text">
{{ `${j+1}. ${item.FileName}` }}
</div>
</el-tooltip>
</div> </div>
</div> </div>
@ -95,10 +102,12 @@ export default {
subjectCode: '', subjectCode: '',
visistTaskId: '', visistTaskId: '',
taskBlindName: '', taskBlindName: '',
readingTaskState: 2 readingTaskState: 2,
bp: []
} }
}, },
mounted() { async mounted() {
this.bp = await this.$getBodyPart(this.$route.query.trialId)
if (this.$router.currentRoute.query.TokenKey) { if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey) store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '') changeURLStatic('TokenKey', '')
@ -186,7 +195,7 @@ export default {
} }
var arr = bodyPart.split(separator) var arr = bodyPart.split(separator)
var newArr = arr.map(i => { var newArr = arr.map(i => {
return this.$fd('Bodypart', i.trim()) return this.$fd('Bodypart', i.trim(), 'Code', { Bodypart: this.bp }, 'Name')
}) })
return newArr.join(' | ') return newArr.join(' | ')
} }
@ -263,13 +272,19 @@ export default {
display: inline-block; display: inline-block;
box-sizing: border-box; box-sizing: border-box;
border-bottom: 2px solid #f3f3f3; border-bottom: 2px solid #f3f3f3;
width: 180px;
height: 50px;
line-height: 50px;
cursor: pointer; cursor: pointer;
// margin-bottom: 5px; // margin-bottom: 5px;
padding-left: 5px; padding-left: 5px;
} }
.img-text{
display: inline-block;
width: 200px;
height: 50px;
line-height: 50px;
overflow: hidden;
text-overflow: ellipsis; /* 用省略号表示溢出的文本 */
white-space: nowrap;
}
.img-box:nth-last-child(1){ .img-box:nth-last-child(1){
margin-bottom: 0px; margin-bottom: 0px;
} }

View File

@ -0,0 +1,452 @@
import * as cornerstoneTools from 'cornerstone-tools'
const external = cornerstoneTools.external
// State
const getToolState = cornerstoneTools.getToolState
const toolStyle = cornerstoneTools.toolStyle
const toolColors = cornerstoneTools.toolColors
const getModule = cornerstoneTools.getModule
// Drawing
const getNewContext = cornerstoneTools.import('drawing/getNewContext')
const draw = cornerstoneTools.import('drawing/draw')
const setShadow = cornerstoneTools.import('drawing/setShadow')
const drawCircle = cornerstoneTools.import('drawing/drawCircle')
const drawHandles = cornerstoneTools.import('drawing/drawHandles')
const drawLinkedTextBox = cornerstoneTools.import('drawing/drawLinkedTextBox')
// Util
// const calculateSUV = cornerstoneTools.import('util/calculateSUV')
const throttle = cornerstoneTools.import('util/throttle')
const getPixelSpacing = cornerstoneTools.import('util/getPixelSpacing')
const circleRoiCursor = cornerstoneTools.import('tools/cursors')
const getROITextBoxCoords = cornerstoneTools.import('util/getROITextBoxCoords')
import getCircleCoords from './getCircleCoords'
// const getCircleCoords = cornerstoneTools.import('util/getCircleCoords')
const numbersWithCommas = cornerstoneTools.import('util/numbersWithCommas')
// import calculateSUV from './../../util/calculateSUV.js'
// import { calculateEllipseStatistics } from './../../util/ellipse/index.js'
// import getROITextBoxCoords from '../../util/getROITextBoxCoords.js'
// import numbersWithCommas from './../../util/numbersWithCommas.js'
// import throttle from './../../util/throttle.js'
// import { getLogger } from '../../util/logger.js'
// import getPixelSpacing from '../../util/getPixelSpacing'
// import { circleRoiCursor } from '../cursors/index.js'
// import getCircleCoords from '../../util/getCircleCoords'
// const logger = getLogger('tools:annotation:CircleRoiTool')
/**
* @public
* @class CircleRoiTool
* @memberof Tools.Annotation
* @classdesc Tool for drawing circular regions of interest, and measuring
* the statistics of the enclosed pixels.
* @extends Tools.Base.BaseAnnotationTool
*/
export default class CircleRoiTool extends cornerstoneTools.CircleRoiTool {
constructor(props = {}) {
const defaultProps = {
name: 'CircleRoi',
supportedInteractionTypes: ['Mouse', 'Touch'],
svgCursor: circleRoiCursor,
configuration: {
centerPointRadius: 0,
renderDashed: false,
hideHandlesIfMoving: false,
digits: 1,
showRadius: false,
showPerimeter: false
}
}
super(props, defaultProps)
console.log(props.configuration)
// this.digits = isNaN(parseInt(props.configuration.digits)) ? 2 : props.configuration.digits
// console.log(this.digits)
this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110)
}
renderToolData(evt) {
const toolData = getToolState(evt.currentTarget, this.name)
if (!toolData) {
return
}
const getDistance = external.cornerstoneMath.point.distance
const eventData = evt.detail
const { image, element, canvasContext } = eventData
const lineWidth = toolStyle.getToolWidth()
const {
handleRadius,
drawHandlesOnHover,
hideHandlesIfMoving,
renderDashed,
centerPointRadius
} = this.configuration
const newContext = getNewContext(canvasContext.canvas)
const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image)
const lineDash = getModule('globalConfiguration').configuration.lineDash
// Meta
const seriesModule =
external.cornerstone.metaData.get('generalSeriesModule', image.imageId) ||
{}
// Pixel Spacing
const modality = seriesModule.modality
const hasPixelSpacing = rowPixelSpacing && colPixelSpacing
draw(newContext, context => {
// If we have tool data for this element, iterate over each set and draw it
for (let i = 0; i < toolData.data.length; i++) {
const data = toolData.data[i]
if (data.visible === false) {
continue
}
// Configure
const color = toolColors.getColorIfActive(data)
const handleOptions = {
color,
handleRadius,
drawHandlesIfActive: drawHandlesOnHover,
hideHandlesIfMoving
}
setShadow(context, this.configuration)
const startCanvas = external.cornerstone.pixelToCanvas(
element,
data.handles.start
)
const endCanvas = external.cornerstone.pixelToCanvas(
element,
data.handles.end
)
// Calculating the radius where startCanvas is the center of the circle to be drawn
const radius = getDistance(startCanvas, endCanvas)
const circleOptions = { color }
if (renderDashed) {
circleOptions.lineDash = lineDash
}
// Draw Circle
drawCircle(
context,
element,
data.handles.start,
radius,
circleOptions,
'pixel'
)
if (centerPointRadius && radius > 3 * centerPointRadius) {
drawCircle(
context,
element,
data.handles.start,
centerPointRadius,
circleOptions,
'pixel'
)
}
if (data.handles) {
data.handles.start.drawnIndependently = true
data.handles.end.drawnIndependently = true
}
drawHandles(context, eventData, data.handles, handleOptions)
// Update textbox stats
if (data.invalidated === true) {
if (data.cachedStats) {
this.throttledUpdateCachedStats(image, element, data)
} else {
this.updateCachedStats(image, element, data)
}
}
// Default to textbox on right side of ROI
if (!data.handles.textBox.hasMoved) {
const defaultCoords = getROITextBoxCoords(
eventData.viewport,
data.handles
)
Object.assign(data.handles.textBox, defaultCoords)
}
const textBoxAnchorPoints = handles =>
_findTextBoxAnchorPoints(handles.start, handles.end)
const textBoxContent = _createTextBoxContent(
context,
image.color,
data.cachedStats,
modality,
hasPixelSpacing,
this.configuration
)
if (data.remark) {
textBoxContent.unshift(data.remark)
}
data.unit = _getUnit(modality, this.configuration.showHounsfieldUnits)
drawLinkedTextBox(
context,
element,
data.handles.textBox,
textBoxContent,
data.handles,
textBoxAnchorPoints,
color,
lineWidth,
20,
true
)
}
})
}
}
/**
*
*
* @param {*} startHandle
* @param {*} endHandle
* @returns {Array.<{x: number, y: number}>}
*/
function _findTextBoxAnchorPoints(startHandle, endHandle) {
const { left, top, width, height } = getCircleCoords(startHandle, endHandle)
return [
{
// Top middle point of ellipse
x: left + width / 2,
y: top
},
{
// Left middle point of ellipse
x: left,
y: top + height / 2
},
{
// Bottom middle point of ellipse
x: left + width / 2,
y: top + height
},
{
// Right middle point of ellipse
x: left + width,
y: top + height / 2
}
]
}
function _getUnit(modality, showHounsfieldUnits) {
return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : ''
}
/**
*
*
* @param {*} context
* @param {*} isColorImage
* @param {*} { area, mean, stdDev, min, max, meanStdDevSUV }
* @param {*} modality
* @param {*} hasPixelSpacing
* @param {*} [options={}] - { showMinMax, showHounsfieldUnits }
* @returns {string[]}
*/
function _createTextBoxContent(
context,
isColorImage,
{
area = 0,
radius = 0,
perimeter = 0,
mean = 0,
stdDev = 0,
min = 0,
max = 0,
meanStdDevSUV = 0
} = {},
modality,
hasPixelSpacing,
options = {}
) {
const showMinMax = options.showMinMax || false
const digits = options.digits || 1
const textLines = []
// Don't display mean/standardDev for color images
const otherLines = []
if (!isColorImage) {
const hasStandardUptakeValues = meanStdDevSUV && meanStdDevSUV.mean !== 0
const unit = _getUnit(modality, options.showHounsfieldUnits)
let meanString = `Mean: ${numbersWithCommas(mean.toFixed(digits))} ${unit}`
const stdDevString = `Std Dev: ${numbersWithCommas(
stdDev.toFixed(digits)
)} ${unit}`
// If this image has SUV values to display, concatenate them to the text line
if (hasStandardUptakeValues) {
const SUVtext = ' SUV: '
const meanSuvString = `${SUVtext}${numbersWithCommas(
meanStdDevSUV.mean.toFixed(digits)
)}`
const stdDevSuvString = `${SUVtext}${numbersWithCommas(
meanStdDevSUV.stdDev.toFixed(digits)
)}`
const targetStringLength = Math.floor(
context.measureText(`${stdDevString} `).width
)
while (context.measureText(meanString).width < targetStringLength) {
meanString += ' '
}
otherLines.push(`${meanString}${meanSuvString}`)
otherLines.push(`${stdDevString} ${stdDevSuvString}`)
} else {
// otherLines.push(`${meanString} ${stdDevString}`)
otherLines.push(`${meanString}`)
otherLines.push(`${stdDevString}`)
}
if (showMinMax) {
let minString = `Min: ${min} ${unit}`
const maxString = `Max: ${max} ${unit}`
const targetStringLength = hasStandardUptakeValues
? Math.floor(context.measureText(`${stdDevString} `).width)
: Math.floor(context.measureText(`${meanString} `).width)
while (context.measureText(minString).width < targetStringLength) {
minString += ' '
}
otherLines.push(`${minString}`)
otherLines.push(`${maxString}`)
// otherLines.push(`${minString}${maxString}`)
}
}
textLines.push(_formatArea(area, hasPixelSpacing, digits))
const showRadius = options.showRadius || false
if (radius && showRadius) {
textLines.push(_formatLength(radius, 'Radius', hasPixelSpacing, digits))
}
const showPerimeter = options.showPerimeter || false
if (perimeter && showPerimeter) {
textLines.push(_formatLength(perimeter, 'Perimeter', hasPixelSpacing, digits))
}
otherLines.forEach(x => textLines.push(x))
// console.log(this.digits)
return textLines
}
/**
*
*
* @param {*} area
* @param {*} hasPixelSpacing
* @returns {string} The formatted label for showing area
*/
function _formatArea(area, hasPixelSpacing, digits) {
// This uses Char code 178 for a superscript 2
const suffix = hasPixelSpacing
? ` mm${String.fromCharCode(178)}`
: ` px${String.fromCharCode(178)}`
return `Area: ${numbersWithCommas(area.toFixed(digits))}${suffix}`
}
function _formatLength(value, name, hasPixelSpacing, digits) {
if (!value) {
return ''
}
const suffix = hasPixelSpacing ? ' mm' : ' px'
return `${name}: ${numbersWithCommas(value.toFixed(digits))}${suffix}`
}
/**
*
*
* @param {*} image
* @param {*} element
* @param {*} handles
* @param {*} modality
* @param {*} pixelSpacing
* @returns {Object} The Stats object
*/
// function _calculateStats(image, element, handles, modality, pixelSpacing) {
// // Retrieve the bounds of the ellipse in image coordinates
// const circleCoordinates = getCircleCoords(handles.start, handles.end)
// // Retrieve the array of pixels that the ellipse bounds cover
// const pixels = external.cornerstone.getPixels(
// element,
// circleCoordinates.left,
// circleCoordinates.top,
// circleCoordinates.width,
// circleCoordinates.height
// )
// // Calculate the mean & standard deviation from the pixels and the ellipse details.
// const ellipseMeanStdDev = calculateEllipseStatistics(
// pixels,
// circleCoordinates
// )
// let meanStdDevSUV
// if (modality === 'PT') {
// meanStdDevSUV = {
// mean: calculateSUV(image, ellipseMeanStdDev.mean, true) || 0,
// stdDev: calculateSUV(image, ellipseMeanStdDev.stdDev, true) || 0
// }
// }
// const radius =
// (circleCoordinates.width *
// ((pixelSpacing && pixelSpacing.colPixelSpacing) || 1)) /
// 2
// const perimeter = 2 * Math.PI * radius
// const area =
// Math.PI *
// ((circleCoordinates.width *
// ((pixelSpacing && pixelSpacing.colPixelSpacing) || 1)) /
// 2) *
// ((circleCoordinates.height *
// ((pixelSpacing && pixelSpacing.rowPixelSpacing) || 1)) /
// 2)
// return {
// area: area || 0,
// radius: radius || 0,
// perimeter: perimeter || 0,
// count: ellipseMeanStdDev.count || 0,
// mean: ellipseMeanStdDev.mean || 0,
// variance: ellipseMeanStdDev.variance || 0,
// stdDev: ellipseMeanStdDev.stdDev || 0,
// min: ellipseMeanStdDev.min || 0,
// max: ellipseMeanStdDev.max || 0,
// meanStdDevSUV
// }
// }

View File

@ -0,0 +1,21 @@
import * as cornerstoneTools from 'cornerstone-tools'
const external = cornerstoneTools.external
/**
* Retrieve the bounds of the circle in image coordinates
*
* @param {*} startHandle
* @param {*} endHandle
* @returns {{ left: number, top: number, width: number, height: number }}
*/
export default function getCircleCoords(startHandle, endHandle) {
const { distance } = external.cornerstoneMath.point
const radius = distance(startHandle, endHandle)
return {
left: Math.floor(Math.min(startHandle.x - radius, endHandle.x)),
top: Math.floor(Math.min(startHandle.y - radius, endHandle.y)),
width: radius * 2,
height: radius * 2
}
}

View File

@ -37,8 +37,8 @@ export default class LengthTool extends cornerstoneTools.LengthTool {
drawHandlesOnHover: false, drawHandlesOnHover: false,
hideHandlesIfMoving: false, hideHandlesIfMoving: false,
renderDashed: false, renderDashed: false,
digits: 2 digits: 2,
} },
} }
super(props, defaultProps) super(props, defaultProps)
@ -48,7 +48,7 @@ export default class LengthTool extends cornerstoneTools.LengthTool {
createNewMeasurement(eventData) { createNewMeasurement(eventData) {
const goodEventData = const goodEventData =
eventData && eventData.currentPoints && eventData.currentPoints.image eventData && eventData.currentPoints && eventData.currentPoints.image
console.log('createNewMeasurement: ',goodEventData)
if (!goodEventData) { if (!goodEventData) {
console.log( console.log(
`required eventData not supplied to tool ${this.name}'s createNewMeasurement` `required eventData not supplied to tool ${this.name}'s createNewMeasurement`
@ -84,7 +84,8 @@ export default class LengthTool extends cornerstoneTools.LengthTool {
drawnIndependently: true, drawnIndependently: true,
allowedOutsideImage: true, allowedOutsideImage: true,
hasBoundingBox: true hasBoundingBox: true
} },
allowedOutsideImage:true
} }
} }
} }

View File

@ -40,7 +40,8 @@ export default class RectangleRoiTool extends cornerstoneTools.RectangleRoiTool
drawHandles: true, drawHandles: true,
drawHandlesOnHover: false, drawHandlesOnHover: false,
hideHandlesIfMoving: false, hideHandlesIfMoving: false,
renderDashed: false renderDashed: false,
showStatsText: false
// showMinMax: false, // showMinMax: false,
// showHounsfieldUnits: true // showHounsfieldUnits: true
}, },
@ -531,12 +532,15 @@ function _createTextBoxContent(
minString += ' ' minString += ' '
} }
otherLines.push(`${minString}${maxString}`) otherLines.push(`${minString}`)
otherLines.push(`${maxString}`)
} }
} }
if (options.showStatsText) {
textLines.push(_formatArea(area, hasPixelSpacing))
otherLines.forEach(x => textLines.push(x))
}
// textLines.push(_formatArea(area, hasPixelSpacing))
// otherLines.forEach(x => textLines.push(x))
if (data.hasOwnProperty('remark')) { if (data.hasOwnProperty('remark')) {
if (data.hasOwnProperty('status') && data.status) { if (data.hasOwnProperty('status') && data.status) {
textLines.push(`${data.remark}(${data.status})`) textLines.push(`${data.remark}(${data.status})`)
@ -546,3 +550,11 @@ function _createTextBoxContent(
} }
return textLines return textLines
} }
function _formatArea(area, hasPixelSpacing) {
// This uses Char code 178 for a superscript 2
const suffix = hasPixelSpacing
? ` mm${String.fromCharCode(178)}`
: ` px${String.fromCharCode(178)}`;
return `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;
}

View File

@ -0,0 +1,432 @@
<template>
<el-form v-if="globalForm.taskList.length > 0" ref="globalRuleForm" :model="globalForm" class="global-form">
<el-table
v-loading="loading"
:data="globalForm.taskList"
>
<!-- 访视名称 -->
<el-table-column
prop="BlindName"
:label="$t('trials:globalReview:table:visitName')"
show-overflow-tooltip
width="150"
/>
<!-- 评估结果 -->
<el-table-column
:label="$t('trials:globalReview:table:evaluationRes')"
align="center"
prop=""
>
<template>
<el-table-column
v-for="(qs,index) in globalInfo.evaluationQsList"
:key="index"
prop=""
:label="qs"
show-overflow-tooltip
width="150"
>
<!-- <template slot-scope="scope">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div>
</template> -->
<template slot-scope="scope">
<template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div>
</template>
</template>
</el-table-column>
</template>
</el-table-column>
<!-- 是否同意访视结果 -->
<el-table-column
prop=""
:label="$t('trials:globalReview:table:isAgreeEvaluationRes')"
show-overflow-tooltip
width="170"
>
<template slot-scope="scope">
<el-form-item
v-if="readingTaskState<2"
:prop="`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`"
label=""
:rules="[
{ required: true,message: $t('common:ruleMessage:select'), trigger: ['change','blur']},
]"
class="form-item"
>
<el-radio-group
v-model="globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]"
@change="handleAgreeOrNotChange(scope.$index,scope.row.AgreeOrNot[0].GlobalAnswerType)"
>
<el-radio
v-for="item of $d.ReadingYesOrNo"
:key="'AgreeOrNot' + item.value"
:label="String(item.value)"
>
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 1" type="primary">
{{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}
</el-tag>
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 0" type="danger"> {{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}</el-tag>
<span v-else />
</template>
</el-table-column>
<!-- 调整后结果 -->
<el-table-column
:label="$t('trials:globalReview:table:adjustedRes')"
align="center"
prop=""
>
<template v-for="(qs,index) in globalInfo.adjustedQsList">
<el-table-column
v-if="qs.isShow"
:key="index"
prop=""
:label="qs.questionName"
show-overflow-tooltip
:min-width="index === 3 ? '200' : '200'"
>
<template slot-scope="scope">
<div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
<el-form-item
style="margin-bottom: 0;"
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
label=""
:rules="[
{ required:parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
]"
>
<label v-if="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0" />
<!-- 裁判问题 -->
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 0 ">
<el-select
v-if="scope.row.AfterQuestionList[index].Type === 'select'"
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
style="width:90%;"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
>
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
<el-option
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
/>
</template>
</el-select>
<el-input
v-if="scope.row.AfterQuestionList[index].Type ==='textarea'"
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
/>
<!-- 输入框 -->
<el-input
v-if="scope.row.AfterQuestionList[index].Type ==='input'"
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
/>
<!-- 单选 -->
<el-radio-group
v-if="scope.row.AfterQuestionList[index].Type ==='radio'"
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
>
<el-radio
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
:key="val.trim()"
:label="val.trim()"
>
{{ val.trim() }}
</el-radio>
</el-radio-group>
<!-- 数值 -->
<el-input
type="number"
v-if="scope.row.AfterQuestionList[index].Type === 'number'"
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
>
</el-input>
</template>
<!-- 评估更新类型 GlobalAnswerType:3 -->
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
<el-tooltip v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" placement="top-start">
<el-select
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
style="width:90%;"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
>
<el-option
v-for="val in globalInfo.assessTypeList"
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
:key="val.Code"
:label="language === 'en'?val.Value:val.ValueCN"
:value="val.Code"
/>
</el-select>
</el-tooltip>
<el-select
v-else
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
style="width:90%;"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
>
<el-option
v-for="val in globalInfo.assessTypeList"
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
:key="val.Code"
:label="language === 'en'?val.Value:val.ValueCN"
:value="val.Code"
/>
</el-select>
</template>
<el-input
v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 1"
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
type="textarea"
maxlength="100"
show-word-limit
style="width:90%;"
:autosize="{ minRows: 2 }"
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
/>
</el-form-item>
</div>
<div v-else>
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
</span>
<span v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode,parseInt(scope.row.AfterQuestionList[index].Answer)) }}
</span>
<span v-else>{{ scope.row.AfterQuestionList[index].Answer }}</span>
</div>
</template>
</el-table-column>
</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
width="100"
>
<template slot-scope="scope">
<el-button
circle
:title="$t('trials:globalReview:table:view')"
icon="el-icon-view"
@click="handleView(scope.row)"
/>
</template>
</el-table-column>
</el-table>
</el-form>
</template>
<script>
import { getToken } from '@/utils/auth'
import { batchSubmitGlobalReadingInfo } from '@/api/trials'
import { mapGetters } from 'vuex'
export default {
props: {
globalInfo: {
type: Object,
default() {
return {}
}
},
globalForm: {
type: Object,
default() {
return {}
}
},
readingTaskState: {
type: Number,
required: true
}
},
data() {
return {
loading: false,
assessTypes: []
}
},
computed: {
...mapGetters(['language'])
},
mounted() {
this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline)
},
methods: {
getText(val, row, type) {
if (type === 3) {
var o = this.globalInfo.assessTypeList.find(v => {
return parseInt(v.Code) === parseInt(val)
})
if (!o) {
return ''
}
return this.language === 'en' ? o.Value : o.ValueCN
} else if (row.TypeValue) {
return val
} else if (row.DictionaryCode) {
return this.$fd(row.DictionaryCode, parseInt(val))
}
},
handleView(row) {
var token = getToken()
var visitTaskId = row.VisitTaskId
var criterionType = this.$router.currentRoute.query.criterionType
var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var path = ''
if (readingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} else {
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
}
const routeData = this.$router.resolve({ path })
var newWindow = window.open(routeData.href, '_blank')
this.$emit('setOpenWindow', newWindow)
},
getLesionCount(lesionList, lesionType) {
const lesion = lesionList.find(i => i.LesionType === lesionType)
return lesion ? lesion.Count : 0
},
handleSave(isPrompt = true) {
return new Promise(async (resolve, reject) => {
let valid = await this.$refs['globalRuleForm'].validate()
if (valid) {
this.loading = true
var visitTaskAnswerList = []
this.globalForm.taskList.forEach((item, index) => {
var answerList = []
item.AfterQuestionList.map(i => {
var obj = {}
if (i.QuestionId) {
obj.questionId = i.QuestionId
obj.globalAnswerType = i.GlobalAnswerType
obj.answer = this.globalForm[ `${index}${i.QuestionId}`]
} else {
obj.questionId = ''
obj.globalAnswerType = i.GlobalAnswerType
obj.answer = this.globalForm[ `${index}${i.GlobalAnswerType}`]
}
answerList.push(obj)
})
answerList.push({ questionId: '', globalAnswerType: item.AgreeOrNot[0].GlobalAnswerType,
answer: this.globalForm[ `${index}${item.AgreeOrNot[0].GlobalAnswerType}`] })
visitTaskAnswerList.push({ visitTaskId: item.VisitTaskId, answerList: answerList })
})
var params = {
globalTaskId: this.globalInfo.visitTaskId,
subjectId: this.globalInfo.subjectId,
trialId: this.globalInfo.trialId,
visitTaskAnswerList
}
try {
await batchSubmitGlobalReadingInfo(params)
this.loading = false
if (isPrompt) {
console.log(isPrompt)
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
this.$emit('getGlInfo')
resolve()
} catch (e) {
this.loading = false
reject()
}
} else {
reject()
}
})
},
getBeforeAnswer(qsId, row) {
var i = row.BeforeQuestionList.findIndex(item => item.QuestionName === qsId)
if (i > -1 && row.BeforeQuestionList[i].Answer) {
var answer = ''
if (row.BeforeQuestionList[i].DictionaryCode) {
answer = row.BeforeQuestionList[i].Answer
} else {
answer = row.BeforeQuestionList[i].Answer
}
return answer
} else {
return ''
}
},
handleAgreeOrNotChange(index, globalAnswerType) {
var agreeOrNot = parseInt(this.globalForm[`${index}${globalAnswerType}`])
if (agreeOrNot === 1) {
var qsList = this.globalForm.taskList[index].AfterQuestionList
qsList.map(v => {
if (v.QuestionId) {
this.globalForm[`${index}${v.QuestionId}`] = ''
} else if (v.GlobalAnswerType !== globalAnswerType) {
this.globalForm[`${index}${v.GlobalAnswerType}`] = ''
}
})
}
console.log(this.globalForm)
},
getAssessType(v) {
console.log(this.language)
var i = this.globalInfo.assessTypeList.findIndex(i => String(i.Code) === String(v))
if (i > -1) {
return this.language === 'en' ? this.globalInfo.assessTypeList[i].Value : this.globalInfo.assessTypeList[i].ValueCN
} else {
return ''
}
}
}
}
</script>
<style lang="scss" scoped>
/deep/ .el-form-item label:before {
content: '*';
color: #F56C6C;
margin-right: 4px;
}
/deep/ .el-textarea .el-input__count{
background: rgba(0,0,0,0);
line-height: normal;
}
/deep/ .el-form-item{
margin-bottom: 0px;
}
.global-form{
/deep/ .el-form-item__content{
padding-bottom: 10px;
}
/deep/ .form-item .el-form-item__error{
top: 60%;
}
}
</style>

View File

@ -26,13 +26,24 @@
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
> >
<template slot-scope="scope"> <!-- <template slot-scope="scope">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}"> <div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode"> <span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }} {{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span> </span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span> <span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div> </div>
</template> -->
<template slot-scope="scope">
<template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div>
</template>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
@ -85,20 +96,20 @@
<template> <template>
<el-table-column <el-table-column
v-for="(qs,index) in globalInfo.adjustedQsList" v-for="(qs,index) in globalInfo.adjustedQsList"
v-if="qs.isShow"
:key="index" :key="index"
prop="" prop=""
:label="qs" :label="qs.questionName"
show-overflow-tooltip show-overflow-tooltip
:min-width="index === 3 ? '200' : '200'" :min-width="index === 3 ? '200' : '200'"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="readingTaskState<2"> <div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)"> <!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }} {{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
</span> </span> -->
<el-form-item <el-form-item
v-else
style="margin-bottom: 0;" style="margin-bottom: 0;"
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`" :prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
label="" label=""
@ -255,7 +266,7 @@
/> />
</el-form-item> </el-form-item>
</div> </div>
<div v-else-if="scope.row.AfterQuestionList.length>index && scope.row.AfterQuestionList[index].Answer"> <div v-else>
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3"> <span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }} {{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
@ -320,7 +331,6 @@ export default {
...mapGetters(['language']) ...mapGetters(['language'])
}, },
mounted() { mounted() {
console.log('iRecist')
this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline) this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline)
}, },
methods: { methods: {
@ -346,11 +356,12 @@ export default {
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} else { } else {
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} }
const routeData = this.$router.resolve({ path }) const routeData = this.$router.resolve({ path })
var newWindow = window.open(routeData.href, '_blank') var newWindow = window.open(routeData.href, '_blank')
@ -361,9 +372,10 @@ export default {
return lesion ? lesion.Count : 0 return lesion ? lesion.Count : 0
}, },
handleSave(isPrompt = true) { handleSave(isPrompt = true) {
return new Promise((resolve, reject) => { return new Promise(async (resolve, reject) => {
this.$refs['globalRuleForm'].validate(valid => { let valid = await this.$refs['globalRuleForm'].validate()
if (valid) {
if (valid) {
this.loading = true this.loading = true
var visitTaskAnswerList = [] var visitTaskAnswerList = []
this.globalForm.taskList.forEach((item, index) => { this.globalForm.taskList.forEach((item, index) => {
@ -392,7 +404,8 @@ export default {
trialId: this.globalInfo.trialId, trialId: this.globalInfo.trialId,
visitTaskAnswerList visitTaskAnswerList
} }
batchSubmitGlobalReadingInfo(params).then(res => { try {
await batchSubmitGlobalReadingInfo(params)
this.loading = false this.loading = false
if (isPrompt) { if (isPrompt) {
console.log(isPrompt) console.log(isPrompt)
@ -400,14 +413,13 @@ export default {
} }
this.$emit('getGlInfo') this.$emit('getGlInfo')
resolve() resolve()
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
reject() reject()
}) }
} else { } else {
reject() reject()
} }
})
}) })
}, },
getBeforeAnswer(qsId, row) { getBeforeAnswer(qsId, row) {
@ -452,23 +464,23 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
>>>.el-form-item label:before { /deep/ .el-form-item label:before {
content: '*'; content: '*';
color: #F56C6C; color: #F56C6C;
margin-right: 4px; margin-right: 4px;
} }
>>>.el-textarea .el-input__count{ /deep/ .el-textarea .el-input__count{
background: rgba(0,0,0,0); background: rgba(0,0,0,0);
line-height: normal; line-height: normal;
} }
>>>.el-form-item{ /deep/ .el-form-item{
margin-bottom: 0px; margin-bottom: 0px;
} }
.global-form{ .global-form{
>>>.el-form-item__content{ /deep/ .el-form-item__content{
padding-bottom: 10px; padding-bottom: 10px;
} }
>>>.form-item .el-form-item__error{ /deep/ .form-item .el-form-item__error{
top: 60%; top: 60%;
} }
} }

View File

@ -26,14 +26,16 @@
width="200" width="200"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer"> <template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode"> <div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }} <span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
</span> {{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
<span v-else-if="scope.row.BeforeQuestionList[index].QuestionType === 22">{{ scope.row.BeforeQuestionList[index].Answer === '-1' ? $t('trials:readingReport:title:unknow') : scope.row.BeforeQuestionList[index].Answer }}</span> </span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span> <span v-else-if="scope.row.BeforeQuestionList[index].QuestionType === 22">{{ scope.row.BeforeQuestionList[index].Answer === '-1' ? $t('trials:readingReport:title:unknow') : scope.row.BeforeQuestionList[index].Answer }}</span>
</div> <span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</template> </div>
</template>
</template>
</el-table-column> </el-table-column>
</template> </template>
</el-table-column> </el-table-column>
@ -47,18 +49,18 @@
<template> <template>
<el-table-column <el-table-column
v-for="(qs,index) in globalInfo.adjustedQsList" v-for="(qs,index) in globalInfo.adjustedQsList"
v-if="qs.isShow"
:key="index" :key="index"
prop="" prop=""
:label="qs" :label="qs.questionName"
:width="index > 0 ? '300' : '200'" :width="index > 0 ? '300' : '200'"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="readingTaskState<2 "> <div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)"> <!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }} {{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
</span> </span> -->
<el-form-item <el-form-item
v-else
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`" :prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
label="" label=""
:rules="[ :rules="[
@ -107,7 +109,7 @@
/> />
</el-form-item> </el-form-item>
</div> </div>
<div v-else-if="scope.row.AfterQuestionList.length>index && scope.row.AfterQuestionList[index].Answer"> <div v-else>
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3"> <span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }} {{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
@ -181,7 +183,6 @@ export default {
} }
}, },
mounted() { mounted() {
console.log(this.globalInfo.adjustedQsList)
}, },
methods: { methods: {
selectChange(v, row, index) { selectChange(v, row, index) {
@ -218,9 +219,9 @@ export default {
this.$emit('handleView', row) this.$emit('handleView', row)
}, },
handleSave(isPrompt = true) { handleSave(isPrompt = true) {
return new Promise((resolve, reject) => { return new Promise(async (resolve, reject) => {
this.$refs['globalRuleForm'].validate(valid => { let valid = await this.$refs['globalRuleForm'].validate()
if (valid) { if (valid) {
this.loading = true this.loading = true
var visitTaskAnswerList = [] var visitTaskAnswerList = []
this.globalForm.taskList.forEach((item, index) => { this.globalForm.taskList.forEach((item, index) => {
@ -246,21 +247,21 @@ export default {
trialId: this.globalInfo.trialId, trialId: this.globalInfo.trialId,
visitTaskAnswerList visitTaskAnswerList
} }
batchSubmitGlobalReadingInfo(params).then(res => { try {
await batchSubmitGlobalReadingInfo(params)
this.loading = false this.loading = false
if (isPrompt) { if (isPrompt) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
} }
this.$emit('getGlInfo') this.$emit('getGlInfo')
resolve() resolve()
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
reject() reject()
}) }
} else { } else {
reject() reject()
} }
})
}) })
} }
} }
@ -268,19 +269,19 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
>>>.el-form-item label:before { /deep/ .el-form-item label:before {
content: '*'; content: '*';
color: #F56C6C; color: #F56C6C;
margin-right: 4px; margin-right: 4px;
} }
>>>.el-form-item--medium .el-form-item__content{ /deep/ .el-form-item--medium .el-form-item__content{
display: flex; display: flex;
} }
.global-form{ .global-form{
>>>.el-form-item__content{ /deep/ .el-form-item__content{
padding-bottom: 10px; padding-bottom: 10px;
} }
>>>.form-item .el-form-item__error{ /deep/ .form-item .el-form-item__error{
top: 60%; top: 60%;
} }
} }

View File

@ -26,13 +26,24 @@
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
> >
<template slot-scope="scope"> <!-- <template slot-scope="scope">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}"> <div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode"> <span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }} {{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span> </span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span> <span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div> </div>
</template> -->
<template slot-scope="scope">
<template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div>
</template>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
@ -85,20 +96,20 @@
<template> <template>
<el-table-column <el-table-column
v-for="(qs,index) in globalInfo.adjustedQsList" v-for="(qs,index) in globalInfo.adjustedQsList"
v-if="qs.isShow"
:key="index" :key="index"
prop="" prop=""
:label="qs" :label="qs.questionName"
show-overflow-tooltip show-overflow-tooltip
:min-width="index === 3 ? '200' : '200'" :min-width="index === 3 ? '200' : '200'"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="readingTaskState<2"> <div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)"> <!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }} {{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
</span> </span> -->
<el-form-item <el-form-item
v-else
style="margin-bottom: 0;" style="margin-bottom: 0;"
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`" :prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
label="" label=""
@ -253,7 +264,7 @@
/> />
</el-form-item> </el-form-item>
</div> </div>
<div v-else-if="scope.row.AfterQuestionList.length>index && scope.row.AfterQuestionList[index].Answer"> <div v-else>
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3"> <span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }} {{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
@ -342,11 +353,12 @@ export default {
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} else { } else {
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} }
const routeData = this.$router.resolve({ path }) const routeData = this.$router.resolve({ path })
var newWindow = window.open(routeData.href, '_blank') var newWindow = window.open(routeData.href, '_blank')
@ -357,9 +369,9 @@ export default {
return lesion ? lesion.Count : 0 return lesion ? lesion.Count : 0
}, },
handleSave(isPrompt = true) { handleSave(isPrompt = true) {
return new Promise((resolve, reject) => { return new Promise(async(resolve, reject) => {
this.$refs['globalRuleForm'].validate(valid => { let valid = await this.$refs['globalRuleForm'].validate()
if (valid) { if (valid) {
this.loading = true this.loading = true
var visitTaskAnswerList = [] var visitTaskAnswerList = []
this.globalForm.taskList.forEach((item, index) => { this.globalForm.taskList.forEach((item, index) => {
@ -388,7 +400,8 @@ export default {
trialId: this.globalInfo.trialId, trialId: this.globalInfo.trialId,
visitTaskAnswerList visitTaskAnswerList
} }
batchSubmitGlobalReadingInfo(params).then(res => { try {
await batchSubmitGlobalReadingInfo(params)
this.loading = false this.loading = false
if (isPrompt) { if (isPrompt) {
console.log(isPrompt) console.log(isPrompt)
@ -396,14 +409,13 @@ export default {
} }
this.$emit('getGlInfo') this.$emit('getGlInfo')
resolve() resolve()
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
reject() reject()
}) }
} else { } else {
reject() reject()
} }
})
}) })
}, },
getBeforeAnswer(qsId, row) { getBeforeAnswer(qsId, row) {
@ -448,23 +460,23 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
>>>.el-form-item label:before { /deep/ .el-form-item label:before {
content: '*'; content: '*';
color: #F56C6C; color: #F56C6C;
margin-right: 4px; margin-right: 4px;
} }
>>>.el-textarea .el-input__count{ /deep/ .el-textarea .el-input__count{
background: rgba(0,0,0,0); background: rgba(0,0,0,0);
line-height: normal; line-height: normal;
} }
>>>.el-form-item{ /deep/ .el-form-item{
margin-bottom: 0px; margin-bottom: 0px;
} }
.global-form{ .global-form{
>>>.el-form-item__content{ /deep/ .el-form-item__content{
padding-bottom: 10px; padding-bottom: 10px;
} }
>>>.form-item .el-form-item__error{ /deep/ .form-item .el-form-item__error{
top: 60%; top: 60%;
} }
} }

View File

@ -26,13 +26,24 @@
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
> >
<template slot-scope="scope"> <!-- <template slot-scope="scope">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}"> <div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode"> <span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }} {{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span> </span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span> <span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div> </div>
</template> -->
<template slot-scope="scope">
<template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
</span>
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
</div>
</template>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
@ -85,20 +96,19 @@
<template> <template>
<el-table-column <el-table-column
v-for="(qs,index) in globalInfo.adjustedQsList" v-for="(qs,index) in globalInfo.adjustedQsList"
v-if="qs.isShow"
:key="index" :key="index"
prop="" prop=""
:label="qs" :label="qs.questionName"
show-overflow-tooltip show-overflow-tooltip
:min-width="index === 3 ? '200' : '200'" :min-width="index === 3 ? '200' : '200'"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="readingTaskState<2"> <div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)"> <!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }} {{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
</span> </span> -->
<el-form-item <el-form-item
v-else
style="margin-bottom: 0;" style="margin-bottom: 0;"
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`" :prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
label="" label=""
@ -247,7 +257,7 @@
/> />
</el-form-item> </el-form-item>
</div> </div>
<div v-else-if="scope.row.AfterQuestionList.length>index && scope.row.AfterQuestionList[index].Answer"> <div v-else>
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3"> <span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }} {{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
@ -337,11 +347,12 @@ export default {
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} else { } else {
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} }
const routeData = this.$router.resolve({ path }) const routeData = this.$router.resolve({ path })
var newWindow = window.open(routeData.href, '_blank') var newWindow = window.open(routeData.href, '_blank')
@ -352,9 +363,9 @@ export default {
return lesion ? lesion.Count : 0 return lesion ? lesion.Count : 0
}, },
handleSave(isPrompt = true) { handleSave(isPrompt = true) {
return new Promise((resolve, reject) => { return new Promise(async (resolve, reject) => {
this.$refs['globalRuleForm'].validate(valid => { let valid = await this.$refs['globalRuleForm'].validate()
if (valid) { if (valid) {
this.loading = true this.loading = true
var visitTaskAnswerList = [] var visitTaskAnswerList = []
this.globalForm.taskList.forEach((item, index) => { this.globalForm.taskList.forEach((item, index) => {
@ -383,7 +394,8 @@ export default {
trialId: this.globalInfo.trialId, trialId: this.globalInfo.trialId,
visitTaskAnswerList visitTaskAnswerList
} }
batchSubmitGlobalReadingInfo(params).then(res => { try {
await batchSubmitGlobalReadingInfo(params)
this.loading = false this.loading = false
if (isPrompt) { if (isPrompt) {
console.log(isPrompt) console.log(isPrompt)
@ -391,14 +403,14 @@ export default {
} }
this.$emit('getGlInfo') this.$emit('getGlInfo')
resolve() resolve()
}).catch(() => { } catch (e) {
this.loading = false this.loading = false
reject() reject()
}) }
} else { } else {
reject() reject()
} }
})
}) })
}, },
getBeforeAnswer(qsId, row) { getBeforeAnswer(qsId, row) {
@ -428,6 +440,7 @@ export default {
} }
}) })
} }
console.log(this.globalForm)
}, },
getAssessType(v) { getAssessType(v) {
console.log(this.language) console.log(this.language)
@ -443,23 +456,23 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
>>>.el-form-item label:before { /deep/ .el-form-item label:before {
content: '*'; content: '*';
color: #F56C6C; color: #F56C6C;
margin-right: 4px; margin-right: 4px;
} }
>>>.el-textarea .el-input__count{ /deep/ .el-textarea .el-input__count{
background: rgba(0,0,0,0); background: rgba(0,0,0,0);
line-height: normal; line-height: normal;
} }
>>>.el-form-item{ /deep/ .el-form-item{
margin-bottom: 0px; margin-bottom: 0px;
} }
.global-form{ .global-form{
>>>.el-form-item__content{ /deep/ .el-form-item__content{
padding-bottom: 10px; padding-bottom: 10px;
} }
>>>.form-item .el-form-item__error{ /deep/ .form-item .el-form-item__error{
top: 60%; top: 60%;
} }
} }

View File

@ -25,7 +25,14 @@
</div> </div>
<div v-if=" readingTaskState < 2" style="text-align:right;margin:5px 0;"> <div v-if=" readingTaskState < 2" style="text-align:right;margin:5px 0;">
<el-button
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button size="small" type="primary" @click="handleSave"> <el-button size="small" type="primary" @click="handleSave">
{{ $t('common:button:save') }} {{ $t('common:button:save') }}
</el-button> </el-button>
@ -34,8 +41,17 @@
{{ $t('trials:globalReview:button:submit') }} {{ $t('trials:globalReview:button:submit') }}
</el-button> </el-button>
</div> </div>
<CustomizeTable
v-if="CriterionType === 0 && Object.keys(globalInfo).length !== 0"
ref="globalTbl"
:global-info="globalInfo"
:global-form="globalInfo.globalForm"
:reading-task-state="readingTaskState"
@getGlInfo="getGlInfo"
@setOpenWindow="setOpenWindow"
/>
<RecistTable <RecistTable
v-if="(CriterionType === 1 || CriterionType === 0) && Object.keys(globalInfo).length !== 0" v-if="CriterionType === 1 && Object.keys(globalInfo).length !== 0"
ref="globalTbl" ref="globalTbl"
:global-info="globalInfo" :global-info="globalInfo"
:global-form="globalInfo.globalForm" :global-form="globalInfo.globalForm"
@ -90,6 +106,12 @@
show-overflow-tooltip show-overflow-tooltip
width="200" width="200"
/> />
<el-table-column
prop="VisitBlindName"
:label="$t('trials:globalReview:table:cutOffVisitName')"
show-overflow-tooltip
width="200"
/>
<el-table-column <el-table-column
:label="$t('common:action:action')" :label="$t('common:action:action')"
width="200" width="200"
@ -126,9 +148,11 @@
<script> <script>
import { getGlobalReadingInfo, getReadingPastResultList, submitGlobalReadingInfo, saveGlobalReadingInfo } from '@/api/trials' import { getGlobalReadingInfo, getReadingPastResultList, submitGlobalReadingInfo, saveGlobalReadingInfo } from '@/api/trials'
import { getAutoCutNextTask } from '@/api/user' import { getAutoCutNextTask } from '@/api/user'
import { setSkipReadingCache } from '@/api/reading'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent' import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import CustomizeTable from './components/CustomizeTable'
import RecistTable from './components/RecistTable' import RecistTable from './components/RecistTable'
import PCWG3Table from './components/PCWG3Table' import PCWG3Table from './components/PCWG3Table'
import IRecistTable from './components/IRecistTable' import IRecistTable from './components/IRecistTable'
@ -138,7 +162,7 @@ import { changeURLStatic } from '@/utils/history.js'
import store from '@/store' import store from '@/store'
export default { export default {
name: 'GlobalReview', name: 'GlobalReview',
components: { RecistTable, PCWG3Table, IRecistTable, RecistBMTable, SignForm }, components: { CustomizeTable, RecistTable, PCWG3Table, IRecistTable, RecistBMTable, SignForm },
props: { props: {
trialId: { trialId: {
type: String, type: String,
@ -231,9 +255,10 @@ export default {
} }
}, },
methods: { methods: {
getGlInfo() { async getGlInfo() {
this.loading = true this.loading = true
getGlobalReadingInfo({ visitTaskId: this.visitTaskId }).then(res => { try {
let res = await getGlobalReadingInfo({ visitTaskId: this.visitTaskId })
var evaluationQsList = [] var evaluationQsList = []
var adjustedQsList = [] var adjustedQsList = []
var agreeOrNotList = [] var agreeOrNotList = []
@ -245,33 +270,38 @@ export default {
evaluationQsList.push(qs.QuestionName) evaluationQsList.push(qs.QuestionName)
}) })
qs.AfterQuestionList.map(qs => { qs.AfterQuestionList.map(qs => {
console.log(qs)
if (qs.GlobalAnswerType === 1 && (this.CriterionType === 10)) { if (qs.GlobalAnswerType === 1 && (this.CriterionType === 10)) {
// 访 // 访
adjustedQsList.push(this.$t('trials:globalReview:table:visitRemark')) adjustedQsList.push({questionName:this.$t('trials:globalReview:table:visitRemark'),isShow:true})
} else if (qs.GlobalAnswerType === 1 && (this.CriterionType === 1 || this.CriterionType === 3 || this.CriterionType === 17 || this.CriterionType === 0)) { } else if (qs.GlobalAnswerType === 1 && (this.CriterionType !== 10)) {
// //
adjustedQsList.push(this.$t('trials:globalReview:table:globalRemark')) adjustedQsList.push({questionName:this.$t('trials:globalReview:table:globalRemark'),isShow:true})
} else if (qs.GlobalAnswerType === 3 && (this.CriterionType === 1 || this.CriterionType === 3 || this.CriterionType === 17 || this.CriterionType === 0)) { } else if (qs.GlobalAnswerType === 3 && (this.CriterionType !== 10)) {
// //
adjustedQsList.push(this.$t('trials:globalReview:table:updateType')) adjustedQsList.push({questionName:this.$t('trials:globalReview:table:updateType'),isShow:true})
} else { } else {
adjustedQsList.push(qs.QuestionName) var isShow = true
if(this.CriterionType === 2 && (qs.QuestionType === 39 || qs.QuestionType === 40 || qs.QuestionType === 41)){
isShow = false
}
adjustedQsList.push({questionName:qs.QuestionName,isShow:isShow})
} }
}) })
qs.AgreeOrNot.map(qs => { qs.AgreeOrNot.map(qs => {
agreeOrNotList.push(qs.QuestionName) agreeOrNotList.push(qs.QuestionName)
}) })
} }
qs.AgreeOrNot.map(qs => {
var answer = qs.Answer
this.$set(globalForm, `${index}${qs.GlobalAnswerType}`, answer)
})
qs.AfterQuestionList.map(q => { qs.AfterQuestionList.map(q => {
if (q.Answer !== q.VisitAnswer) { if (q.Answer !== q.VisitAnswer) {
this.$set(q, 'isChange', true) this.$set(q, 'isChange', true)
} }
var answer = '' var answer = q.Answer
if (q.DictionaryCode) {
answer = q.Answer
} else {
answer = q.Answer
}
if (!q.QuestionId) { if (!q.QuestionId) {
this.$set(globalForm, `${index}${q.GlobalAnswerType}`, answer) this.$set(globalForm, `${index}${q.GlobalAnswerType}`, answer)
} else { } else {
@ -291,70 +321,44 @@ export default {
trialId: this.trialId, subjectId: this.subjectId, subjectCode: this.subjectCode, visitTaskId: res.Result.GlobalTaskId, globalForm, globalUpdateType, evaluationQsList, adjustedQsList, agreeOrNotList, readingTaskState: this.readingTaskState, assessTypeList: res.Result.AssessTypeList trialId: this.trialId, subjectId: this.subjectId, subjectCode: this.subjectCode, visitTaskId: res.Result.GlobalTaskId, globalForm, globalUpdateType, evaluationQsList, adjustedQsList, agreeOrNotList, readingTaskState: this.readingTaskState, assessTypeList: res.Result.AssessTypeList
} }
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
getHistoryGlobalInfo() { async getHistoryGlobalInfo() {
this.historyLoading = true this.historyLoading = true
getReadingPastResultList({ visitTaskId: this.visitTaskId }).then(res => { try {
let res = await getReadingPastResultList({ visitTaskId: this.visitTaskId })
this.historyTaskList = res.Result this.historyTaskList = res.Result
this.historyLoading = false this.historyLoading = false
}).catch(() => { this.historyLoading = false }) } catch (e) {
}, this.historyLoading = false
changeAgreeOrNotList(callback, row, visitTaskId) {
var message = ''
if (parseInt(callback) === 1) {
message = '是否确认更改?'
row.Answer = '0'
} else {
message = '是否确认更改?'
row.Answer = '1'
} }
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
}).then(() => {
this.loading = true
var params = {
globalTaskId: this.visitTaskId,
subjectId: this.subjectId,
trialId: this.trialId,
questionList: [
{
questionId: row.QuestionId ? row.QuestionId : '',
visitTaskId: visitTaskId,
globalAnswerType: row.GlobalAnswerType,
answer: row.Answer === '1' ? '0' : '1'
}
]
}
saveGlobalReadingInfo(params).then(res => {
this.loading = false
if (res.IsSuccess) {
this.$message.success('保存成功!')
this.getGlInfo()
}
}).catch(() => { this.loading = false })
}).catch(() => {})
}, },
// handleEdit(row) { handleSave() {
// this.rowData = { ...row } this.$refs['globalTbl'].handleSave(true)
// if (this.CriterionType === 1) { },
// this.rowData.AfterQuestionList.forEach(item => { async skipTask() {
// if (item.GlobalAnswerType === 1) { try {
// // //
// item.QuestionName = this.$t('trials:globalReview:table:globalRemark') const confirm = await this.$confirm(
// } else if (item.GlobalAnswerType === 3) { this.$t('trials:readingReport:message:skipConfirm'),
// // {
// item.QuestionName = this.$t('trials:globalReview:table:updateType') type: 'warning',
// } distinguishCancelAndClose: true
// }) }
// } )
// // this.editVisible = true if (confirm !== 'confirm') return
// }, this.loading = true
async handleSave() { const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
this.loading = true this.loading = false
await this.$refs['globalTbl'].handleSave(true) if (res.IsSuccess) {
this.loading = false window.location.reload()
}
} catch (e) {
this.loading = false
console.log(e)
}
}, },
async handleConfirm() { async handleConfirm() {
// 访 // 访
@ -384,53 +388,51 @@ export default {
} }
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
var params = { var params = {
data: { data: {
globalTaskId: this.visitTaskId globalTaskId: this.visitTaskId
}, },
signInfo: signInfo signInfo: signInfo
} }
submitGlobalReadingInfo(params).then(async res => { try{
let res = await submitGlobalReadingInfo(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
this.signVisible = false this.signVisible = false
// //
this.readingTaskState = 2 this.readingTaskState = 2
var isAutoTask = await this.getAutoTaskVal() const res = await getAutoCutNextTask()
var isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) { if (isAutoTask) {
DicomEvent.$emit('getNextTask') // DicomEvent.$emit('getNextTask')
window.location.reload()
} else { } else {
// //
this.$confirm(this.$t('trials:globalReview:message:msg2'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:globalReview:message:msg2'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(() => { distinguishCancelAndClose: true
store.dispatch('reading/resetVisitTasks') }
DicomEvent.$emit('getNextTask') )
}) if (confirm === 'confirm') {
.catch(action => { // store.dispatch('reading/resetVisitTasks')
changeURLStatic('visitTaskId', this.visitTaskId) // DicomEvent.$emit('getNextTask')
}) window.location.reload()
} else {
changeURLStatic('visitTaskId', this.visitTaskId)
}
} }
window.opener.postMessage('refreshTaskList', window.location) window.opener.postMessage('refreshTaskList', window.location)
} }
this.loading = false this.loading = false
}).catch(_ => { } catch (e) {
this.loading = false this.loading = false
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
}) }
},
getAutoTaskVal() {
return new Promise((resolve, reject) => {
getAutoCutNextTask().then(res => {
resolve(res.Result.AutoCutNextTask)
}).catch(() => { reject() })
})
}, },
handleView(row) { handleView(row) {
if (this.openWindow) { if (this.openWindow) {
@ -439,15 +441,16 @@ export default {
try { try {
var token = getToken() var token = getToken()
var visitTaskId = row.VisitTaskId var visitTaskId = row.VisitTaskId
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var criterionType = this.$router.currentRoute.query.criterionType var criterionType = this.$router.currentRoute.query.criterionType
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.$router.currentRoute.query.readingTool
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool) readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var path = '' var path = ''
if (readingTool === 0) { if (readingTool === 0) {
path = `/readingDicoms?trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} else { } else {
path = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
} }
const routeData = this.$router.resolve({ path }) const routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, '_blank') this.openWindow = window.open(routeData.href, '_blank')

View File

@ -1,17 +1,15 @@
<template> <template>
<!-- <el-tabs v-model="activeName" v-loading="loading" style="min-height:500px">--> <div style="min-height:500px">
<!-- <el-tab-pane--> <h3 v-if="isReadingShowSubjectInfo" style="padding: 5px 0px;margin: 0;">
<!-- v-for="criterion in criterions"--> <span v-if="subjectCode">{{ subjectCode }} </span>
<!-- :key="criterion.ReadingQuestionCriterionTrialId"--> <span style="margin-left:5px;">{{ taskBlindName }}</span>
<!-- :label="criterion.ReadingQuestionCriterionTrialName"--> </h3>
<!-- :name="criterion.ReadingQuestionCriterionTrialId"-->
<!-- >-->
<div v-loading="loading" style="min-height:500px">
<ECRF <ECRF
:trial-id="trialId" :trial-id="trialId"
:subject-id="subjectId" :subject-id="subjectId"
:criterion-id="criterionId" :criterion-id="criterionId"
:visit-task-id="visitTaskId" :visit-task-id="visitTaskId"
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
/> />
</div> </div>
@ -43,6 +41,22 @@ export default {
criterionId: { criterionId: {
type: String, type: String,
required: true required: true
},
subjectCode: {
type: String,
required: true
},
taskBlindName: {
type: String,
required: true
},
isReadingShowSubjectInfo: {
type: Boolean,
required: true
},
iseCRFShowInDicomReading: {
type: Boolean,
required: true
} }
}, },
data() { data() {

View File

@ -55,6 +55,7 @@
:question-form="questionForm" :question-form="questionForm"
:reading-task-state="readingTaskState" :reading-task-state="readingTaskState"
:visit-task-id="visitTaskId" :visit-task-id="visitTaskId"
:calculation-list="calculationList"
@setFormItemData="setFormItemData" @setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData" @resetFormItemData="resetFormItemData"
/> />
@ -77,8 +78,15 @@
<el-form-item v-if="readingTaskState < 2"> <el-form-item v-if="readingTaskState < 2">
<div style="text-align:center;"> <div style="text-align:center;">
<el-button type="primary" @click="handleSave">{{ $t('common:button:save') }}</el-button> <el-button type="primary" @click="skipTask" v-if="iseCRFShowInDicomReading">
<el-button type="primary" @click="handleSubmit">{{ $t('common:button:submit') }}</el-button> {{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button type="primary" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
<el-button type="primary" @click="handleSubmit" v-if="iseCRFShowInDicomReading">
{{ $t('common:button:submit') }}
</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -103,7 +111,8 @@
<script> <script>
import { getTrialReadingQuestion, saveVisitTaskQuestions, submitVisitTaskQuestionsInDto } from '@/api/trials' import { getTrialReadingQuestion, saveVisitTaskQuestions, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import FormItem from './FormItem' import FormItem from './FormItem'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
@ -131,6 +140,10 @@ export default {
visitTaskId: { visitTaskId: {
type: String, type: String,
required: true required: true
},
iseCRFShowInDicomReading: {
type: Boolean,
required: true
} }
}, },
data() { data() {
@ -145,104 +158,136 @@ export default {
currentUser: zzSessionStorage.getItem('userName'), currentUser: zzSessionStorage.getItem('userName'),
readingTaskState: 0, readingTaskState: 0,
activeName: 0, activeName: 0,
formType: null formType: null,
classArr: [],
calculationList: []
} }
}, },
mounted() { mounted() {
this.getQuestionCalculateRelation()
this.getQuestions() this.getQuestions()
DicomEvent.$on('refreshQuestionAnswer', _ => {
this.getQuestions()
})
}, },
methods: { methods: {
getQuestions() { async getQuestions() {
this.loading = true this.loading = true
var param = { try {
readingQuestionCriterionTrialId: this.criterionId, const param = {
visitTaskId: this.visitTaskId readingQuestionCriterionTrialId: this.criterionId,
} visitTaskId: this.visitTaskId
getTrialReadingQuestion(param).then(res => { }
this.readingTaskState = res.OtherInfo.readingTaskState const res = await getTrialReadingQuestion(param)
this.formType = res.OtherInfo.FormType if (res.IsSuccess) {
if (res.OtherInfo.FormType === 2) { this.readingTaskState = res.OtherInfo.readingTaskState
if (res.Result.MultiPage.length > 0) { this.formType = res.OtherInfo.FormType
res.Result.MultiPage.map((v) => { if (res.OtherInfo.FormType === 2) {
if (v.Type === 'group' && v.Childrens.length === 0) return if (res.Result.MultiPage.length > 0) {
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') { res.Result.MultiPage.map((v) => {
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null) if (v.Type === 'group' && v.Childrens.length === 0) return
} if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
if (v.Childrens.length > 0) { this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
this.setChild(v.Childrens) }
} if (v.Type === 'class') {
}) this.classArr.push({triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType})
this.questions = res.Result.MultiPage }
this.activeName = res.Result.MultiPage[0].PageName if (v.Childrens.length > 0) {
} this.setChild(v.Childrens)
if (res.Result.PublicPage.length > 0) { }
res.Result.PublicPage.map((v) => { })
if (v.Type === 'group' && v.Childrens.length === 0) return this.questions = res.Result.MultiPage
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') { this.activeName = res.Result.MultiPage[0].PageName
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null) }
} if (res.Result.PublicPage.length > 0) {
if (v.Childrens.length > 0) { res.Result.PublicPage.map((v) => {
this.setChild(v.Childrens) if (v.Type === 'group' && v.Childrens.length === 0) return
} if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
}) this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
this.publicQuestions = res.Result.PublicPage }
} if (v.Type === 'class') {
} else { this.classArr.push({triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType})
res.Result.SinglePage.map((v) => { }
if (v.Type === 'group' && v.Childrens.length === 0) return if (v.Childrens.length > 0) {
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') { this.setChild(v.Childrens)
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null) }
} })
if (v.Childrens.length > 0) { this.publicQuestions = res.Result.PublicPage
this.setChild(v.Childrens) }
} } else {
}) res.Result.SinglePage.map((v) => {
this.questions = res.Result.SinglePage if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
}
if (v.Type === 'class') {
this.classArr.push({triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType})
}
if (v.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.SinglePage
}
this.isRender = true
} }
this.isRender = true
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
setChild(obj) { setChild(obj) {
obj.forEach(i => { obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) { if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null) this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
} }
if (i.Type === 'class') {
this.classArr.push({triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType})
}
if (i.Childrens && i.Childrens.length > 0) { if (i.Childrens && i.Childrens.length > 0) {
this.setChild(i.Childrens) this.setChild(i.Childrens)
} }
}) })
}, },
handleSave() { async getQuestionCalculateRelation() {
this.$refs['questions'].validate((valid) => { try {
if (!valid) return let res = await getQuestionCalculateRelation({TrialReadingCriterionId: this.criterionId})
this.loading = true this.calculationList = res.Result
var answers = [] } catch(e) {
for (const k in this.questionForm) { console.log(e)
answers.push({ readingQuestionTrialId: k, answer: this.questionForm[k] }) }
}
var params = {
trialId: this.trialId,
visitTaskId: this.visitTaskId,
readingQuestionCriterionTrialId: this.criterionId,
answerList: answers
}
saveVisitTaskQuestions(params).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.loading = false
}).catch(() => {
this.loading = false
})
})
}, },
handleSubmit() { async handleSave() {
this.$refs['questions'].validate((valid) => { const valid = await this.$refs['questions'].validate()
if (!valid) return if (!valid) return
const { ImageAssessmentReportConfirmation } = const_.processSignature this.loading = true
this.signCode = ImageAssessmentReportConfirmation const answers = []
this.signVisible = true for (const k in this.questionForm) {
}) answers.push({ readingQuestionTrialId: k, answer: this.questionForm[k] })
}
const params = {
trialId: this.trialId,
visitTaskId: this.visitTaskId,
readingQuestionCriterionTrialId: this.criterionId,
answerList: answers
}
try {
const res = await saveVisitTaskQuestions(params)
if (res.IsSuccess) {
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
this.loading = false
} catch (e) {
this.loading = false
}
},
async handleSubmit() {
const valid = await this.$refs['questions'].validate()
if (!valid) return
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}, },
// //
closeSignDialog(isSign, signInfo) { closeSignDialog(isSign, signInfo) {
@ -253,7 +298,7 @@ export default {
} }
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
var answers = [] var answers = []
for (const k in this.questionForm) { for (const k in this.questionForm) {
@ -268,49 +313,80 @@ export default {
}, },
signInfo: signInfo signInfo: signInfo
} }
submitVisitTaskQuestionsInDto(params).then(res => { try {
const res = await submitVisitTaskQuestionsInDto(params)
this.loading = false
if (res.IsSuccess) { if (res.IsSuccess) {
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.isEdit = false this.isEdit = false
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
this.signVisible = false this.signVisible = false
this.readingTaskState = 2 this.readingTaskState = 2
window.opener.postMessage('refreshTaskList', window.location) window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:globalReview:message:msg2'), { const confirm = await this.$confirm(
type: 'warning', this.$t('trials:noneDicoms:message:msg1'),
distinguishCancelAndClose: true {
}) type: 'warning',
.then(() => { distinguishCancelAndClose: true
DicomEvent.$emit('getNextTask') }
}) )
.catch(action => { if (confirm !== 'confirm') return
window.location.reload()
})
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
// var token = getToken()
// var subjectCode = this.$router.currentRoute.query.subjectCode
// var criterionType = this.$router.currentRoute.query.criterionType
// var readingTool = this.$router.currentRoute.query.readingTool
// var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
// var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
// const routeData = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
// this.$router.push({ path: routeData })
// this.$router.push({
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${this.subjectId}&trialId=${this.trialId}&TokenKey=${token}`
// })
} }
this.loading = false } catch (e) {
}).catch(_ => {
this.loading = false this.loading = false
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
}) }
},
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)
}
}, },
resetFormItemData(v) { resetFormItemData(v) {
this.questionForm[v] = null this.questionForm[v] = null
}, },
setFormItemData(obj) { setFormItemData(obj) {
this.questionForm[obj.key] = obj.val this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
this.classArr.map(i=>{
if (i.triggerId === obj.key) {
let answer = null
let list = JSON.parse(i.classifyAlgorithms)
if (i.classifyType === 0) {
let o = list.find(v => {
return (
parseFloat(obj.val) >= parseFloat(v.gt) &&
parseFloat(obj.val) < parseFloat(v.lt)
)
})
answer = o ? o.label : null
} else if (i.classifyType === 1) {
let o = list.find(v => {
return v.val.includes(obj.val)
})
answer = o ? o.label : null
}
this.$set(this.questionForm, i.classId, answer)
}
})
} }
} }
} }

View File

@ -18,8 +18,8 @@
:label="`${question.QuestionName}`" :label="`${question.QuestionName}`"
:prop="question.Id" :prop="question.Id"
:rules="[ :rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary', { required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (question.RelevanceValueList.includes(isNaN(parseFloat(questionForm[question.RelevanceId])) ? questionForm[question.RelevanceId] : questionForm[question.RelevanceId].toString())))) && question.Type!=='group' && question.Type!=='summary',
message: '请注明', trigger: ['blur', 'change']}, message: $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
]" ]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']" :class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
> >
@ -39,27 +39,27 @@
:disabled="readingTaskState >= 2" :disabled="readingTaskState >= 2"
/> />
<!-- 下拉框 --> <!-- 下拉框 -->
<!-- <el-select--> <!-- <el-select-->
<!-- v-if="question.Type==='select'"--> <!-- v-if="question.Type==='select'"-->
<!-- v-model="questionForm[question.Id]"--> <!-- v-model="questionForm[question.Id]"-->
<!-- :disabled="readingTaskState >= 2"--> <!-- :disabled="readingTaskState >= 2"-->
<!-- clearable--> <!-- clearable-->
<!-- @change="((val)=>{formItemChange(val, question)})"--> <!-- @change="((val)=>{formItemChange(val, question)})"-->
<!-- >--> <!-- >-->
<!-- <el-option--> <!-- <el-option-->
<!-- v-for="val in question.TypeValue.split('|')"--> <!-- v-for="val in question.TypeValue.split('|')"-->
<!-- :key="val"--> <!-- :key="val"-->
<!-- :label="val"--> <!-- :label="val"-->
<!-- :value="val"--> <!-- :value="val"-->
<!-- />--> <!-- />-->
<!-- </el-select>--> <!-- </el-select>-->
<el-select <el-select
v-if="question.Type==='select'" v-if="question.Type==='select'"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
filterable filterable
:placeholder="$t('common:placeholder:select')" :placeholder="$t('common:placeholder:select')"
:disabled="readingTaskState >= 2" :disabled="readingTaskState >= 2"
@change="((val)=>{formItemChange(val, qs)})" @change="((val)=>{formItemChange(val, question)})"
> >
<template v-if="question.DictionaryCode"> <template v-if="question.DictionaryCode">
<el-option <el-option
@ -72,9 +72,9 @@
<template v-else-if="question.TypeValue"> <template v-else-if="question.TypeValue">
<el-option <el-option
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
:key="val" :key="val.trim()"
:label="val" :label="val.trim()"
:value="val" :value="val.trim()"
/> />
</template> </template>
</el-select> </el-select>
@ -91,16 +91,16 @@
:key="item.id" :key="item.id"
:label="item.value.toString()" :label="item.value.toString()"
> >
{{item.label}} {{ item.label }}
</el-radio> </el-radio>
</template> </template>
<template v-else-if="question.TypeValue"> <template v-else-if="question.TypeValue">
<el-radio <el-radio
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
:key="val" :key="val.trim()"
:label="val" :label="val.trim()"
> >
{{ val }} {{ val.trim() }}
</el-radio> </el-radio>
</template> </template>
</el-radio-group> </el-radio-group>
@ -112,23 +112,97 @@
> >
<el-checkbox <el-checkbox
v-for="val in question.TypeValue.split('|')" v-for="val in question.TypeValue.split('|')"
:key="val" :key="val.trim()"
:label="val" :label="val.trim()"
> >
{{ val }} {{ val.trim() }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<!-- 数值 --> <!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" --> <!-- :precision="2" :step="0.1" :max="10" -->
<el-input-number <template v-if="question.Type==='number'">
v-if="question.Type==='number'" <!-- 数值 -->
<el-select
v-if="question.TypeValue"
v-model="questionForm[question.Id]"
clearable
@change="(val) => { formItemNumberChange(val, question) }"
>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
/>
</el-select>
<el-input
type="number"
v-if="question.DataSource !== 1"
@change="(val) => { formItemNumberChange(val, question) }"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));"
@input="limitInput($event, questionForm, question.Id)"
v-model="questionForm[question.Id]"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
<template slot="append" v-else-if="question.ValueType === 2">%</template>
</el-input>
<el-input
type="number"
v-if="question.DataSource === 1"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));"
@input="limitInput($event, questionForm, question.Id)"
:disabled="question.DataSource === 1"
v-model="questionForm[question.Id]"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
<template slot="append" v-else-if="question.ValueType === 2">%</template>
</el-input>
</template>
<!-- 自动分类 -->
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2" :disabled="!question.ClassifyEditType"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
/>
</el-select>
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
v-for="item of question.TypeValue.split('|')"
:key="item.trim()"
:label="item.trim()"
>
{{ item.trim() }}
</el-radio>
</el-radio-group>
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 4"
type="number"
:disabled="!question.ClassifyEditType"
v-model="questionForm[question.Id]"
@change="(val) => { formItemNumberChange(val, question) }"
/> />
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-if="question.Type==='upload'"
:action="accept" action
:accept="accept"
:limit="question.ImageCount" :limit="question.ImageCount"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
@ -143,7 +217,6 @@
<div slot="file" slot-scope="{file}"> <div slot="file" slot-scope="{file}">
<img <img
class="el-upload-list__item-thumbnail" class="el-upload-list__item-thumbnail"
crossOrigin="Anonymous"
:src="OSSclientConfig.basePath + file.url" :src="OSSclientConfig.basePath + file.url"
alt="" alt=""
> >
@ -170,7 +243,7 @@
:visible.sync="imgVisible" :visible.sync="imgVisible"
width="600px" width="600px"
> >
<el-image :src="imageUrl" width="100%"> <el-image :src="OSSclientConfig.basePath + imageUrl" width="100%">
<div slot="placeholder" class="image-slot"> <div slot="placeholder" class="image-slot">
{{ $t('trials:readingUnit:qsList:message:loading') }}<span class="dot">...</span> {{ $t('trials:readingUnit:qsList:message:loading') }}<span class="dot">...</span>
</div> </div>
@ -186,13 +259,15 @@
:reading-task-state="readingTaskState" :reading-task-state="readingTaskState"
:question-form="questionForm" :question-form="questionForm"
:visit-task-id="visitTaskId" :visit-task-id="visitTaskId"
:calculationList="calculationList"
@setFormItemData="setFormItemData" @setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData" @resetFormItemData="resetFormItemData"
@formItemNumberChange="formItemNumberChange"
/> />
</div> </div>
</template> </template>
<script> <script>
import { uploadReadingAnswerImage } from '@/api/trials' // import { uploadReadingAnswerImage } from '@/api/trials'
export default { export default {
name: 'FormItem', name: 'FormItem',
props: { props: {
@ -215,6 +290,12 @@ export default {
visitTaskId: { visitTaskId: {
type: String, type: String,
default: '' default: ''
},
calculationList: {
type: Array,
default() {
return []
}
} }
}, },
data() { data() {
@ -223,15 +304,25 @@ export default {
accept: '.png,.jpg,.jpeg', accept: '.png,.jpg,.jpeg',
imgVisible: false, imgVisible: false,
imageUrl: '', imageUrl: '',
urls: [] urls: [],
digitPlaces: null,
} }
}, },
watch: { watch: {
questionForm: { questionForm: {
deep: true, deep: true,
immediate: true, immediate: true,
handler(v) { handler(v, oldv) {
// console.log(v) try {
if (!v || !v[this.question.Id] || !oldv || !oldv[this.question.Id])
return
} catch (e) {
console.log(e, v)
}
if (this.question.Type === 'class') {
this.$emit("setFormItemData", { key: this.question.Id, val: v[this.question.Id], question: v })
}
this.formItemNumberChange(this.question.Id, false)
} }
} }
}, },
@ -242,15 +333,180 @@ export default {
this.fileList = [] this.fileList = []
this.urls.map(url => { this.urls.map(url => {
this.fileList.push({ name: '', url: `/api/${url}` }) this.fileList.push({ name: '', url: `${url}` })
}) })
} }
} }
this.digitPlaces = localStorage.getItem('digitPlaces') ? parseInt(localStorage.getItem('digitPlaces')) : 0
}, },
methods: { methods: {
limitInput(value, a, b) {
if (value.indexOf('.') > -1) {
if (value.split('.')[1].length >= this.digitPlaces) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
}
}
},
logic(rules, num = 0) {
try {
if (rules.CalculateQuestionList.length === 0) {
return false
}
let dataArr = []
rules.CalculateQuestionList.forEach((o, i) => {
if (i === 0) {
if (rules.CustomCalculateMark > 4 && rules.CustomCalculateMark < 10) {
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 = parseFloat(q[o.TableQuestionId])
} else {
num += 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:
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])
if (!isNaN(num)) {
dataArr.push(num)
}
}
} 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:
if (parseFloat(this.questionForm[o.TableQuestionId]) === 0) {
num = 0
} else {
num /= parseFloat(this.questionForm[o.TableQuestionId])
}
break;
case 10:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => {
return acc + (typeof curr === "number" ? curr : 0);
}, 0) / dataArr.length;
break;
case 11:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = Math.max(...dataArr);
break;
case 12:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = Math.min(...dataArr);
break;
case 13:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => acc && curr) ? 1 : 0
break;
case 14:
if (!isNaN(parseFloat(this.questionForm[o.TableQuestionId]))) {
dataArr.push(parseFloat(this.questionForm[o.TableQuestionId]))
}
num = dataArr.length === 0 ? 0 : dataArr.reduce((acc, curr) => acc || curr, 0) ? 1 : 0;
break;
}
}
})
} catch (e) {
console.log(e)
}
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
if (rules.ValueType === 2) {
num = num * 100
}
if (rules.CustomCalculateMark === 13 || rules.CustomCalculateMark === 14) {
return num
} else {
return num.toFixed(digitPlaces)
}
},
formItemNumberChange(questionId, isTable) {
if (isTable) {
this.calculationList.forEach((v, i) => {
var find = v.CalculateQuestionList.filter(o => {
return o.QuestionId === questionId
})
// findnumber
if (find) {
var num = this.logic(v)
if (num !== false) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
}
}
})
} else {
this.calculationList.forEach(v => {
var find = v.CalculateQuestionList.filter(o => {
return o.TableQuestionId === questionId
})
// findnumber
if (find) {
var num = this.logic(v)
if (num !== false) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
}
}
})
}
},
formItemChange(v, question) { formItemChange(v, question) {
if (question.Childrens.length > 0) { if (question.Childrens.length > 0) {
this.resetChild(question.Childrens) this.resetChild(question.Childrens)
} else {
this.$emit('setFormItemData', { key: question.Id, val: v, question: question})
} }
}, },
resetChild(obj) { resetChild(obj) {
@ -267,7 +523,7 @@ export default {
setFormItemData(obj) { setFormItemData(obj) {
this.$emit('setFormItemData', obj) this.$emit('setFormItemData', obj)
}, },
uploadScreenshot(param) { async uploadScreenshot(param) {
if (!this.visitTaskId) return if (!this.visitTaskId) return
const loading = this.$loading({ const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'), target: document.querySelector('.ecrf-wrapper'),
@ -276,18 +532,12 @@ export default {
text: 'Loading', text: 'Loading',
spinner: 'el-icon-loading' spinner: 'el-icon-loading'
}) })
const formData = new FormData() var file = await this.fileToBlob(param.file)
formData.append('file', param.file) const res = await this.OSSclient.put(`/${this.trialId}/ReadAttachment/${this.subjectId}/${this.visitTaskId}/${param.file.name}`, file)
uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => { this.fileList.push({ name: param.file.name, url: this.$getObjectName(res.url) })
if (res.IsSuccess) { this.urls.push(this.$getObjectName(res.url))
this.fileList.push({ url: `${res.Result.Path}` }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
this.urls.push(res.Result.Path) loading.close()
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
}
loading.close()
}).catch(() => {
loading.close()
})
}, },
handleBeforeUpload(file) { handleBeforeUpload(file) {
// //
@ -310,7 +560,7 @@ export default {
}, },
// //
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
this.imageUrl = file.url this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true this.imgVisible = true
}, },
// //
@ -328,7 +578,7 @@ export default {
margin-bottom: 0px; margin-bottom: 0px;
} }
.disabled{ .disabled{
>>>.el-upload--picture-card { /deep/ .el-upload--picture-card {
display: none; display: none;
} }
} }

View File

@ -0,0 +1,956 @@
<template>
<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-switch
v-model="isShowDetail"
:active-text="$t('trials:readingReport:title:expandDetails')"
:inactive-text="$t('trials:readingReport:title:collapseDetails')"
style="margin-right:5px"
@change="handleShowDetail"
/> -->
<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 v-if="task.LatestScanDate">-->
<!-- {{ task.LatestScanDate.split(' ')[0] }}-->
<!-- </div>-->
<!-- {{ `(影像点击跳转)` }} -->
<!-- {{ $t('trials:readingReport:button:jump') }}-->
</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')">
<template>
<!-- 输入框 -->
<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>
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.Type === 'upload'">
<UploadFile
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
:visit-task-id="visitTaskId"
:question="scope.row"
:task="task"
:reading-task-state="readingTaskState"
:init-url="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}"
/>
<UploadFile
v-else-if="scope.row.Type==='upload'"
:visit-task-id="visitTaskId"
:question="scope.row"
:task="task"
:reading-task-state="readingTaskState"
:init-url="questionForm[scope.row.QuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
/>
</template>
<template v-else-if="scope.row.Type === 'upload'">
<UploadFile
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
:visit-task-id="visitTaskId"
:question="scope.row"
:task="task"
:reading-task-state="readingTaskState"
:init-url="scope.row.Answers[task.VisitTaskId]"
/>
<UploadFile
v-else-if="scope.row.Type==='upload'"
:visit-task-id="visitTaskId"
:question="scope.row"
:task="task"
:reading-task-state="readingTaskState"
:init-url="scope.row.Answers[task.VisitTaskId]"
/>
</template>
<template v-else-if="scope.row.QuestionType=== 22">
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }}
</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>
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
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: 'Report',
components: { SignForm, UploadFile },
props: {
trialId: {
type: String,
required: true
},
visitTaskId: {
type: String,
required: true
},
subjectId: {
type: String,
required: true
},
readingTool: {
type: String,
required: true
},
criterionType: {
type: String,
required: true
},
isReadingTaskViewInOrder: {
type: Number,
required: true
}
},
data() {
return {
currentUser: zzSessionStorage.getItem('userName'),
signVisible: false,
signCode: null,
visitTaskList: [],
taskQuestions: [],
loading: false,
answers: [],
readingTaskState: 2,
tumorEvaluate: null,
currentEvaluateResult: null,
isExistDisease: null,
currentExistDisease: null,
currentTaskReason: '',
answerArr: [],
questions: [],
isShowDetail: false,
CriterionType: 0,
CalculationList: [],
TrialReadingCriterionId: null,
tableAnswers: {},
questionForm: {},
questionId: 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)
}
},
taskQuestions() {
this.$nextTick(() => {
this.setScrollTop()
})
}
},
async mounted() {
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
this.digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
this.TrialReadingCriterionId = this.$route.query.TrialReadingCriterionId
window.addEventListener('resize', () => {
this.handleResize()
this.setScrollTop()
})
DicomEvent.$on('getReportInfo', isRefresh => {
if (!isRefresh) return
this.getReportInfo()
})
await this.getQuestionCalculateRelation()
this.getReportInfo()
},
beforeDestroy() {
DicomEvent.$off('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
})
// findnumber
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
})
// findnumber
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.$router.currentRoute.query.trialId
}
this.taskQuestions = []
getReadingReportEvaluation(params).then(res => {
this.readingTaskState = res.Result.ReadingTaskState
this.tumorEvaluate = res.Result.CalculateResult.TumorEvaluate ? parseInt(res.Result.CalculateResult.TumorEvaluate) : null
this.isExistDisease = res.Result.CalculateResult.IsExistDisease ? parseInt(res.Result.CalculateResult.IsExistDisease) : null
this.answerArr = []
this.questions = res.Result.TaskQuestions.concat()
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
taskQuestions.forEach(item => {
this.$set(this.taskQuestions, this.taskQuestions.length, item)
})
this.visitTaskList = res.Result.VisitTaskList
this.InitVisitTaskQuestionForm()
this.handleResize()
this.setScrollTop()
this.loading = false
}).catch(() => { this.loading = false })
},
setScrollTop(a) {
setTimeout(() => {
this.$nextTick(() => {
if (this.$refs.reportList) {
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
}
})
}, 50)
},
getQuestions(questions, isNTFilterLength, lesionType, isLymphNodes) {
const arr = []
if (questions.length !== 0) {
questions.forEach((item) => {
//
//
//
lesionType = item.LesionType
var filterArr = []
if ((item.LesionType === 1 || item.LesionType === 2) && isNTFilterLength) {
filterArr = [0, 1, 3, 4, 5, 6, 2, 8, 10]
} else {
filterArr = [3, 4, 5, 6, 2, 8, 10]
}
if (lesionType === 0 && isLymphNodes === 0 && !this.isShowDetail && this.CriterionType === 1) {
filterArr.push(1)
}
if (!(filterArr.includes(item.QuestionMark))) {
const obj = item
this.$set(obj, 'Answers', {})
// obj.Answers = {}
if (item.RowIndex > 0) {
var idx = item.Childrens.findIndex(i => i.QuestionMark === 8)
var idxLoc = item.Childrens.findIndex(i => i.QuestionMark === 10)
if (idx > -1) {
if (item.Childrens[idx].Answer.length > 0) {
var k = item.Childrens[idx].Answer.findIndex(v => v.Answer !== '')
var part = ''
if (obj.IsCanEditPosition) {
part = `${item.Childrens[idx].Answer[k].Answer}--${item.Childrens[idxLoc].Answer[k].Answer}`
} else {
part = `${item.Childrens[idx].Answer[k].Answer}`
}
if (item.SplitOrMergeLesionName && k > -1) {
obj.QuestionName = `${obj.QuestionName} --${part} (Split from ${item.SplitOrMergeLesionName})`
// obj.QuestionName = `${obj.QuestionName} `
} else if (!item.SplitOrMergeLesionName && k > -1) {
obj.QuestionName = `${obj.QuestionName} --${part}`
// obj.QuestionName = `${obj.QuestionName} `
} else {
obj.QuestionName = `${obj.QuestionName} `
}
if (this.CriterionType === 1) {
var idxLymphNode = item.Childrens.findIndex(i => i.QuestionMark === 2)
if (idxLymphNode > -1) {
isLymphNodes = item.Childrens[idxLymphNode].Answer[k].Answer ? parseInt(item.Childrens[idxLymphNode].Answer[k].Answer) : null
}
}
}
}
}
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, isNTFilterLength, lesionType, isLymphNodes)
}
arr.push(obj)
}
})
}
return arr
},
handleShowDetail(val) {
this.getReportInfo()
// this.taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null)
},
handleExistDiseaseChange(val) {
// this.currentExistDisease = parseInt(val)
if (val === this.isExistDisease && this.tumorEvaluate === this.currentEvaluateResult) {
this.currentTaskReason = ''
this.evaluateReasonChange('')
}
var idx = this.answerArr.findIndex(i => i.questionType === 15)
if (idx > -1) {
this.answerArr[idx].answer = val
}
},
handleEvaluateResultChange(val) {
// this.currentEvaluateResult = parseInt(val)
if (val === this.tumorEvaluate && this.isExistDisease === this.currentExistDisease) {
this.currentTaskReason = ''
this.evaluateReasonChange('')
}
var idx = this.answerArr.findIndex(i => i.questionType === 13)
if (idx > -1) {
this.answerArr[idx].answer = val
}
},
evaluateReasonChange(val) {
var idx = this.answerArr.findIndex(i => i.questionType === 14)
if (idx > -1) {
this.answerArr[idx].answer = val
}
},
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;
}
/deep/ .el-table--border th.gutter:last-of-type{
border: none;
}
/deep/ .el-card__header{
border: none;
padding: 10px;
}
/deep/ .el-upload-list--picture-card .el-upload-list__item{
width: 30px;
height: 30px;
}
/deep/ .el-upload--picture-card{
width: 30px;
height: 30px;
line-height: 40px;
}
}
/deep/ .el-switch__label.is-active{
color: #428bca;
}
.uploadWrapper{
display: flex;
flex-direction: column;
align-items: flex-start;
}
</style>

View File

@ -0,0 +1,168 @@
<template>
<div>
<el-upload
action
:accept="accept"
:limit="question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
:http-request="uploadScreenshot"
list-type="picture-card"
:on-remove="handleRemove"
:file-list="fileList"
:class="{disabled:readingTaskState >= 2 || (fileList.length >= question.ImageCount) || (task.VisitTaskId !== visitTaskId) || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))}"
:disabled="readingTaskState >= 2 || task.VisitTaskId !== visitTaskId || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))"
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<viewer
:ref="file.url"
:images="[imageUrl]"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
>
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
crossOrigin="anonymous"
alt=""
style="max-width: 100%; max-height: 100%"
/>
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span
v-if="readingTaskState < 2"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete" />
</span>
</span>
</viewer>
</div>
</el-upload>
</div>
</template>
<script>
export default {
name: "UploadFile",
props: {
task: {
Type: Object,
required: true
},
question: {
Type: Object,
required: true
},
visitTaskId: {
type: String,
required: true
},
readingTaskState: {
type: Number,
required: true
},
initUrl: {
type: String,
default: ''
}
},
data () {
return {
imgVisible: false,
imageUrl: null,
accept: '.png,.jpg,.jpeg',
fileList: [],
}
},
mounted() {
this.urls = this.initUrl === '' ? [] : this.initUrl.split('|')
console.log(this.visitTaskId, this.urls)
this.fileList = []
this.urls.map(url => {
this.fileList.push({ name: '', url: `${url}` })
})
console.log(this.fileList)
},
methods: {
checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length)
if (this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false
} else {
return true
}
},
async uploadScreenshot(param) {
if (!this.visitTaskId) return
const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'),
fullscreen: false,
lock: true,
text: 'Loading',
spinner: 'el-icon-loading'
})
var trialId = this.$route.query.trialId
var subjectId = this.$route.query.trialId
var file = await this.fileToBlob(param.file)
const res = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${param.file.name}`, file)
console.log(res)
this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url)})
this.urls.push(this.$getObjectName(res.url))
this.$emit('setImageUrl', this.urls.length > 0 ? this.urls.join('|') : '')
loading.close()
},
handleBeforeUpload(file) {
//
if (this.checkFileSuffix(file.name)) {
// this.fileList = []
return true
} else {
this.$alert(`必须是 ${this.accept} 格式`)
return false
}
},
//
handlePictureCardPreview(file) {
var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
// this.imgVisible = true
this.$refs[file.url].$viewer.show()
}
},
//
handleRemove(file, fileList) {
this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
},
}
}
</script>
<style lang="scss" scoped>
.disabled{
/deep/ .el-upload--picture-card {
display: none;
}
}
</style>

View File

@ -1,9 +1,9 @@
<template> <template>
<div v-loading="loading" class="img-container"> <div class="img-container">
<el-card class="box-card left"> <el-card v-loading="loading" class="box-card left">
<div v-if="otherInfo && otherInfo.IsReadingShowSubjectInfo" class="title"> <div v-if="isReadingShowSubjectInfo" class="title">
<span>{{$t('trials:auditRecord:table:subject')}}{{ otherInfo.SubjectCode }} </span> <h4>{{ subjectCode }} </h4>
<span>({{ otherInfo.TaskBlindName }})</span> <h4>{{ taskBlindName }}</h4>
</div> </div>
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane :label="$t('trials:clinicaldara:title:currentTask')" name="first" class="left-content"> <el-tab-pane :label="$t('trials:clinicaldara:title:currentTask')" name="first" class="left-content">
@ -28,10 +28,16 @@
'is-boxActive': item.Id === currentFileId 'is-boxActive': item.Id === currentFileId
}" }"
class="img-box" class="img-box"
style="text-overflow: ellipsis;overflow: hidden;white-space: nowrap;"
@click="selected(item,i,j,true)" @click="selected(item,i,j,true)"
> >
{{ `${j+1}. ${item.FileName}` }} <div v-if="item.FileName.length < 15" class="img-text">
{{ `${j+1}. ${item.FileName}` }}
</div>
<el-tooltip v-else :content="item.FileName" placement="bottom">
<div class="img-text">
{{ `${j+1}. ${item.FileName}` }}
</div>
</el-tooltip>
</div> </div>
</div> </div>
@ -42,7 +48,7 @@
<div style="height:100%;"> <div style="height:100%;">
<!-- 文件层级 --> <!-- 文件层级 -->
<div v-if="associatedList.length === 0" class="empty-text"> <div v-if="associatedList.length === 0" class="empty-text">
<slot name="empty">{{$t('trials:audit:message:noData')}}</slot> <slot name="empty">{{ $t('trials:audit:message:noData') }}</slot>
</div> </div>
<div v-else> <div v-else>
<div <div
@ -54,9 +60,15 @@
class="img-box" class="img-box"
@click="handleImageRead(task)" @click="handleImageRead(task)"
> >
{{ `${j+1}. ${task.TaskBlindName}` }} <div v-if="task.TaskBlindName.length < 15" class="img-text">
{{ `${j+1}. ${task.TaskBlindName}` }}
</div>
<el-tooltip v-else :content="task.TaskBlindName" placement="bottom">
<div class="img-text">
{{ `${j+1}. ${task.TaskBlindName}` }}
</div>
</el-tooltip>
</div> </div>
</div> </div>
</div> </div>
</el-tab-pane> </el-tab-pane>
@ -64,7 +76,7 @@
</el-card> </el-card>
<!-- 预览图像 --> <!-- 预览图像 -->
<el-card class="box-card right"> <el-card v-loading="loading" class="box-card right">
<div style="width:100%;height: 100%;"> <div style="width:100%;height: 100%;">
<Preview <Preview
v-if="previewImage.imgList.length > 0" v-if="previewImage.imgList.length > 0"
@ -79,20 +91,25 @@
</el-card> </el-card>
<el-card class="box-card" style="width:400px;height:100%;padding: 10px;margin-left:10px;overflow-y: auto;"> <el-card class="box-card" style="width:400px;height:100%;padding: 10px;margin-left:10px;overflow-y: auto;">
<el-button <div style="text-align:right;">
v-if="otherInfo && otherInfo.IsExistsClinicalData" <el-button
type="primary" v-if="otherInfo && otherInfo.IsExistsClinicalData"
size="mini" type="text"
@click="previewCD" @click="previewCD"
> >
{{ $t('trials:crcUpload:label:clinicalData') }} {{ $t('trials:crcUpload:label:clinicalData') }}
</el-button> </el-button>
</div>
<Criterions <Criterions
v-if="otherInfo && visitTaskId!== '' && subjectId!== '' && readingCategory!==null && readingCategory!==4" v-if="otherInfo && visitTaskId!== '' && subjectId!== '' && readingCategory!==null && readingCategory!==4"
:trial-id="trialId" :trial-id="trialId"
:subject-id="subjectId" :subject-id="subjectId"
:visit-task-id="visitTaskId" :visit-task-id="visitTaskId"
:criterion-id="otherInfo.TrialCriterionId" :criterion-id="otherInfo.TrialCriterionId"
:subject-code="subjectCode"
:task-blind-name="taskBlindName"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:ise-c-r-f-show-in-dicom-reading="iseCRFShowInDicomReading"
/> />
</el-card> </el-card>
</div> </div>
@ -127,9 +144,33 @@ export default {
type: String, type: String,
required: true required: true
}, },
taskBlindName: {
type: String,
required: true
},
readingCategory: { readingCategory: {
type: Number, type: Number,
required: true required: true
},
isReadingShowSubjectInfo: {
type: Boolean,
required: true
},
readingTool: {
type: String,
required: true
},
criterionType: {
type: String,
required: true
},
isReadingTaskViewInOrder: {
type: Number,
required: true
},
iseCRFShowInDicomReading: {
type: Boolean,
required: true
} }
}, },
data() { data() {
@ -155,7 +196,9 @@ export default {
associatedList: [], associatedList: [],
currentTaskId: '', currentTaskId: '',
otherInfo: null, otherInfo: null,
isReadingShowPreviousResults: false isReadingShowPreviousResults: false,
bp: [],
openWindow: null
} }
}, },
computed: { computed: {
@ -163,11 +206,17 @@ export default {
return this.otherInfo && this.otherInfo.IsReadingShowPreviousResults && this.isReadingShowPreviousResults return this.otherInfo && this.otherInfo.IsReadingShowPreviousResults && this.isReadingShowPreviousResults
} }
}, },
mounted() { async mounted() {
this.bp = await this.$getBodyPart(this.$route.query.trialId)
this.isReadingShowPreviousResults = this.$router.currentRoute.query.isReadingShowPreviousResults !== undefined ? this.$router.currentRoute.query.isReadingShowPreviousResults : true this.isReadingShowPreviousResults = this.$router.currentRoute.query.isReadingShowPreviousResults !== undefined ? this.$router.currentRoute.query.isReadingShowPreviousResults : true
this.getNoneDicomList(this.isReadingShowPreviousResults) this.getNoneDicomList(this.isReadingShowPreviousResults)
}, },
beforeDestroy() {
if (this.openWindow) {
this.openWindow.close()
}
},
methods: { methods: {
// Dicom // Dicom
getNoneDicomList() { getNoneDicomList() {
@ -248,18 +297,21 @@ export default {
}) })
}, },
handleImageRead(task) { handleImageRead(task) {
if (this.openWindow) {
this.openWindow.close()
}
this.currentTaskId = task.VisitTaskId this.currentTaskId = task.VisitTaskId
var criterionType = this.$router.currentRoute.query.criterionType var criterionType = this.criterionType
var readingTool = this.$router.currentRoute.query.readingTool var readingTool = this.readingTool
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder var isReadingTaskViewInOrder = this.isReadingTaskViewInOrder
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
var token = getToken() var token = getToken()
const path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}` const path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
// const routeData = this.$router.resolve({ // const routeData = this.$router.resolve({
// path: `/readingPage?subjectId=${this.subjectId}&trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&TokenKey=${token}` // path: `/readingPage?subjectId=${this.subjectId}&trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&TokenKey=${token}`
// }) // })
const routeData = this.$router.resolve({ path }) const routeData = this.$router.resolve({ path })
window.open(routeData.href, '_blank') this.openWindow = window.open(routeData.href, '_blank')
}, },
previewCD() { previewCD() {
var token = getToken() var token = getToken()
@ -280,7 +332,7 @@ export default {
} }
var arr = bodyPart.split(separator) var arr = bodyPart.split(separator)
var newArr = arr.map(i => { var newArr = arr.map(i => {
return this.$fd('Bodypart', i.trim()) return this.$fd('Bodypart', i.trim(), 'Code', { Bodypart: this.bp }, 'Name')
}) })
return newArr.join(' | ') return newArr.join(' | ')
} }
@ -293,7 +345,7 @@ export default {
flex: 1; flex: 1;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 10px; padding-bottom: 10px;
display: flex; display: flex;
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 7px; width: 7px;
@ -303,7 +355,7 @@ export default {
border-radius: 10px; border-radius: 10px;
background: #d0d0d0; background: #d0d0d0;
} }
>>>.el-card__body{ /deep/ .el-card__body{
padding: 0px; padding: 0px;
} }
} }
@ -317,37 +369,43 @@ export default {
width:240px; width:240px;
height: 100%; height: 100%;
>>>.el-card__body{ /deep/ .el-card__body{
height: 100%; height: 100%;
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.title{ .title{
height: 40px; // height: 40px;
line-height: 40px; // line-height: 40px;
border: 1ppx solid; border: 1ppx solid;
border: 1px solid #ebe7e7; border: 1px solid #ebe7e7;
padding-left: 10px; // padding-left: 10px;
background-color: #4e4e4e; background-color: #4e4e4e;
color: #ffffff; color: #ffffff;
h4{
padding: 5px 0px;
margin: 0;
text-align: center;
background-color: #4c4c4c;
}
} }
.left-content{ .left-content{
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
} }
>>>.el-tabs{ /deep/ .el-tabs{
height: 100%; height: 100%;
display:flex; display:flex;
flex-direction: column; flex-direction: column;
} }
>>>.el-tabs__header{ /deep/ .el-tabs__header{
height: 40px; height: 40px;
padding: 0 5px; padding: 0 5px;
margin-bottom: 5px; margin-bottom: 5px;
} }
>>>.el-tabs__content{ /deep/ .el-tabs__content{
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
padding: 0 5px; padding: 0 5px;
@ -357,13 +415,19 @@ export default {
display: inline-block; display: inline-block;
box-sizing: border-box; box-sizing: border-box;
border-bottom: 2px solid #f3f3f3; border-bottom: 2px solid #f3f3f3;
width: 180px;
height: 50px;
line-height: 50px;
cursor: pointer; cursor: pointer;
// margin-bottom: 5px; // margin-bottom: 5px;
padding-left: 5px; padding-left: 5px;
} }
.img-text{
display: inline-block;
width: 200px;
height: 50px;
line-height: 50px;
overflow: hidden;
text-overflow: ellipsis; /* 用省略号表示溢出的文本 */
white-space: nowrap;
}
.img-box:nth-last-child(1){ .img-box:nth-last-child(1){
margin-bottom: 0px; margin-bottom: 0px;
} }
@ -379,7 +443,7 @@ export default {
flex: 1; flex: 1;
height: 100%; height: 100%;
margin-left: 10px; margin-left: 10px;
>>>.el-card__body{ /deep/ .el-card__body{
height: 100%; height: 100%;
width: 100%; width: 100%;
} }

View File

@ -1,15 +1,40 @@
<template> <template>
<div ref="container" v-loading="loading" class="none-dicom-reading-container"> <div ref="container" v-loading="loading" class="none-dicom-reading-container">
<!-- 访视阅片 --> <!-- 访视阅片 -->
<VisitReview <div v-if="isShow && readingCategory && readingCategory=== 1" class="reading-wrapper">
v-if="isShow && readingCategory && readingCategory=== 1" <el-tabs v-model="activeName" :before-leave="beforeLeave">
:trial-id="trialId" <!-- 阅片 -->
:subject-id="subjectId" <el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
:subject-code="subjectCode" <VisitReview
:visit-task-id="visitTaskId" :trial-id="trialId"
:reading-category="readingCategory" :subject-id="subjectId"
:is-exists-clinical-data="isExistsClinicalData" :subject-code="subjectCode"
/> :visit-task-id="visitTaskId"
:task-blind-name="taskBlindName"
:reading-category="readingCategory"
:readingTool="readingTool"
:criterionType="criterionType"
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
/>
</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 <GlobalReview
v-else-if="isShow && readingCategory && readingCategory === 2" v-else-if="isShow && readingCategory && readingCategory === 2"
@ -59,7 +84,7 @@
:show-close="false" :show-close="false"
> >
<span slot="title" class="dialog-footer"> <span slot="title" class="dialog-footer">
当前阅片任务存在临床数据请查看若已查看请点击确认 {{ $t('trials:reading:noneDicom:tip:hasCllinicalData') }}
</span> </span>
<div :style="{'height':dialogH,'margin':0}"> <div :style="{'height':dialogH,'margin':0}">
<ClinicalData <ClinicalData
@ -70,7 +95,7 @@
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleConfirmCD"></el-button> <el-button type="primary" @click="handleConfirmCD">{{ $t("common:button:confirm") }}</el-button>
</span> </span>
</el-dialog> </el-dialog>
@ -83,16 +108,18 @@ import { getNextTask, readClinicalData } from '@/api/trials'
import store from '@/store' import store from '@/store'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent' import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import Report from './components/Report'
import VisitReview from './components/VisitReview' 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 ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
import { getToken } from '@/utils/auth' // 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: 'NoneDicomReading',
components: { components: {
VisitReview, VisitReview,
Report,
AdReview, AdReview,
GlobalReview, GlobalReview,
OncologyReview, OncologyReview,
@ -113,12 +140,15 @@ export default {
isExistsClinicalData: false, isExistsClinicalData: false,
isNeedReadClinicalData: false, isNeedReadClinicalData: false,
isReadClinicalData: false, isReadClinicalData: false,
iseCRFShowInDicomReading: false,
criterionType: null, criterionType: null,
readingTool: null, readingTool: null,
isNewSubject: null, isNewSubject: null,
dialogVisible: false, dialogVisible: false,
dialogH: 0, dialogH: 0,
isShow: false isShow: false,
activeName:'',
tabs: []
} }
}, },
mounted() { mounted() {
@ -136,7 +166,8 @@ export default {
this.readingTool = this.$router.currentRoute.query.readingTool this.readingTool = this.$router.currentRoute.query.readingTool
this.isNewSubject = this.$router.currentRoute.query.isNewSubject this.isNewSubject = this.$router.currentRoute.query.isNewSubject
if (this.isNewSubject && this.isReadingTaskViewInOrder) { if (this.isNewSubject && this.isReadingTaskViewInOrder) {
this.$message.success(`已开始受试者${this.subjectCode}阅片任务`) const message = this.$t('trials:reading:noneDicom:message:startRead').replace('xxx', this.subjectCode)
this.$message.success(message)
changeURLStatic('isNewSubject', '') changeURLStatic('isNewSubject', '')
} }
if (this.$router.currentRoute.query.TokenKey) { if (this.$router.currentRoute.query.TokenKey) {
@ -163,10 +194,14 @@ export default {
this.isShow = false this.isShow = false
getNextTask(param).then(res => { getNextTask(param).then(res => {
this.readingCategory = res.Result.ReadingCategory this.readingCategory = res.Result.ReadingCategory
if (this.subjectId !== res.Result.SubjectId && this.isReadingTaskViewInOrder) { // if (this.subjectId !== res.Result.SubjectId && this.isReadingTaskViewInOrder) {
store.dispatch('reading/resetVisitTasks') // store.dispatch('reading/resetVisitTasks')
var token = getToken() // 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}` // 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.subjectId = res.Result.SubjectId
this.visitTaskId = res.Result.VisitTaskId this.visitTaskId = res.Result.VisitTaskId
@ -175,7 +210,8 @@ export default {
this.isExistsClinicalData = res.Result.IsExistsClinicalData this.isExistsClinicalData = res.Result.IsExistsClinicalData
this.isReadClinicalData = res.Result.IsReadClinicalData this.isReadClinicalData = res.Result.IsReadClinicalData
this.isNeedReadClinicalData = res.Result.IsNeedReadClinicalData this.isNeedReadClinicalData = res.Result.IsNeedReadClinicalData
this.iseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
this.digitPlaces = res.Result.DigitPlaces this.digitPlaces = res.Result.DigitPlaces
@ -189,15 +225,32 @@ export default {
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) }).catch(() => { this.loading = false })
}, },
handleConfirmCD() { async handleConfirmCD() {
this.loading = true this.loading = true
var visitTaskId = this.visitTaskId var visitTaskId = this.visitTaskId
readClinicalData({ visitTaskId }).then(res => { try {
await readClinicalData({ visitTaskId })
this.loading = false this.loading = false
this.dialogVisible = false this.dialogVisible = false
this.isReadClinicalData = true this.isReadClinicalData = true
}).catch(() => { this.loading = false }) } 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> </script>
@ -210,19 +263,50 @@ export default {
flex-direction: column; flex-direction: column;
.el-dialog{ .el-dialog{
margin-top: 0px !important; margin-top: 0px !important;
>>>.el-dialog__wrapper{ /deep/ .el-dialog__wrapper{
margin-top: 0px !important; margin-top: 0px !important;
} }
>>>.el-dialog__body{ /deep/ .el-dialog__body{
padding: 10px; padding: 10px;
} }
} }
.reading-wrapper{
width: 100%;
height: 100%;
padding: 0 10px;
box-sizing: border-box;
/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%;
}
>>>.dialog-container{ }
}
/deep/ .dialog-container{
margin-top: 50px !important; margin-top: 50px !important;
} }
>>>.el-dialog__body{ /deep/ .el-dialog__body{
padding: 10px; padding: 10px;
} }
} }

View File

@ -26,6 +26,14 @@
> >
{{ $t('trials:oncologyReview:button:clinicalData') }} {{ $t('trials:oncologyReview:button:clinicalData') }}
</el-button> </el-button>
<el-button
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<!-- 保存 --> <!-- 保存 -->
<el-button <el-button
v-if="oncologyInfo.ReadingTaskState < 2" v-if="oncologyInfo.ReadingTaskState < 2"
@ -93,7 +101,7 @@
<span>{{ $fd('YesOrNo', scope.row.IsHaveChange ) }}</span> <span>{{ $fd('YesOrNo', scope.row.IsHaveChange ) }}</span>
<!-- 查看详情 --> <!-- 查看详情 -->
<el-button <el-button
v-if="scope.row.IsHaveChange && !!oncologyInfo.GlobalTaskId" v-if="scope.row.IsHaveChange && oncologyInfo.GlobalTaskId"
type="text" type="text"
style="margin-left:5px;" style="margin-left:5px;"
@click="handleViewDetail(oncologyInfo.GlobalTaskId)" @click="handleViewDetail(oncologyInfo.GlobalTaskId)"
@ -122,18 +130,24 @@
<!-- 结论 --> <!-- 结论 -->
<el-table-column <el-table-column
prop="EvaluationResult" prop="EvaluationResult"
:label="$t('trials:oncologyReview:title:findings')"
show-overflow-tooltip show-overflow-tooltip
width="150" width="150"
> >
<template slot="header">
<div>
<span>{{ $t('trials:oncologyReview:title:findings') }}</span>
<span style="color:red">*</span>
</div>
</template>
<template slot-scope="scope"> <template slot-scope="scope">
<el-select <el-select
v-if="oncologyInfo.ReadingTaskState < 2" v-if="oncologyInfo.ReadingTaskState < 2 && !scope.row.IsBaseLine"
v-model="scope.row.EvaluationResult" v-model="scope.row.EvaluationResult"
:placeholder="$t('common:ruleMessage:select')" :placeholder="$t('common:ruleMessage:select')"
> >
<el-option <el-option
v-for="item in assessTypeList" v-for="item in assessTypeList"
v-show="item.Code !== '-1'"
:key="item.Id" :key="item.Id"
:label="item.Value" :label="item.Value"
:value="item.Code" :value="item.Code"
@ -156,14 +170,14 @@
<div> <div>
<!-- 原因 --> <!-- 原因 -->
<span>{{ $t('trials:oncologyReview:title:reason') }}</span> <span>{{ $t('trials:oncologyReview:title:reason') }}</span>
<span style="color:red">*</span> <span style="color:red">!</span>
</div> </div>
</el-tooltip> </el-tooltip>
</template> </template>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
v-if="oncologyInfo.ReadingTaskState < 2" v-if="oncologyInfo.ReadingTaskState < 2 && !scope.row.IsBaseLine"
v-model="scope.row.EvaluationReason" v-model="scope.row.EvaluationReason"
/> />
<span v-else>{{ scope.row.EvaluationReason }}</span> <span v-else>{{ scope.row.EvaluationReason }}</span>
@ -207,6 +221,12 @@
show-overflow-tooltip show-overflow-tooltip
width="200" width="200"
/> />
<el-table-column
prop="VisitName"
:label="$t('trials:globalReview:table:cutOffVisitName')"
show-overflow-tooltip
width="200"
/>
<el-table-column <el-table-column
:label="$t('common:action:action')" :label="$t('common:action:action')"
width="200" width="200"
@ -241,8 +261,12 @@
</template> </template>
<script> <script>
import { getOncologyReadingInfo, getReadingPastResultList, setOncologyReadingInfo, submitOncologyReadingInfo } from '@/api/trials' import { getOncologyReadingInfo, getReadingPastResultList, setOncologyReadingInfo, submitOncologyReadingInfo } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
// import store from '@/store'
import { changeURLStatic } from '@/utils/history.js'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent' import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
export default { export default {
@ -331,9 +355,10 @@ export default {
} }
}, },
methods: { methods: {
getList() { async getList() {
this.loading = true this.loading = true
getOncologyReadingInfo({ visitTaskId: this.visitTaskId }).then(res => { try {
const res = await getOncologyReadingInfo({ visitTaskId: this.visitTaskId })
var questions = [] var questions = []
if (res.Result.OncologyVisits.length > 0) { if (res.Result.OncologyVisits.length > 0) {
var task = res.Result.OncologyVisits[0] var task = res.Result.OncologyVisits[0]
@ -345,7 +370,9 @@ export default {
this.assessTypeList = res.Result.AssessTypeList this.assessTypeList = res.Result.AssessTypeList
this.oncologyInfo = res.Result this.oncologyInfo = res.Result
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) } catch (e) {
this.loading = false
}
}, },
getAssessType(val) { getAssessType(val) {
var idx = this.assessTypeList.findIndex(i => i.Code === val) var idx = this.assessTypeList.findIndex(i => i.Code === val)
@ -356,62 +383,81 @@ export default {
} }
}, },
handleSave(isPrompt) { handleSave(isPrompt) {
this.loading = true return new Promise(async(resolve, reject) => {
var index = this.oncologyInfo.OncologyVisits.findIndex(item => !item.EvaluationResult)
if (index > -1) {
this.loading = false
// ''
this.$confirm(this.$t('trials:oncologyReview:message:msg1'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
return Promise.reject(false)
})
.catch(action => {
return Promise.reject(false)
})
} else {
this.loading = true this.loading = true
var oncologyQuestionList = [] // var index = this.oncologyInfo.OncologyVisits.findIndex(item => !item.EvaluationResult && !item.IsBaseLine)
this.oncologyInfo.OncologyVisits.map(item => { var isDiffer = this.checkDifferResult()
if (item.EvaluationResult) { if (isDiffer) {
oncologyQuestionList.push( this.loading = false
{ const confirm = await this.$confirm(
visitTaskId: item.VisitTaskId, this.$t('trials:oncologyReview:message:msg2'),
evaluationResult: item.EvaluationResult, {
evaluationReason: item.EvaluationReason type: 'warning',
} distinguishCancelAndClose: true
) }
)
if (confirm === 'confirm') reject(false)
} else {
this.loading = true
var oncologyQuestionList = []
this.oncologyInfo.OncologyVisits.map(item => {
if (item.EvaluationResult && !item.IsBaseLine) {
oncologyQuestionList.push(
{
visitTaskId: item.VisitTaskId,
evaluationResult: item.EvaluationResult,
evaluationReason: item.EvaluationReason
}
)
}
})
var params = {
oncologyTaskId: this.visitTaskId,
oncologyQuestionList: oncologyQuestionList,
globalTaskId: this.oncologyInfo.GlobalTaskId,
relatedTaskId: this.oncologyInfo.RelatedTaskId
} }
}) try {
var params = { await setOncologyReadingInfo(params)
oncologyTaskId: this.visitTaskId,
oncologyQuestionList: oncologyQuestionList
}
return new Promise((resolve, reject) => {
setOncologyReadingInfo(params).then(res => {
this.loading = false this.loading = false
this.getList() this.getList()
if (isPrompt) { if (isPrompt) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
} }
resolve(true) resolve(true)
}).catch(_ => { } catch (e) {
this.loading = false this.loading = false
reject(false) reject(false)
}) }
}) }
}
},
handleSubmit() {
this.$refs['adForm'].validate((valid) => {
if (!valid) return
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}) })
}, },
checkDifferResult() {
var isDiffer = false
var criterionType = parseInt(this.$route.query.criterionType)
if (criterionType === 2) {
for (let i = 0; i < this.oncologyInfo.OncologyVisits.length; i++) {
if (this.oncologyInfo.OncologyVisits[i].IsBaseLine) continue
var tumorAssessment = ''
var idx = this.oncologyInfo.OncologyVisits[i].QuestionList.findIndex(v => v.DictionaryCode === 'ImagingOverallAssessment_Lugano')
if (idx > -1) {
tumorAssessment = this.oncologyInfo.OncologyVisits[i].QuestionList[idx].Answer
if (!(this.oncologyInfo.OncologyVisits[i].EvaluationResult !== '' && (tumorAssessment === this.oncologyInfo.OncologyVisits[i].EvaluationResult || (tumorAssessment !== this.oncologyInfo.OncologyVisits[i].EvaluationResult && this.oncologyInfo.OncologyVisits[i].EvaluationReason)))) {
isDiffer = true
break
}
}
}
}
return isDiffer
},
async handleSubmit() {
const valid = await this.$refs['adForm'].validate()
if (!valid) return
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
},
// //
closeSignDialog(isSign, signInfo) { closeSignDialog(isSign, signInfo) {
if (isSign) { if (isSign) {
@ -420,17 +466,16 @@ export default {
this.signVisible = false this.signVisible = false
} }
}, },
handleConfirm() { async handleConfirm() {
this.handleSave(false).then(res => { const res = await this.handleSave(false)
if (res) { if (res) {
const { ImageAssessmentReportConfirmation } = const_.processSignature const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true this.signVisible = true
} }
})
}, },
// //
signConfirm(signInfo) { async signConfirm(signInfo) {
this.loading = true this.loading = true
var params = { var params = {
data: { data: {
@ -438,7 +483,8 @@ export default {
}, },
signInfo: signInfo signInfo: signInfo
} }
submitOncologyReadingInfo(params).then(res => { try {
const res = await submitOncologyReadingInfo(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.isEdit = false this.isEdit = false
@ -448,43 +494,47 @@ export default {
// window.opener.postMessage('refreshTaskList', window.location) // window.opener.postMessage('refreshTaskList', window.location)
// //
this.oncologyInfo.ReadingTaskState = 2 this.oncologyInfo.ReadingTaskState = 2
window.opener.postMessage('refreshTaskList', window.location)
// ''
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
// var token = getToken()
// var criterionType = this.$router.currentRoute.query.criterionType
// var readingTool = this.$router.currentRoute.query.readingTool
// var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
// var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
// var path = ''
// if (readingTool && parseInt(readingTool) === 0) {
// path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
// } else {
// path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
// }
// this.$router.push({ path })
DicomEvent.$emit('getNextTask')
})
.catch(action => {
}) const res = await getAutoCutNextTask()
var isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
// store.dispatch('reading/resetVisitTasks')
// DicomEvent.$emit('getNextTask')
window.location.reload()
} else {
// ''
const confirm = await this.$confirm(
this.$t('trials:oncologyReview:title:msg2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm === 'confirm') {
// store.dispatch('reading/resetVisitTasks')
// DicomEvent.$emit('getNextTask')
window.location.reload()
} else {
changeURLStatic('visitTaskId', this.visitTaskId)
}
}
window.opener.postMessage('refreshTaskList', window.location)
} }
this.loading = false this.loading = false
}).catch(_ => { } catch (e) {
this.loading = false this.loading = false
this.$refs['signForm'].btnLoading = false this.$refs['signForm'].btnLoading = false
}) }
}, },
getPriorList() { async getPriorList() {
this.priorLoading = true this.priorLoading = true
getReadingPastResultList({ visitTaskId: this.visitTaskId }).then(res => { try {
const res = await getReadingPastResultList({ visitTaskId: this.visitTaskId })
this.priorList = res.Result this.priorList = res.Result
this.priorLoading = false this.priorLoading = false
}).catch(() => { this.priorLoading = false }) } catch (e) {
this.priorLoading = false
}
}, },
handleViewDetail(visitTaskId) { handleViewDetail(visitTaskId) {
if (this.openWindow) { if (this.openWindow) {
@ -514,6 +564,28 @@ export default {
path: `/clinicalData?subjectId=${this.oncologyInfo.SubjectId}&trialId=${this.trialId}&visitTaskId=${this.oncologyInfo.OncologyTaskId}&TokenKey=${token}` path: `/clinicalData?subjectId=${this.oncologyInfo.SubjectId}&trialId=${this.trialId}&visitTaskId=${this.oncologyInfo.OncologyTaskId}&TokenKey=${token}`
}) })
window.open(routeData.href, '_blank') window.open(routeData.href, '_blank')
},
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)
}
} }
} }
} }

View File

@ -79,15 +79,15 @@ module.exports = {
}, },
plugins: [ plugins: [
new CopyPlugin([ new CopyPlugin([
{ from: './node_modules/cornerstone-wado-image-loader/dist/cornerstoneWADOImageLoaderWebWorker.min.js', to: 'webWorker.js' }, // { from: './node_modules/cornerstone-wado-image-loader/dist/cornerstoneWADOImageLoaderWebWorker.min.js', to: 'webWorker.js' },
{ from: './node_modules/cornerstone-wado-image-loader/dist/cornerstoneWADOImageLoader.min.js', to: 'dicomCodecs.js' }, // { from: './node_modules/cornerstone-wado-image-loader/dist/cornerstoneWADOImageLoader.min.js', to: 'dicomCodecs.js' },
// { from: './node_modules/@cornerstonejs/codec-charls/dist/charlsjs.js', to: 'charlsjs.js' }, // { from: './node_modules/@cornerstonejs/codec-charls/dist/charlsjs.js', to: 'charlsjs.js' },
// { from: './node_modules/@cornerstonejs/codec-charls/dist/charlsjs.js.mem', to: './static/js/charlsjs.js.mem' }, // { from: './node_modules/@cornerstonejs/codec-charls/dist/charlsjs.js.mem', to: './static/js/charlsjs.js.mem' },
// { from: './node_modules/@cornerstonejs/codec-charls/dist/charlswasm.js', to: './static/js/charlswasm.js' }, // { from: './node_modules/@cornerstonejs/codec-charls/dist/charlswasm.js', to: './static/js/charlswasm.js' },
// { from: './node_modules/@cornerstonejs/codec-charls/dist/charlswasm.wasm', to: './static/js/charlswasm.wasm' }, // { from: './node_modules/@cornerstonejs/codec-charls/dist/charlswasm.wasm', to: './static/js/charlswasm.wasm' },
{ from: './node_modules/@ffmpeg/core/dist/ffmpeg-core.js', to: 'ffmpeg-core.js' }, // { from: './node_modules/@ffmpeg/core/dist/ffmpeg-core.js', to: 'ffmpeg-core.js' },
{ from: './node_modules/@ffmpeg/core/dist/ffmpeg-core.wasm', to: 'ffmpeg-core.wasm' }, // { from: './node_modules/@ffmpeg/core/dist/ffmpeg-core.wasm', to: 'ffmpeg-core.wasm' },
{ from: './node_modules/@ffmpeg/core/dist/ffmpeg-core.worker.js', to: 'ffmpeg-core.worker.js' }, // { from: './node_modules/@ffmpeg/core/dist/ffmpeg-core.worker.js', to: 'ffmpeg-core.worker.js' },
{ {
from: path.resolve(__dirname, './static'), from: path.resolve(__dirname, './static'),
to: path.resolve(__dirname, './dist/static'), to: path.resolve(__dirname, './dist/static'),